ACID特性とトランザクション
🔄 ACID特性とトランザクション
Section titled “🔄 ACID特性とトランザクション”トランザクションは、データベースの整合性を保証する重要な仕組みです。ACID特性を理解することで、適切なトランザクション管理ができます。
🎯 なぜトランザクションが重要なのか
Section titled “🎯 なぜトランザクションが重要なのか”❌ トランザクションなしの処理
Section titled “❌ トランザクションなしの処理”❌ 問題のある実装:
-- 銀行口座間の送金処理(トランザクションなし)-- 1. 送金元の口座から引き出すUPDATE accounts SET balance = balance - 1000 WHERE id = 1;
-- 2. 送金先の口座に振り込むUPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- 問題点:-- - 1つ目のUPDATEが成功し、2つ目のUPDATEが失敗した場合、-- 送金元の口座から1000円が消えてしまう-- - データの整合性が保証されない発生する問題:
- データの不整合
- お金が消える
- 二重処理のリスク
トランザクションによる解決
Section titled “トランザクションによる解決”改善された実装:
-- トランザクションを使用BEGIN TRANSACTION;
-- 1. 送金元の口座から引き出すUPDATE accounts SET balance = balance - 1000 WHERE id = 1;
-- 2. 送金先の口座に振り込むUPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- すべて成功した場合のみコミットCOMMIT;
-- エラーが発生した場合はロールバック-- ROLLBACK;メリット:
- すべての処理が成功するか、すべて失敗するか(All or Nothing)
- データの整合性が保証される
- エラー時の自動ロールバック
ACID特性
Section titled “ACID特性”Atomicity(原子性)
Section titled “Atomicity(原子性)”定義: トランザクション内のすべての操作が、すべて成功するか、すべて失敗するかのいずれかです。
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- エラーが発生した場合、すべての変更がロールバックされる-- 成功した場合のみ、すべての変更がコミットされるCOMMIT;Consistency(一貫性)
Section titled “Consistency(一貫性)”定義: トランザクションの前後で、データベースの整合性制約が満たされる状態です。
-- 整合性制約: 口座残高は0以上でなければならないALTER TABLE accounts ADD CONSTRAINT check_balance CHECK (balance >= 0);
BEGIN TRANSACTION;
-- この操作は整合性制約違反のため失敗するUPDATE accounts SET balance = -100 WHERE id = 1;-- エラー: CHECK制約違反
-- トランザクション全体がロールバックされるROLLBACK;Isolation(分離性)
Section titled “Isolation(分離性)”定義: 同時実行されるトランザクションが互いに影響を与えないことです。
-- トランザクション1BEGIN TRANSACTION;SELECT balance FROM accounts WHERE id = 1; -- 1000を読み取るUPDATE accounts SET balance = balance - 100 WHERE id = 1;-- まだコミットしていない
-- トランザクション2(同時実行)BEGIN TRANSACTION;SELECT balance FROM accounts WHERE id = 1; -- 1000を読み取る(変更前の値)-- トランザクション1の変更は見えないDurability(永続性)
Section titled “Durability(永続性)”定義: コミットされたトランザクションの変更は、システム障害が発生しても失われないことです。
BEGIN TRANSACTION;UPDATE accounts SET balance = balance - 1000 WHERE id = 1;COMMIT; -- コミット後、変更は永続化される
-- システム障害が発生しても、変更は失われないトランザクションの実装
Section titled “トランザクションの実装”基本的なトランザクション
Section titled “基本的なトランザクション”-- トランザクションの開始BEGIN TRANSACTION;-- またはSTART TRANSACTION;
-- 処理の実行UPDATE accounts SET balance = balance - 1000 WHERE id = 1;UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- コミット(変更を確定)COMMIT;
-- ロールバック(変更を取消)-- ROLLBACK;エラーハンドリング
Section titled “エラーハンドリング”BEGIN TRANSACTION;
BEGIN TRY UPDATE accounts SET balance = balance - 1000 WHERE id = 1; UPDATE accounts SET balance = balance + 1000 WHERE id = 2; COMMIT;END TRYBEGIN CATCH ROLLBACK; -- エラーログを記録 PRINT 'Error occurred: ' + ERROR_MESSAGE();END CATCH;トランザクションの分離レベル
Section titled “トランザクションの分離レベル”READ UNCOMMITTED(未コミット読み取り)
Section titled “READ UNCOMMITTED(未コミット読み取り)”特徴:
- 最も低い分離レベル
- ダーティリードが発生する可能性がある
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION;SELECT balance FROM accounts WHERE id = 1;-- 他のトランザクションの未コミットの変更も読み取れるCOMMIT;READ COMMITTED(コミット済み読み取り)
Section titled “READ COMMITTED(コミット済み読み取り)”特徴:
- デフォルトの分離レベル(多くのデータベース)
- ダーティリードは防げるが、非再現読み取りが発生する可能性がある
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRANSACTION;SELECT balance FROM accounts WHERE id = 1;-- コミット済みの変更のみ読み取れるCOMMIT;REPEATABLE READ(再現可能読み取り)
Section titled “REPEATABLE READ(再現可能読み取り)”特徴:
- 同じトランザクション内で同じクエリを実行しても同じ結果が得られる
- ファントムリードが発生する可能性がある
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION;SELECT balance FROM accounts WHERE id = 1;-- 同じトランザクション内では同じ値が読み取れるSELECT balance FROM accounts WHERE id = 1; -- 同じ値COMMIT;SERIALIZABLE(直列化可能)
Section titled “SERIALIZABLE(直列化可能)”特徴:
- 最も高い分離レベル
- すべての並行性の問題を防げるが、パフォーマンスが低下する可能性がある
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;SELECT balance FROM accounts WHERE id = 1;-- 完全に分離された状態で読み取れるCOMMIT;デッドロック
Section titled “デッドロック”デッドロックの発生
Section titled “デッドロックの発生”デッドロックの例:
-- トランザクション1BEGIN TRANSACTION;UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- ロック1を取得-- ロック2を待機
-- トランザクション2(同時実行)BEGIN TRANSACTION;UPDATE accounts SET balance = balance - 100 WHERE id = 2; -- ロック2を取得-- ロック1を待機
-- デッドロックが発生デッドロックの回避
Section titled “デッドロックの回避”対策:
-
ロックの順序を統一
-- 常にIDの小さい順にロックを取得UPDATE accounts SET balance = balance - 100 WHERE id = 1;UPDATE accounts SET balance = balance - 100 WHERE id = 2; -
タイムアウトの設定
SET LOCK_TIMEOUT 5000; -- 5秒でタイムアウト -
トランザクションの時間を短くする
-- トランザクション内の処理を最小限にするBEGIN TRANSACTION;-- 必要な処理のみを実行COMMIT;
ACID特性とトランザクションのポイント:
- ACID特性: Atomicity、Consistency、Isolation、Durability
- トランザクション: BEGIN、COMMIT、ROLLBACK
- 分離レベル: READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE
- デッドロック: ロックの順序を統一し、タイムアウトを設定
- エラーハンドリング: TRY-CATCHブロックでエラーを処理
適切なトランザクション管理により、データの整合性を保証できます。