Ho una procedura memorizzata che genera UID da una tabella "ticket", ma sotto carico sto ottenendo molti deadlock. Sto chiamando questa procedura molte volte da più connessioni simultanee ogni volta che il mio compito ha bisogno di un nuovo UID.Blocchi MySQL con stored procedure che generano UID
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
ho considerato utilizzando:
BEGIN
REPLACE INTO uid_data (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
END
Comunque io non ero sicuro se questo sarebbe al sicuro con connessioni simultanee in quanto non c'è blocco, a differenza della prima procedura con il SELECT FOR UPDATE
.
Ecco la tabella:
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 | |
+-------+---------------------+------+-----+---------+----------------+
Ho installato per la lettura impegnata isolamento delle transazioni:
mysql> SHOW VARIABLES LIKE 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | READ-COMMITTED |
+---------------+-----------------+
Ecco quello che sto tornando da 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)
I Sarei grato se qualcuno potesse spiegare cosa sta succedendo e come possono essere evitati.
Per informazioni: il deadlock si verifica anche quando si utilizza questa semplice sequenza: 'START TRANSACTION; SELECT uid FROM uid_data FOR UPDATE; UPDATE uid_data SET uid = uid +1 [[deadlock possibile qui]]; COMMIT; '(quindi non ha nulla a che fare con la clausola' ON DUPLICATE'). Tuttavia, non si verifica un deadlock con un livello di isolamento di 'REPEATABLE READ;'. Ancora non so cosa concludere da questo punto. – RandomSeed