And*_*and 14 mysql deadlock innodb transactions
我发现了一个非常令人困惑的死锁情况,我需要帮助才能理解.
有两个事务正在进行:
(2)持有查询锁delete from myTable where id = NAME_CONST('p_id',10000).这是PRIMARY KEY的锁定,虽然不是完整的密钥而是范围.看起来这对我来说是一个完整的写锁定lock_mode X locks rec but not gap.
(1)正在等待同样的锁,也用于查询delete from myTable where id = NAME_CONST('p_id',10000).
(2)也试着去获取此锁并且MySQL检测到死锁.
我无法理解的是为什么(2)必须再次获取锁,因为它已经拥有它并且它在所有情况下都是写锁(lock_mode X).
它看起来也像是完全相同的查询.
这是表定义
create myTable (
id int unsigned not null,
value1 char(8) not null,
value2 int unsigned,
primary key (id, value1)
);
Run Code Online (Sandbox Code Playgroud)
这是来自的信息 SHOW ENGINE INNODB STATUS\G
------------------------
LATEST DETECTED DEADLOCK
------------------------
130313 14:46:28
*** (1) TRANSACTION:
TRANSACTION 75ACB8A3, ACTIVE 0 sec, process no 6110, OS thread id 139973945382656 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 5154970, query id 5201313618 192.168.0.2 user updating
delete from myTable where id = NAME_CONST('p_id',10000)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB8A3 lock_mode X waiting
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 0005af3a; asc :;;
1: len 8; hex 2020202020202020; asc ;;
2: len 6; hex 000075acb890; asc u ;;
3: len 7; hex ea0000020d011e; asc ;;
4: len 4; hex 00000065; asc e;;
*** (2) TRANSACTION:
TRANSACTION 75ACB890, ACTIVE 0 sec, process no 6110, OS thread id 139973957895936 starting index read
mysql tables in use 1, locked 1
7 lock struct(s), hea
p size 1248, 6 row lock(s), undo log entries 4
MySQL thread id 5155967, query id 5201313625 192.168.0.1 user updating
delete from myTable where id = NAME_CONST('p_id',10000)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB890 lock_mode X locks rec but not gap
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 0005af3a; asc :;;
1: len 8; hex 2020202020202020; asc ;;
2: len 6; hex 000075acb890; asc u ;;
3: len 7; hex ea0000020d011e; asc ;;
4: len 4; hex 00000065; asc e;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB890 lock_mode X waiting
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 0005af3a; asc :;;
1: len 8; hex 2020202020202020; asc ;;
2: len 6; hex 000075acb890; asc u ;;
3: len 7; hex ea0000020d011e; asc ;;
4: len 4; hex 00000065; asc e;;
*** WE ROLL BACK TRANSACTION (1)
Run Code Online (Sandbox Code Playgroud)
Mar*_*son 23
它不是同一个锁 - 锁事务1只在(索引)记录上,而不是间隙锁.
这是发生了什么:
我不完全确定为什么事务2不立即获得下一键锁定 - 也许获取记录锁定然后间隙锁定的过程不是原子的(在一般意义上).
我认为问题是你有一个复合主键(id,value1)但是你要从一个范围中删除(仅指定id) - 这需要间隙锁.请参阅http://dev.mysql.com/doc/refman/5.0/en/innodb-record-level-locks.html,特别是:
使用唯一索引锁定行以搜索唯一行的语句不需要间隙锁定.(这不包括搜索条件仅包含多列唯一索引的某些列的情况;在这种情况下,确实会发生间隙锁定.)
您可以更改代码,以便在删除时指定完整的主键,即id 和 value1吗?
其他选择:
如果由于死锁而失败,请始终准备重新发布事务.死锁并不危险.再试一次.
| 归档时间: |
|
| 查看次数: |
7990 次 |
| 最近记录: |