数据库在数据导入时的并发问题(使用myBatis)

我有一个批量导入数据到数据库中的程序,代码主要做2件事情.

1.首先检查数据库中有无重复记录.如果有则返回false,不进行导入操纵.

2.没有重复数据,则导入这批数据.

现在我有这样一个疑问,当我做完检查的时候,系统发现没有重复,于是执行下面的导入操作.

可当我还没提交这批数据时,另一个系统修改了数据库,导致出现重复记录,也就是说出现了数据不一致的问题.

明明在检查的时候没有重复,可在提交的时候出现重复.象这种问题应该怎么解决,或者此类问题的解决思路是怎样的?

是在检查数据有无重复时就锁住整张表?如果要锁表,myBatis里应该怎么做呢?

4个回答

  1. 行锁只能针对已经存在的记录,对于insert数据来说,行锁是无效的;
  2. 表锁是可以的,但是操作太重了,效率会很低;

建议使用如下两种方式之一:

  1. 如果记录本身有主键类的标识的话,将这个字段的唯一性设置为True,这样两线程的insert相同记录就会有一个导致失败,Catch这个Exception就可以了,这个方法比较简单;

  2. 使用分布式锁,如果题主对Zookpeeper有了解的话可以通过Zookeeper设置加一个分布式锁(比如使用insert的主键标识拼接成为一个path,在insert之前获取锁,insert之后释放锁)

前提是需要有能够设别两条记录是同一条记录的手段。

select for update 可以锁住那一行

或者你多加一个正在导入的状态是最好的

典型的事物隔离级别的问题

将Connection的隔离级别设置为 "不可重复读"

connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ)即可

conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_REA)

1查询数据库的状态 //查询的时候会帮当前数据行锁住

2批量保存

conn.close()

s_help
s_help 基本搞清楚了,谢谢你的启发,以前有这方面的积累,翻书找到了答案。
接近 7 年之前 回复
s_help
s_help 好像隔离级别应该是不允许幻读,比不可重复读更高一级,不可重复读是原来的数据被修改导致两次读取不一致,幻读是新增加了数据导致两次读取不一致,前者需要行级锁,而幻读则需要表级锁。看来导数据的确影响系统性能啊,导数据的事务期间需要把整个表都锁起来。
接近 7 年之前 回复
s_help
s_help 对隔离级别有一些认识,现在的纠结是,这个隔离级别,能保证不被插入新行么.也就是说行不被修改,我能理解,然后他还能保证行不被添加?是这样么?一直在这个插入新行上无法突破心中的纠结,一直觉得要用锁住整表的那个隔离级别。
接近 7 年之前 回复

第一个答案很好,解释的很到位。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问