作者:宋丹琪(花名:三思)袋鼠云云服务部DBA团队 数据库工程师

时常会有开发的同学突然紧张兮兮地找我,

然后丢给我一个代码层面的

CannotAcquireLockException的报错,

一脸无辜地问我是不是自己搞出了一个死锁。

好像大家看到LOCK的字眼

总会第一时间想到死锁而忽略了锁,

难道我们锁没有面子的嘛,

我们锁的大家族可足足有七种呢?

那么到底什么是锁,有哪些锁,

请听我娓娓道来。。

01 共享锁(S锁)和排它锁(X锁)

事务拿到某一行记录的共享S锁,才可以读取这一行,并阻止别的事物对其添加X锁

事务拿到某一行记录的排它X锁,才可以修改或者删除这一行

共享锁的目的是提高读读并发

排他锁的目的是为了保证数据的一致性

02 意向锁

1)意向共享锁

预示事务有意向对表中的某些行加共享S锁

2)意向排他锁

预示着事务有意向对表中的某些行加排他X锁

3) IS、S、IX、X锁之间的兼容性比较

4)意向锁的意义在哪里?

1.IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突

2.意向锁是在添加行锁之前添加。

3.如果没有意向锁,当向一个表添加表级X锁时,就需要遍历整张表来判断是否存行锁,以免发生冲突

4.如果有了意向锁,只需要判断该意向锁与表级锁是否兼容即可。

03 插入意向锁(insert intention looks)

插入意向锁是间隙锁的一种,针对insert操作产生。

目的是提高插入并发。

多个事物,在同一个索引,同一个范围区间进行插入记录的时候,如果 插入的位置不冲突,不会阻塞彼此。

示例:

由于事物一和事物二都是对表的同一索引范围进行insert,使用的插入意向锁,由于插入的记录并不冲突,所以并不会阻塞事物二。如果事物二插入的记录与事物一冲突,会被X锁阻塞。

04 记录锁

对单条索引记录进行加锁,锁住的是索引记录而非记录本身,即使表中没有任何索引,MySQL会自动创建一个隐式的row_id作为聚集索引来进行加锁。

05 间隙锁(gap锁)

封锁记录中的间隔,防止间隔中被其他事务插入。

间隙锁主要出现在RR隔离级别,避免出现幻读。

MVCC(多版本并发)

1.MVCC的作用

避免脏读、写不阻塞读、实现可重复读、多版本控制

2.在MVCC下,读操作可以分为两种:快照读、当前读

1)快照读

select * from tbl_name where ...

2)当前读

select * from tbl_name where ... for update;

update

delete

insert

3)为什么delete/update也是一种当前读?(如一个update操作)

a.在进行update的时候,MySQL会根据where条件得到过滤出来的第一条记录,并进行加锁(currenet read)

b.对该条记录进行update

c.再次读取下一条记录,直到没有满足条件的记录为止

d.delete原理与之类似

4)为什么insert也是一种当前读?

insert操作可能会触发Unique Key的冲突检查,也会进行一个当前读。

隔离级别

1.Read Uncommitted

可以读取到未提交的事物。

2.Rrad Committed(RC)

针对当前读,RC隔离级别保证对读取到的记录加锁 (记录锁),存在幻读现象。

3.Repeatable Read (RR)

针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

4.Serializable

所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。

读写冲突,并发行很差。

几种触发间隙锁的情况

1.id非唯一索引+RR

SQL:delete from t1 where id = 10;

加锁流程如下:

a.通过id索引定位到第一条满足查询条件的记录,加记录上的X锁,加GAP上的GAP锁,

b.然后加主键聚簇索引上的记录X锁,然后返回;

c.然后读取下一条,重复进行。

d.直至进行到第一条不满足条件的记录[11,f],此时,不需要加记录X锁,但是仍旧需要加GAP锁,最后返回结束。

2.id无索引+RR

SQL:delete from t1 where id = 10;

a.由于id字段无索引,进行全表扫描的当前读,

b.聚簇索引上的所有记录,都被加上了X锁。其次,聚簇索引每条记录间的间隙都被加上了GAP锁。

3.针对id无索引+RR MySQL性能上做的一些优化

semi-consistent read

semi-consistent read开启的情况下,对于不满足查询条件的记录,MySQL会提前放锁。

针对上面的这个用例,就是除了记录[d,10],[g,10]之外,所有的记录锁都会被释放,同时不加GAP锁。

4.semi-consistent read如何触发?

