Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2. ScalarDB Cluster Development - ScalarDB Tran...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

2. ScalarDB Cluster Development - ScalarDB Transaction: Recovery

本資料は、ScalarDBにおけるトランザクションのリカバリー処理について解説した資料です。

ScalarDBはトランザクションのリカバリー処理として「Lazy Recovery(遅延リカバリ)」を採用しており、別のトランザクションが不整合状態のレコードを読み込んだタイミングでリカバリーを実行します。
本資料では、複数のバックエンドDBを跨ぐトランザクション処理において、各フェーズで障害が発生した場合の具体的なリカバリーの挙動を図解で詳しく解説しています。

【主な内容】
- ScalarDBトランザクションのリカバリー処理(Lazy Recovery)の概要
- Prepareフェーズで障害が発生した場合の動作
- Commitフェーズ1で障害が発生した場合の動作(Rollbackの仕組み)
- Commitフェーズ2で障害が発生した場合の動作(Rollforwardの仕組み)

各フェーズでの障害時に、Before imageやコーディネーターテーブルを利用してどのようにAtomicity(原子性)を保証しているかを、具体的な構成例(アカウント残高とクレジット利用額の更新トランザクション)を用いてステップバイステップで確認できます。

Avatar for Scalar, Inc.

Scalar, Inc. PRO

May 14, 2026

More Decks by Scalar, Inc.

Other Decks in Technology

