如往常一样下班准备6点准时跑路,刚回到家准备躺着刷无脑短视频。霸道总裁爱上我之类的爽文男主角。突然电话一直响个不停,公司那头炸雷了,要求我立马赶回公司处理问题。表现现象是所有的用户登录不见了,直接登录报错。
直接先连vpn连上公司网络,打开k8s容器查看日志发现,大量的数据库死锁日志,第一想法就是先杀掉死锁的连接。发现根本行不通。
报错日志如下
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
观察报错日志文件我们可以看到
Lock wait timeout exceeded; try restarting transaction
登录用户直接报错,锁事物超时。
- 首先第一想到的是是不是并发登录,导致长事物了。因为登录的时候会修改修改用户登录时间
编辑
直接 100 线程开测。但是服务器容器日志中并没有发现事物死锁问题。
经过排查mysql 连接工具看到一条业务 sql很是奇怪
String sql="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";
replace into
————-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;