首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2EE

J2EE 事務並發控制策略總結:樂觀鎖、悲觀鎖、離線鎖全景解析與 Hibernate/JPA 實戰映射

     編輯:J2EE

前言:為何必須理解並發控制原理?

持久層框架 (Hibernate/JPA) 已封裝大量細節,但理解底層機制是排查死鎖、失敗重試、數據不一致的前提。本文結合 Hibernate/JPA 標準,系統梳理四大策略。

基石:ANSI SQL 四大隔離級別

隔離級別髒讀不可重複讀幻影讀性能/並發
READ UNCOMMITTED✅ 可能✅ 可能✅ 可能最高/最好
READ COMMITTED (多數 DB 默認)❌✅ 可能✅ 可能高/好
REPEATABLE READ (MySQL 默認)❌❌✅ 可能中/中
SERIALIZABLE❌❌❌最低/最差

工程共識:採用 READ COMMITTED + 應用層並發控制策略,平衡性能與正確性。SERIALIZABLE 視為核選項。

同一事務系統內:樂觀鎖 vs 悲觀鎖

1. 樂觀鎖 —— 相信衝突稀少,衝突則重試

核心邏輯:更新前檢查「讀取後數據是否被修改」,若被修改則拋異常回滾重試。

三種實現路徑

  1. 版本號:實體加 @Version int version,更新時 WHERE version = ?,成功則 version++;推薦;
  2. 時間戳:比較 lastModified,集群時鐘同步風險、高併發可能碰撞;
  3. 全字段比較:Hibernate 髒檢測自動生成 WHERE col1=? AND col2=? ...,字段多時 SQL 膨脹。

JDBC 手寫示範

SELECT version, ... FROM Account WHERE id = ?;
UPDATE Account SET balance=?, version=version+1 WHERE id=? AND version=?;
if (rowsUpdated == 0) throw new OptimisticLockingFailureException();

Hibernate/JPA 註解一鍵啟用

@Entity
public class Account {
    @Id Long id;
    @Version int version;  // 或 @Version Timestamp lastModified
    // ...
}

Hibernate 自動生成帶版本檢查的 SQL,衝突拋 StaleObjectStateException (JPA 為 OptimisticLockException)。

⚠️ 關鍵限制

樂觀鎖不加鎖,故 無法防止不可重複讀 (READ COMMITTED 下)。業務必須容忍「讀取過程中數據被他人修改」的現象。

2. 悲觀鎖 —— 相信衝突頻繁,讀即加鎖

核心邏輯:SELECT ... FOR UPDATE 讀取時加排他鎖,他事務更新/讀取(若也 FOR UPDATE)阻塞至提交/回滾。

JDBC 手寫

SELECT * FROM Account WHERE id = ? FOR UPDATE;

缺點:所有衝突事務必須一致使用 FOR UPDATE,否則失效。

Hibernate API

// 方式 1: 先查後鎖
session.lock(account, LockMode.UPGRADE);        // 或 UPGRADE_NO_WAIT

// 方式 2: 查詢時直接加鎖
session.get(Account.class, id, LockMode.UPGRADE);

Hibernate 內部轉為 SELECT ... FOR UPDATE。JPA 對應 LockModeType.PESSIMISTIC_WRITE。

⚠️ 關鍵限制

悲觀鎖解決不可重複讀,但無法防止幻影讀 (需 SERIALIZABLE)。且長事務持有鎖易導致死鎖、並發度下降。

跨事務/長會話場景:離線鎖

策略核心思想適用場景實現要點
樂觀離線鎖 實體攜帶版本號跨請求傳遞,提交時檢查版本 Web 編輯頁面、長業務流程、用戶思考時間長 表單隱藏域攜帶 version,提交時合併檢查;Hibernate 自動支援脫管實體合併
悲觀離線鎖 編輯開始獲取邏輯鎖 (資料庫鎖表/專用鎖表/Redis 分布式鎖),編輯結束釋放 極高衝突、業務不允許覆蓋、需強一致性 鎖超時機制必備,防止用戶離開不釋放;分布式環境用 Redisson/Redlock

Hibernate/JPA 並發控制最佳實踐清單

  1. 默認選樂觀鎖:@Version 字段覆蓋 90% 場景;
  2. 高衝突熱點數據:評估悲觀鎖 (LockMode.UPGRADE) 或應用層分布式鎖;
  3. 長會話/脫管實體:session.merge() 自動攜帶版本檢查,或手工 DTO 携帶 version;
  4. 避免 SERIALIZABLE:除非極少數強一致場景 (如庫存扣減最後一件);
  5. 死鎖預防:統一加鎖順序、縮短事務邊界、設置 lock_timeout;
  6. 監控指標:樂觀鎖失敗率、悲觀鎖等待時間、死鎖計數。

附錄:原文末尾出現 C++/Java 語言對比片段,屬誤粘內容,已剔除。並發控制無語言邊界,原理通用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved