一條合法的 SQL 執行時,對應資料庫的一個「資料狀態」。此狀態定義為:截至該執行時刻,沒有任何語句層級操作正在併發執行。換句話說,實際上正在併發的多條語句,可以假定在該語句之後執行。
強調「語句層級」是因為一個交易可能包含多條 SQL。若交易已執行前幾條、正執行第 N 條,不能簡單認為前幾條「還沒發生」——這取決於隔離等級。但在語句層級上,可以視為序列化執行。
PL/SQL 在獨立的 PL/SQL 引擎中執行,引擎解析程式碼並不斷向 Oracle 發送 SQL。這與 Java 應用透過 JDBC 在同一 Session 中發送多條 SQL 本質無異。因此,Oracle 對併發與恢復的管理機制完全一致,無特殊差異。
Oracle 使用鎖控制併發。執行語句時,根據語句語意與隔離等級解析所需鎖類型與釋放時機。隔離等級越高,佔用鎖資源越多,死鎖機率越大。
交易的 SQL 是分批發送給 Oracle,資料庫無法在交易開始時一次解析所有需要的鎖與釋放時機,無法統一排程。若無交易概念(單語句自動提交),Oracle 解析時已知所有鎖,若無法一次取得則等待,完全不會產生死鎖。
若能在交易開始時將所有可能執行的 SQL 交給 Oracle,資料庫可預先鎖定資源。但業務邏輯中常夾雜非 DB 操作,且條件分支導致實際執行路徑不確定,會造成鎖資源浪費、降低併發度。
允許幻讀(Read Committed)等較低隔離等級的存在,本質是在「應用自行控制併發的複雜度」與「資料庫併發吞吐量」之間的權衡。若應用不想自管併發、又想要高併發,必須在隔離等級上做取捨。
理解 Oracle 併發控制的核心在於「語句層級序列化」與「交易分批送達的鎖無法預知」,死鎖是交易機制的必然代價。解決之道不外乎:提升應用層協調能力或接受資料庫層面的犧牲與重試。