Spanner 交易提供兩種並行控制模式:悲觀和樂觀。並行控制模式的選擇會影響交易處理同步讀取和寫入作業的方式,進而影響效能、延遲和交易中止率。請選擇最符合應用程式效能和一致性需求的模式。
預設行為取決於交易使用的隔離等級:
悲觀並行控制
根據預設,Spanner 會使用悲觀並行,並採用可序列化隔離。這個模式會假設並行交易可能會爭用相同資料。在交易中讀取或寫入資料時,系統會主動取得資料的鎖定。此外,它也會驗證交易中先前取得的鎖定,是否仍保留在後續陳述式中。Spanner 偵測到鎖定衝突時,會使用「受傷等待」演算法解決衝突。
在悲觀並行中,交易會在交易的執行和提交階段取得資料鎖定。
- 讀取作業:交易讀取資料時,會在執行階段取得共用讀取 (
ReaderShared) 鎖定。這些鎖定會保留到交易完成為止。 - DML 和寫入作業:
- 執行期間,如果 DML 或寫入作業修改了資料,交易可能會取得資料列存在狀態的讀取鎖定。
- 在提交時,交易會嘗試取得所寫入資料的寫入或專屬鎖定。寫入鎖定會封鎖並行讀取,但可能不會封鎖並行寫入,尤其是在兩者都使用寫入鎖定的情況下。也就是說,多筆交易可以繼續進行修訂,而寫入/寫入衝突會在修訂時使用 wound-wait 演算法解決。所有鎖定都會保留,直到交易提交為止。
使用可序列化隔離層級的悲觀並行控制的好處
在可序列化隔離中,使用悲觀並行控制的主要優點是,在高度競爭的工作負載中,這有助於交易進展。發生衝突時,Spanner 會優先處理較舊的交易,確保交易最終能完成,並減少重複取消交易的次數。
悲觀並行作業的風險
採用可序列化隔離等級的悲觀並行作業會帶來下列風險:
- 長時間執行的讀取作業可能會阻斷對延遲時間敏感的寫入作業。
- 如果交易完成前需要使用者互動,可能會導致鎖定狀態維持很長一段時間,進而封鎖其他作業。
悲觀並行控制的用途
悲觀並行適合讀寫和寫寫爭用較高的工作負載。如果交易中止和重試的成本很高,也適合使用這項功能。除非工作負載的鎖定延遲時間過長,或受到鎖定衝突的影響很大,否則請使用這個預設模式。
最佳化並行控制
Spanner 也提供樂觀並行控制。使用可重複讀取隔離時,預設模式為樂觀並行控制。您也可以設定可序列化的隔離層級,使用樂觀並行控制。
最佳化的並行控制會假設衝突很少發生,即使在讀寫交易中,讀取和查詢作業也會繼續進行,不會取得鎖定。使用 Spanner 的預設可序列化隔離層級時,系統會在提交時驗證讀取作業。這可確保沒有其他並行修訂的交易修改交易先前讀取的資料。如果您使用可重複讀取隔離,系統會在提交時驗證含有 FOR UPDATE 或 lock_scanned_ranges=exclusive 提示的讀取作業。如果 Spanner 偵測到衝突,就會中止交易。
樂觀並行控制的運作方式
樂觀並行會改變 Spanner 執行讀取、查詢和提交交易的方式。在讀取階段,這項作業會執行無鎖定作業,並在提交時驗證一致性。
讀取和查詢
讀取和查詢作業不會鎖定。樂觀交易中的所有讀取和查詢作業,都會在單一快照時間戳記執行。Spanner 會在執行第一次讀取或查詢時選擇這個時間戳記。這樣可確保交易中的所有後續讀取和查詢作業,都會看到在第一次讀取或查詢前修訂的寫入作業。
讀取和寫入
如果是包含讀寫作業的樂觀交易,Spanner 會在修訂時執行驗證步驟。只有在未偵測到任何衝突,且符合下列條件時,交易才會成功提交:
- 沒有任何並行修訂的寫入作業與這項交易讀取的資料衝突,也就是說,在讀取時間戳記之後,但這項交易修訂自身寫入作業之前,沒有任何寫入作業修訂。
- 自讀取時間戳記以來,結構定義未經過修改。
隔離等級會決定要驗證的讀取作業集。使用可序列化隔離等級時,系統會驗證所有讀取作業。使用可重複讀取隔離等級時,系統會在提交時驗證含有 FOR UPDATE 或 lock_scanned_ranges=exclusive 提示的讀取作業。
在高度爭用情況下,樂觀交易可能會反覆中止。相反地,悲觀交易會允許較舊的交易提交,並重試較新的交易,藉此解決讀寫衝突。
樂觀並行控制的優點
樂觀並行具備下列優點:
- 讀取作業不會取得鎖定:樂觀交易不會取得讀取作業的鎖定,因此長時間執行的讀取作業不會封鎖延遲時間敏感的寫入作業。
- 縮短唯讀交易的提交延遲時間:由於樂觀交易中的所有讀取作業都以相同的快照時間戳記為準,因此在執行或提交這些讀取作業時,不需要驗證一致性,可大幅縮短延遲時間。
樂觀並行作業的風險
樂觀並行會帶來風險,特別是在搭配可序列化隔離使用時,若讀寫爭用情況嚴重,針對工作負載使用可序列化隔離層級的樂觀並行控制項之前,請先瞭解這些風險。
- 在讀寫爭用嚴重的情況下,樂觀交易的終止率可能會偏高,因為並行寫入可能會使樂觀交易的讀取失效。
- 如果持續發生高爭用情形,交易可能會重複中止,且永遠不會因交易資源不足而提交。
樂觀並行控制的用途
樂觀並行適用於讀寫爭用較低的交易工作負載。對於可序列化交易,這項功能也適用於可容許交易中止的工作負載。
下列工作負載適合採用樂觀並行控制:
- 長時間執行的交易,且延遲容許度較高的低優先順序工作負載: 如果長時間執行的讀取或查詢作業可能會延遲對延遲時間敏感的寫入作業,請使用樂觀並行。這樣可避免讀取鎖定造成的延遲。舉例來說,行動用戶端連線速度緩慢時的交易,或是服務水準協議較低的交易,會對許多資料列或大範圍資料列保留讀取鎖定。
- 讀取延遲時間敏感的交易工作負載,且讀寫爭用情況較少: 在多區域設定中,使用樂觀並行來提供區域讀取服務、縮短讀取延遲時間,並避免因熱門分割區的讀取流量暴增而導致生產環境發生問題。 此外,還能提升讀取可用性,避免領導者過度負載或無法使用。
- 交易工作負載,其中大多數交易都是唯讀: 切換至樂觀並行控制,可減少這些工作負載中常見唯讀交易的提交延遲時間。確保讀寫爭用程度較低,避免讀寫交易的終止率過高。
對於讀寫衝突頻繁的延遲時間敏感型交易工作負載,請避免使用樂觀並行。
設定並行控制
您可以使用 Spanner 用戶端程式庫、REST 和 RPC API,指定讀取/寫入交易的並行模式。
用戶端程式庫
Java
Go
Node.js
Python
C#
REST
Spanner TransactionOptions REST API 會在 ReadWrite 訊息中提供 ReadLockMode 列舉,讓您選取 PESSIMISTIC 或 OPTIMISTIC 鎖定模式。
RPC
Spanner Transactionoptions RPC API 會在 ReadWrite 訊息中提供 ReadLockMode 列舉,讓您選取 PESSIMISTIC 或 OPTIMISTIC 鎖定模式。
驅動程式
您可以使用 Spanner 的驅動程式,在連線層級將 read_lock_mode 設為連線參數,或在交易層級將 SET 設為陳述式選項。如要進一步瞭解各個驅動程式,請參閱「驅動程式總覽」。
後續步驟
- 進一步瞭解 Spanner 隔離層級。
- 瞭解如何使用可重複讀取隔離等級。