[英]Transaction Isolation Level
我将尝试在 JPA 事务隔离级别中描述我的问题。
数据库结构:
Table1
1 -> PK 定义为日期('ddMMyyyy')Table2
-> 使用 FK 到表 1 JPA(隔离级别:: read_commited
)-代码:
Query query = em.createQuery("from Table1 trd where trd.id = :d");
query.setParameter("d", date);
Table1 t = null;
try{
t = (Table1) query.getSingleResult();
}catch(javax.persistence.NoResultException e){
t = null;
}
if(t==null){
t=new Table1 (date);
em.persist(trd);
}
for(Table2 q:tables2){
q.setTable1(t);
em.merge(q);
}
所以程序检查记录是否存在于数据库中,如果不存在则创建新记录。 如果系统仅基于一个线程,则方法是完全正确的。 否则可能会出现这样的情况:
他们都认为这样的记录还没有,所以添加一个新的。 在提交交易之前一切正常。 第一个将毫无例外地提交,购买第二个与主键重复相关的异常。
除了将隔离级别更改为SERIALIZABLE
之外,是否有可能保留这种情况?
是的,一般隔离级别 = SERIALIZABLE 应该可以解决您的问题。 将隔离级别更改为最严格的选项时,不要低估副作用。 它可能会影响数据库利用率以及请求吞吐量。 也许您可以在创建 T1 后显式提交您的 TRX,然后打开另一个 TRX:EntityManager.getTransaction().commit()
您仍然必须捕获重复键异常。
这是高度并发环境中数据库最难解决的问题之一。 最后,您唯一真正的解决方案是捕获异常并适当地处理它。
根据您提供的代码,很难判断这可能是什么。 如果这是一个 web 应用程序,您很可能希望捕获重复键异常并向最终用户显示一些有用的消息。 例如“此记录已创建”,或类似的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.