0 前提

前提一:id列是不是主键?
前提二:当前系统的隔离级别是什么?
前提三:id列如果不是主键,那么id列上有索引吗?
前提四:id列上如果有二级索引,那么这个索引是唯一索引吗?
前提五:两个SQL的执行计划是什么?索引扫描?全表扫描?

1 RR级别

1.1 insert

加入gap意向锁 排他锁是一定的

1.1.1 只有主键

插入后加入 排它锁

1.1.2 只有 唯一键

插入后加入 共享锁

1.1.3 主键 和唯一键

插入后加入 主键加排它锁 唯一键加共享锁

1.2 delete update

delete form table where id =1
update table set name =“chenyixin” where id =1

1.2.1 id 为主键

1 表中有id为1的,锁住1 行锁 排它锁。
2 表中没有id为1的,加入间隙锁

1.2.2 id 为非主键,为唯一键

与主键一致

1.2.3 非key

聚簇索引上的所有记录,都被加上了 X 锁。其次,聚
簇索引每条记录间的间隙(GAP),也同时被加上了 GAP 锁
没有其他的路径可以选择,只能进行全表扫描。不能更新,不能删除,不能插入,全表被锁死

semi-consistent read 开启的情况下,对于不满足查询条件的记录,MySQL 会提前放锁。针对上面的这个用例,就是除了记录[d,10],[g,10]之外,所有的记录锁都会被释放,同时不加 GAP 锁。semi-consistent read 如何触发:要么是 read committed 隔 离 级 别 ; 要 么 是Repeatable Read 隔 离 级 别 , 但 是 设 置 了innodb_locks_unsafe_for_binlog 参数

2 RC级别

2.1 insert

2.1.1 只有主键

插入后加入 排它锁

2.1.2 只有 唯一键

插入后加入 共享锁

2.1.3 主键 和唯一键

插入后加入 主键加排它锁 唯一键加共享锁

2.2 delete update

delete form table where id =1
update table set name =“chenyixin” where id =1

2.2.1 id为主键

1 存在加入行锁
2 不存在 不加锁

2.2.3 为 唯一索引

1存在 加入行锁
2不存在 不加锁

2.2.4 普通索引

1 存在加行锁
2 不存在 不加锁

2.2 5 非key

如果一个条件无法通过索引快速过滤,那么存储引擎层面就会将所有记录加锁后返回,然后由 MySQL Server 层进行过滤。因此也就把所有的记录,都锁上了。
注:在实际的实现中,MySQL 有一些改进,在 MySQL Server 过滤条件,发现不满足后,会调用 unlock_row 方法,把不满足条件的记录放锁 (违背了 2PL 的约束)。这样做,保证了最后只会持有满足条件记录上的锁,但是每条记录的加锁操作还是不能省略的。