MySQL のギャップロックを理解する:原理から金融レベルの選定まで

tianlong.xiang

システムサービス間のデータ同期において、最近の変更により特定のインターフェースのデータ量が増加し、頻繁に死鎖が発生しました。同僚による調査の結果、間隙ロックが原因であることが判明しました。MySQL の利用は少ないため、記録として残します。

MySQL の間隙ロック、背景、原理、間隙ロックを閉じる方法、閉じた際の注意点;あなたは経験豊富なデータベース DBA として、私の問題に対して拡張的な分析と補足情報を提供してください。幻読とは何ですか? 主流の大手企業は RC モードか RR モードを選択しますか? 私は金融業界の券商システムを担当しており、あなたはそのようなシステムに最適なソリューションを提案してください。上記の質問を整理し、ドキュメントを作成してください。

MySQL において、特に高負荷環境下では、「ロック」を回避することはできません。ギャップロックは InnoDB エンジンにおける重要な特性ですが、同時にパフォーマンスボトルネックや死鎖の根源となることもあります。

この記事では、ギャップロックの核心、利点・欠点を迅速に整理し、あなた(特に金融業界)に対して明確なアーキテクチャ選定のアドバイスを提供します。

幻読とギャップロックとは何か?

  • 幻読 (Phantom Read): トランザクション中に、例えば ID > 100 の範囲を最初に検索し、10件のデータを取得する。その後、別のトランザクションが ID=101 を挿入してコミットすると、2回目の検索で11件に増加してしまう。この「幻のような」追加されたデータが、その名も「幻読」と呼ばれる。

  • ギャップロック (Gap Lock): MySQL は RR(可繰り返し読み) 隔離レベル下において、「幻読」の問題を解決するために発明された。行自体をロックするのではなく、データの間の「隙間」をロックする。

    • 作用: 他のトランザクションがその「隙間」に INSERT を実行できないように防止する。
    • コスト: ロック範囲が広がり、コンカレンシー能力が低下し、死鎖を引き起こす可能性がある。

間隙ロックを「閉じる」方法

最も直接的な方法は、データベースの分離レベルをRR (Repeatable Read) からRC (Read Committed) に降下させることです。

-- 現在のセッションの分離レベルをRCに設定
SET SESSION transaction_isolation = 'READ-COMMITTED';

-- 永続的に変更(my.cnf を修正し、mysqld を再起動する必要があります)
-- [mysqld]
-- transaction-isolation = READ-COMMITTED

⚠️ 关闭の影響(即 RC レベルの特性)

  1. パフォーマンス向上: ギャップロックがなくなるため、ロック粒度が細かくなり、同時スループットが大幅に向上します。
  2. 死鎖減少: ほとんどのギャップロックによる死鎖は解消されます。
  3. 幻読/不整合な読みが発生する: これは RC レベルの「特性」であり、トランザクション内で二回クエリを実行しても結果が一致しない可能性があります。
  4. 【必須要件】ROW形式のBinlogとの併用が必要: RC レベルを使用する場合、必ず binlog_formatROW に設定する必要があります。そうしないと、ギャップロックの保護がないため、主従レプリケーション中に主従データが不整合になる可能性があります。

主要ベンダーの選択:RC または RR?

回答:ほとんどの主要なインターネット企業は RC (Read Committed) + ROW Binlog モードを選択しています。

  • 理由: インターネットビジネス(例:eコマース、ソーシャル)は、極めて高い同時性を追求します。RR のロックスロットによる頻繁なロック待ちや死鎖に耐えられません。
  • トレードオフ: データベースレベルでの「読み取り追跡可能」を放棄し、代わりにアプリケーション層でオプティミスティックロック(バージョン番号、CAS など)などの方法を用いて、重要なビジネス(例:在庫、残高)の論理的一貫性を保証します。

金融業界(証券会社)における選択の指針

データの一貫性要件が極めて高い証券会社システムの場合、シナリオ別対応を推奨します:

方案一:コア取引システム(高同時多接続、低遅延)

推奨:RC (Read Committed) + ROW Binlog + アプリケーション層のオプティミスティックロック

  • シナリオ: 注文撮合、注文、資金決済。
  • 理由: 取引システムの同時アクセス負荷は、秒殺サイトに匹敵する。RR の間隙ロックが性能ボトルネックとなり、深刻なロック競合や死鎖を引き起こすことは、取引システムでは容認できない。
  • 対策: RC を使用して高性能を確保し、アプリケーションコード(例: Java)で UPDATE ... WHERE balance > ? または CAS バージョン番号メカニズムを使用して資金の安全性を保証し、オーバーサブスクリプションを防ぐ。

方案二:清算対帳システム(バッチ処理、高整合性)

推奨:RR (Repeatable Read)

  • シナリオ: 期末バッチ対帳、レポート生成、日終清算。
  • 理由: バッチ処理タスクは、「絶対的な整合性」のあるデータスナップショット上で実行する必要があります。それは RR レベルが提供する能力を必要とし、統計プロセス全体を通して「幻読」が発生しないことを保証し、最終勘定帳が正確であることを確認します。

まとめ

レベル メリット デメリット 適用シナリオ
RR (デフォルト) 幻読を解決し、データの一貫性が高い 并行性が低い、死鎖しやすい(ギャップロック) レポート、決済、データの一貫性要求が極高く、並行性が少ないシナリオ

まとめ

レベル メリット デメリット 適用シナリオ
RC 并行性が高く、死鎖が少ない ファントム読み、不整合な読みが得られる 高い同時性を持つコアビジネス(例:ECサイト、金融取引)で、ROW Binlogと組み合わせて使用

まとめ

証券会社のコアシステムにおいて、RC + ROW Binlog はパフォーマンスと整合性を両立させる主要なアーキテクチャソリューションですが、データ整合性の保証をアプリケーション層でより多く担うことを要求します。

金融ITプログラマーのいじくり回しと日常のつぶやき
Hugo で構築されています。
テーマ StackJimmy によって設計されています。