MySQLのロック機構に関する最も包括的な説明

MySQLのロック機構に関する最も包括的な説明

序文

ロックの粒度に応じて区別する

  • グローバルロック
  • テーブルロック
  • 行ロック
    • レコードロック
    • ギャップロック
    • プロキーロック

ロックのシナリオによると

  • 楽観的ロック
  • 悲観的ロック

グローバルロック

ロック対象は、データベースインスタンス全体です。

読み取りロック付きテーブルフラッシュ (FTWRL) - データベース全体を読み取り専用にする

使用シナリオ: データベース全体の論理バックアップを作成する

完全なデータベース論理バックアップ

データをバックアップするためにグローバル ロックが必要なのはなぜですか?

たとえば、売上の場合、出荷を記録するテーブルと控除を記録するテーブルが 1 つあります。その結果、出荷記録テーブルをバックアップしました。このとき、誰かが何かを購入したのに、代金のみが控除され、出荷記録はありませんでした。これは明らかに受け入れられません。

公式の論理バックアップ ツールは mysqldump です。 mysqldump がパラメータ –single-transaction を使用する場合、一貫したビューを確保するために、データをインポートする前にトランザクションが開始されます。 MVCC のサポートのおかげで、このプロセス中にデータを正常に更新できます。ただし、これはトランザクションに基づいており、MyISAM データ エンジンでは使用できません。この場合、一部のテーブルが InnoDB データ エンジンに基づいていない可能性があります。

もちろん、すべてが InnoDB データ エンジン テーブルである場合は、デフォルトの mysqldump を使用して、パラメーター –single-transaction を追加し、グローバル論理バックアップを実行することをお勧めします。

FTWRL と set global readonly=true の違い

  1. Readonly は他のロジックで使用されます (システムによって異なる)
  2. ftwrlは、クライアント接続が切断されたときに自動的にロックを解除し、デッドロックの問題を防ぐことができます。

テーブルロック

コマンド: テーブル {tableName} を読み取り/書き込みでロックする (書き込みは読み取りよりも強力です。書き込みができる場合は読み取りもできます)、テーブルのロックを解除する

ロックされたリソースでは、現在のスレッドのみが対応する操作を実行できます。また、現在のスレッドは、ロックされたテーブルに対してのみ対応する操作を実行できます。

たとえば、テーブル t1 を読み取りロックすると、現在のスレッドは読み取りのみ可能で書き込みはできず、他のスレッドは読み取りも書き込みもできません。

MDLロック

明示的な使用は必要ありません。テーブルにアクセスするときに自動的に追加されます (テーブル構造の変更によって発生する問題を防ぐため)

テーブルを追加、削除、変更、またはチェックするときに MDL 読み取りロックを適用し、テーブルの構造を変更するときに MDL 書き込みロックを適用します。

  • MDL読み取りロック(共有ロック)では、ロックは相互に排他的ではありません。そのため、複数のスレッドが同時に追加、削除、変更、クエリを実行できます。
  • MDL書き込みロック(排他ロック)は、他の読み取り/書き込みロックと相互に排他的です。つまり、現在のデータ変更、クエリ、または構造変更は、実行前に他のMDL書き込みロックが解除されるのを待つ必要があります。

行ロック

行ロックは各エンジンによってエンジンレベルで実装されます (MyISAM は行ロックをサポートしていないため、エンジンは一度に 1 つのスレッドでのみ更新操作を実行できます)

トランザクションの場合: 1 行または複数行のデータが必要なときに行ロックが追加されますが、トランザクションがコミットされるまですべての行ロックは解除されません。つまり、他のスレッドが行データにアクセスする必要がある場合、そのスレッドのトランザクションがコミットされるまで待ってからアクセスする必要があります。

例:

スレッドAは次のことを行います
始める;
t1 を更新し、id=1 の場合に a=1 を設定します。

t2を更新し、id=2の場合にb=2を設定します。

専念

このとき、スレッド A は t1 の id=1 と t2 の id=2 をそれぞれロックします。このとき、スレッド B が t1 の id=1 にアクセスしても、アクセスできません。最初のステートメントが実行されたとしても、スレッド B はスレッド A がコミット操作を実行した後にのみデータを取得できます。

したがって、注意すべき点は、トランザクション操作を実行するときに、更新が連続していない場合は、アクセスが最も多いステートメントを最後に実行することです(ロックは連続していますが、ロックの解放は一緒に解放されるため)。

特徴テーブルロック行ロック
ロックレベルMySQL サーバー層データエンジン層
エンジンMyISAM、innoDB翻訳
特徴デッドロックなし、低オーバーヘッド、高速ロック、大きなロック粒度デッドロックしやすい、オーバーヘッドが高い、ロックが遅い、ロックの粒度が小さい

デッドロック

デッドロックは多くの状況で発生しますが、そのほとんどはデータベース操作の問題によって発生します。例えば

スレッドAとスレッドBは両方ともid=1とid=2を変更し、トランザクションを開始します。

スレッドAは最初にid=1を変更し、id=1がスレッドAによってロックされる。

スレッドBがid=2を変更し、id=2が郡Bによってロックされる

このとき、スレッド A は id=2 がロックを解除するまで待機してから id=2 に対する操作を実行する必要があり、スレッド B は id=1 がロックを解除するまで待機してから id=1 に対する操作を実行する必要があります。

その結果、循環的なデッドロック状態が発生します。

