Oracle 執行單條 SQL 時,基於語句級一致性讀:該語句看到的數據狀態為「啟動時刻已提交的所有事務 + 本事務已執行的前序語句」。語句執行過程中,底層數據塊變更不對該語句可見;語句成功完成前,其寫入不對其他會話可見(除非 READ UNCOMMITTED,Oracle 不支持)。
PL/SQL 引擎解析代碼,將 SQL 發送給 SQL 引擎執行。並發控制與恢復邏輯與 JDBC/ODBC 發送多條 SQL 完全一致,無特殊優待。事務邊界由顯式 COMMIT/ROLLBACK 或宿主環境(如觸發器隱式提交)決定。
根因:Oracle 無法在事務開始時預知全套鎖需求(業務邏輯動態決定),只能隨語句逐步獲取。隔離級別越高(如 SERIALIZABLE),持鎖時間越長,死鎖概率指數級上升。
// 業務邏輯入口
public void transfer(Account from, Account to, BigDecimal amt) {
// 1. 按全局唯一順序獲取分布式鎖 (Redis Redlock / ZK / DB 行鎖 SELECT FOR UPDATE NOWAIT)
String lockKey = "acc:" + (from.id < to.id ? from.id + ":" + to.id : to.id + ":" + from.id);
try (DistributedLock lock = lockManager.acquire(lockKey, 5, TimeUnit.SECONDS)) {
// 2. 開啟數據庫事務 (READ COMMITTED 即可)
tx.begin();
// 3. 執行扣款/入賬 SQL
// 4. 提交
tx.commit();
} catch (LockTimeoutException e) {
throw new BusinessException("系統繁忙,請稍後重試");
}
}
收益:
✅ 消除數據庫層死鎖
✅ 鎖粒度可設計為業務實體 (賬戶、訂單) 而非物理行
✅ 降低數據庫隔離級別 (RC) 減少一致性讀開銷
⚠️ 代價:同步壓力移至應用層,需解決單點、重入、超時、時鐘漂移等分布式鎖難題。
request_id 唯一約束)。| 級別 | 幻讀 | 不可重複讀 | 髒讀 | 鎖開銷 | 適用場景 |
|---|---|---|---|---|---|
| READ COMMITTED (默認) | 允許 | 允許 | 禁止 | 低 | 高併發 OLTP、應用層可容忍/重試 |
| SERIALIZABLE | 禁止 | 禁止 | 禁止 | 極高 | 極少數強一致性報表、批量對賬 |
| READ ONLY | 禁止 | 禁止 | 禁止 | 無鎖 (SCN 掃描) | 長跑查詢、備份、導出 |
Oracle 事務管理通過「語句級原子 + 鎖 + 多版本」實現 ACID。死鎖是分階段獲取鎖的必然副作用。高併發系統的正解不是調優數據庫鎖,而是在應用層設計業務語義鎖,將數據庫降級為「無鎖存儲引擎」。這要求架構師具備分布式系統設計能力,但換來的是線性擴展的吞吐天花板。