☰
Current Page
Main Menu
Home
Home
Editing
关于锁超时问题排查
Edit
Preview
h1
h2
h3
default
Set your preferred keybinding
default
vim
emacs
markdown
Set this page's format to
AsciiDoc
Creole
Markdown
MediaWiki
Org-mode
Plain Text
RDoc
Textile
Rendering unavailable for
BibTeX
Pod
reStructuredText
Help 1
Help 1
Help 1
Help 2
Help 3
Help 4
Help 5
Help 6
Help 7
Help 8
Autosaved text is available. Click the button to restore it.
Restore Text
## 排查问题 ``` 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 ``` 示例代码 ``` /** * 创建用户服务 * * @param user * @throws InterruptedException */ @MethodService(description = "创建用户") public void createUser() throws InterruptedException { String sql="replace\r\n" + "into\r\n" + " test_user (\r\n" + "id,\r\n" + " name,\r\n" + " age,\r\n" + " `password`,\r\n" + " create_user,\r\n" + " create_date,\r\n" + " update_user,\r\n" + " update_date\r\n" + ")\r\n" + "select\r\n" + " d.id,\r\n" + " d.name,\r\n" + " d.age,\r\n" + " d.tenant_id,\r\n" + " u1.name,\r\n" + " d.create_date,\r\n" + " u2.name,\r\n" + " d.update_date\r\n" + "from\r\n" + " edo_user d,\r\n" + " rbac_user u1,\r\n" + " rbac_user u2\r\n" + "where\r\n" + " u1.id = d.create_user\r\n" + " and u2.id = d.update_user"; BussModelDataAccess bussModelDataAccess = (BussModelDataAccess) ModelDataAccessFactory.getDataAccess(ModelTypeEnum.Buss); RelationDBAccessor dataAccessor = bussModelDataAccess.getRelationDBAccessor(); dataAccessor.execute(sql); // // TestUser user=new TestUser(); // user.setId("10000"); // user.setName(System.currentTimeMillis()+""); // user.setAge(32); // user.setEmail(System.currentTimeMillis()+"@qq.com"); // user.setPassword("123456"); // user.create(); TestUser testUser = super.selectById("10000"); if (testUser != null) { testUser.setEmail("cdchencw@120.com"); testUser.setAge(5); testUser.update(); } TestRole role = new TestRole(); role.setRoleName("test"); role.set("remark", "测试"); role.create(); Thread.sleep(11000); System.out.println("执行完毕: #0001"); } ``` 长事物导致更改rbac_user表的数据锁超时,事物没有结束所以拿不到锁。 经过排查到一段业务比较特殊,是REPLACE INTO,并且有可能导致长事物,并且会行锁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; ```
Uploading file...
Sidebar
[[_TOC_]]
Edit message:
Cancel