この問題に対処するには 2 つの戦略があります。

  1. タイムアウトまで待機状態に直接移行します。このタイムアウトは、パラメータ innodb_lock_wait_timeout (デフォルトは 50 秒) によって設定できます。これをあまり短く設定することはできません。デッドロックではない場合はどうなるでしょうか?
  2. デッドロック検出を開始します。デッドロックが見つかった場合は、デッドロック チェーン内のトランザクションを積極的にロールバックして、他のトランザクションの実行を継続できるようにします。パラメータ innodb_deadlock_detect をオンに設定すると (デフォルトはオン)、このロジックがオンになります。

レコードロック

列ロックのケース

トランザクションによってロックされた特定のレコード情報をロック後に対象とする

トリガー条件: クエリ条件が正確に一致し、一致条件フィールドが一意である

例: update t1 set name="张三" where id=12138

機能: レコードが現在のトランザクションによって管理されている場合、ロックされた後は他のトランザクションによって取得されず、「繰り返し読み取り」や「データ ダーティ リード」の問題が発生します。

ギャップロック

列ロックのケース

ギャップとは、その間にあるデータを意味します

主キーインデックス id に複数の未入力データがあります。このとき、スレッド A と B の 2 つがあり、A が 0 ~ 10 の間のデータを照会し、B が id=3 にデータを挿入すると、データのダーティ リード問題が発生します。

そのため、between などの範囲でトランザクションを実行する場合は、制約のためにギャップロックが追加されます。

プロキーロック

一時キー ロックは、クエリされたレコードをロックし、範囲クエリ内のすべてのギャップ スペースもロックし、次に次の隣接する間隔もロックします。

(リンは隣接を意味します)

楽観的ロックと悲観的ロック

コンセプト楽観的ロック悲観的ロック
コンセプト同時実行の競合がないと仮定する
提出時にデータに問題があるかどうかのみを判断する
同時実行の競合が発生すると想定する
ロック
実装レベルビジネスコードレベル、自分で実装する
(特定のビジネスロジックと組み合わせる必要がある)
MySQLデータベース自体
同時実行性同時実行性同時小規模
実装データベースにバージョン番号フィールドを追加します。
送信時に、操作前のバージョン番号が現在のバージョン番号と一致しているかどうかを確認します。
共有ロック: ロック xxxxxx を選択
排他ロック: 更新用に xxxx を選択
他のMySQL の同期ロックは、実際には排他ロックです。
共有ロック: チェックする他のスレッドを実行しても、追加、削除、変更は許可されません
排他ロック: 追加も削除も許可されません

要約する

MySQL のロック機構に関するこの記事はこれで終わりです。MySQL のロック機構についてさらに詳しく知りたい方は、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL 悲観的ロックと楽観的ロックの実装
  • MySQLの関連ロックについての簡単な理解
  • MySQLのさまざまなロックに関する詳細な理解

<<:  docker リモート API のワンクリック TLS 暗号化の実装

>>:  CSSスプライト技術は複数の背景を1つのPNG画像に統合しますCSSポジショニング

推薦する

React antdはフォームの動的な増減を実現します

以前、動的フォームを記述しているときに落とし穴に遭遇しました。インデックスの添え字をキーとして使用す...

JS を使用してデータ型を決定する 4 つの方法

目次序文1. 型2. インスタンス3. コンストラクター詳細: 4. 文字列要約する序文Javasc...

MySQL ユーザー権限管理の分析例

この記事では、MySQL ユーザー権限管理の例について説明します。ご参考までに、詳細は以下の通りです...

Nginx SSL証明書設定エラーの解決策

1. はじめにWeb プロジェクトを Linux サーバーで公開する場合、SSL 証明書を構成する必...

Docker Swarmを使用してWordPressを構築する方法

原因かつて私は Vultr に WordPress を設定しましたが、よく知られている理由により、こ...

Vue3は現在のルーティングアドレスを取得します

正解useRouterの使用: // ルーターパス: "/user/:uid" ...

MySQL 文字セットの変更に関する実践的なチュートリアル

序文: MySQL では、システムが多くの文字セットをサポートしており、異なる文字セット間にはわずか...

Nginx 構成 クロスドメイン リクエスト Access-Control-Allow-Origin * 詳細な説明

序文403 クロスオリジン エラーが発生しNo 'Access-Control-Allow-...

rem をモバイル デバイスに適応させる方法の例

序文モバイル端末のREM適応ソリューションのレビューと概要remの使い方rem 単位の計算は、HTM...

MySQL 8.0.23のルートパスワードをリセットするための最適なソリューション

この方法は2021年2月7日に編集されました。私が使用しているバージョンは8.0.23です。事件の原...

HTMLファイル内の中国語の文字化けとブラウザでの表示の問題

今日も私のページが文字化けしていたので、インターネットで関連する問題を検索しました。この方法はかなり...

MySQL 5.7.13 のインストールと設定方法の Mac でのグラフィック チュートリアル

MySQL 5.7.13 Mac用インストールチュートリアル、非常に詳細で、以下のように記録されてい...

角丸四角形の HTML+CSS 実装コード

退屈していたので、突然角丸四角形の実装を思いつきました。しかし、私たちはこの話題についてあまりにも長...

動的および静的分離を実装するための Nginx サンプル コード

この記事のシナリオと組み合わせて、Nginx と Java 環境 (SpringBoot プロジェク...