发生时间:2022年8月10日 19:17:57
| 事务 1 | 事务 2(已回滚) | |
|---|---|---|
| Session ID | 727939584 | 727941241 |
| Thread id | 6231422 | 6231449 |
| 请求类型 | update | update |
| 事务ID | 133197651 | 133197662 |
| 涉及表 | dev.t_table | dev.t_table |
| 等待锁 | index PRIMARY of table dev.t_table trx id 133197651 lock_mode X locks gap before rec insert intention waiting | index PRIMARY of table dev.t_table trx id 133197662 lock_mode X locks gap before rec insert intention waiting |
| 等待锁索引名 | PRIMARY | PRIMARY |
| 等待锁类型 | X locks gap before rec insert intention waiting | X locks gap before rec insert intention waiting |
| 持有锁 | index PRIMARY of table dev.t_table trx id 133197651 lock mode S locks gap before rec | index PRIMARY of table dev.t_table trx id 133197662 lock mode S locks gap before rec |
| 持有锁索引名 | PRIMARY | PRIMARY |
| 持有锁类型 | S locks gap before rec | S locks gap before rec |
| 事务SQL | INSERT INTO dev.t_table ( id,create_time ) VALUES('AC1881EE00064CD1716D41DD1D7A3795', '2022-09-13 19:17:22.788') | INSERT INTO dev.t_table ( id,create_time ) VALUES('AC1881EE00064CD1716D41DD1D7A3795', '2022-09-13 19:17:40.352') |
表作用:是为了防止重复消费的,一条消息发到mq,消费者这边有可能会消费多次这条消息,消费前,用messageId做主键往这张表中插入,如果插入成功,说明这条消息没有被消费,就开始消费,如果没插入成功,说明之前消费过,就不会再消费了。
分析死锁原因:
- MQ发了两次, 两个相同的消息ID
- 第一个没提交,长时间没消费成功,事务回滚,消费失败,返回消息给mq服务端,短时间内会再次拉取这条消息消费,也就是重试了
- 第一个没有执行完事务, 第二个重试的都已经来了
- 二十几秒,第一个事务还没提交
- 插入t_unique_message,之后的事务执行时间太久,导致锁释放不掉
- mq的messageId,就是一种uuid,就是看起来有点顺序而已,也是不重复的字符串
- 该锁是独占锁(X):独占锁:指该锁一次只能被一个线程所持有。对于ReentrantLock和Synchronized而言都是独占锁。共享锁:该锁可以被多个线程所持有。对于ReentrantReadWriteLock来说,其读锁是共享锁,写锁是独占锁。读锁的共享锁可保证并发读是非常高效的,读写,写读,读读的过程是互斥的。