transaction
一まとめに処理を行う単位
ACID原則
Transaction isolation level
2つの性質を満たす
同時実行制御
同時にデータ書き換えが起きても、データ不整合を防ぐ
クラッシュリカバリ
処理の途中でクラッシュしても復帰してロールバック可能
口座の例 (同時実行制御)
口座残高が 10,000円 だとして、
A が 5,000円引き出す
B も 5,000円引き出す
これを トランザクションなしで同時に実行すると
A が「残高 10,000 円」を読み取る
B も「残高 10,000 円」を読み取る
A が残高を 5,000 円に更新
B も残高を 5,000 円に更新(A の変更を上書き)
本来は 0円 になるべきなのに、5,000円 残ってしまう
/mrsekut-book-4774171972/346: 第14章 トランザクションの本質
#wip
内部的にはスケジューリングが大事
/mrsekut-book-4774171972/350
並列に処理したい
個々のトランザクションを直列化して実行したときと同じ結果になれば「正しい」と言える
スケジュールの性能
多くのトランザクションを並列化できる
最適なスケジュールを探し出すためのコストが小さい
DBにおけるtransaction
複数のtable操作を、1つのまとまりとして実行するためにtxを使う
例えば、
ある値を read
その結果をもとに 条件判断
条件を満たしたら write
例えば、
複数のtableにwriteする
みたいな一連の処理の最中で、他の処理に割り込まれず、整合性を保ったまま行うためにtxを使う
逆に言えば、単純な read / write では不要である
トランザクション数が多いこと自体は問題ではない
以下のようなこと自体は問題ではない
トランザクションが大量に存在する
同時に多くのトランザクションが走っている
下記を満たすなら、DBは大量のトランザクションでも処理できる
短時間で終わり
互いに 別のレコードを扱い
ロック競合しない
「tx が張り付く」「tx が枯渇する」みたいな表現
これは、トランザクションの数そのものではなく、以下のような現象を指している
ロック待ちによる停滞
トランザクションは状況によって ロックを取る
トランザクションが居座り続けると、後続のトランザクションが連鎖的に待たされることになる
Connection Poolの枯渇
多くのシステムでは
1トランザクション = 1 DBコネクション
tx が長時間生きるとコネクションが返却されない
その結果、コネクションプールの上限に到達
新しいリクエストが DB に接続できない
DB内部リソースの制約
理論上は tx に上限がなくても、実装上は制約がある
e.g.
ロック管理用メモリ
undo / MVCC 領域
内部スレッド・管理構造
トランザクションタイムアウト
上記のような問題を防ぐために、DBにはタイムアウトがある
e.g.
ロック待ちタイムアウト
idle transaction timeout(BEGIN したまま放置)
クエリ実行時間の上限
これらは、張り付いた tx を強制的に終了させる安全装置と言える
トランザクション設計で意識すること
トランザクションは短く保つ
ロックを取る範囲を最小化する
read → write の間で待たせない
https://qiita.com/zd6ir7/items/6568b6c3efc5d6a13865
https://zenn.dev/tockn/articles/4268398c8ec9a9
https://kumagi.hatenablog.com/entry/2015/12/22/235933