昌珉宋茜吃火锅照片,南京影楼,白癜风手拉手
| 作者王起帆,腾讯CSIG数据库产品中心后台开发工程师,目前主要参与DBbrain开发工作,热爱技术,欢迎留言进行交流。
我们都知道,数据库系统中,不同线程并发访问数据,为了保护数据,在执行SQL语句时候需要对数据加锁。而死锁是一个经常遇到问题,SQL语句加锁和事物隔离级别,访问的索引是不是唯一,访问数据是否存在都有关系,往往死锁分析非常复杂。这篇文章将介绍一个“简单的死锁”,这个死锁产生的事物中SQL语句都只有一条,而且业务非常简单就是删除一条记录。两个事物同时执行以下两个SQL语句就有可能死锁。
DELETE FROM dept_manager WHERE num = 0;
DELETE FROM dept_manager WHERE dept_no = 'd001';
一、死锁模拟
死锁模拟
首先介绍下表结构,这个表除了主键索引 PRIMARY,还有一个唯一索引 num 和一个非唯一索引 dept_no ,建表语句如下:
CREATE TABLE `dept_manager` (
`emp_no` int(11) NOT ,
`dept_no` char NOT ,
`num` int(11) NOT ,
`to_date` date NOT ,
PRIMARY KEY (`emp_no`),
unique index(`num`),
KEY `dept_no` (`dept_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
然后再准备下数据:
INSERT INTO `dept_manager` VALUES (1001,'d001',0,'1991-10-01'),
(1002,'d005',,'9999-01-01'),
(1005,'d002',,'1989-12-17'),
(1007,'d002',,'9999-01-01'),
(1008,'d004',,'1988-09-09'),
(1009,'d004',,'1992-08-02'),
(1010,'d005',9,'1996-08-30');
使用执行两个sql很难,使用 mysqlslap 来高并发碰碰运气:
# mysqlslap --create-schema dldb -q "begin;DELETE FROM dept_manager WHERE num = 0; rollback;" --number-of-queries=100000 -uroot -p123456 &
# mysqlslap --create-schema dldb -q "begin;DELETE FROM dept_manager WHERE dept_no = 'd001'; rollback;" --number-of-queries=100000 -uroot -p123456 &
这两个事物非常都是删除一行相同的数据 (1001,'d001',0,'1991-10-01')只不过一个https://www.3tt.net/?mod=artinfo&aid=415根据索引 num ,一个根据索引 dept_no 。
二、原因分析
1. 数据是怎么找到的?
要说清楚死锁产生原因,就要先理清楚这条SQL是怎么执行的,会在那些地方加锁。在此之前先说说数据库是怎么找到我们要删除的这行数据的。下面两幅图展示根据年龄为30来查记录的示意图。首先根据 name 为 seven, 在 name 这个辅助索引查找,但是只能拿到主键的 id。随后再根据主键id 去主键查找,这个过程称为回表。访问数据是要通过索引的,而且数据就在主键索引上面,所以加锁就是加在索引上面的。
2. Delete 是怎么执行的
Delete 删除数据其实并不是把数据删除了,只是把数据标记一下,表示这里可以复用的,如果下次这里有数据要插入就可以直接复用原来空间里。所以Delete 和 Update 操作比较类似。Delete 和 Update 是根据条件找到第一条数据,进行修改,然后找到第二条数据,以此类推直到再也查不到符合条件的数据。
本文地址:http://www.reviewcode.cn/youxikaifa/207311.html 转载请注明出处!