项目中遇到的MySql行锁与并发性关系(3)--发生deadlock的原因
2014-05-15 23:45
253 查看
重点到了!发生deadlock的原因:
deadlock是死锁,一般发生的原因就是两个同时加上事务的连接互相UPDATE对方的加锁行,导致互相等待,这样的操作逻辑上会永远执行下去,这应该就是死锁的概念,但是数据库不会让这种情况真正发生,当判断出发生这种情况的时候MySql会先中断并且回滚后执行的连接并且报deadlock异常,同时允许先进行DML操作的连接,示例如下:
然后在连接1中加事务和对表TEST_ALR的ID=1行加行锁
然后在连接2中加事务和对表TEST_ALR的ID=2行加行锁,同时把ID=4的行进行UPDATE操作
此时都执行成功了,这两个连接之间也没有影响
此时在连接1中对ID=2行进行UPDATE,出现等待,在没报等待超时之前在连接2中对ID=1行进行UPDATE:
出现deadlock异常,说明发生了之前描述的情况
查看TEST_ALR表ID=4的数据:
4 赵六
发现已经回滚
再切回连接1查看,发现此时连接1的UPDATE赢成功执行完成:
1 row(s) affected
之前的项目因为需要用到并发,所以需要并发的CALL存储过程,当时的过程写的存在一些问题,行锁是上对了,但是加完行锁之后,后面的UPDATE操作不是以索引列为条件,所以造成了虽然连接中最开始写的行锁是加的行锁,但是到UPDATE操作的时候还是想对当前表进行表级锁操作,但是另外一个连接中也同时对此表加行级锁了,所以要等待行级锁事务解除,这边才能继续执行UPDATE操作,但是另外一边因为是CALL的同一个过程,所以也是会出现一个一模一样的UPDATE操作,所以这两个连接之间出现了互相等待的情况造成了死锁,示例如下:
现在连接1和连接2都加上事务和不同行的行锁:
连接1:
连接2:
此时在连接1中以NAME当做条件对TEST_ALARM的进行UPDATE(张三在表中其实是唯一的,但是不是索引列):
发现出现等待,在未超时的时候在连接2中执行同样原理的UPDATE:
出现死锁异常:
EooroCode:1213
在切回连接1中:
deadlock是死锁,一般发生的原因就是两个同时加上事务的连接互相UPDATE对方的加锁行,导致互相等待,这样的操作逻辑上会永远执行下去,这应该就是死锁的概念,但是数据库不会让这种情况真正发生,当判断出发生这种情况的时候MySql会先中断并且回滚后执行的连接并且报deadlock异常,同时允许先进行DML操作的连接,示例如下:
然后在连接1中加事务和对表TEST_ALR的ID=1行加行锁
SET autocommit=0; SELECT * FROM TEST_ALR WHERE ID=1 FOR UPDATE;
然后在连接2中加事务和对表TEST_ALR的ID=2行加行锁,同时把ID=4的行进行UPDATE操作
SET autocommit=0; SELECT * FROM TEST_ALR WHERE ID=2 FOR UPDATE;
UPDATE TEST_ALR SET NAME='ABC' WHERE ID=4;
此时都执行成功了,这两个连接之间也没有影响
此时在连接1中对ID=2行进行UPDATE,出现等待,在没报等待超时之前在连接2中对ID=1行进行UPDATE:
UPDATE TEST_ALR SET NAME='TEST2' WHERE ID=2;
Deadlock found when trying to get lock; try restarting transaction
出现deadlock异常,说明发生了之前描述的情况
查看TEST_ALR表ID=4的数据:
SELECT * FROM TEST_ALR WHERE ID=4;ID NAME
4 赵六
发现已经回滚
再切回连接1查看,发现此时连接1的UPDATE赢成功执行完成:
1 row(s) affected
之前的项目因为需要用到并发,所以需要并发的CALL存储过程,当时的过程写的存在一些问题,行锁是上对了,但是加完行锁之后,后面的UPDATE操作不是以索引列为条件,所以造成了虽然连接中最开始写的行锁是加的行锁,但是到UPDATE操作的时候还是想对当前表进行表级锁操作,但是另外一个连接中也同时对此表加行级锁了,所以要等待行级锁事务解除,这边才能继续执行UPDATE操作,但是另外一边因为是CALL的同一个过程,所以也是会出现一个一模一样的UPDATE操作,所以这两个连接之间出现了互相等待的情况造成了死锁,示例如下:
现在连接1和连接2都加上事务和不同行的行锁:
连接1:
SET autocommit=0; SELECT * FROM TEST_ALR WHERE ID=1 FOR UPDATE;
连接2:
SET autocommit=0; SELECT * FROM TEST_ALR WHERE ID=2 FOR UPDATE;
此时在连接1中以NAME当做条件对TEST_ALARM的进行UPDATE(张三在表中其实是唯一的,但是不是索引列):
UPDATE TEST_ALR SET NAME ='张三1' WHERE NAME='张三';
发现出现等待,在未超时的时候在连接2中执行同样原理的UPDATE:
UPDATE TEST_ALR SET NAME ='TEST' WHERE NAME='TEST';
出现死锁异常:
EooroCode:1213
Deadlock found when trying to get lock; try restarting transaction
在切回连接1中:
1 row(s) affected其实在TEST_ALR表中的NAME字段的'张三'和'TEST'是分别对应着自己所在行的数据,但是当你的UPDATE操作条件不是根据索引列操作的话,数据库不会去实际读取表中的数据,所以数据库并不知道你的条件是否在之前加的行锁的范围内,或者说因为UPDATE操作的条件不是索引列,所以会重新对表加上表级锁,导致的互相等待造成的deadlock;
相关文章推荐
- 项目中遇到的MySql行锁与并发性关系(1)
- 项目中遇到的MySql行锁与并发性关系(2)
- 为了后面自动化部署,需要整理公司项目的maven依赖关系,eclipse下maven组件的安装以及用eclipse构建maven多模块工程(即有父子依赖关系的工程)遇到一个class not fond
- w3wp进程发生死锁ISAPI aspnet_isapi.dll报告它自身有问题,原因Deadlock detected
- 项目开发中遇到的问题,原因,解决思路
- Linux环境下段错误的产生原因及调试方法小结 最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多、花费时间最长的问题就是
- 自由职客想跟你发生点关系,比如谈个几十亿的项目
- VS.NET项目调入时发生错误的原因
- 遇到项目上面有叉,但是找不到错误的原因
- 部署ASP.Net项目 遇到总是启用目录浏览或者报HTTP 错误 403.14 - Forbidden 的原因
- 当 FreeBSD 遇到 Ubuntu 会发生什么?ubuntuBSD 项目发布安装镜像
- 中日就算不发生战争 关系也会长期冷下去[转帖]
- 项目开发过程中遇到的一点小知识点
- 最近要做个项目,遇到一些关于ansys问题,看看兄弟们能否帮我解决?
- 由于个人原因分层计算项目暂缓进行
- IIS 无法启动:发生意外错误0x8ffe2740 的原因
- 由于工作的关系,出差在外,很久没有更新了,最近接触到几个优秀的开源项目,准备研究研究
- 错误发生原因之首
- 使用Visual SourceSafe管理Asp.Net项目出现速度极慢的故障原因