Slide 1

Slide 1 text

トランザクションに 歩み寄る はじめの第1 歩編

Slide 2

Slide 2 text

留意事項 本発表ではPostgreSQL の使用を前提とした話をします

Slide 3

Slide 3 text

トランザクションとは 複数のDB 操作を行う際にデータの整合性を保つための仕組み すべてのDB 操作が成功すれば反映(COMMIT) 1 つでも失敗すれば、全ての操作を取り消し(ROLLBACK)

Slide 4

Slide 4 text

トランザクションのACID 特性 A tomicity C onsistensy I solation Durability ... ... ... ... 原子性 一貫性 独立性 永続性 ( 全て実行 or 1 つも実行されない) ( データの整合性が取れている) ( トランザクションを外部から隠蔽) ( 成功すればデータが保存される)

Slide 5

Slide 5 text

トランザクションはすべての特性を 必ずしも満たしているわけではない トランザクションのACID 特性の前提

Slide 6

Slide 6 text

Atomicity( 原子性) トランザクションは全て実行 or 1 つも実行されない のどちらかであるという特性 COMMIT で全て実行 ROLLBACK で1 つも実行されない All or Nothing なのか

Slide 7

Slide 7 text

Consistency( 一貫性) トランザクションの実行後もDB の整合性は取れていること 各ステートメントごと or 全ステートメント後( =コミット 直前) に制約チェックが走る SET CONTSTRAINTS で設定可能

Slide 8

Slide 8 text

Isolation( 独立性) キーワード ↓ 直列化可能性、トランザクション分離レベル、 MVCC( 多版型同時実行制御) 実行中のトランザクションが他のトランザクション に影響を与えないという特性 同時実行性( ≒パフォーマンス) と分離レベルは トレードオフ

Slide 9

Slide 9 text

Durability( 永続性) トランザクションが実行されたら、その結果は記録される システム障害などが生じてもログから復旧できる キーワード ↓ WAL 、チェックポイント

Slide 10

Slide 10 text

共有ロック 排他ロック 共有ロック ◯ ✕ 排他ロック ✕ ✕ ロックとは(1) 共有ロック ・・・参照時にかけるロック 排他ロック ・・・更新時にかけるロック テーブルや行にロックをかけるよ リソースの状態 獲得するロック 獲得したいリソースの共有ロックが 開放されるまで待つことになる テーブルや行にロックをかけるよ PostgreSQL には8 種類くらいあるよ

Slide 11

Slide 11 text

ロックとは(2) users id: 1, name: "user 1" id: 2, name: "user 2" id: 3, name: "user 3" id: 4, name: "user 4" Tr1 SELECT * FROM users WHERE id = 2 Tr2 UPDATE users ( 略) WHERE id = 2 SELECT * FROM users WHERE id = 4 Tr 3 SELECT * FROM users WHERE id = 4 id が2 のレコードに共有ロックをかける id が4 のレコードに共有ロックをかける id が2 のレコードの共有ロックが開放されるのを待つ 共有ロックが取得されていても、共有ロックは 取得できるので待たない

Slide 12

Slide 12 text

COMMIT or ROLLBACK 衰退相 2PL (2相ロック方式) トランザクション内で順にロックを獲得していく トランザクションの終了時に、獲得したロックを全開放する トランザクション中に一度獲得したロックは決して開放しない 獲得ロック数 時間 成長相

Slide 13

Slide 13 text

読み取り時にトランザクション開始前のスナップショットを参照 する 読み込み( 共有) ロックと書き込み( 排他) ロックが競合しない 読み込みは書き込みを絶対にブロックしない 書き込みは読み込みを絶対にブロックしない 排他ロック MVCC (多版型同時実行制御) 読み取りは待たされない 更新前の結果が返る

Slide 14

Slide 14 text

R1 R2 T1 T2 デッドロック(1) お互いのトランザクションが、ロックの開放待ちになっている状態 Tr1 ロック獲得済 ロック獲得済 ロック獲得したい R2 のロック解除待ち (= T2 待ち) ロック獲得したい R1 のロック解除待ち (= T1 待ち)

Slide 15

Slide 15 text

デッドロック(2) ロック待機が一定時間経過するとデッドロック検出動作が入る デッドロックが発生していると、一方のトランザクションが中断 Tr1 デフォルトでは1 秒で検査が走るよ

Slide 16

Slide 16 text

id = 1 id = 2 T1 T2 トランザクション1 トランザクション2 デッドロック(3) ① ロック獲得 ① ロック獲得 ② ロック解放待ち ① ロック獲得 ② ロック解放待ち

Slide 17

Slide 17 text

トランザクション1 デッドロック(4) 挙動確認 上記を実行するとデッドロック発生 トランザクション2

Slide 18

Slide 18 text

危険なトランザクション 実行時間が長すぎる 他のトランザクションから更新はできない 各レコードの処理が終わってもロックは開放されないため トランザクション分離レベルの問題 to be continued... 2 相ロック方式

Slide 19

Slide 19 text

危険なトランザクション例 実行時間が長すぎるトランザクション例 大量レコードの更新 インデックスの貼られているカラムの更新 トランザクション中にアプリケーション側で他の重い処理がある API リクエストやファイルアップロードなど

Slide 20

Slide 20 text

単一のUPDATE 文を途中でキャンセルすると途中まで更新されるの? postgres では全てのステートメント実行前に暗黙的にトランザク ションを開始する ユーザーがキャンセルするとROLLBACK される 複数レコードのUPDATE 文を実行し、一部のレコードのみ更新さ れることはない https://www.postgresql.org/message-id/[email protected] https://www.postgresql.org/docs/13/tutorial-transactions.html#:~:text=PostgreSQL%20actually%20treats,transaction%20block. 素朴な疑問 UPDATE users SET name = “user updated”;

Slide 21

Slide 21 text

まとめ トランザクション中に、他のトランザクションは同一リソースの... 読み込みはできる (MVCC) 書き込みはできないので、待たされる 長時間のトランザクションはなるべく避ける ( 長時間実行にならないように工夫する )

Slide 22

Slide 22 text

参考文献 https://www.postgresql.org/docs/ https://www.postgresqlinternals.org/ https://en.wikipedia.org/wiki/Two-phase_locking データ指向アプリケーションデザイン