实战演示疑惑 mysql insert到底加什么锁
innodb的事务隔离级别是可重复读级别且innodb_locks_unsafe_for_binlog禁用,也就是说允许next-key lock
实验来自网上. ( 如果你没有演示出来,请check order_id 是否是非unique key.) 如果你看不懂,请看后续文章. next-key lock (glap lock)完全解析.
CREATE TABLE `LockTest` (
`order_id` varchar(20) NOT NULL,
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
select * from LockTest;
empty set;
事务1 事务2
begin
delete from LockTest where order_id = 'D20'
begin
delete from LockTest where order_id = 'D19'
insert into LockTest (order_id) values ('D20')
insert into LockTest (order_id) values ('D19')
commit
commit
事务1 执行到insert语句会block住,事务2执行insert语句会提示死锁错误
错误码: 1213
Deadlock found when trying to get lock; try restarting transaction
Execution Time : 00:00:00:000
Transfer Time : 00:00:00:000
Total Time : 00:00:00:000
show engine innodb status 显示死锁信息
------------------------
LATEST DETECTED DEADLOCK
------------------------
2014-04-30 15:01:55 a233b90
*** (1) TRANSACTION:
TRANSACTION 596042, ACTIVE 7 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 320, 2 row lock(s), undo log entries 1
MySQL thread id 10851, OS thread handle 0x2abfb90, query id 251521 10.10.53.122 root update
insert into LockTest (order_id) values ('D20')
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 502 page no 4 n bits 72 index `idx_order_id` of table `test`.`LockTest` trx id 596042 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) TRANSACTION:
TRANSACTION 596041, ACTIVE 19 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 320, 2 row lock(s), undo log entries 1
MySQL thread id 10848, OS thread handle 0xa233b90, query id 251522 10.10.53.122 root update
insert into LockTest (order_id) values ('D19')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 502 page no 4 n bits 72 index `idx_order_id` of table `test`.`LockTest` trx id 596041 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 502 page no 4 n bits 72 index `idx_order_id` of table `test`.`LockTest` trx id 596041 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** WE ROLL BACK TRANSACTION (2)
简单分析上面的场景先删除再插入的sql是hibernage保存集合关联的处理方式。delete语句删除不存在且删除的order_id大于现有表中的所有order_id,所以delete语句会使用next-key锁住(当前最大-无穷大)
lock_id lock_trx_id lock_mode lock_type lock_table lock_index lock_space lock_page lock_rec lock_data
596133:502:4:1 596133 X RECORD `test`.`LockTest` idx_order_id 502 4 1 supremum pseudo-record
596134:502:4:1 596134 X RECORD `test`.`LockTest` idx_order_id 502 4 1 supremum pseudo-record
比较奇怪的是为啥两个事务都拿到了相同区间的(当前最大-无穷大)的X锁。不过换成read-commited级别后就没死锁了。
终于在官方文档找到答案, 区间锁只是用来防止其他事务在区间中插入数据,区间x锁 与区间S锁效果是一样的。也就是说不会因为两个事务都用加相同区间锁而相互等待的
https://dev.mysql.com/doc/refman/5.1/en/innodb-record-level-locks.html
Gap locks in InnoDB are “purely inhibitive”, which means they only stop other transactions from inserting to the gap. Thus, a gap X-lock has the same effect as a gap S-lock.
当两个事务拿到相同区间锁后,就会阻止对方忘区间内做insert操作。所以第一个事务insert会阻塞,第二个事务会提示死锁
详情见 https://dev.mysql.com/doc/refman/5.6/en/innodb-record-level-locks.html
换成read-commited级别后就没死锁了! 因为没有了间隙所,读提交不需要幻读控制,也就不需要间隙锁了.
万变归一: 事务内加锁总归是为了隔离级别.
再来分析另外一个现象:
上述现象表明, delete/update会阻塞insert .那么换成先insert,再delete/update呢?
实验表明不会阻塞? 这个感觉挺矛盾的,锁的互斥是相对的. 主要原因是insert 不会产生 间隙锁.
间隙锁的作用本身就是单向的.
再次从事务内加锁原因是为了隔离级别这个角度分析. insert
【解决方案有两种】
1、改变程序中数据库操作的逻辑
2、取消gap lock机制
innodb_locks_unsafe_for_binlog启用
或者设置为隔离级别为读提交
Gap locking can be disabled explicitly.This occurs if you change the transaction isolation level to READ COMMITTED orenable the innodb_locks_unsafe_for_binlog system variable.
3. 加上unique锁
select for update / update where
1. 有该行 对非unique列会加 间隙共享锁 和 行锁 见 (14.2.2.4 InnoDB Record, Gap, and Next-Key Locks http://dev.mysql.com/doc/refman/5.7/en/innodb-record-level-locks.html)
2. 无该行 对非unique 会加间隙共享锁 . 这个文档比较麻烦. 要通过 上面(该文)
(Unexpected deadlock between concurrent INSERTs when unique key violation may occ http://bugs.mysql.com/bug.php?id=35821)和
(Deadlock detected on concurrent insert into same table (InnoDB) https://bugs.mysql.com/bug.php?id=43210 )
里面有个很好玩的案例,这两个中文博客里也是该话题 (innodb next-key lock引发的死锁 http://www.cnblogs.com/xhan/p/3701459.html)
---------------------
原文:https://blog.csdn.net/fei33423/article/details/46731891
实战演示疑惑 mysql insert到底加什么锁的更多相关文章
- 关于MySQL insert into ... select 的锁情况
摘要: 一直以为"insert into tb select * from tbx" 这样的导入操作是会把tbx表给锁住的,在锁期间是不允许任何操作(保证一致性).看完 ...
- 二十种实战调优MySQL性能优化的经验
二十种实战调优MySQL性能优化的经验 发布时间:2012 年 2 月 15 日 发布者: OurMySQL 来源:web大本营 才被阅读:3,354 次 消灭0评论 本文将为大家介 ...
- MySQL insert语句锁分析
最近对insert的锁操作比较费解,所以自己动手,一看究竟.主要是通过一下三个sql来看一下执行中的sql的到底使用了什么锁. select * from information_schema.INN ...
- mysql insert锁机制【转】
最近再找一些MySQL锁表原因,整理出来一部分sql语句会锁表的,方便查阅,整理的不是很全,都是工作中碰到的,会持续更新 笔者能力有限,如果有不正确的,或者不到位的地方,还请大家指出来,方便你我,方便 ...
- [实战]MVC5+EF6+MySql企业网盘实战(22)——图片列表
写在前面 实现逻辑是:单击图片节点,加载所有的当前用户之前上传的图片,分页,按时间倒序加载. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MyS ...
- [实战]MVC5+EF6+MySql企业网盘实战(21)——网盘操作日志
写在前面 上篇文章介绍了一个bootstrap的分页插件,这篇将弄一个完整的例子,就以日志分页为例说明如何请求服务端然后进行分页. 系列文章 [EF]vs15+ef6+mysql code first ...
- [实战]MVC5+EF6+MySql企业网盘实战(11)——新建文件夹2
写在前面 上篇文章实现了创建文件夹的功能,这里面将实现单击文件夹,加载列表的功能. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企业网 ...
- [实战]MVC5+EF6+MySql企业网盘实战(6)——ajax方式登录
写在前面 今天回来的比较早,就趁着有空,把登录的代码更新一下.上篇文章实现了ajax的注册,这篇将实现登录,实现目标,ajax登录方式,如果勾选记住我,则下次不再输入用户名密码,直接跳转到网盘界面. ...
- 关联数组的错误,mysql insert varchar 原生的错误
在写代码的时候,没注意犯了2个低级错误: 关联数组的错误 $array = ['id' => '03657', 'kf_phone ' => 18796442]; 然后你再读取的时候就需要 ...
随机推荐
- 关于VS2017的安装和WDK的选择问题
首先就是关于VS2017的安装,我们可以通过微软的官网去寻找我们想要安装的VS版本 我们可以随便选择一个我们需要的版本进行下载,任意版本的VS都可以. 然后下载安装的时候,要进行一下这个安装选项的选择 ...
- 请读下面的这句绕口令:ResourceManager中的Resource Estimator框架介绍与算法剖析
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由宋超发表于云+社区专栏 本文首先介绍了Hadoop中的ResourceManager中的estimator service的框架与运行 ...
- JS和Java正则表达式验证
js代码 <script type="text/javascript"> function SubmitCk() { var reg = /^([a-zA-Z0-9]+ ...
- 解决U盘拷贝时提示文件过大问题(不能拷贝超过4个g的文件)
为什么一个16G的U盘却拷不进一个4G大点的文件呢,想必很多朋友们都在疑问? 其实这跟U盘的磁盘格式有关,目前市面上常用的U盘大都是FAT32格式,我们可以查看U盘属性. 那么FAT32是什么呢? F ...
- nginx权限问题failed(13:Permission denied)
nginx权限问题failed(13:Permission denied) 环境配置 nginx Permission denied 问题: 使用nginx代理uwsgi,出现500错误,查看ngi ...
- zoj 2060 Fibonacci Again(fibonacci数列规律、整除3的数学特性)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2060 题目描述: There are another kind ...
- 基于卷积神经网络的手写数字识别分类(Tensorflow)
import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...
- http server 简单实现
本blog主要是模仿http server的实现,使得客户端使用浏览器访问server所指定的目录. 当访问的为一个目录时, 则列出改目录下的所有文件 当访问的是文件时,则下载文件到本地 本log仅仅 ...
- 并发编程之 CountDown 源码分析
前言 Doug Lea 大神在 JUC 包中为我们准备了大量的多线程工具,其中包括 CountDownLatch ,名为倒计时门栓,好像不太好理解.不过,今天的文章之后,我们就彻底理解了. 如何使用? ...
- 在ASP.NET MVC使用JavaScriptResult
本例中,我们尝试把javascript程序搬至控制器中去.更好地在控制器编写程序. 首先来看看原来的写法. 在SepController控制器,添加如下操作: public ActionResult ...