ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Innodb锁相关总结

2019-03-11 17:49:07  阅读:310  来源: 互联网

标签:总结 事务 记录 互斥 Locks 插入 Innodb 意向锁 相关


一、InnoDB共有七种类型的锁:
(1)共享/排它锁(Shared and Exclusive Locks)
(2)意向锁(Intention Locks)
(3)插入意向锁(Insert Intention Locks)
---InnoDB并发插入,居然使用意向锁? https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961461&idx=1&sn=b73293c71d8718256e162be6240797ef&chksm=bd2d0da98a5a84bfe23f0327694dbda2f96677aa91fcfc1c8a5b96c8a6701bccf2995725899a&scene=21#wechat_redirect
插入意向锁,是间隙锁(Gap Locks)的一种(所以,也是实施在索引上的),它是专门针对insert操作的。
多个事务,在同一个索引,同一个范围区间插入记录时,如果插入的位置不冲突,不会阻塞彼此。
例如:在MySQL,InnoDB,RR下:
t(id unique PK, name);
数据表中有数据:
10, shenjian
20, zhangsan
30, lisi
事务A先执行,在10与20两条记录中插入了一行,还未提交:
insert into t values(11, xxx);
事务B后执行,也在10与20两条记录中插入了一行:
insert into t values(12, ooo);
(1)会使用什么锁?
(2)事务B会不会被阻塞呢?
回答:虽然事务隔离级别是RR,虽然是同一个索引,虽然是同一个区间,但插入的记录并不冲突,故这里:
使用的是插入意向锁
并不会阻塞事务B
(4)记录锁(Record Locks)
记录锁,它封锁索引记录,例如:
select * from t where id=1 for update;
它会在id=1的索引记录上加X锁,以阻止其他事务插入,更新,删除id=1的这一行。
需要说明的是:
select * from t where id=1;
则是快照读(SnapShot Read),它并不加锁
(5)间隙锁(Gap Locks)
间隙锁,它封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
依然是上面的例子,InnoDB,RR:
t(id PK, name KEY, sex, flag);
表中有四条记录:
1, shenjian, m, A
3, zhangsan, m, A
5, lisi, m, A
9, wangwu, f, B
这个SQL语句
select * from t where id between 8 and 15 for update;
会封锁区间,以阻止其他事务id=10的记录插入。
画外音:
为什么要阻止id=10的记录插入?
如果能够插入成功,头一个事务执行相同的SQL语句,会发现结果集多出了一条记录,即幻影数据。
间隙锁的主要目的,就是为了防止其他事务在间隔中插入数据,以导致幻读。
如果把事务的隔离级别降级为读提交(Read Committed, RC),间隙锁则会自动失效。
(6)临键锁(Next-key Locks)
临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。
更具体的,临键锁会封锁索引记录本身,以及索引记录之前的区间。
如果一个会话占有了索引记录R的共享/排他锁,其他会话不能立刻在R之前的区间插入新的索引记录。
依然是上面的例子,InnoDB,RR:
t(id PK, name KEY, sex, flag);
表中有四条记录:
1, shenjian, m, A
3, zhangsan, m, A
5, lisi, m, A
9, wangwu, f, B
PK上潜在的临键锁为:
(-infinity, 1]
(1, 3]
(3, 5]
(5, 9]
(9, +infinity]
临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效。
InnoDB,select为啥会阻塞insert? https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961471&idx=1&sn=da257b4f77ac464d5119b915b409ba9c&chksm=bd2d0da38a5a84b5fc1417667fe123f2fbd2d7610b89ace8e97e3b9f28b794ad147c1290ceea&scene=21#wechat_redirect
(7)自增锁(Auto-inc Locks) 插入InnoDB自增列,居然是表锁? https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961455&idx=1&sn=4c26a836cff889ff749a1756df010e0e&chksm=bd2d0db38a5a84a53db91e97c7be6295185abffa5d7d1e88fd6b8e1abb3716ee9748b88858e2&scene=21#wechat_redirect
自增锁是一种特殊的表级别锁(table-level lock),专门针对事务插入AUTO_INCREMENT类型的列。
最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。
例如:t(id AUTO_INCREMENT, name);,其中id为自增

