1. 加锁过程
    以记录锁为例,当对一条记录加写锁时,会向内存申请一个锁,然后看当前记录目前有什么锁,如果没有锁,或者兼容当前锁,锁的iswaiting项为false,然后操作记录,否则为true,在此等待。
  2. mysql差锁 mysql查询加锁_mysql差锁

  3. 各种语句分别加什么锁
    select xxx 不加锁,快照读
    select xxx in share mode 行共享锁 读意向锁
    select xxx for update 行排它锁 写意向锁
    update 行排它锁 写意向锁
    delete 行排它锁 写意向锁
    增删改查(或者说开启事务后第一次执行增删改查) 都会自动加元数据读锁(隐式锁),执行DDL语句加元数据写锁。元数据锁读读不互斥,读写互斥
  4. 什么时候释放锁
    一般的锁,都是在事务提交后释放,元数据锁也是在释放,自增锁在插入完数据后释放
  5. 加什么样的行级锁
    加锁的基本单位是混合锁
  6. 等值id查询
    (1)读也能阻塞的例子
  7. mysql差锁 mysql查询加锁_数据库_02

  8. (2) id为查询条件,等值查询,查到了

加的是记录锁

为什么?

因为加记录锁,锁住读取到的记录,就能避免该记录被删除 修改,进而保证相同sql语句前后读取一致,避免了幻读

mysql差锁 mysql查询加锁_mysql差锁_03

mysql差锁 mysql查询加锁_mysql_04


如果 LOCK_MODE 为 X,说明是 next-key 锁;

如果 LOCK_MODE 为 X, REC_NOT_GAP,说明是记录锁;

如果 LOCK_MODE 为 X, GAP,说明是间隙锁(3) 等值查询,记录不存在的情况

加间隙锁

mysql差锁 mysql查询加锁_mysql_05


记录不存在,找到第一个比待查询id大的记录,加间隙锁,该id正好落在间隙内,防止插入,避免幻读

mysql差锁 mysql查询加锁_数据库_06


6. 唯一索引范围查询

针对扫描到的该范围内的非端点,都会加混合锁,端点根据情况讨论

(1) 大于

mysql差锁 mysql查询加锁_记录锁_07


如果15不在表中,不会对15加锁,20是混合锁,如果在,也不会对15加锁

mysql差锁 mysql查询加锁_mysql_08

mysql差锁 mysql查询加锁_mysql差锁_09


(2)大于等于

mysql差锁 mysql查询加锁_数据库_10


如果15在表格中,会对15加记录锁,如果不在?应该会在20加混合锁锁住(13,20](3) 小于

mysql差锁 mysql查询加锁_sql_11


如果6不在表中,会对10(第一个比查询条件大的值)加间隙锁,锁住(5,10)

mysql差锁 mysql查询加锁_记录锁_12

(4)小于等于,且条件不在表中

同小于

(5)小于,且查询条件值记录在表中

mysql差锁 mysql查询加锁_mysql差锁_13


会对6加间隙锁(5)小于等于,且查询条件值记录在表中

mysql差锁 mysql查询加锁_mysql_14


会对6加混合锁

  1. 非唯一索引(可重复的二级索引)等值查询

    (1)记录不存在

    对第一个大于该值的二级索引记录加间隙锁,该间隙内不会在插入记录,避免幻读(没有聚簇索引记录,所以不用加锁)

(2)当记录存在时

mysql差锁 mysql查询加锁_记录锁_15


mysql差锁 mysql查询加锁_mysql差锁_16


在二级索引,会对比我打的第一条记录加间隙锁,其余符合条件的记录加混合锁

在聚簇索引,所有符合条件的记录加记录锁,防止删除,更改(为什么还对聚簇索引加锁,不是已经锁住二级索引了吗,我知道了,二级索引只能保证不插入等于25的新值(锁住区间了)不能修改索引列的值和主键列的值,不能保证修改其它列的值,这一点需要主键的记录锁保证)

  1. 什么时候插入记录不会阻塞,什么时候又不会阻塞
    (1)主键不冲突,满足表约束,例如唯一性,非空等
    (2)在1的前提下,在索引(聚簇和二级)中找到第一条比自己"大"的元素,如果其没有间隙锁,就能插入,如果有,不能
  2. 非唯一索引范围查询
    会对所有符合条件的记录加混合锁 ,所有符合条件的聚簇索引加记录锁
  3. 非索引列查询