[英]How to isolate transactions with hibernate
我已經閱讀了有關isolation levels
的hibernate
文檔,並在使用PostgreSql
的示例中嘗試了它們,以檢查在並發執行同一數據集上的事務時它們是否保證線程安全。 我使用最強的isolation level
,將Serializable
用作:
<property name="hibernate.connection.isolation">8</property>
這段代碼是:
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0, 20).forEach(t -> {
service.submit(() -> {
updateSalary(2L);
});
});
static void updateSalary(long id) {
Session s = sessionFactory.openSession();
org.hibernate.Transaction tx = null;
try {
tx = s.beginTransaction();
Customer c = (Customer) s.load(Customer.class, id);
c.setSalary(c.getSalary() + 10);
tx.commit();
}
catch(Exception e) {
e.printStackTrace();
tx.rollback();
}
finally {
s.close();
}
}
但是會引發異常:
org.postgresql.util.PSQLException: ERROR: could not serialize access due to concurrent update
如果我使用ReentrantLock
同步方法updateSalary()
:
static void updateSalary(long id) {
lock.lock();
Session s = sessionFactory.openSession();
org.hibernate.Transaction tx = null;
try {
tx = s.beginTransaction();
Customer c = (Customer) s.load(Customer.class, id);
c.setSalary(c.getSalary() + 10);
tx.commit();
}
catch(Exception e) {
e.printStackTrace();
tx.rollback();
}
finally {
s.close();
}
lock.unlock();
}
它有效並且線程安全。 這是在休眠事務中實現線程安全的適當方法嗎? 如果沒有,推薦的方法是什么? 在這種情況下,如何使用Session.buildLockRequest()
實現線程安全?
事務並非旨在使程序具有線程安全性。 它們用於保證對數據庫所做的一組更改是完全應用或根本不應用,包括確保您已讀取的數據在事務期間沒有更改。
您所看到的行為是完全可以預期的。 數據庫檢測到並發更新,並引發異常通知您,因此您可以采取適當的措施(例如重試,或通知用戶數據可能已更改)。
正如john16384回答的那樣,事務旨在確保一組語句是否一起執行。
我不會鎖定關鍵方法,因為它將影響性能和可伸縮性。 我將讓方法並發執行,但是使用Hibernates VERSION列來確定數據在獲取后是否已更新。 您可以使用Hibernate VERSION列方法找到大量材料。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.