疫情期间在家工作时,同事使用了 insert into on duplicate key update 语句进行插入去重,但是在测试过程中发现了死锁现象:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

由于开发任务紧急,只是暂时规避了一下,但是对触发死锁的原因和相关原理不甚了解,于是这几天一直在查阅相关资料,总结出一个系列文章供大家参考。本篇是上篇,主要介绍 MySQL 加锁原理和锁的不同模式或类型的基本知识。后续会讲解常见语句的加锁情况和通过 MySQL 死锁日志分析死锁原因。

由于本篇文章涉及很多 MySQL 的基础知识,大家可以自行阅读我之前的 MySQL系列文章 《MySQL探秘》中的对应章节。

表锁和行锁

我们首先来了解一下表锁和行锁:表锁是指对一整张表加锁,一般是 DDL 处理时使用;而行锁则是锁定某一行或者某几行,或者行与行之间的间隙。

表锁由 MySQL Server 实现,行锁则是存储引擎实现,不同的引擎实现的不同。在 MySQL 的常用引擎中 InnoDB 支持行锁,而 MyISAM 则只能使用 MySQL Server 提供的表锁。

表锁

表锁由 MySQL Server 实现,一般在执行 DDL 语句时会对整个表进行加锁,比如说 ALTER TABLE 等操作。在执行 SQL 语句时,也可以明确指定对某个表进行加锁。

mysql> lock table user read(write); # 分为读锁和写锁
Query OK, 0 rows affected (0.00 sec)mysql> select * from user where id = 100; # 成功
mysql> select * from role where id = 100; # 失败,未提前获取该 role的读表锁
mysql> update user  set name = 'Tom' where id = 100; # 失败,未提前获得user的写表锁mysql> unlock tables; # 显示释放表锁
Query OK, 0 rows affected (0.00 sec)

表锁使用的是一次性锁技术,也就是说,在会话开始的地方使用 lock 命令将后续需要用到的表都加上锁,在表释放前,只能访问这些加锁的表,不能访问其他表,直到最后通过 unlock tables 释放所有表锁。

除了使用 unlock tables 显示释放锁之外,会话持有其他表锁时执行lock table 语句会释放会话之前持有的锁;会话持有其他表锁时执行 start transaction 或者 begin 开启事务时,也会释放之前持有的锁。

行锁

不同存储引擎的行锁实现不同,后续没有特别说明,则行锁特指 InnoDB 实现的行锁。

在了解 InnoDB 的加锁原理前,需要对其存储结构有一定的了解。InnoDB 是聚簇索引,也就是 B+树的叶节点既存储了主键索引也存储了数据行。而 InnoDB 的二级索引的叶节点存储的则是主键值,所以通过二级索引查询数据时,还需要拿对应的主键去聚簇索引中再次进行查询。关于 InnoDB 和 MyISAM 的索引的详细知识可以阅读《Mysql探索(一):B+Tree索引》一文。

下面以两条 SQL 的执行为例,讲解一下 InnoDB 对于单行数据的加锁原理。

update user set age = 10 where id = 49;
update user set age = 10 where name = 'Tom';

第一条 SQL 使用主键索引来查询,则只需要在 id = 49 这个主键索引上加上写锁;第二条 SQL 则使用二级索引来查询,则首先在 name = Tom 这个索引上加写锁,然后由于使用 InnoDB 二级索引还需再次根据主键索引查询,所以还需要在 id = 49 这个主键索引上加写锁,如上图所示。

也就是说使用主键索引需要加一把锁,使用二级索引需要在二级索引和主键索引上各加一把锁。

根据索引对单行数据进行更新的加锁原理了解了,那如果更新操作涉及多个行呢,比如下面 SQL 的执行场景。

update user set age = 10 where id > 49;

上述 SQL 的执行过程如下图所示。MySQL Server 会根据 WHERE 条件读取第一条满足条件的记录,然后 InnoDB 引擎会将第一条记录返回并加锁,接着 MySQL Server 发起更新改行记录的 UPDATE 请求,更新这条记录。一条记录操作完成,再读取下一条记录,直至没有匹配的记录为止。

这种场景下的锁的释放较为复杂,有多种的优化方式,我对这块暂时还没有了解,还请知道的小伙伴在下方留言解释。

下面主要依次介绍 InnoDB 中锁的模式和类型,锁的类型是指锁的粒度或者锁具体加在什么地方;而锁模式描述的是锁的兼容性,也就是加的是什么锁,比如写锁或者读锁。