1)隔离级别是read committed;

2)隔离级别是Repeatable Read,同时设置了innodb_locks_unsafe_for_binlog 参数。

示例一

示例二

示例三

06 临键锁(Next-Key Locks)

临键锁是记录锁和间隙锁的组合,既锁住了记录也锁住了范围。

临键锁的主要目的,也是为了避免幻读。

如果把事务的隔离级别降级为RC,临键锁就也会失效。

通常情况下,InnoDB在搜索或扫描索引的行锁机制中使用“临键锁(next-key locking)”算法来锁定某索引记录及其前部的间隙(gap),以阻塞其它用户紧跟在该索引记录之前插入其它索引记录。

innodb_locks_unsafe_for_binlog默认为OFF,意为禁止使用非安全锁,也即启用间隙锁功能。将其设定为ON表示禁止锁定索引记录前的间隙,也即禁用间隙锁,InnoDB仅使用索引记录锁(index-record lock)进行索引搜索或扫描,不过,这并不禁止InnoDB在执行外键约束检查或重复键检查时使用间隙锁。

innodb_locks_unsafe_for_binlog的效果:

(1)对UPDATE或DELETE语句来说,InnoDB仅锁定需要更新或删除的行,对不能够被WHERE条件匹配的行施加的锁会在条件检查后予以释放。这可以有效地降低死锁出现的概率;

(2)执行UPDATE语句时,如果某行已经被其它语句锁定,InnoDB会启动一个“半一致性(semi-consistent)”读操作从MySQL最近一次提交版本中获得此行,并以之判定其是否能够并当前UPDATE的WHERE条件所匹配。如果能够匹配,MySQL会再次对其进行锁定,而如果仍有其它锁存在,则需要先等待它们退出。

(3)innodb_locks_unsafe_for_binlog可能会造成幻读

示例一

innodb_locks_unsafe_for_binlog=off的情况下:

示例二

innodb_locks_unsafe_for_binlog=on的情况下:

查看binlog日志:

因此,当innodb_locks_unsafe_for_binlog=on的情况下,会让你容易造成数据的不一致。

07 自增长锁

自增长锁是一种表级锁,专门针对auto_increment类型的列。

自增长列锁各模式分析:

innodb_autoinc_lock_mode:自增长长锁模式

0:

不管是insert into values (simple insert)还是insert into select (bulk insert),都是:持有锁、读取/修改、执行SQL、释放,不需要等到事务提交就释放锁,但是需要SQL执行完成,并且不能保证连续。

持有latch ---> 读取和修改auto锁 ---> 执行insert ---> 释放

注意:不需要等待insert所在的事务是否提交

缺点:可能出现数字不连续

持有时间相对过长:SQL执行完毕,不需要事务提交

1:

默认值,对于回滚是不能保证自增长列连续的。

对于simple insert (insert into values):持有锁、读取、释放、执行SQL,最快,不需要执行完SQL就释放,不需要等待insert执行完毕就可以释放锁。

对于bulk insert (insert into select):持有锁、读取、执行SQL、释放,需要执行完SQL才释放。(对于批量insert来说等同于0)

优点:

对于simple insert 来说,性能比0好些,对于批量来说,性能等同于0

缺点:

数字不连续

对于批量来说持有锁的时间相对过长

2:

经常改为2,主要是为了唯一,不是为了连续,在批量insert时或者批量insert并发的时候用

优点:速度最快

缺点:只能保证唯一,不能保证递增和连续。持有、读取和修改、释放、执行SQL

建议修改成2,对于批量的insert可以提升性能

示例

由于innodb_autoinc_lock_mode=1,所以事物一并不会阻塞事物二的simple insert,保证了id字段的唯一性。

参考引用:

何登成的技术博客——《MySQL 加锁处理分析》

微信公众号:架构师之路

