% 本当に怖いデータ不整合 % id:tanishiking24 % Hatena × サポーターズ 2017-09-22
- \includegraphics[width=50px]{./icon.jpg}
- 谷口力斗(id:tanishiking24)
- 2017年4月新卒入社
- Webアプリケーションエンジニア@はてな
- 京都大学工学部情報学科計算機科学コース卒
\Huge RDBMSを使ったアプリケーション書いたことありますか?
\large データを出し入れしてるだけのように見えるけど実は奥が深い
\large いろいろあるけど今日はトランザクションの話をします
- RDBMSについてさらっと話すので興味を持ってもらえると嬉しい
- キーワードだけ拾ってもらってあとで検索
\large トランザクションとは「1つ以上の連続した操作の単位」
- データベースへのSQLを用いた操作としてはSELECT,UPDATE,INSERT,DELETEなど
- アプリケーションとしては複数の操作をもって一つの意味のある操作となることがあり、その複数のひとまとまりの操作をトランザクションと呼ぼう
\large トランザクションはCOMMITかABORTされる。
\large COMMITされたトランザクション内の操作は永続化され、ABORTされたトランザクション内の操作はすべて無かったことになる(ROLLBACK処理)
\large 連続するはずの操作が中途半端な状態で終るのを防ぐ(後述するAtomicity)
トランザクションはACID特性を満たすと言われる
- Atomicity: 原子性
- Consistency: 一貫性/整合性
- Isolation: 分離性/独立性
- Durability: 耐久性
トランザクションの終了時点にデータの状態が整合しているという性質
- 「整合性」とは、主キーや外部キー制約やNOT NULL制約といった諸々の制約をすべて満たしているということ
- トランザクションのConsistencyは他のAtomic、Isolation、Durabilyにより保証されるものでユーザーが意識することはない
\huge すべてのトランザクション内操作が成功したか、すべて無かった事になるかという特性
例えば課金用の石を100個使って10連ガチャを回すロジック
- ユーザーの持つ石を100個減らす
- ユーザーに課金アイテムを10個与える
最初の操作を実行した時点でエラーが起こってしまったら破滅
各トランザクションがひとつずつ逐次的に実行されるなら何も問題ない。
実際のアプリケーションでは複数のトランザクションが並列に実行される。
あたかも複数の並行トランザクションが逐次的に実行されたかのように結果の整合性を担保してくれるという特性。
\small keyword: (Final State / View / Conflict) Serializability
2PL(Two Phase Lock)というプロトコルでロックを取りながらレコードを読み書きすることでSerializabilityを実現できる
そのままじゃ遅すぎる->2PLでの制約を緩めたいくつかの分離レベルが策定される
\small keyword: トランザクション分離レベル
制約がゆるすぎると不整合が起こってくる
例: Dirty Read コミットしてない値を読んでしまう
trx1 | trx2 |
---|---|
Read(X) | - |
Write(X := X+10) | - |
- | Read(X) |
- | Write(X := X-10) |
COMMIT | |
ROLLBACK |
trx1はROLLBACKされるので、trx2は本来X-10になってるはずだが...
トランザクションは復旧の単位
障害が発生する前に終了したトランザクションについては、システム再起動時には整合性を保った状態で復旧できる
\includegraphics[width=250px]{./transaction.png}
- コミットしてもすぐさまデータがディスクに書き込まれるわけじゃない。
- 読み/書き込み性能を上げるなどの理由でバッファプールにまず書き込まれる
- ログ法: Redoログへの書き込み(トランザクションで行われた操作が記録される)(シーケンシャルライト)
- システムがクラッシュし再起動した時はRedoログに書き込まれた内容から整合性のある状態に復元する(ロールフォワード)
- 「Redoログへの書き込み」が必ず「データベース(ディスク)への操作」に先行することでRedoログによる整合性を保った状態への復旧を保証することができる(WAL)
\includegraphics[width=250px]{./transaction.png}
ログはSQLのクエリごとに書き込まれるのではなく log buffer に貯められ、定期的(基本的にCOMMIT時)にディスクにflushされる
- 単純なアプリケーションを書くだけなら多分必須ではない
- 複雑なアプリケーションを書く時トランザクションの知識があると破滅を防げるかも
- RDBMSの設定パラメータの意味がわかってくる
- ミドルウェアの作るのに活かせたり(ジョブキューシステムとか)
\Huge トランザクション技術を学んで破滅を防ごう!!!!!
- おうちで学べるデータベースのきほん(翔泳社)
- RDBMS解剖学 よくわかるリレーショナルデータベースの仕組み(翔泳社)
- リレーショナルデータベース入門(サイエンス社)
- 一人トランザクション技術アドベントカレンダー
- 各種RDBMSの公式ドキュメント