MySQL行锁和表锁
MySQL常用引擎有MyISAM和InnoDB,而InnoDB是mysql默认的引擎。MyISAM不支持行锁,而InnoDB支持行锁和表锁。
MyISAM在执行select时,会自动给所有涉及的表加读锁,在执行update、delete、insert前,会给所有涉及的表加写锁,无需用户操作。
读锁:
select math from zje where math>60 lock in share mode;
写锁:
select math from zje where math >60 for update;
表锁
适用表锁不会出现死锁,发生锁冲突的几率高,并发量低。
MySQL的表锁表现形式:
- 表共享读锁(对MyISAM表的读操作,不会阻塞其他线程对同一表的读请求,但无法进行写操作,除非读锁被释放)
- 表独占写锁(对MyISAM表的写操作,会阻塞其他线程对同一表的读写操作,除非写锁别释放)
MyISAM不适合作为主表的引擎,因为在进行写操作时,其他的线程全被阻塞了。
行锁
MySQL的行锁加载在索引响应的行上的,如果对应的sql语句没有适用索引的话,则会进行全盘扫描,无法适用行锁,而是适用表锁,其他事务无法对当前表进行更新或插入操作。
如果如上所示在一条select后面加上for update
查询的数据会加上一条排他锁,其他事务可以进行读操作,但不能进行写操作。
注意事项
- 行锁必须是通过索引来实现的,否则的话就是表锁
- 不同的事务不能锁住相同的索引
- 事务中如果有写操作(update、delete、insert),会自动加上排他锁
间隙锁
当适用范围查询检索数据时,如果请求了共享锁或者排他锁,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内并不存在的记录,叫做间隙InnoDB也会对这个"间隙"加锁,这种锁机制就是所谓的间隙锁
总结
- 尽量控制事务大小,减少锁定资源量和时间长度
- 合理设计索引,尽量缩小锁的范围
- 尽可能减少索引条件,避免间隙锁
- 尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