锁的分类
- 操作类型分类:
- 读锁 : 针对同一份数据,多个读操作可以同时进行而互不影响
- 写锁 : 当前写操作没完成前,会阻断其他写锁和读锁
操作粒度分:
手动加锁: lock table 表名字 read(write) , 表名字2 read(write) … ;
- 释放锁: unlock tables;
- 查看表上加过的锁 show open tables;

小节
- 对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一张表的读操作,但会阻塞对同一张表的写操作,需要等待读锁释放后,才会执行其他进程的写操作
- 对MyISAM表的写操作(加写锁),会阻塞其他进程对同一张表的读写操作,只有当写锁释放,才会执行其他进程的读写操作
- 简而言之:读锁阻塞写,写锁阻塞读写
表锁分析(偏向MyISAM)

行锁分析(偏向InnoDB)
- 特点:开销大,加锁慢;会出现死锁,锁粒度小,锁冲突概率低,并发度高
- InnoDB 和 MyISAM最大区别:支持事务,行锁 (由于行锁支持事务)
- 并发事务带来的问题:
- 更新丢失
- 脏读: 事务A读到事务B尚未提交的数据
- 不可重复读:事务A再次读取之前的数据发生了改变,即事务A读到了事务B已提交的数据
- 幻读:事务A读到了事务B新提交的数据
- 隔离级别
- 未提交读(Read uncommited) :
- 已提交读(Read commited):
- 可重复读(Repeatable read) : MySQL的默认级别
- 可序列化(Serializable):

- 查看当前事务隔离级别:show variables like ‘tx_isolation’;
- 索引失效导致行锁变表锁
- 间隙锁的危害
- 什么是间隙锁:当我们使用范围条件检索数据,并请求共享排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁,对于键值在范围内但不存在的记录,叫做间隙(比如数据库本来存在id为1、3、4、5的记录,然后事务A范围更新1~5的记录,此时如果另一个事务插入id = 2的记录,在事务A调教事务之前会被阻塞)
- InnoDB也会对这个间隙加锁,这种锁机制称为间隙锁(Next-Key锁)
- 如何锁定某一行?
- select * from A where id = ? for update 单独锁定某一行
- 优化建议:
- 尽可能让所有数据检索通过索引完成,避免行锁变表锁
- 合理设计索引,缩小锁的范围
- 尽可能较少索引条件,避免锁间隙
- 控制事务大小,减少锁定资源量和时间长度
- 尽可能低级别事务隔离
