MySQL并发插入,为什么会发生以及处理它的最佳方法是什么?

标签 mysql hibernate concurrency insert deadlock

我目前正在维护一些由以前的开发人员编写的处理车辆跟踪的项目。 我发现有时系统会卡住大约一分钟,然后就继续工作,我们已经尝试寻找原因很长时间了。

我可以在 error.log 中看到“超出锁定等待超时;尝试重新启动事务”,并且在发生这种情况时,我总是看到两个类似的查询在 MySQL 中运行:

Insert into idling_events (gps_position_id, vehicle_id) values (23083665777 ,'46881') 

insert into idling_events (gps_position_id, vehicle_id, created_at, updated_at) values (23083665761, null, null, null) 

两个查询始终运行相同的秒数(因此它们同时开始)。一个是由我正在维护的项目执行的,另一个是由正在执行类似工作的遗留项目执行的(但我想这没有任何区别,因为即使查询是从同一项目的不同线程)。

我尝试谷歌,似乎当两个插入到同一个表的同时发生时,mysql可能会死锁。我不明白为什么会变成这样?为什么mysql不将两个查询放入队列中并以随机顺序一一执行?

我们使用的隔离级别是REPEATABLE READ。我在 Stackoverflow 上看到了一些将其更改为 READ COMMITTED 的建议,但我不确定这是否能解决我们的问题,而且据我了解,它也可能会破坏复制。

表的结构如下:

id                bigint(14) unsigned, not null, primary key, auto_increment
gps_position_id   bigint(14) unsigned, not null, key: mul
vehicle_id        int(11), can be null, key: mul
created_at        datetime, can be null
updated_at        datetime, can be null

表正在使用 innodb。 该表中还有 gps_position_index 和vehicle_index。我想知道这个问题是否与我们在表上有索引有关?

我们用来保存空闲事件的方法是GenericHibernateDaoImpl中的save():

@Override
public T save(T item) {
    factory.getCurrentSession().saveOrUpdate(item);
    return item;
}

类 GenericHibernateDaoImpl 有 @Transactional 指令,因此,据我了解,事务在调用 save() 方法之前打开,并在 save() 完成时提交和保存。

遗留项目没有使用Hibernate,它只是使用java.sql.Statement:

    setStatement.execute(FleetManagerSqlHelper.insertIdlingEvent(deviceBinding.getVehicleId(), Long.toString(gpsPositionId)));

处理这种情况的最佳方法是什么?我可以减少 innodb_lock_wait_timeout (目前是 50)并在每次发生时捕获 TimeoutException,重试直到完成工作(我什至看到有人在网上推荐它),但这是正确的方法吗?这种情况也可能发生在其他表上,我猜,这是否意味着我需要重试项目内的所有查询?

我很感激任何建议,因为我没有太多使用 MySQL 的经验,而且我对这种行为感到非常困惑。

非常感谢!

最佳答案

我们已将事务隔离级别更改为 READ-COMMITTED,似乎已经解决了问题

关于MySQL并发插入,为什么会发生以及处理它的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40716303/

相关文章:

java - 如何拯救带 child 的家长?

java - Java中的可变变量

c# - 如何通过C# async/await为同步程序添加并发

java - 新线程的thread.start()方法是否立即返回到当前线程?

java - 单元测试的 Hibernate 覆盖策略

php - MySQL select * 但将 id 数组放在结果的底部

jquery - JSON格式转换

php - 对于我的目的来说,许多表是一种有效的数据库设计吗?

mysql - 将 SQL 链接到 Access,重新查询显示 #Deleted

java - jpa标准错误或放错地方