最近项目中出现了死锁的问题,临时在现场帮忙解决
现场mysql采用主从架构,服务代码3台机器
查询mysql查看死锁信息:
2021-03-19 12:46:24 0xfff769b3f1e0
*** (1) TRANSACTION:
TRANSACTION 285798543, ACTIVE 0 sec updating or deleting
mysql tables in use 1, locked 1
LOCK WAIT 7 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 8
MySQL thread id 953886, OS thread handle 281472129626592, query id 185465723 bd-zw-25 13.114.15.25 root update
replace into traffic_flow_cross_turn_hours_num (cross_id, direction, turn, date, start_time, num) values ( '86204428361203434', '3', '1', '2021-03-19', '120000', 336 ) , ( '86204428361203434', '3', '2', '2021-03-19', '120000', 81 ) , ( '86204428361203434', '5', '1', '2021-03-19', '120000', 621 ) , ( '86204428361203434', '5', '2', '2021-03-19', '120000', 165 ) , ( '86204428361203434', '7', '1', '2021-03-19', '120000', 417 ) , ( '86204428361203434', '7', '2', '2021-03-19', '120000', 91 )
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 280 page no 452 n bits 280 index PRIMARY of table `traffic_analysis`.`traffic_flow_cross_turn_hours_num` trx id 285798543 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;*** (2) TRANSACTION:
TRANSACTION 285798544, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
9 lock struct(s), heap size 1136, 7 row lock(s), undo log entries 9
MySQL thread id 954617, OS thread handle 281438095405536, query id 185465722 bd-zw-26 13.114.15.26 root update
replace into traffic_flow_cross_turn_hours_num (cross_id, direction, turn, date, start_time, num) values ( '1390515961993707490', '1', '1', '2021-03-19', '120000', 684 ) , ( '1390515961993707490', '1', '2', '2021-03-19', '120000', 177 ) , ( '1390515961993707490', '3', '1', '2021-03-19', '120000', 149 ) , ( '1390515961993707490', '3', '2', '2021-03-19', '120000', 184 ) , ( '1390515961993707490', '7', '1', '2021-03-19', '120000', 378 ) , ( '1390515961993707490', '7', '2', '2021-03-19', '120000', 102 )
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 280 page no 452 n bits 280 index PRIMARY of table `traffic_analysis`.`traffic_flow_cross_turn_hours_num` trx id 285798544 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;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 280 page no 452 n bits 280 index PRIMARY of table `traffic_analysis`.`traffic_flow_cross_turn_hours_num` trx id 285798544 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;*** WE ROLL BACK TRANSACTION (1)
之后查看代码,方法是同步的事物,一个机器一次只能有一个MQ消息进行消费
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
synchronized public void getKafkaCrossFlowData (CrossMsg msg) {
}
代码中加了分布式锁如下:
try {
if (execute()) {
redisTemplate.opsForValue().set(REDIS_KEY, "execute", 5, TimeUnit.SECONDS);
}
// 路口级别数据同步
// 道路级别同步
//eg:
f (!CollectionUtils.isEmpty(maps)) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i< maps.size(); i++) {
sb.append(" ( ?, ?, ?, ?, ?, ? ) , ");
}
// 去掉最后一个逗号
String strSql = sb.toString().substring(0, sb.toString().trim().length() - 1);
Query query = entityManager.createNativeQuery(" replace into " +
" cross_turn_hours_num (cross_id, direction, turn, date, start_time, num) " +
" values " + strSql + ";");
int index = 1;
for (int j = 0; j < maps.size(); j++) {
query.setParameter(index++, crossingId);
query.setParameter(index++, maps.get(j).get("direction"));
query.setParameter(index++, maps.get(j).get("turn"));
query.setParameter(index++, timeAry[0]);
query.setParameter(index++, hour);
query.setParameter(index++, maps.get(j).get("num"));
}
query.executeUpdate();
}
} catch (Exception e) {
Map map = new HashMap();
map.put("exception", e);
trafficSonLog.error(false, "cross_flow_data_is_error", map, null);
} finally {
redisTemplate.delete(REDIS_KEY);
}
// 是否正在执行入库操作
private boolean execute() {
while (redisTemplate.hasKey(REDIS_KEY)) {
}
return true;
}
如上面执行数据库操作是进行replace into 操作,同时数据库加了主键索引,唯一索引和普通索引
CREATE TABLE `cross_turn_hours_num` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`cross_id` varchar(50) NOT NULL COMMENT '路口id',
`direction` varchar(10) NOT NULL COMMENT '方向',
`turn` varchar(10) NOT NULL COMMENT '转向',
`date` date NOT NULL,
`start_time` time NOT NULL,
`num` int(11) DEFAULT NULL,
`created_by` varchar(255) DEFAULT NULL,
`created_date` datetime DEFAULT CURRENT_TIMESTAMP,
`last_modified_by` varchar(255) DEFAULT NULL,
`last_modified_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `INDEX_DATE` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
初步修改是怀疑replace into 一次执行多次操作导致,后调整代码为一次执行单条语句:
if (!CollectionUtils.isEmpty(maps)) {
for (int i = 0; i< maps.size(); i++) {
Query query = entityManager.createNativeQuery(" replace into " +
" traffic_flow_cross_turn_hours_num (cross_id, direction, turn, date, start_time, num) " +
" values ( ?, ?, ?, ?, ?, ? ) ;");
int index = 1;
query.setParameter(index++, crossingId);
query.setParameter(index++, maps.get(i).get("direction"));
query.setParameter(index++, maps.get(i).get("turn"));
query.setParameter(index++, timeAry[0]);
query.setParameter(index++, hour);
query.setParameter(index++, maps.get(i).get("num"));
query.executeUpdate();
}
}
当天发现没有继续报死锁了,但是之后第三天又开始出现死锁了:
=====================================
2021-03-21 11:00:00 0xffff56acf1e0 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 52 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 1260499 srv_active, 0 srv_shutdown, 562720 srv_idle
srv_master_thread log flush and writes: 1823219
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 380940313
OS WAIT ARRAY INFO: signal count 256155235
RW-shared spins 0, rounds 491314388, OS waits 255496279
RW-excl spins 0, rounds 2697011021, OS waits 84376581
RW-sx spins 907101, rounds 26122335, OS waits 823576
Spin rounds per wait: 491314388.00 RW-shared, 2697011021.00 RW-excl, 28.80 RW-sx
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2021-03-17 22:02:56 0xfff769d1f1e0 Transaction:
TRANSACTION 284513244, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1
MySQL thread id 861867, OS thread handle 281438097371616, query id 163560981 bd-zw-25 13.114.15.25 root update
insert into traffic_line_segment (del, segment_type, seq, line_id, segment_id) values (0, 'forward', 0, 'artery_0114_16118871173239', 'RS_0114_NB1562157626_NB1521890492_1')
Foreign key constraint fails for table `boss`.`traffic_line_segment`:
,
CONSTRAINT `FKaxrefjp8489179c5wt29awvwe` FOREIGN KEY (`segment_id`) REFERENCES `traffic_segment` (`id`)
Trying to add in child table, in index FKaxrefjp8489179c5wt29awvwe tuple:
DATA TUPLE: 2 fields;
0: len 35; hex 52535f303131345f4e42313536323135373632365f4e42313532313839303439325f31; asc RS_0114_NB1562157626_NB1521890492_1;;
1: len 6; hex 000000013f19; asc ? ;;But in parent table `boss`.`traffic_segment`, in index PRIMARY,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 20; compact format; info bits 0
0: len 7; hex 342d395f342d38; asc 4-9_4-8;;
1: len 6; hex 00000570b231; asc p 1;;
2: len 7; hex 23000002ab1c02; asc # ;;
3: SQL NULL;
4: len 5; hex 99a6faeed5; asc ;;
5: SQL NULL;
6: len 5; hex 99a760852a; asc ` *;;
7: len 19; hex 38343738373935303635303534373733303436; asc 8478795065054773046;;
8: len 8; hex 0000000000f07640; asc v@;;
9: len 30; hex e887aae4b89ce9a38ee8b7afe88eb2e6b1a0e5a4a7e8a197e4baa4e58f89; asc ; (total 66 bytes);
10: len 19; hex 31393637323933373139393531313936333434; asc 1967293719951196344;;
11: len 4; hex 80000001; asc ;;
12: len 4; hex 80000000; asc ;;
13: len 30; hex 7b226c6f6e676974756465223a3131352e3439363435352c226c61746974; asc {"longitude":115.496455,"latit; (total 45 bytes);
14: len 30; hex e4b89ce9a38ee8b7afe88eb2e6b1a0e5a4a7e8a197e4baa4e58f89e58fa3; asc ; (total 69 bytes);
15: len 30; hex 5b7b226c61746974756465223a33382e3836363033342c226c6f6e676974; asc [{"latitude":38.866034,"longit; (total 276 bytes);
16: len 1; hex 00; asc ;;
17: len 4; hex 80000003; asc ;;
18: len 23; hex 383437383739353036353035343737333034365f315f31; asc 8478795065054773046_1_1;;
19: len 23; hex 313936373239333731393935313139363334345f335f32; asc 1967293719951196344_3_2;;------------------------
LATEST DETECTED DEADLOCK
------------------------
2021-03-20 00:02:58 0xfffa3697f1e0
*** (1) TRANSACTION:
TRANSACTION 286226066, ACTIVE 1 sec updating or deleting
mysql tables in use 1, locked 1
LOCK WAIT 7 lock struct(s), heap size 1136, 5 row lock(s), undo log entries 1
MySQL thread id 988363, OS thread handle 281450111037920, query id 199669537 bd-zw-26 13.114.15.26 root update
replace into traffic_flow_road_days_num ( road_id, date, num ) values ('1-2-朝阳南大街|清苑区|1', '2021-03-19', 36825)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 291 page no 26 n bits 160 index PRIMARY of table `traffic_analysis`.`traffic_flow_road_days_num` trx id 286226066 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;*** (2) TRANSACTION:
TRANSACTION 286226078, ACTIVE 1 sec updating or deleting
mysql tables in use 1, locked 1
6 lock struct(s), heap size 1136, 5 row lock(s), undo log entries 1
MySQL thread id 988423, OS thread handle 281450122834400, query id 199669683 bd-zw-27 13.114.15.27 root update
replace into road_days_num ( road_id, date, num ) values ('1-2-七一西路P38754429431', '2021-03-19', 170875)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 291 page no 26 n bits 160 index PRIMARY of table `road_days_num` trx id 286226078 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;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 291 page no 26 n bits 160 index PRIMARY of table `road_days_num` trx id 286226078 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;*** WE ROLL BACK TRANSACTION (2)
------------
TRANSACTIONS
------------
Trx id counter 287478335
Purge done for trx's n:o < 287478242 undo n:o < 0 state: running but idle
History list length 84
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 562948130720112, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130719192, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130718272, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130717352, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130715512, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130684232, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130683312, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130679632, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130713672, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130712752, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130702632, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130700792, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130692512, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130699872, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130691592, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130695272, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130694352, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130688832, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130685152, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130686992, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130678712, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130707232, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130681472, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130693432, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130689752, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130677792, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130708152, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130704472, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130673192, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130696192, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130680552, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130710912, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130716432, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130709992, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130687912, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130690672, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130711832, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130709072, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130706312, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130703552, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130701712, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130675952, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130674112, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130670432, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130675032, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130671352, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130672272, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130705392, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130686072, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130676872, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130698952, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130698032, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 562948130721952, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
891637096 OS file reads, 65263476 OS file writes, 21360026 OS fsyncs
258.26 reads/s, 16384 avg bytes/read, 22.42 writes/s, 10.21 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 2900, seg size 2902, 3008067 merges
merged operations:
insert 5301255, delete mark 5882997, delete 1393808
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 5 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 5 buffer(s)
Hash table size 34679, node heap has 6 buffer(s)
Hash table size 34679, node heap has 3 buffer(s)
Hash table size 34679, node heap has 3 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 131 buffer(s)
6466.91 hash searches/s, 1488.82 non-hash searches/s
---
LOG
---
Log sequence number 475105098027
Log flushed up to 475105098010
Pages flushed up to 475104827027
Last checkpoint at 475104826859
0 pending log flushes, 0 pending chkp writes
13514965 log i/o's done, 6.71 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 1424281
Buffer pool size 8192
Free buffers 0
Database pages 8037
Old database pages 2961
Modified db pages 302
Pending reads 1
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 913174029, not young 34075770154
0.00 youngs/s, 0.00 non-youngs/s
Pages read 891644372, created 2152820, written 49261359
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 993 / 1000, young-making rate 5 / 1000 not 308 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 8037, unzip_LRU len: 0
I/O sum[4231]:cur[8924], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
3 read views open inside InnoDB
Process ID=28942, Main thread ID=281472847901152, state: sleeping
Number of rows inserted 61827250, updated 10012981, deleted 7113600, read 45686448636
258.61 inserts/s, 5.54 updates/s, 0.35 deletes/s, 34640.51 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
之后分析感觉这个分布式锁不太好,有可能导致一台redis失效后,两位的2台机器在where循环等待时都同时获取了锁并进入代码执行。(此方法只是从分布式锁方面限制,只让一个事物执行,并没有完全处理数据库死锁)
下面进行了redis分布式锁的优化:
// 是否正在执行入库操作
private boolean execute() {
// 机器错开
try {
Thread.sleep(new Random(400).nextInt() + 100);
}catch (Exception e){
}
while (true) {
Boolean has = redisTemplate.hasKey(REDIS_KEY);
if(!has){
try {
Thread.sleep(new Random(200).nextInt() + 100);
}catch (Exception e){
}
//防止redis锁释放,另外2个机器同时从while循环过来
Integer num = (Integer) redisTemplate.opsForValue().get(REDIS_KEY_ROAD_NUM);
if(num == 0){
break;
}
}
}
return true;
}
try {
if (execute()) {
Integer num = (Integer) redisTemplate.opsForValue().get(REDIS_KEY_ROAD_NUM);
redisTemplate.opsForValue().set(REDIS_KEY_ROAD_NUM, ++num, 5, TimeUnit.SECONDS);
redisTemplate.opsForValue().set(REDIS_KEY, "execute", 5, TimeUnit.SECONDS);
log.info("====当前进程加琐,REDIS_KEY_ROAD_NUM加1操作变为:{}=============",num);
}
// 道路级别数据同步
// 路段数据同步
} catch (Exception e) {
Map map = new HashMap();
map.put("exception", e);
trafficSonLog.error(false, "road_flow_data_is_error", map, null);
} finally {
redisTemplate.delete(REDIS_KEY);
Integer num = (Integer) redisTemplate.opsForValue().get(REDIS_KEY_ROAD_NUM);
redisTemplate.opsForValue().set(REDIS_KEY_ROAD_NUM, --num, 5, TimeUnit.SECONDS);
log.info("====当前进程释放锁,REDIS_KEY_ROAD_NUM减1操作变为:{}=============",num);
}
另外学习了部分mysql相关内容:
注意:replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中, 1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。 2. 否则,直接插入新数据。
要注意的是:插入数据的表必须有主键或者是唯一索引!否则的话,replace into 会直接插入数据,这将导致表中出现重复的数据。
insert的大致加锁流程:
INSERT 加锁流程如下(参考):
首先对插入的间隙加插入意向锁(Insert Intension Locks)
如果该间隙已被加上了 GAP 锁或 Next-Key 锁,则加锁失败进入等待;
如果没有,则加锁成功,表示可以插入;
然后判断插入记录是否有唯一键,如果有,则进行唯一性约束检查
如果不存在相同键值,则完成插入
如果存在相同键值,则判断该键值是否加锁
如果没有锁, 判断该记录是否被标记为删除
如果标记为删除,说明事务已经提交,还没来得及 purge,这时加 S 锁等待;
如果没有标记删除,则报 1062 duplicate key 错误;
如果有锁,说明该记录正在处理(新增、删除或更新),且事务还未提交,加 S 锁等待;
插入记录并对记录加 X 记录锁;
这里的表述其实并不准确,有兴趣的同学可以去阅读 InnoDb 的源码分析 INSERT 语句具体的加锁过程,我在 《读 MySQL 源码再看 INSERT 加锁流程》 这篇博客中有详细的介绍
在此感谢https://www.aneasystone.com/archives/2018/04/solving-dead-locks-four.html 的博主的分享