Transcript

  1. 変更履歴 Version Date Name Supported products and versions Description 1.0

    Satoshi Hikida ScalarDB Cluster 3.15.1 First draft
  2. リカバリー不要 DBには何も書き込みがない ため ロールバック TX1が書いたレコードを別 のトランザクションが読み 込んだ際に、Beforeイメー ジを使ってロールバック ロールフォワード TX1が書いたレコードを別

    のトランザクションが読み 込んだ際に、ロールフォ ワード(PrepareをCommit に書き換え) リカバリー不要 ScalarDBトランザクションのリカバリー処理 Crash 4 • トランザクションのリカバリー処理は遅延的に実⾏(Lazy Recovery) • 別のトランザクションが不整合状態のレコードを読み込んだ時にリカバリー処理を実⾏ Prepareフェーズ Commitフェーズ1 Commitフェーズ2 リカバリー処理 TX1
  3. Namespace: ns1 Namespace: ns2 Namespace: coordinator 前提 6 Backend DB1

    • 以降では下記の構成例を⽤いてScalarDBのリカバリ時における動作例を紹介する • ユーザーテーブル(ns1.account, ns2.credit)は別々のストレージ(Backend DB 1, 2)に保持 • コーディネータテーブル(coordinator.state)も独⽴したストレージ(Backend DB 3)に配置 Backend DB2 Backend DB3 account credit state
  4. Prepareフェーズで障害発⽣ 7 Tx1's memory space あるユーザー (user1) がクレジットカード決済で商品を購⼊する場合の処理の⼀部を例として記載する。ユーザーの⼝座 (残⾼) 情報は

    ns1.accountテーブルに、ユーザーのクレジットカードの利⽤額 (利⽤総額) 情報は ns2.creditテーブル にそれぞれ格納されている。この状態 で、ScalarDB を利⽤し「⼝座から残⾼を減算 (-200) する処理」と「クレジットカードの利⽤総額を加算 (+200) する処理」を 1つのトランザ クションで実⾏する。 ns1 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ns2 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image coordinator tx_id tx_state XXX Commit YYY Commit account credit state
  5. ns1 ns2 coordinator Prepareフェーズで障害発⽣ 8 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit Tx1は、メモリ上に更新対象のデータを読み込み、各データを更新する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  6. ns1 ns2 coordinator Prepareフェーズで障害発⽣ 9 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit このタイミングで ns2.creditテーブル に障害が発⽣ ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  7. ns1 ns2 coordinator Prepareフェーズで障害発⽣ 10 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit ns1.accountテーブルへの Write は成功し、更新前のデータを Before image として同⼀レコード内に保存する。 しかし、ns2.creditテーブル への Write は失敗する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  8. ns1 ns2 coordinator Prepareフェーズで障害発⽣ 11 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit ns2.creditテーブル への Write がエラーになったので、Tx1 の状態が Abort であることを コーディネーターテーブルに書き 込む。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Tx1 Abort accoun t credit state
  9. ns1 ns2 coordinator Prepareフェーズで障害発⽣ 12 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit コーディネーターテーブルにTx1 が Abort したことを追記した後、ns1.accountテーブルで更新したレコードについては、 Before image に保存されている値を利⽤して Rollback する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Tx1 Abort accoun t credit state
  10. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 14 Tx1's memory space 初期状態は「Prepareフェーズで障害発⽣」のケースと同じとする。 ID

    Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit accoun t credit state
  11. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 15 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit Tx1は、メモリ上に更新対象のデータを読み込み、各データを更新する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  12. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 16 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit 更新対象のレコードの tx_id と tx_version の値が事前に読み込んだ際の (更新前の) レコードの値と⼀致する場合は、更新 したデータを各テーブルに Write する(条件付き書込み)。また、更新前のデータを Before image として同⼀レコード内 に保存する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  13. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 17 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit このタイミング (Prepare フェーズ完了後) にコーディネーターテーブルが格納されている DB で障害が発⽣した場合につい て記載する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  14. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 18 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit Prepareフェーズが完了しているため、Commit フェーズ1の処理としてコーディネーターテーブルにTx1の状態がCommit であることを追記しようとするが、コーディネーターテーブルに障害が発⽣しているため、Tx1の状態を書き込むことがで きない。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit state
  15. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 19 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit コーディネーターテーブルの障害に伴い Commitフェーズ1の処理が実施できなため、Tx1では例外 (UnknownTransactionStatusException) が発⽣する。なお、Tx1 の処理はエラーになるが、「Tx1 が Commit したか Abort したか」について、この時点でアプリケーションからは判断できないので注意が必要。 UnknownTransactionStatusException accoun t credit state
  16. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 20 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit Tx1の処理が Commit or Abort のどちらであるかを確認する場合は、UnknownTransactionStatusException からトランザ クションIDを取得 (getUnknownTransactionId() メソッドを利⽤して取得) し、別途リカバリ処理を実施する必要がある。 UnknownTransactionStatusException accoun t credit state
  17. ns1 ns2 coordinator Commitフェーズ1で障害発⽣ 21 ID Balance tx_state tx_id tx_version

    user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit Tx1 が異常終了した後、コーディネーターテーブルが復旧する。この時、各ユーザーテーブル(ns1.account, ns2.credit) 内には tx_state = Prepare になっているレコードが複数残存している。 accoun t credit state 復旧
  18. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 22 ID Balance tx_state tx_id

    tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit コーディネーターテーブルの復旧後、他のトランザクション (Tx2) が tx_state = Prepare の状態で残存しているレコードを Read する。 Tx2's memory space ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 accoun t credit state
  19. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 23 ID Balance tx_state tx_id

    tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_state = Prepare になっているレコードを読み込んだ Tx2は、当該レコードを書き込んだトランザクション (Tx1) の状態を 確認するために、コーディネーターテーブルに tx_id = Tx1 になっているレコードが存在するかを確認する。しかし、コー ディネーターテーブルに Tx1 のレコードは存在していない。 Tx2's memory space ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 tx_id = Tx1, tx_state = Prepare missing accoun t credit state tx_id tx_state XXX Commit YYY Commit
  20. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 24 ID Balance tx_state tx_id

    tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_id tx_state XXX Commit YYY Commit コーディネーターテーブルに Tx1 のレコードが存在しない場合は、Read したレコードの「Prepareを書き込んだ時刻」を 確認する。tx_prepared_at の時刻が閾値 (15秒) より古い時刻であった場合は、 当該レコードを書き込んだ Tx1 に何等かの 問題が発⽣した (Rollback が必要である) と判断する。 Tx2's memory space ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 (Prepareを書き込んだ時刻 + 15秒) < 現在時刻 であれば rollback を実施 accoun t credit state
  21. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 25 ID Balance tx_state tx_id

    tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Rollback が必要であると判断した場合は、コーディネーターテーブルに Tx1 の状態が Abort であることを追記する。 Tx2's memory space ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 (Prepareを書き込んだ時刻 + 15秒) < 現在時刻 であれば rollback を実施 tx_id tx_state XXX Commit YYY Commit Tx1 Abort accoun t credit state
  22. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 26 ID Balance tx_state tx_id

    tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Tx1 は Abort したものとして扱うため、tx_state = Prepare になっているレコードを発⾒した Tx2 が、Before image を利⽤ して当該レコードの値を Rollback する。 Tx2's memory space ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 (Prepareを書き込んだ時刻 + 15秒) < 現在時刻 であれば rollback を実施 Rollback accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Abort state
  23. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 27 ID Balance tx_state tx_id

    tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image 更に、Tx2 による account テーブルの Rollback 完了後に、別のトランザクション (Tx3) が ns2.credit テーブルの user1 のレ コード (tx_state = Prepare のレコード) を Read した場合について記載する。 Tx3's memory space accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Abort state
  24. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 28 ID Balance tx_state tx_id

    tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Tx3 が当該レコードを Read すると、tx_state = Prepare になっていることを検出する。 Tx3's memory space ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 tx_state = Prepare accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Abort state
  25. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 29 ID Balance tx_state tx_id

    tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_state = Prepare になっているレコードを読み込んだTx3は、当該レコードを書き込んだトランザクション (Tx1) の状態を 確認するために、コーディネーターテーブルに tx_id = Tx1 になっているレコードが存在するかを確認する。コーディネー ターテーブルには、Tx2 が Lazy Recovery を実施した際に追記した Tx1 のレコードが存在しているため、Tx1 は Abort して いると判断できる。 Tx3's memory space ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 tx_id = Tx1, tx_state = Prepare accoun t credit Abort済み を確認 tx_id tx_state XXX Commit YYY Commit Tx1 Abort state
  26. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 30 ID Balance tx_state tx_id

    tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Tx1 は既に Abort していることが確認できたため、tx_state = Prepare になっているレコードを発⾒した Tx3 が、Before image を利⽤して当該レコードの値を Rollback する。 Tx3's memory space ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 tx_id = Tx1, tx_state = Prepare Rollback accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Abort state
  27. ns1 ns2 coordinator Commitフェーズ1で障害発⽣:Lazy Recovery 31 ID Balance tx_state tx_id

    tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image このように、コーディネーターテーブルに障害が発⽣した場合であっても、Lazy Recovery を利⽤して、正しく Rollback 処 理を実施できる (Abort を確定させて Atomicity を保証できる)。 accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Abort state
  28. ns1 ns2 coordinator Commitフェーズ2で障害発⽣ 33 Tx1's memory space 初期状態は「Prepareフェーズで障害発⽣」のケースと同じとする。 ID

    Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image tx_id tx_state XXX Commit YYY Commit accoun t credit state
  29. ns1 ns2 coordinator Commitフェーズ2で障害発⽣ 34 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 1000 Commit XXX 3 Balance tx_state tx_id tx_version 1500 Commit AAA 2 Before image ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 Amount tx_state tx_id tx_version 2700 Commit BBB 4 Before image Tx1は、メモリ上に更新対象のデータを読み込み、各データを更新する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit tx_id tx_state XXX Commit YYY Commit state
  30. ns1 ns2 coordinator Commitフェーズ2で障害発⽣ 35 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image 更新対象のレコードの tx_id と tx_version の値が事前に読み込んだ際の (更新前の) レコードの値と⼀致する場合は、更新 したデータを各テーブルに Write する(条件付き書込み)。また、更新前のデータを Before image として同⼀レコード内 に保存する。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit tx_id tx_state XXX Commit YYY Commit state
  31. ns1 ns2 coordinator Commitフェーズ2で障害発⽣ 36 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Prepare Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Prepare フェーズの完了後、Tx1はトランザクションの状態が Commit であることをコーディネーターテーブルに書き込む (Commit フェーズ1の処理を実施する)。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 tx_id tx_state XXX Commit YYY Commit Tx1 Commit accoun t credit state
  32. ns1 ns2 coordinator Commitフェーズ2で障害発⽣ 37 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Commit フェーズ1完了後、Tx1は Prepare 状態で書き込んでいたレコードの tx_state を Commit に更新する (Commit フェーズ2)。この時、ns2.creditテーブル には障害が発⽣しているため tx_state の値を更新することができない。 ID Balance tx_state tx_id tx_version user1 1000 Commit XXX 3 ID Amount tx_state tx_id tx_version user1 3000 Commit YYY 5 ID Balance tx_state tx_id tx_version user1 800 Prepare Tx1 4 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  33. ns1 ns2 coordinator Commitフェーズ2で障害発⽣ 38 Tx1's memory space ID Balance

    tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image しかし、Tx1 はコーディネーターテーブルにTx1がCommitであることを記録しているため、このエラー (ns2.creditテーブル での tx_state の更新失敗) を無視して、Commit 完了と判断する。 Commit 完了 accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  34. ns1 ns2 coordinator Commitフェーズ2で障害発⽣:Lazy Recovery 39 ID Balance tx_state tx_id

    tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Tx1 の Commit 完了後、ns2.creditテーブルが復旧する。この時、ns2.creditテーブル上のレコードは tx_state = Prepare に なっている。 accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  35. ns1 ns2 coordinator Commitフェーズ2で障害発⽣:Lazy Recovery 40 Tx2's memory space ID

    Balance tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image ns2.creditテーブル復旧後、他のトランザクション (Tx2) が Prepare 状態で残存しているレコードを Read する。 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  36. ns1 ns2 coordinator Commitフェーズ2で障害発⽣:Lazy Recovery 41 Tx2's memory space ID

    Balance tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image この時、Tx2 は当該レコードの tx_state が Prepare になっていることを検知する。 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 tx_state = Prepare accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  37. ns1 ns2 coordinator Commitフェーズ2で障害発⽣:Lazy Recovery 42 Tx2's memory space ID

    Balance tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image tx_state = Prepare を検知した Tx2 は、コーディネーターテーブルにアクセスし、当該レコードを書き込んだ Tx1 の状態を 確認する。その結果、Tx1 は既に Commit していることが確認できる。 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 tx_id = Tx1, tx_state = Prepare accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  38. ns1 ns2 coordinator Commitフェーズ2で障害発⽣:Lazy Recovery 43 Tx2's memory space ID

    Balance tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Commit Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Tx1 は既に Commit していることが確認できたため、Tx2が After image の tx_state の値を Prepare から Commit に変更 (Rollforward) する。つまり、Commitフェーズ1の完了後であればテーブルの障害が発⽣した場合であっても、Lazy Recovery でリカバリできるようになっている。 ID Amount tx_state tx_id tx_version user1 3200 Prepare Tx1 6 Rollforward accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state
  39. ns1 ns2 coordinator Commitフェーズ2で障害発⽣:Lazy Recovery 44 Tx2's memory space ID

    Balance tx_state tx_id tx_version user1 800 Commit Tx1 4 Balance tx_state tx_id tx_version 1000 Commit XXX 3 Before image ID Amount tx_state tx_id tx_version user1 3200 Commit Tx1 6 Amount tx_state tx_id tx_version 3000 Commit YYY 5 Before image Lazy Recoveryした後に、Tx2は例外(UncommittedRecordException)をスローする。以降のトランザクションでは当該 レコードを読み出すことが可能となる。 UncommittedRecordException accoun t credit tx_id tx_state XXX Commit YYY Commit Tx1 Commit state