问题
Lock wait timeout exceeded; try restarting transaction
详细异常
UPDATE `rbac_user` t SET t.`login_count` = 0, `pwd_expire_day` = 90, `last_login_time` = TIMESTAMP '2024-10-25 10:39:08.000', `status` = '0', `update_user` = 'rbac_user_superuser', `update_date` = TIMESTAMP '2024-10-25 10:39:08.625' WHERE t.id IN ('03xqnu2hykkzt')
2024-10-25 10:39:18.685 [pool-8-thread-1] ERROR c.s.snest.engine.db.relationdb.RelationDBAccessor -数据源:main,执行SQL失败:Lock wait timeout exceeded; try restarting transaction
长事物导致更改rbac_user表的数据锁超时,事物没有结束所以拿不到锁。
经过排查到一段业务比较特殊,是批量插入,并且有可能导致长事物,并且会行锁rbac_user表
REPLACE INTO test_user (id, name, age, `password`, create_user, create_date, update_user, update_date) SELECT d.id, d.name, d.age, d.tenant_id, u1.name , d.create_date, u2.name, d.update_date FROM edo_user d, rbac_user u1, rbac_user u2 WHERE u1.id = d.create_user AND u2.id = d.update_user
待投批次数据统计定时任务出现异常:
解决方案
————-chat GPT ——-
是的,REPLACE INTO 语句在 MySQL 中确实可能导致死锁,尤其是在高并发环境下。以下是一些导致死锁的常见原因和解决方案:
死锁原因 唯一键冲突:REPLACE INTO 操作会尝试插入新记录,如果发现唯一键冲突,则会删除旧记录并插入新记录。这一过程中涉及到多个锁操作,可能会导致死锁 。 锁的类型和顺序:REPLACE INTO 操作需要获取多个锁,包括行锁、间隙锁和插入意向锁。在高并发环境下,不同事务获取锁的顺序不同,可能导致死锁 。 锁等待:当一个事务持有锁并等待另一个事务释放锁,而另一个事务也在等待第一个事务释放锁时,就会发生死锁 。 解决方案 使用 INSERT … ON DUPLICATE KEY UPDATE:这种方式在处理唯一键冲突时,只会更新现有记录,而不会删除再插入,减少了锁操作的复杂性 。
sql
INSERT INTO table_name (column1, column2)
VALUES (value1, value2)
ON DUPLICATE KEY UPDATE column2 = value2;