假设我有桌子:
CREATE TABLE t (id INTEGER AUTOINCREMENT NOT NULL, desc TEXT NOT NULL)
我用1个元素填充表格:
INSERT INTO TABLE t VALUES (1, 'Hello')
我在MySQL中运行两个事务。在t1
我运行:
START TRANSACTION;
SELECT * FROM t WHERE id = 1 FOR UPDATE;
在t2
我跑:
START TRANSACTION;
SELECT * FROM t WHERE id = 1 FOR UPDATE;
此时我希望t1
在行上保持e(X)集群锁定,并t2
等待它可以获得X锁定(t2
确实获得阻止,到目前为止一切顺利)。然后我在t1
中运行更新(没有任何WHERE子句!):
UPDATE t SET desc = 'Hello from t1';
此时t2
我立刻得到了(不需要COMMIT
交易)错误:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
为什么我收到此错误?我想有一个锁t2
正在获取完整的UPDATE需要继续进行,造成死锁,但我不明白t2
如何获得锁定,因为它应该等待{ {1}}完成。
答案 0 :(得分:2)
使两个事务都运行而没有死锁的方法是在两个连接中将isolation level更改为 READ COMMITED (或 READ UNCOMMITED ): / p>
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
(start transaction
之前)。
在t2
中设置它就足够了,但为了确保这个例子,请在两者中设置它。
更改事务的隔离级别会引入一些副作用,在生产环境中更改之前,应该告知in the manual。
------------------------
LATEST DETECTED DEADLOCK
------------------------
140424 8:45:46
*** (1) TRANSACTION:
TRANSACTION B6F18A3, ACTIVE 5 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 13885, OS thread handle 0x7f8b1dbd2700, query id 901012
localhost root statistics
SELECT * FROM t WHERE id = 1 FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
`test`.`t` trx id B6F18A3 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000001; asc ;;
1: len 6; hex 00000b6f1883; asc o ;;
2: len 7; hex 06000059a211ea; asc Y ;;
3: len 5; hex 48656c6c6f; asc Hello;;
*** (2) TRANSACTION:
TRANSACTION B6F18A2, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 13888, OS thread handle 0x7f8b1f64d700, query id 901068
localhost root Updating
UPDATE t SET `descc` = 'Hello from t1'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
`test`.`t` trx id B6F18A2 lock_mode X locks rec but not gap
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000001; asc ;;
1: len 6; hex 00000b6f1883; asc o ;;
2: len 7; hex 06000059a211ea; asc Y ;;
3: len 5; hex 48656c6c6f; asc Hello;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
`test`.`t` trx id B6F18A2 lock_mode X waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000001; asc ;;
1: len 6; hex 00000b6f1883; asc o ;;
2: len 7; hex 06000059a211ea; asc Y ;;
3: len 5; hex 48656c6c6f; asc Hello;;
*** WE ROLL BACK TRANSACTION (1)
正如a_horse_with_no_name所提到的,这似乎是MySQL中的一个错误。交易(2)持有并等待相同的锁定,这没有任何意义。