mysql 插入加锁_MySQL的死锁系列- 锁的类型以及加锁原理相关推荐

  1. 触发死锁怎么办?MySQL 的死锁系列:锁的类型以及加锁原理了解一下!

    来源 | 程序员历小冰 责编 | Carol 封图 | CSDN 付费下载于视觉中国 疫情期间在家工作时,同事使用了 insert into on duplicate key update 语句进行插 ...

  2. mysql插入删除_mysql插入、更新与删除

    数据库增删改查都是要熟练掌握的. 这部分就来看看前面3个比较简单的部分,增,删,改. 插入数据 为表的所有字段插入数据 insert into table_name (column_list) val ...

  3. mysql 插入字符串_MySQL插入特殊字符

    有时候在插入字符的时候,经常会发现',"很难插进去.在MYSQL里用就OK了. 举例如下: mysql> create table new (name varchar(200)); Q ...

  4. php mysql 插入图片_mysql中怎样插入图片

    mysql中插入图片的方法:首先要在数据库中建表:然后装载JDBC驱动,建立连接:最后创建Statement接口类,来执行SQL语句即可. mysql中插入图片的方法: 1.首先,先要在数据库中建表. ...

  5. mysql数据库实战_mysql数据库实战系列--再入泥坑

    开源数据库MySQL DBA运维实战 第2章 SQL1 作者:帽子先生 SQL语言分类 SQL(Structured Query Language 即结构化查询语言) SQL语言主要用于存取数据.查询 ...

  6. Mysql共享锁实例_mysql共享锁与排他锁用法实例分析

    本文实例讲述了mysql共享锁与排他锁用法.分享给大家供大家参考,具体如下: mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称 ...

  7. mysql插入性能_mysql 数据量大时插入和查询性能

    现在mysql中有数据33.8w的数据,然后做查询和更新或插入操作,速度很慢,基本100条数据就要1.68s.好慢啊,我要测试一下,到底慢在哪?能不能提高点速度? 参考一篇博文:http://blog ...

  8. mysql 插入优化_MySQL批量SQL插入性能优化

    对于一些数据量较大的系统,数据库面临的问题除了查询效率低下,还有就是数据入库时间长.特别像报表系统,每天花费在数据导入上的时间可能会长达几个小时或十几个小时之久.因此,优化数据库插入性能是很有意义的. ...

  9. mysql插入日期_MySQL 的两个特殊数据类型属性 unsigned与 zerofill

    概述 我们在了解mysql数据类型不可避免的要先了解这两个属性--unsigned与 zerofill,是否选用这两个属性对选择数据类型有莫大的关系. 1.unsigned unsigned 就是将数 ...

最新文章

  1. 昨日关注-你说过的每一句话
  2. 算法------------存在重复元素 II(Java 版本)
  3. vivo应用商店电脑版_好车网APP|苹果商城、华为应用市场、腾讯应用宝、vivo应用商店、OPPO应用商店用户免费下载...
  4. linux设置账号权限设置,Linux账号管理与ACL权限设置
  5. wxWidgets:wxTextCompleterSimple类用法
  6. “达观杯”文本智能处理挑战赛,季军带你飞
  7. 子组件是表格时向父组件传值
  8. 设计模式六大原则(5)——迪米特原则
  9. nagios 监控配置介绍(二)
  10. mysql char varchar 性能_Mysql小细节:varchar与char在性能上的特点
  11. 学习日报 day02 java的语法骨架 myeclipse编辑java代码
  12. python控制gpio产生固定数量的脉冲_STM32L151用dma控制GPIO口发出指定的脉冲个数的疑惑!...
  13. gif 动态加载_搞笑GIF:这个游戏最大的成功就是失败!
  14. php设计模式-责任链模式
  15. WDA基础七:TABStrip
  16. 订阅付费专栏,支付299.9元,免费送代码
  17. 照片教你eclipse通过使用gradle 打包Android
  18. egret 之序列帧动画MoveClip
  19. 【信号与系统实验】实验四 傅里叶变换、系统的频域分析
  20. 主流编程语言的介绍及特点

热门文章

  1. Windows编程中引入winsock2.h后导致的错误解决
  2. asp.net MVC ViewData详解
  3. ptmalloc、tcmalloc与jemalloc内存分配器对比分析
  4. 【BP神经网络】使用反向传播训练多层神经网络的原则+“常见问题”
  5. 代码重新发布后docker服务会不会受影响_分享点经验 | 浅谈微服务架构
  6. Django:ORM基本操作-CRUD,管理器对象objects,----->查询2(filter,exclude,get,查询谓词)
  7. Django:模型层ORM,创建模型类,字段类型
  8. RecognizerIntent(语音识别)
  9. 对java的集合的理解_谈谈你对java集合类的理解
  10. idea 热部署时 tomcat处 没有update classes and resource 选项