我们一直在使用MySQL (Server version: 5.6.10 MySQL Community Server)
使用Hibernate作为ORM和Spring进行事务管理。
我们在许多地方使用悲观锁定。但是今天在调试并发问题时,我发现了一个奇怪的问题。如果两个线程试图在同一时刻获取对某一行的悲观锁定,那么它们都能够获得它。以下是获取锁的DAO方法:
@Override
public PurchaseOrder lockOnPurchaseOrder(Integer purchaseOrderId) {
Query query = sessionFactory.getCurrentSession().createQuery("select p from PurchaseOrder p where p.id = :purchaseOrderId);
query.setParameter("purchaseOrderId", purchaseOrderId);
query.setLockMode("p", LockMode.PESSIMISTIC_WRITE);
return (PurchaseOrder) query.uniqueResult();
}
以下是使用该服务的服务的代码段:
@Override
public void doService(int purchaseOrderId) {
purchaseService.lockOnPurchaseOrder(purchaseOrderId); // Problematic line
// If lock is acquired, so something
}
然后我测试了如果一个线程获得了锁,然后其他线程稍后尝试获取它,它会阻止此调用。所以这很好。
但如果两个线程同时执行有问题的行,它们都会获得锁定。我通过启用常规日志来检查mysql日志,正在执行两个select for update
语句。
有人可以帮我吗?