mysql x key 组合_技本功丨浅谈MySQL的七种锁相关推荐

  1. sql server的密码采用自带什么密码技术存储_【技术分享】浅谈MYSQL 8.0新特性

    于树文 云技术管理处 01 MySQL 8.0中添加的功能 1. 新的系统字典表 整合了存储有关数据库对象信息的事务数据字典,所有的元数据都用InnoDB引擎进行存储. 2. 支持DDL 原子操作 I ...

  2. pymysq向mysql写数据 为什么本地无法查看_从运维角度浅谈MySQL数据库优化,中小企业DBA必会...

    原文:http://www.enmotech.com/web/detail/1/712/1.html(复制链接,打开浏览器即可查看原文) 作者:搬砖游击队 一个成熟的数据库架构并不是一开始设计就具备高 ...

  3. MySQL子查询的优缺点_浅谈mysql的子查询

    浅谈mysql的子查询 mysql的子查询的优化一直不是很友好,一直有受业界批评比较多,也是我在sql优化中遇到过最多的问题之一,你可以点击这里 ,这里来获得一些信息,mysql在处理子查询的时候,会 ...

  4. 支付宝的数据库是MySQL变种_浅谈MySql的储存引擎(表类型)

    浅谈mysql的存储引擎(表类型) 什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合. 我们通常说的MySql数据库, ...

  5. 技本功丨收藏!斜杠青年与你共探微信小程序云开发(下篇)

    2019年2月26日,人们为了一个杯子疯了一天. 星巴克猫爪杯,一场已经与猫无关了的"圣杯战争".网上的倒卖价格,已炒至近千元! 求而不得,舍而不能,得而不惜.这是人最大的悲哀.. ...

  6. mysql 用户通配符_浅谈mysql通配符进行模糊查询的实现方法

    在mysql数据库中,当我们需要模糊查询的时候 ,我们会使用到通配符. 首先我们来了解一下2个概念,一个是操作符,一个是通配符. 操作符 like就是SQL语句中的操作符,它的作用是指示在SQL语句后 ...

  7. mysql declare与set的区别_浅谈MySQL存储过程中declare和set定义变量的区别

    在存储过程中常看到declare定义的变量和@set定义的变量.简单的来说,declare定义的类似是局部变量,@set定义的类似全局变量. 1.declare定义的变量类似java类中的局部变量,仅 ...

  8. mysql维护计划任务_浅谈MySQL event 计划任务

    一.查看event是否开启 show variables like '%sche%'; set global event_scheduler =1; 二. -- 设置时区并设置计划事件调度器开启,也可 ...

  9. mysql 计划任务消耗_浅谈MySQL event 计划任务

    一.查看event是否开启 show variables like '%sche%'; set global event_scheduler =1; 二. -- 设置时区并设置计划事件调度器开启,也可 ...

最新文章

  1. 一位老码农的分享:一线程序员该如何面对「中年危机」?
  2. 面试 -- ListView对其指定的子Item进行单独的刷新
  3. H3C学习笔记《五》(初级理论知识)
  4. 分布式通信框架 - rmi
  5. Java对异常处理或抛出之后,后面代码会不会再执行?
  6. 统计学要学的计算机课程有哪些,统计学专业主要课程学什么_课程设置安排及分类...
  7. 原来国家的名字可以如此浪漫!(ZZ)
  8. XorPay.com 支付平台介绍【免费申请个人微信支付接口】
  9. 计算机二级操作范文,计算机二级考试(范文).doc
  10. QuickBI助你成为分析师——搞定数据源
  11. Android Studio Flutter 调试技巧 Flutter Inspector 提升你的维护开发效率 轻松定位复杂嵌套Widget代码位置
  12. Vivado使用ILA调试报错解决
  13. 一家世界500强企业为什么还要做不赚钱的生意?
  14. c++ 模板类实现堆栈实验报告_5分钟学会C/C++多线程编程进程和线程
  15. DISK 100% BUSY,谁造成的?
  16. Windows timeout命令
  17. 8. 无内容可写?应该注重平常的素材收集
  18. Android - 购物车页面【仿】淘宝App
  19. 直观理解线性插值(linear interpolation)和双线性插值(Bilinear interpolation)
  20. 快来天津科技大学找我玩

热门文章

  1. TIOBE 3 月编程语言:Swift 一路低走,Java 份额大跌
  2. 建设可信赖、公平开放的HMS生态,华为与全球伙伴合作共赢
  3. 我发现了个 Python 黑魔法,执行任意代码都会自动念上一段「平安经」
  4. 还在烦恼高性能网关设计?看这文就够啦!
  5. 中国最优秀的程序员都有哪些?王兴、张小龙、张一鸣是哪类?| 蒋涛说
  6. 滴滴技术总监受贿 1000 万,列入招聘黑名单,互联网大厂反腐有多强?
  7. 百度发布全新 NLG 训练模型 ERNIE-GEN,获 5 项 SOTA!
  8. C 语言漏洞最严重,PHP 最易受攻击,程序员该怎么写代码?
  9. @程序员,如何快速配置 Spring?
  10. 我们为什么用 Go 编写机器学习架构,却不用 Python?