How these transactions cause deadlock? - mysql

I've 2 types of transactions:
Type 1 includes the following Sqls:
UPDATE userdb_ingest_report SET start_time='%s', end_time='%s', is_csv_ingest=%d, success=%d, failed=%d WHERE clientid='%s' AND filename='%s' AND network_id=%d AND data_provider_id=%d;\n
or
INSERT INTO userdb_ingest_report(clientid, filename, network_id, data_provider_id, start_time, end_time, is_csv_ingest, success, failed) VALUES ('%s', '%s', %d, %d, '%s', '%s', %d, %d, %d);\n"
and
DELETE FROM userdb_ingest_report WHERE clientid<>'%s' AND filename='%s' AND network_id=%d AND data_provider_id=%d;\n
Type 2 includes the following Sqls:
UPDATE userdb_ingest_report SET start_time=LEAST(%s, start_time), end_time=GREATEST(%s, end_time), is_csv_ingest=%d, success=success+%d, failed=failed+%d WHERE clientid='%s' AND filename='%s' AND network_id='%d' AND data_provider_id='%d'"
or
INSERT INTO userdb_ingest_report(clientid, filename, network_id, data_provider_id, start_time, end_time, is_csv_ingest, success, failed) VALUES ('%s', '%s', %d, %d, '%s', '%s', %d, %d, %d);\n
There may be 1 instance of type1 and 1-6 instances of type2 running concurrently. Sometimes I'll get the deadlock failure:
Update table userdb_ingest_report error. Sql:UPDATE userdb_ingest_report SET start_time=LEAST(20170622134845, start_time), end_time=GREATEST(20170622134846, end_time), is_csv_ingest=1, success=success+184, failed=failed+0 WHERE clientid='clienta' AND filename='file1' AND network_id='48804' AND data_provider_id='386123', Error:Error 1213: Deadlock found when trying to get lock; try restarting transaction
or
Insert table userdb_ingest_report error. Sql:INSERT INTO userdb_ingest_report(clientid, filename, network_id, data_provider_id, start_time, end_time, is_csv_ingest, success, failed) VALUES ('clientb', 'fileb', 385316, 385316, '20170622140908', '20170622140922', 1, 372521, 0); , Error:Error 1213: Deadlock found when trying to get lock; try restarting transaction
and this is the schema of this table:
CREATE TABLE `userdb_ingest_report` (
`filename` varchar(255) NOT NULL,
`network_id` bigint(20) NOT NULL,
`data_provider_id` bigint(20) NOT NULL,
`start_time` datetime NOT NULL,
`end_time` datetime NOT NULL,
`is_csv_ingest` smallint(1) NOT NULL,
`success` bigint(20) DEFAULT '0',
`failed` bigint(20) DEFAULT '0',
`clientid` char(30) DEFAULT '',
KEY `network_data_provider_clientid_idx` (`network_id`,`data_provider_id`,`clientid`,`filename`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
When I use show innodb status in mysql, I got the following messages about the last deadlock information:
------------------------
LATEST DETECTED DEADLOCK
------------------------
170622 21:15:22
*** (1) TRANSACTION:
TRANSACTION 3F427F4B, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 30 lock struct(s), heap size 6960, 41 row lock(s), undo log entries 14
MySQL thread id 43053224, OS thread handle 0x2b8f80ffe940, query id 1158507552 10.1.10.42 backend_new update
INSERT INTO userdb_ingest_report(clientid, filename, network_id, data_provider_id, start_time, end_time, is_csv_ingest, success, failed) VALUES ('auingest03.fwmrm.net_1', '/mnt/sftponly/381963/files/audience/ingest/pending/visitor_attr_381963_20170622145737.csv.gz', 0, 381963, '20170622211520', '20170622211522', 1, 18203, 0)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 1026 page no 711706 n bits 176 index `network_data_provider_clientid_idx` of table `fwmrm_stats`.`userdb_ingest_report` trx id 3F427F4B lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 16 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 8; hex 8000000000000000; asc ;;
1: len 8; hex 800000000005d457; asc W;;
2: len 30; hex 202020202020202020202020202020202020202020202020202020202020; asc ;;
3: len 30; hex 2f6d6e742f736674706f6e6c792f3338323033392f66696c65732f617564; asc /mnt/sftponly/382039/files/aud; (total 92 bytes);
4: len 6; hex 00000c420d62; asc B b;;
*** (2) TRANSACTION:
TRANSACTION 3F427F4C, ACTIVE 0 sec inserting, thread declared inside InnoDB 500
mysql tables in use 1, locked 1
28 lock struct(s), heap size 6960, 38 row lock(s), undo log entries 13
MySQL thread id 43053207, OS thread handle 0x2b8f80bee940, query id 1158507553 10.1.10.41 backend_new update
INSERT INTO userdb_ingest_report(clientid, filename, network_id, data_provider_id, start_time, end_time, is_csv_ingest, success, failed) VALUES ('auingest02.fwmrm.net_1', '/mnt/sftponly/381963/files/audience/ingest/pending/visitor_attr_381963_20170622145737.csv.gz', 0, 381963, '20170622211520', '20170622211522', 1, 36103, 0)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 1026 page no 711706 n bits 176 index `network_data_provider_clientid_idx` of table `fwmrm_stats`.`userdb_ingest_report` trx id 3F427F4C lock_mode X locks gap before rec
Record lock, heap no 16 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 8; hex 8000000000000000; asc ;;
1: len 8; hex 800000000005d457; asc W;;
2: len 30; hex 202020202020202020202020202020202020202020202020202020202020; asc ;;
3: len 30; hex 2f6d6e742f736674706f6e6c792f3338323033392f66696c65732f617564; asc /mnt/sftponly/382039/files/aud; (total 92 bytes);
4: len 6; hex 00000c420d62; asc B b;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 1026 page no 711706 n bits 176 index `network_data_provider_clientid_idx` of table `fwmrm_stats`.`userdb_ingest_report` trx id 3F427F4C lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 16 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 8; hex 8000000000000000; asc ;;
1: len 8; hex 800000000005d457; asc W;;
2: len 30; hex 202020202020202020202020202020202020202020202020202020202020; asc ;;
3: len 30; hex 2f6d6e742f736674706f6e6c792f3338323033392f66696c65732f617564; asc /mnt/sftponly/382039/files/aud; (total 92 bytes);
4: len 6; hex 00000c420d62; asc B b;;
so how would this happen, and how can I solve this deadlock?

Related

mysql select for update read committed deadlock

mysql version:5.7.23-log
isolation level:read committed
mysql data
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for app_record_lock_test
-- ----------------------------
DROP TABLE IF EXISTS `app_record_lock_test`;
CREATE TABLE `app_record_lock_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hash` bigint(20) NOT NULL DEFAULT '0',
`cluster` varchar(256) NOT NULL,
`namespace` varchar(256) NOT NULL DEFAULT '',
`service` varchar(256) NOT NULL DEFAULT '',
`pod` varchar(256) NOT NULL DEFAULT '',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `cluster_hash` (`cluster`,`hash`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=120236025 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of app_record_lock_test
-- ----------------------------
INSERT INTO `app_record_lock_test` VALUES ('120236012', '1', 'cluster', 'namespace', 'service', 'pod', '2022-02-18 14:14:59', '2022-02-09 10:00:00');
INSERT INTO `app_record_lock_test` VALUES ('120236013', '2', 'cluster', 'namespace', 'service', 'pod', '2022-02-18 14:14:59', '2022-02-09 10:00:00');
INSERT INTO `app_record_lock_test` VALUES ('120236014', '3', 'cluster', 'namespace', 'service', 'pod', '2022-02-18 14:14:59', '2022-02-09 10:00:00');
session 1:
START TRANSACTION;
SELECT HASH
FROM
app_record_lock_test
WHERE
cluster = 'cluster' FOR UPDATE;
INSERT INTO app_record_lock_test ( HASH, cluster, namespace, service, pod, updated_at )
VALUES
( 1, 'cluster', 'namespace', 'service', 'pod', '2022-02-09 10:00:00' )
ON DUPLICATE KEY UPDATE updated_at = '2022-02-09 11:00:01';
COMMIT;
session 2:
START TRANSACTION;
SELECT HASH
FROM
app_record_lock_test
WHERE
cluster = 'cluster' FOR UPDATE;
INSERT INTO app_record_lock_test ( HASH, cluster, namespace, service, pod, updated_at )
VALUES
( 1, 'cluster', 'namespace', 'service', 'pod', '2022-02-09 10:00:00' )
ON DUPLICATE KEY UPDATE updated_at = '2022-02-09 11:00:01';
COMMIT;
Steps to reproduce
1、session 1 first execute select for update
2、session 2 execute select for update
3、session 1 executes insert,This is session 2 and an error will be reported
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
why is this?
show engine innodb status,before insert:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2022-02-21 16:13:48 0x7f2026049700
*** (1) TRANSACTION:
TRANSACTION 421085334, ACTIVE 8 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 41539545, OS thread handle 139773723899648, query id 20729357470 10.190.176.247 console Sending data
/* ApplicationName=DBeaver 21.3.5 - SQLEditor <Script-8.sql> */ SELECT HASH
FROM
app_record_lock_test
WHERE
cluster = 'cluster' FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12005 page no 4 n bits 72 index cluster_hash of table `console`.`app_record_lock_test` trx id 421085334 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000001; asc ;;
2: len 4; hex 872aa7ec; asc * ;;
*** (2) TRANSACTION:
TRANSACTION 421085333, ACTIVE 13 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
MySQL thread id 41539561, OS thread handle 139776053516032, query id 20729357538 10.190.176.247 console update
/* ApplicationName=DBeaver 21.3.5 - SQLEditor <Script-5.sql> */ INSERT INTO app_record_lock_test ( HASH, cluster, namespace, service, pod, updated_at )
VALUES
( 1, 'cluster', 'namespace', 'service', 'pod', '2022-02-09 10:00:00' )
ON DUPLICATE KEY UPDATE updated_at = '2022-02-09 11:00:01'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 12005 page no 4 n bits 72 index cluster_hash of table `console`.`app_record_lock_test` trx id 421085333 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000001; asc ;;
2: len 4; hex 872aa7ec; asc * ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12005 page no 4 n bits 72 index cluster_hash of table `console`.`app_record_lock_test` trx id 421085333 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000001; asc ;;
2: len 4; hex 872aa7ec; asc * ;;
*** WE ROLL BACK TRANSACTION (1)
after insert:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2022-02-22 09:26:16 0x7f216925a700
*** (1) TRANSACTION:
TRANSACTION 421416755, ACTIVE 22 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 41565582, OS thread handle 139778307692288, query id 20731658463 10.190.176.247 console Sending data
/* ApplicationName=DBeaver 21.3.5 - SQLEditor <Script-8.sql> */ SELECT HASH
FROM
app_record_lock_test
WHERE
cluster = 'cluster' FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12005 page no 4 n bits 72 index cluster_hash of table `console`.`app_record_lock_test` trx id 421416755 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000001; asc ;;
2: len 4; hex 872aa7ec; asc * ;;
*** (2) TRANSACTION:
TRANSACTION 421416754, ACTIVE 26 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 7 row lock(s), undo log entries 1
MySQL thread id 41565555, OS thread handle 139781474723584, query id 20731658615 10.190.176.247 console update
/* ApplicationName=DBeaver 21.3.5 - SQLEditor <Script-5.sql> */ INSERT INTO app_record_lock_test ( HASH, cluster, namespace, service, pod, updated_at )
VALUES
( 1, 'cluster', 'namespace', 'service', 'pod', '2022-02-09 10:00:00' )
ON DUPLICATE KEY UPDATE updated_at = '2022-02-09 11:00:01'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 12005 page no 4 n bits 72 index cluster_hash of table `console`.`app_record_lock_test` trx id 421416754 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000001; asc ;;
2: len 4; hex 872aa7ec; asc * ;;
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000002; asc ;;
2: len 4; hex 872aa7ed; asc * ;;
Record lock, heap no 4 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000003; asc ;;
2: len 4; hex 872aa7ee; asc * ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12005 page no 4 n bits 72 index cluster_hash of table `console`.`app_record_lock_test` trx id 421416754 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 7; hex 636c7573746572; asc cluster;;
1: len 8; hex 8000000000000001; asc ;;
2: len 4; hex 872aa7ec; asc * ;;
*** WE ROLL BACK TRANSACTION (1)

INSERT ON DUPLICATE KEY UPDATE occurs a deadlock error, which is about record lock

I use insert ... on duplicate key updateto insert data in batches.
But I get a error when do it with more than one threads, actually just two threads do it.
The table is:
create table alarm {
id varchar(20) not null collate utf8_unicode_ci,
`date` date not null,
adas blob,
dsm blob,
bsd blob,
primary key(id, `date`)
) engine=innodb default charset=utf8
collate=utf8_unicode_ci
The insert statement is like:
insert into alarm(id, `date`, adas) values
('10001', 20220105, 0x1231231),
('10002', 20220105, 0xAFED001),
....
on duplicate key update
adas=concat(ifnull(adas,''), ifnull(values(adas),''));
The another insert statement is like:
insert into alarm(id, `date`, dsm) values
('10001', 20220105, 0x1231231),
('10002', 20220105, 0xAFED001),
('10008', 20220105, 0xAFED001),
('00008', 20220105, 0xAFED34),
....
on duplicate key update
dsm=concat(ifnull(dsm,''), ifnull(values(dsm),''));
sometimes, it will occur a dead lock error. The database log as following:
> myql show engine innodb status \G;
------------------------
LATEST DETECTED DEADLOCK
------------------------
2022-02-22 16:49:29 0x1fac
*** (1) TRANSACTION:
TRANSACTION 3902837, ACTIVE 1 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 23 lock struct(s), heap size 1080, 28 row lock(s), undo log entries 31
MySQL thread id 85930, OS thread handle 17464, query id 34130124 DESKTOP-AJ1S2TF 192.168.20.191 root update
INSERT INTO device_alarm (did, `date`, dsm) VALUES('4044383', '20220222', 0x3a000a043078313012043078303220422945b8c9a832303f4031832f4ca60a685e40389ac7d2900642120a0e33303334333133313336333233301001),('4050503', '20220222', 0x38000a043078313012043078303229342db1321a493f4031ca4e3fa88b685e4038a1c7d2900642120a0e33303334333133323331333633371001),('2000023', '20220222', 0x3a000a0430783034120430783031202f29e08618af79fd36403159ddea39e9695c4038a5c7d2900642120a0e33303332333333313333333433351005),('4026821', '20220222', 0x38000a04307831301204307830322982aca7565f293f40316347e350bf725e40388cc7d2900642120a0e34313432353934413337333833331001),('4051611', '20220222', 0x3a000a0430783130120430783032201229377007ea94473f403113d38558fd545e403891c7d2900642120a0e33303334333133313339333633351001),('6493492', '20220222', 0x38000a043078303412043078303220432939d4efc2d65e4040317e54c37e4f5e5c40388ec7d29006421
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 682 page no 31 n bits 112 index PRIMARY of table `httpserver`.`device_alarm` /* `p20220223` */ trx id 3902837 lock_mode X locks rec but not gap waiting
Record lock, heap no 42 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
0: len 11; hex 3430373336373431363336; asc 4073674;;
1: len 3; hex 8fcc56; asc V;;
2: len 6; hex 0000003b8d76; asc ; v;;
3: len 7; hex 5500000bba09b8; asc U ;;
4: len 30; hex 46000a04307830321204307830312a0430783031320430783030403149d1; asc F 0x02 0x01* 0x012 0x00#1I ; (total 576 bytes);
5: len 30; hex 38000a043078313012043078303229fe7bf0daa5e13e403124d1cb289672; asc 8 0x10 0x02) { >#1$ ( r; (total 412 bytes);
6: SQL NULL;
*** (2) TRANSACTION:
TRANSACTION 3902838, ACTIVE 1 sec inserting
mysql tables in use 1, locked 1
36 lock struct(s), heap size 3296, 39 row lock(s), undo log entries 48
MySQL thread id 85931, OS thread handle 8108, query id 34130125 DESKTOP-AJ1S2TF 192.168.20.191 root update
INSERT INTO device_alarm (did, `date`, adas) VALUES('1810534', '20220222', 0x46000a04307830321204307830322a0430783032320430783030404349a2410a9e42aa424051a2410a9e42aa42405895c7d2900662120a0e33353333333433303338333633381005),('2000041', '20220222', 0x46000a04307830321204307830312a04307830323204307830304020491920d1048a343f40511920d1048a343f40589ac7d2900662120a0e33303334333133313334333333391005),('1800684', '20220222', 0x48000a0430783032120430783031200b2a0430783031320430783030402e498bfcfa2136b24240518bfcfa2136b2424058a5c7d2900662120a0e33363338333433393336333133381005),('1030014', '20220222', 0x48000a043078303112043078303120062a0430783030320430783030402c4945b8c9a832ac38405145b8c9a832ac38405892c7d2900662120a0e33303331333433303333333433311005),('2000024', '20220222', 0x46000a04307830321204307830312a0430783032320430783030401f49284696ccb100374051284696ccb10037405897c7d2900662120a0e33303332333
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 682 page no 31 n bits 112 index PRIMARY of table `httpserver`.`device_alarm` /* `p20220223` */ trx id 3902838 lock_mode X locks rec but not gap
Record lock, heap no 42 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
0: len 11; hex 3430373336373431363336; asc 4073674;;
1: len 3; hex 8fcc56; asc V;;
2: len 6; hex 0000003b8d76; asc ; v;;
3: len 7; hex 5500000bba09b8; asc U ;;
4: len 30; hex 46000a04307830321204307830312a0430783031320430783030403149d1; asc F 0x02 0x01* 0x012 0x00#1I ; (total 576 bytes);
5: len 30; hex 38000a043078313012043078303229fe7bf0daa5e13e403124d1cb289672; asc 8 0x10 0x02) { >#1$ ( r; (total 412 bytes);
6: SQL NULL;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 682 page no 136 n bits 120 index PRIMARY of table `httpserver`.`device_alarm` /* `p20220223` */ trx id 3902838 lock_mode X locks rec but not gap waiting
Record lock, heap no 50 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
0: len 11; hex 3138373030383530303738; asc 1870085;;
1: len 3; hex 8fcc56; asc V;;
2: len 6; hex 0000003b8d75; asc ; u;;
3: len 7; hex 540000223f2ba1; asc T "?+ ;;
4: len 30; hex 46000a04307830321204307830312a0430783032320430783030402f4983; asc F 0x02 0x01* 0x022 0x00#/I ; (total 360 bytes);
5: len 30; hex 3a000a04307830341204307830312027292ae109bdfe0e4340317a8b87f7; asc : 0x04 0x01 ')* C#1z ; (total 602 bytes);
6: SQL NULL;
*** WE ROLL BACK TRANSACTION (1)
The lock is lock_mode X locks rec but not gap, it's too strange for me to undertand it. Why did the dead lock happen?

is there any way to show MySQL table lock history

I am using MySQL 5.7.26,is there any way to show table lock history?I know how to check current table lock using:
show OPEN TABLES where In_use > 0;
I want to avoid table lock in my SQL query,so view the history may help.Current lock may not get all locked table(Maybe the locked table query not execute right now).
Today I found a way to show this in MySQL 5.7:
show engine innodb status
this is the part of result output:
====================================
2020-09-25 10:36:53 0x7ff4b4c5d700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 12 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 762213 srv_active, 0 srv_shutdown, 139997 srv_idle
srv_master_thread log flush and writes: 902210
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 363879865
OS WAIT ARRAY INFO: signal count 448819672
RW-shared spins 0, rounds 425739262, OS waits 209673117
RW-excl spins 0, rounds 4271714439, OS waits 133598673
RW-sx spins 135926, rounds 2757000, OS waits 52788
Spin rounds per wait: 425739262.00 RW-shared, 4271714439.00 RW-excl, 20.28 RW-sx
------------------------
LATEST DETECTED DEADLOCK
------------------------
2020-09-25 10:10:41 0x7ff4b4ce1700
*** (1) TRANSACTION:
TRANSACTION 841893940, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 108348, OS thread handle 140688980530944, query id 184994716 172.19.104.233 root Searching rows for update
UPDATE r_room_seat SET status = 1,
id = (SELECT #update_id := id),
user_id = 62659,
robot_flag = 1
WHERE room_play_id = 539 and status = 0 and online = 1
LIMIT 1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 3493 page no 528 n bits 176 index PRIMARY of table `room_db`.`r_room_seat` trx id 841893940 lock_mode X locks rec but not gap waiting
Record lock, heap no 56 PHYSICAL RECORD: n_fields 20; compact format; info bits 0
0: len 8; hex 000000000000d649; asc I;;
1: len 6; hex 0000322d9b9a; asc 2- ;;
2: len 7; hex 3e000040042eda; asc > # . ;;
3: len 8; hex 800000000000021b; asc ;;
4: len 8; hex 8000000000000097; asc ;;
5: len 8; hex 800000000000f4d5; asc ;;
6: len 8; hex 7fffffffffffffff; asc ;;
7: len 8; hex 8000017452aa2c5e; asc tR ,^;;
8: len 4; hex 80000000; asc ;;
9: len 4; hex 80000000; asc ;;
10: len 8; hex 8000017452aa2c5e; asc tR ,^;;
11: len 8; hex 8000017452aa2c5e; asc tR ,^;;
12: len 4; hex 80000001; asc ;;
13: len 1; hex 81; asc ;;
14: len 8; hex 8000000000000005; asc ;;
15: len 10; hex 48415050595f5241494e; asc HAPPY_RAIN;;
16: len 4; hex 80000001; asc ;;
17: len 8; hex 8000000000000000; asc ;;
18: len 8; hex 8000000000000074; asc t;;
19: len 4; hex 80000001; asc ;;
*** (2) TRANSACTION:
TRANSACTION 841893905, ACTIVE 0 sec fetching rows
mysql tables in use 2, locked 2
746 lock struct(s), heap size 90320, 128960 row lock(s)
MySQL thread id 100540, OS thread handle 140688982152960, query id 184994612 172.19.104.233 root Sending data
UPDATE r_room_seat s
SET s.status = 1,
s.room_play_id = (SELECT #update_id := max(room_play_id)),
s.user_id = (
case when s.seat_num = 1
then 63182
when s.seat_num = 2
then 16472
else -1 end
),
s.robot_flag = (
case when s.seat_num = 1
then 1
when s.seat_num = 2
then 0
else 0 end
)
WHERE s.status = 0
and s.online = 1
and s.room_play_id in (
select room_play_id
from (
select room_play_id as room_play_id
from r_room_seat
where room_id = 166
and status = 0
group by room_play_id
having count(*) = 2
limit 1
) a
)
and s.room_id = 166
LIMIT 2
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 3493 page no 528 n bits 176 index PRIMARY of table `room_db`.`r_room_seat` trx id 841893905 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
you can get the dead lock information and analysis.

MySQL 5.6.26 high concurrency dead lock

Table structure:
CREATE TABLE `extend_0` (
`id` bigint(20) NOT NULL,
`code` varchar(30) NOT NULL,
`data_key` varchar(50) NOT NULL,
`data_value` varchar(200) NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`yn` tinyint(3) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`,`create_time`),
UNIQUE KEY `idx_unq_code_data_key` (`code`,`data_key`,`create_time`) USING BTREE,
KEY `idx_code` (`code`) USING BTREE
) ENGINE=InnoDB;
When two transactions at the same time delete and insert the same data, sometimes a deadlock happened. The tx_isolation is RR.
For example:
DELETE FROM extend_0 WHERE code = '00226915986' AND yn = 1;
INSERT INTO extend_0 (id, code, data_key, data_value, create_time) VALUES (1133296779049299970, '00226915986', 'consignWare', 'food', '2019-05-28 16:59:42.418'), (1133296779049299971, '00226915986', 'productType', '0001,0006', '2019-05-28 16:59:42.418');
Deadlock log:
------------------------------------------------------------------------------
2019-05-30 14:48:07 0x7fbb7872c700
*** (1) TRANSACTION:
TRANSACTION 125554670, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 5148727, OS thread handle 140443189679872, query id 6111057236 192.168.162.16 waybill updating
DELETE FROM extend_0 WHERE code = '00226915986' AND yn = 1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 77 page no 3145 n bits 360 index idx_unq_code_data_key of table `waybill_0`.`extend_0` trx id 125554670 lock_mode X waiting
Record lock, heap no 285 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc 00226915986;;
1: len 11; hex 636f6e7369676e57617265; asc consignWare;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf000; asc ;;
*** (2) TRANSACTION:
TRANSACTION 125554668, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 3
MySQL thread id 5148728, OS thread handle 140443156399872, query id 6111057237 192.168.162.16 waybill update
INSERT INTO extend_0 (id, code, data_key, data_value, create_time) VALUES (i-1, '00226915986', 'consignWare', 'food', '2019-05-28 16:59:42.418'), (i, '00226915986', 'productType', '0001,0006', '2019-05-28 16:59:42.418')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 77 page no 3145 n bits 360 index idx_unq_code_data_key of table `waybill_0`.`extend_0` trx id 125554668 lock_mode X
Record lock, heap no 285 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc 00226915986;;
1: len 11; hex 636f6e7369676e57617265; asc consignWare;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf000; asc ;;
Record lock, heap no 287 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc 00226915986;;
1: len 11; hex 70726f6475637454797065; asc productType;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf020; asc ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 77 page no 3145 n bits 360 index idx_unq_waybill_code_data_key of table `waybill_0`.`extend_0` trx id 125554668 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 285 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
0: len 15; hex 4a4456433030323236393135393836; asc JDVC00226915986;;
1: len 11; hex 636f6e7369676e57617265; asc consignWare;;
2: len 4; hex 5cecf87e; asc \ ~;;
3: len 8; hex 911d8ce2e1ddf000; asc ;;
*** WE ROLL BACK TRANSACTION (1)
------------------------------------------------------------------------------
The transaction2 has lock_mode X already. Why does "lock_mode X locks gap before rec insert intention waiting" happen?
But when we execute the transactions one by one a deadlock does not happen. For example:
step1: tx1 begin; delete.....;
step2: tx2 begin; delete.....;
step3: tx1 insert....;
step4: tx2 insert....;
step5: tx1 commit;
The deadlock happens only when there is high concurrency; the deadlock looks to be caused by the concurrency of tx1's delete and tx2's insert.
What lock does transaction 1 hold?Why transaction 2 is waiting for transaction 1?
Plan A:
Live with it. That is, check for errors, see that there is a deadlock, and restart the transaction. You should have this code even if you go with Plan B.
Plan B:
BEGIN;
SELECT ... WHERE code = '00226915986' AND yn = 1 FOR UPDATE;
DELETE ...
INSERT ...
COMMIT;
This should force any other connection to wait instead of deadlock.

mysql deadlock with foreign key

DDL(removed some irrelevant columns info)
Table: config_version
Create Table: CREATE TABLE `config_version` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`config_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_config_version_config_1` (`config_id`),
CONSTRAINT `fk_config_version_config_1` FOREIGN KEY (`config_id`) REFERENCES `config` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=85532 DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=COMPACT
Table: config
Create Table: CREATE TABLE `config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_config_name_namespace_id` (`name`,`namespace_id`),
KEY `fk_config_namespace_1` (`namespace_id`),
CONSTRAINT `fk_config_namespace_1` FOREIGN KEY (`namespace_id`) REFERENCES `namespace` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1901 DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=COMPACT
show engine innodb status;
*** (1) TRANSACTION:
TRANSACTION 125411, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 7, OS thread handle 123145570861056, query id 4898 localhost 127.0.0.1 root updating
update config set name = 'bts_driver_list_filter_gray_onceagain_list_filter_tw_control_group', description = '?????????????', namespace_id = 4, current_version = 89950, create_time = '2017-11-14 15:54:45', created_by = 'chenchongyu' where id = 982
2017-12-01T04:12:43.711301Z 6 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 672 page no 11 n bits 216 index PRIMARY of table `apollo_config_dev`.`config` trx id 125411 lock_mode X locks rec but not gap waiting
Record lock, heap no 97 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
0: len 8; hex 80000000000003d6; asc ;;
1: len 6; hex 00000001e9da; asc ;;
2: len 7; hex 24000001830584; asc $ ;;
3: len 30; hex 6274735f6472697665725f6c6973745f66696c7465725f677261795f6f6e; asc bts_driver_list_filter_gray_on; (total 66 bytes);
4: len 13; hex 3f3f3f3f3f3f3f3f3f3f3f3f3f; asc ?????????????;;
5: len 11; hex 6368656e63686f6e677975; asc chenchongyu;;
6: len 8; hex 8000000000000004; asc ;;
7: len 8; hex 8000000000015f56; asc _V;;
8: len 5; hex 999e1cfdad; asc ;;
9: len 1; hex 01; asc ;;
2017-12-01T04:12:43.712251Z 6 [Note] InnoDB: *** (2) TRANSACTION:
TRANSACTION 125408, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 6, OS thread handle 123145570582528, query id 4904 localhost 127.0.0.1 root updating
update config set name = 'bts_driver_list_filter_gray_onceagain_list_filter_tw_control_group', description = '?????????????', namespace_id = 4, current_version = 89947, create_time = '2017-11-14 15:54:45', created_by = 'chenchongyu' where id = 982
2017-12-01T04:12:43.712308Z 6 [Note] InnoDB: *** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 672 page no 11 n bits 216 index PRIMARY of table `apollo_config_dev`.`config` trx id 125408 lock mode S locks rec but not gap
Record lock, heap no 97 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
0: len 8; hex 80000000000003d6; asc ;;
1: len 6; hex 00000001e9da; asc ;;
2: len 7; hex 24000001830584; asc $ ;;
3: len 30; hex 6274735f6472697665725f6c6973745f66696c7465725f677261795f6f6e; asc bts_driver_list_filter_gray_on; (total 66 bytes);
4: len 13; hex 3f3f3f3f3f3f3f3f3f3f3f3f3f; asc ?????????????;;
5: len 11; hex 6368656e63686f6e677975; asc chenchongyu;;
6: len 8; hex 8000000000000004; asc ;;
7: len 8; hex 8000000000015f56; asc _V;;
8: len 5; hex 999e1cfdad; asc ;;
9: len 1; hex 01; asc ;;
2017-12-01T04:12:43.713122Z 6 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 672 page no 11 n bits 216 index PRIMARY of table `apollo_config_dev`.`config` trx id 125408 lock_mode X locks rec but not gap waiting
Record lock, heap no 97 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
0: len 8; hex 80000000000003d6; asc ;;
1: len 6; hex 00000001e9da; asc ;;
2: len 7; hex 24000001830584; asc $ ;;
3: len 30; hex 6274735f6472697665725f6c6973745f66696c7465725f677261795f6f6e; asc bts_driver_list_filter_gray_on; (total 66 bytes);
4: len 13; hex 3f3f3f3f3f3f3f3f3f3f3f3f3f; asc ?????????????;;
5: len 11; hex 6368656e63686f6e677975; asc chenchongyu;;
6: len 8; hex 8000000000000004; asc ;;
7: len 8; hex 8000000000015f56; asc _V;;
8: len 5; hex 999e1cfdad; asc ;;
9: len 1; hex 01; asc ;;
2017-12-01T04:12:43.714133Z 6 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (2)
简化业务流程代码(code)
#Transaction
public void service(){
Config config = configMapper.selectByPrimaryKey(configId)
ConfigVersion configVersion = toConfigVersion(config, configDTO)
configVersionMapper.insert(configVersion)
config.setCurrentVersion(configVersion.id)
config.setDescription(configDTO.description)
configMapper.updateByPrimaryKey(config)
wait for service C http response
}
sql of the code
insert into config_version (config_id, name, create_time, namespace_id, type, status,base_version_id, value, created_by, enable_from, description)
values
( #{configId,jdbcType=BIGINT},
#{name,jdbcType=VARCHAR}, now(),
#{namespaceId,jdbcType=BIGINT}, #{type,jdbcType=TINYINT},
#{status,jdbcType=TINYINT},
#{baseVersionId,jdbcType=BIGINT}, #{value,jdbcType=LONGVARCHAR}, #{createdBy,jdbcType=VARCHAR},
#{enableFrom,jdbcType=TIMESTAMP},#{description,jdbcType=VARCHAR})
update config set
name = #{name,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
namespace_id = #{namespaceId,jdbcType=BIGINT},
current_version = #{currentVersion,jdbcType=BIGINT},
create_time = #{createTime,jdbcType=TIMESTAMP},
created_by = #{createdBy,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
业务场景(service invoke order)
服务A 调用服务B 更新 config version,服务B 将更新内容持久化到mysql 以后会调用服务C,等待服务C返回以后,服务B再返回给服务A
如果服务A 一定时间内没有接受到服务B返回,那么服务A 会重试,重新向服务A 发起一个请求
(service A -> A, service B -> B, service C ->C;
A invoke B, to update config_version,B persist to mysql, and then invoke C,after C returned, B return to A.
A will retry if B did not return;
)
解决办法(solution)
去掉config_version 对config的外键依赖(remove the foreign key)
CONSTRAINT `fk_config_version_config_1` FOREIGN KEY (`config_id`) REFERENCES `config` (`id`)
Question
但是没明白mysql insert 和update 时需要获取什么锁,所以没明白这里产生死锁的原因。
(the reason why deadlock happened, which kind of lock get in a tx)
软件版本信息(mysql info)
sql
mysql 版本信息
mysql: stable 5.7.20