元ドキュメント: ロックメカニズムの解析とトラブルシューティング
ロック機構の解析と障害対応
概要
データベースにおけるロックメカニズムは、同時実行制御の中核となる技術です。TDSQL Boundless では、分散環境において高い整合性を維持しつつ、優れた並行処理性能を実現するために、複数のロック方式を採用しています。
本ドキュメントでは、悲観ロック・楽観ロックのメカニズム、デッドロックの検知と解消、ロック待ちタイムアウトの対処法、そして実践的なトラブルシューティング手法について解説します。
悲観ロック(Pessimistic Locking)
基本概念
悲観ロックは、データの競合が頻繁に発生することを前提として、データアクセス時にロックを取得する方式です。
特徴:
- データ読み取り時にロックを取得し、トランザクション完了まで保持する
- 他のトランザクションからのアクセスを排他的にブロックする
- データの整合性が厳密に保証される
使用例
-- 行レベルの悲観ロック(SELECT ... FOR UPDATE)
BEGIN;
SELECT * FROM accounts WHERE account_id = 1001 FOR UPDATE;
-- この行は現在のトランザクションが完了するまでロックされる
UPDATE accounts SET balance = balance - 500 WHERE account_id = 1001;
COMMIT;-- 共有ロック(SELECT ... LOCK IN SHARE MODE)
BEGIN;
SELECT * FROM products WHERE product_id = 100 LOCK IN SHARE MODE;
-- 他のトランザクションは読み取り可能だが、更新はブロックされる
COMMIT;適用シーン
- 金融トランザクション(口座残高の更新など)
- 在庫管理(在庫数の減算処理など)
- データの競合が頻繁に発生する環境
楽観ロック(Optimistic Locking)
基本概念
楽観ロックは、データの競合がまれであることを前提として、更新時にのみ競合チェックを行う方式です。データベースのロック機能ではなく、アプリケーション層で実装します。
特徴:
- データ読み取り時にロックを取得しない
- 更新時にバージョン番号やタイムスタンプで競合を検知する
- ロック待ちが発生しないため、並行処理性能が高い
実装パターン
バージョン番号方式
-- バージョン番号カラムを持つテーブル
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
stock INT,
version INT DEFAULT 0
);
-- 読み取り時にバージョン番号を取得
SELECT id, name, stock, version FROM products WHERE id = 100;
-- 例:version = 5 が返される
-- 更新時にバージョン番号を条件に含める
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 100 AND version = 5;
-- 影響行数が0の場合、他のトランザクションにより更新済みタイムスタンプ方式
UPDATE products
SET stock = stock - 1, updated_at = NOW()
WHERE id = 100 AND updated_at = '2026-03-07 10:00:00';適用シーン
- 読み取りが多く書き込みが少ないワークロード
- 競合発生頻度が低い環境
- ユーザーインターフェースからの更新処理
デッドロックの検知と解消
デッドロックとは
デッドロックは、2つ以上のトランザクションが互いにロックの解放を待ち合う状態です。
トランザクションA: 行1をロック → 行2のロックを待機
トランザクションB: 行2をロック → 行1のロックを待機
→ 双方が永久に待機し続ける(デッドロック)デッドロックの検知
TDSQL Boundless は、デッドロック検知メカニズムを内蔵しており、デッドロックを自動的に検知します。
-- デッドロック情報の確認
SHOW ENGINE INNODB STATUS;
-- デッドロック関連のステータス変数
SHOW STATUS LIKE 'innodb_deadlocks';デッドロックの解消
デッドロックが検知されると、TDSQL Boundless はコストの低いトランザクションを選択してロールバックします。アプリケーション側では、ロールバックされたトランザクションを再試行するロジックを実装する必要があります。
デッドロックの予防
- トランザクションを短くする — ロック保持時間を最小化する
- アクセス順序を統一する — テーブルや行へのアクセス順序を一定にする
- 適切なインデックスを設計する — テーブルスキャンによるロック範囲の拡大を防ぐ
- ロックの粒度を意識する — 必要最小限の行のみをロックする
-- 悪い例:アクセス順序が不統一
-- トランザクションA
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- トランザクションB
UPDATE accounts SET balance = balance - 50 WHERE id = 2;
UPDATE accounts SET balance = balance + 50 WHERE id = 1;
-- 良い例:アクセス順序を統一(IDの昇順)
-- トランザクションA
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- トランザクションB
UPDATE accounts SET balance = balance + 50 WHERE id = 1;
UPDATE accounts SET balance = balance - 50 WHERE id = 2;ロック待ちタイムアウトの対処
タイムアウトの設定
-- ロック待ちタイムアウトの確認
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
-- タイムアウト値の設定(秒単位)
SET innodb_lock_wait_timeout = 50;タイムアウト発生時の対処
ロック待ちタイムアウトが発生した場合(エラーコード: 1205)、以下の手順で対処してください。
- ロックを保持しているトランザクションの特定
-- 現在のロック待ち状況の確認
SELECT * FROM information_schema.innodb_lock_waits;
-- ロックを保持しているトランザクションの確認
SELECT * FROM information_schema.innodb_trx
WHERE trx_state = 'LOCK WAIT';原因の分析
- 長時間実行されているトランザクションの有無
- 不要なロック取得の有無
- インデックスの不備によるロック範囲の拡大
対処方法
- 必要に応じてブロッキングトランザクションを強制終了する
- アプリケーション側でリトライロジックを実装する
- タイムアウト値を適切に調整する
トラブルシューティングの実践
ステップ1:問題の特定
-- アクティブなトランザクションの確認
SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started;
-- プロセスリストの確認
SHOW PROCESSLIST;ステップ2:ロック競合の分析
-- ロック情報の詳細確認
SELECT * FROM performance_schema.data_locks;
-- ロック待ちの依存関係を確認
SELECT * FROM performance_schema.data_lock_waits;ステップ3:解決策の実行
- 不要な長時間トランザクションの終了
- クエリの最適化(適切なインデックスの追加)
- アプリケーションロジックの見直し
分散環境での注意事項
TDSQL Boundless の分散環境では、ロックメカニズムに以下の特有の考慮事項があります。
- 分散トランザクションのロック — 複数ノードにまたがるトランザクションでは、グローバルなロック調整が行われる
- ネットワーク遅延の影響 — ノード間の通信遅延がロック待ち時間に影響する可能性がある
- ロック情報の確認 — 分散環境では、各ノードのロック状態を個別に確認する必要がある場合がある
まとめ
ロックメカニズムの理解は、高性能なデータベースアプリケーションの構築に不可欠です。悲観ロックと楽観ロックを適切に使い分け、デッドロックの予防策を講じることで、TDSQL Boundless 環境での安定した運用が実現できます。
詳細な仕様については、元ドキュメントをご参照ください。