我有一个存储过程从“票据”表生成UID的,但在负载下我得到了很多的死锁。无论何时我的任务需要新的UID,我都会从多个并发连接多次调用此过程。存储过程生成UID的MySQL死锁
BEGIN
DECLARE a_uid BIGINT(20) UNSIGNED;
START TRANSACTION;
SELECT uid INTO a_uid FROM uid_data FOR UPDATE; # Lock
INSERT INTO uid_data (stub) VALUES ('a') ON DUPLICATE KEY UPDATE uid=uid+1;
SELECT a_uid+1 AS `uid`;
COMMIT;
END
我没有考虑使用:
BEGIN
REPLACE INTO uid_data (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
END
不过,我不知道,如果这将是与并发连接的安全,因为没有锁定,不像与SELECT FOR UPDATE
的第一个过程。
这里的表:
mysql> DESCRIBE uid_data;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| uid | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| stub | char(1) | NO | UNI | NULL | |
+-------+---------------------+------+-----+---------+----------------+
我已经为读提交的事务隔离设置:
mysql> SHOW VARIABLES LIKE 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | READ-COMMITTED |
+---------------+-----------------+
这里就是我从SHOW ENGINE INNODB STATUS;
...
... dozens and dozens of the following record locks...
Record lock, heap no 1046 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 1; hex 61; asc a;;
1: len 8; hex 00000000000335f2; asc 5 ;;
Record lock, heap no 1047 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 1; hex 61; asc a;;
1: len 8; hex 00000000000335f1; asc 5 ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 13 page no 4 n bits 1120 index `stub` of table `my_db`.`uid_data` trx id 13AA89 lock_mode X waiting
Record lock, heap no 583 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 1; hex 61; asc a;;
1: len 8; hex 00000000000334a8; asc 4 ;;
*** WE ROLL BACK TRANSACTION (1)
我找回如果有人能够解释发生了什么以及如何避免这些事情,我会很感激。
有关信息:即使使用此简单序列,也会发生死锁:'START TRANSACTION; SELECT uid FROM uid_data FOR UPDATE; UPDATE uid_data SET uid = uid +1 [[此处可能存在死锁]]; COMMIT;'(因此它与'ON DUPLICATE'子句无关)。但是,隔离级别为'REPEATABLE READ;'时不会发生死锁。我仍然不知道从这一点可以得出什么结论。 – RandomSeed 2012-07-06 11:40:11