+ -
当前位置:首页 → 问答吧 → 请教一个MYSQL中死锁的问题

请教一个MYSQL中死锁的问题

时间:2011-08-26

来源:互联网

我之前对死锁的理解一般情况就是A事务锁定了行a,B事务锁定了行b,然后这时A事务请求行b的锁,B事务请求行a的锁,就会HANG住不动,这就产生了死锁。
最近刚刚接触MYSQL,今天在看文档的过程中看到文档中举得一个死锁的例子,如下

下列的例子演示当锁定请求可能会导致死锁之时一个错误会如何发生。例子中包括两个客户端A和B。
首先客户端A创建一个包含一个行的表,然后开始一个事务。在这个事务内,A通过在共享模式选择行获得对行的S 锁定:
mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)

mysql> INSERT INTO t (i) VALUES(1);

Query OK, 1 row affected (0.09 sec)

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;

+------+

| i    |

+------+

|    1 |

+------+

1 row in set (0.10 sec)

接着,客户端B开始一个事务并尝试从该表删除行:

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM t WHERE i = 1;

删除操作要求一个X 锁定。因为这个锁定不兼容客户端A持有的S锁定,所以X 锁定不被允许,所以请求进入对行及客户端阻挡的锁定请求队列。

最后,客户端A也试图从表中删除该行:

mysql> DELETE FROM t WHERE i = 1;

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

try restarting transaction

客户端A首先对i=1那一行获取了S锁,然后客户端B在delete的时候尝试获取X锁就会进入等待,直到这一步我还是能理解的。可是后来在客户端A尝试删除i=1的数据行的时候,却报发生了死锁的错误,这里是为什么呢?

作者: hwang1987   发布时间: 2011-08-26

原文档中还有这么一段
“因为客户端A需要一个X 锁定来删除该行,所以在这里发生死锁。尽管如此,锁定请求不被允许,因为客户端B已经有一个对X锁定的请求并且它正等待客户端A释放S锁定。因为客户端B之前对X 锁定的请求,被客户端A持有的S锁定也不能升级到X锁定。因此,InnoDB对客户端A产生一个错误,并且释放它的锁定。在那一点上,客户端B的锁定请求可以被许可,并且客户端B从表中删除行。 ”

如果非要理解,我只能这么理解:
1、就是说事务B优先进入了等待X锁的队列,而事务A排在它后面,因此只要B获取不了X锁,A肯定获取不到
2、A锁持有S锁,因此B也不可能获得X锁

这样就发生死锁了
不知道这样理解正确吗?还望大家指点指点

作者: hwang1987   发布时间: 2011-08-26

热门下载

更多