0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

データベースにおけるトランザクションの概念

Posted at

トランザクションとは何か

データベースにおけるトランザクションは、複数のデータベース操作を一つの論理的な作業単位として扱う仕組みです。銀行の送金処理を想像してください。口座Aから1万円を引き落とし、口座Bに1万円を入金する — この2つの操作は必ず両方成功するか、両方失敗する必要があります。片方だけが成功してしまうと、お金が消えたり増えたりしてしまいます。

トランザクションは、このような「全か無か」の原則を保証することで、データの整合性と信頼性を維持します。

トランザクションの基本的な流れ

1. BEGIN(トランザクション開始)

BEGIN TRANSACTION;
-- または
START TRANSACTION;

この時点から、以降の操作はトランザクションの一部として記録されます。

2. 一連のデータ操作

UPDATE accounts SET balance = balance - 10000 WHERE account_id = 'A001';
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 'B002';
INSERT INTO transaction_log (from_account, to_account, amount, timestamp) 
VALUES ('A001', 'B002', 10000, NOW());

3. COMMIT(確定)または ROLLBACK(取り消し)

-- すべて成功した場合
COMMIT;

-- エラーが発生した場合
ROLLBACK;

ACID特性:トランザクションの4つの保証

Atomicity(原子性)

トランザクション内の操作は「すべて成功」か「すべて失敗」のどちらかです。部分的な成功は許されません。システムクラッシュが発生しても、中途半端な状態にはなりません。

Consistency(一貫性)

トランザクション前後でデータベースは常に一貫した状態を保ちます。例えば、「口座残高は常に0以上」といった制約が守られます。

Isolation(独立性)

同時に実行される複数のトランザクションは互いに干渉しません。各トランザクションは、他のトランザクションが存在しないかのように動作します。

Durability(永続性)

一度コミットされたトランザクションの結果は、システム障害が発生しても失われません。電源が落ちても、ディスクが故障しない限りデータは保持されます。

実践例:ECサイトの注文処理

BEGIN TRANSACTION;

-- 1. 在庫を減らす
UPDATE inventory 
SET quantity = quantity - 2 
WHERE product_id = 'PRD001' AND quantity >= 2;

-- 2. 注文レコードを作成
INSERT INTO orders (user_id, product_id, quantity, total_price)
VALUES (123, 'PRD001', 2, 5000);

-- 3. 決済処理(外部APIと連携する場合もある)
INSERT INTO payments (order_id, amount, status)
VALUES (LAST_INSERT_ID(), 5000, 'completed');

-- すべて成功したら確定
COMMIT;

もし在庫が不足していたり、決済が失敗した場合は、ROLLBACKによってすべての変更が取り消されます。

分離レベル:並行性と一貫性のトレードオフ

トランザクションの分離レベルは、並行実行時の挙動を制御します:

  1. READ UNCOMMITTED:最も低い分離レベル。ダーティリードが発生する可能性あり
  2. READ COMMITTED:コミットされたデータのみ読み取り可能
  3. REPEATABLE READ:同一トランザクション内では同じデータを読む
  4. SERIALIZABLE:最も高い分離レベル。完全な分離を保証

NoSQLデータベースにおけるトランザクション

DynamoDBの場合

DynamoDBはNoSQLデータベースとして、RDBMSとは異なるアプローチを取っています:

  • TransactWriteItems API:最大100項目まで、複数のテーブルにまたがるトランザクション書き込みが可能
  • TransactGetItems API:複数項目の一貫性のある読み取りを保証
  • 条件付き書き込みによる楽観的ロック制御
# DynamoDBのトランザクション例
response = dynamodb.transact_write_items(
    TransactItems=[
        {
            'Update': {
                'TableName': 'Users',
                'Key': {'user_id': {'S': 'user123'}},
                'UpdateExpression': 'ADD points :points',
                'ExpressionAttributeValues': {':points': {'N': '100'}}
            }
        },
        {
            'Put': {
                'TableName': 'PointHistory',
                'Item': {
                    'user_id': {'S': 'user123'},
                    'points': {'N': '100'},
                    'timestamp': {'S': '2024-01-20T10:00:00Z'}
                }
            }
        }
    ]
)

まとめ:トランザクションを使いこなすために

トランザクションは、データの整合性を保証する強力な仕組みです。しかし、過度に長いトランザクションはパフォーマンスの低下やデッドロックの原因となります。以下の点に注意して設計しましょう:

  • トランザクションは必要最小限の範囲に留める
  • 適切な分離レベルを選択する
  • デッドロックに備えたリトライ処理を実装する
  • NoSQLを使う場合は、その特性に合わせた設計を行う

データベースの種類や要件に応じて、最適なトランザクション戦略を選択することが、堅牢なシステム構築の鍵となります。​​​​​​​​​​​​​​​​

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?