二、共享/排它锁(Shared and Exclusive Locks)

  参考博客:https://blog.csdn.net/u014292162/article/details/83271299
  共享锁(Share Locks,记为S锁),读取数据时加S锁,也叫读锁。
  排他锁(eXclusive Locks,记为X锁),修改数据时加X锁,也叫写锁。
    (1)事务拿到某一行记录的共享S锁,才可以读取这一行;
    (2)事务拿到某一行记录的排它X锁,才可以修改或者删除这一行;
  其兼容互斥表如下:
   S X
    S 兼容 互斥
    X 互斥 互斥
   即:
    (1)共享锁之间不互斥,多个事务可以拿到一把S锁,读读可以并行;
    (2)排他锁与其他任何锁互斥,只有一个事务可以拿到X锁,写写/读写必须互斥;
  因此,一旦写数据的事务没有完成,数据是不能被其他事务读取的,这对并发度有较大的影响。写事务没有提交,读相关数据的select也会被阻塞。  
由于数据加排他锁后,读相关数据也会被阻塞,因此并发性很低,由此引出了MVCC多版本并发控制:
  参考博客:https://www.cnblogs.com/dongqingswt/p/3460440.html
  数据多版本是一种能够进一步提高并发的方法,它的核心原理是:
    (1)写任务发生时,将数据克隆一份,以版本号区分;
    (2)写任务操作新克隆的数据,直至提交;
    (3)并发读任务可以继续读取旧版本的数据,不至于阻塞;
  MVCC就是通过“读取旧版本数据”来降低并发事务的锁冲突,提高任务的并发度。

三、意向锁(Intention Locks)

  意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。
  意向锁有这样一些特点:
    (1)首先,意向锁,是一个表级别的锁(table-level locking);
    (2)意向锁分为:
      意向共享锁(intention shared lock, IS),它预示着,事务有意向对表中的某些行加共享S锁
      意向排它锁(intention exclusive lock, IX),它预示着,事务有意向对表中的某些行加排它X锁
      举个例子:
        select ... lock in share mode,要设置IS锁;
        select ... for update,要设置IX锁;
    (3)意向锁协议(intention locking protocol)并不复杂:
      事务要获得某些行的S锁,必须先获得表的IS锁
      事务要获得某些行的X锁,必须先获得表的IX锁
    (4)由于意向锁仅仅表明意向,它其实是比较弱的锁,意向锁之间并不相互互斥,而是可以并行,其兼容互斥表如下:
    IS IX
     IS 兼容 兼容
     IX 兼容 兼容
    (5)额,既然意向锁之间都相互兼容,那其意义在哪里呢?它会与表级的共享锁/排它锁互斥,其兼容互斥表如下:
           S X
      IS 兼容 互斥
      IX 互斥 互斥
  意向锁的作用就是:
    当一个事务在需要获取资源的锁定时,如果该资源已经被排他锁占用,则数据库会自动给该事务申请一个该表的意向锁。
    如果自己需要一个共享锁定,就申请一个意向共享锁。如果需要的是某行(或者某些行)的排他锁定,则申请一个意向排他锁。
    注:意向共享锁可以同时并存多个,但是意向排他锁同时只能有一个存在。



四、插入意向锁(Insert Intention Locks)

  ---InnoDB并发插入,居然使用意向锁? https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961461&idx=1&sn=b73293c71d8718256e162be6240797ef&chksm=bd2d0da98a5a84bfe23f0327694dbda2f96677aa91fcfc1c8a5b96c8a6701bccf2995725899a&scene=21#wechat_redirect
  插入意向锁,是间隙锁(Gap Locks)的一种(所以,也是实施在索引上的),它是专门针对insert操作的。
  多个事务,在同一个索引,同一个范围区间插入记录时,如果插入的位置不冲突,不会阻塞彼此。
  例如:在MySQL,InnoDB,RR下:
    t(id unique PK, name);
    数据表中有数据:
      10, shenjian
      20, zhangsan
      30, lisi
    事务A先执行,在10与20两条记录中插入了一行,还未提交:
      insert into t values(11, xxx);
    事务B后执行,也在10与20两条记录中插入了一行:
      insert into t values(12, ooo);
    (1)会使用什么锁?
    (2)事务B会不会被阻塞呢?
    回答:虽然事务隔离级别是RR,虽然是同一个索引,虽然是同一个区间,但插入的记录并不冲突,故这里:
使用的是插入意向锁
并不会阻塞事务B

标签:总结,事务,记录,互斥,Locks,插入,Innodb,意向锁,相关
来源: https://www.cnblogs.com/aiqiqi/p/10512051.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有