在循环中插入MySql数据库而不发生死锁
我使用nodejs(AdonisJs)创建一个脚本来更新我的数据库(Mysql)。大概是这样的:在循环中插入MySql数据库而不发生死锁,mysql,node.js,async-await,transactions,deadlock,Mysql,Node.js,Async Await,Transactions,Deadlock,我使用nodejs(AdonisJs)创建一个脚本来更新我的数据库(Mysql)。大概是这样的: const trx = await Database.beginTransaction(); try { const async = use('async'); await async.eachOfLimit(arr, 50, async item => { `select * from table1 where id = 1 LOCK IN SHARE MO
const trx = await Database.beginTransaction();
try {
const async = use('async');
await async.eachOfLimit(arr, 50, async item => {
`select * from table1 where id = 1 LOCK IN SHARE MODE`
`insert into ....`
`another query...`
});
trx.commit();
} catch (err) {
trx.rollback();
}
问题是eachOfLimit
并行运行查询,所以上面的代码抛出错误:在尝试获取锁时发现死锁;尝试重新启动事务
。如果我使用同步循环的for运行它,它工作正常。
如何修复此问题或我的脚本的任何想法。对不起,我的英语不好
顺便说一句,我使用LOCK IN SHARE MODE
或FOR UPDATE
来避免在运行许多查询INSERT
时出现重复,即使我使用findOrCreate
来检查行是否存在您可以尝试使用“FOR UPDATE”而不是“LOCK IN SHARE MODE”来防止对同一行进行锁定
从
选择。。。锁定共享模式
在读取的任何行上设置共享模式锁。其他会话可以读取行,但在事务提交之前无法修改它们。如果这些行中的任何一行被另一个尚未提交的事务更改,则查询将等待该事务结束,然后使用最新的值
选择。。。更新
对于搜索遇到的索引记录,锁定行和任何关联的索引项,就像为这些行发出UPDATE语句一样。其他事务被阻止更新这些行,无法执行选择。。。锁定在共享模式下,或从某些事务隔离级别读取数据。一致读取忽略在读取视图中存在的记录上设置的任何锁。(记录的旧版本无法锁定;它们是通过在记录的内存副本上应用撤消日志重建的。)我找到了一个临时解决方案:使用
插入忽略而不是插入。
因此,我删除了选择
查询并使用插入忽略
const language = await Database.raw(trx('languages').insert({
...languageItem,
created_at: this.getTimeNow(),
updated_at: this.getTimeNow()
}).toString().replace('insert', 'INSERT IGNORE'));
我的脚本运行时没有死锁。我已经尝试了更新,仍然是相同的错误。我认为这里的问题是eachOfLimit
同时运行多个查询SELECT
,所以它们锁定同一行。