MySQL データベース分離レベルと MVCC の詳細な説明

MySQL データベース分離レベルと MVCC の詳細な説明

MySQL は、日常の制作や学習で最もよく使用されるデータベースの 1 つです。今日は、MySQL (または他の同様のデータベース) の分離レベルと、効率性を向上させるために使用されるマルチバージョン同時実行制御 (MVCC) について説明します。

1. 分離レベル

まず、「トランザクション」という概念について説明する必要があります。トランザクションとは何ですか?トランザクションは、基本的な操作を完了する一連の操作ステートメントの集合です。たとえば、口座 A から口座 B に 200 元を送金したい場合は、次のようにします。
a. 口座Aの残高が200元を超えていることを確認します。
b. 口座Aの残高を200人民元減らします。
c. 口座Bの残高に200人民元を追加します。
上記の 3 つの操作 abc を 1 つのトランザクションに結合します。
この時点で、ここで取り上げているトランザクションは複数のステートメントで構成されている可能性があり、トランザクションはアトミックである、つまりトランザクションの実行は中断できないことに気付くでしょう。ここで疑問が生じます。これらの 3 つのステップの実行に別のステートメントが挿入された場合、この時点でトランザクションのアトミック性が破壊されるため、結果に影響が出るのでしょうか。この種の挿入は並行環境では非常に一般的です。したがって、私たち (またはデータベース エンジン) は、トランザクションの実行中にトランザクションを「保護」する必要があります。つまり、他の外部トランザクションからのステートメントが、実行中のトランザクション ステートメントに勝手に挿入されないようにし、トランザクションが正常に実行されるようにする必要があります。このとき、「ロック」という方法を思いつくのは簡単です。これは実は非常に一般的な発言です。ロックによってトランザクションの正常な実行が保証される一方で、多くの追加オーバーヘッドが発生するからです。したがって、適切なタイミングで適切なロック方法を選択すると、検索効率に大きな影響を与えます。 「ロック」の厳密さによって、さまざまな分離レベルが決まります。

コミットされていない読み取り

この分離レベルでは、データの読み取りはまったく影響を受けません。つまり、他のトランザクションによって変更されているデータも読み取ることができ、いつでも読み取って変更することができます。確かにオーバーヘッドはほとんどありませんが、「ダーティ リード」などの多くの問題が発生する可能性があります。つまり、変更中だがまだ送信されていないデータが読み取られ、データ読み取りエラーが発生します。パフォーマンスの面では、READ UNCOMMITED は他のレベルと比べてそれほど優れているわけではありませんが、多くの厄介な問題を引き起こすため、実際にはほとんど使用されません。

READ COMMITED (コミット読み取り/非反復読み取り)

このレベルでは、READ UNCOMMITED に基づいていくつかの規定が追加され、一部のデータベースのデフォルトの分離レベルになります。 READ UNCOMMITED との違いは、読み取り中に読み取られるデータはコミットされたデータのみであると規定されている点です。たとえば、最後の送信後のデータ a の値は 1 です。このとき、スレッドが a を変更するために入ってきて、a を 2 に変更しますが、この時点ではトランザクション (COMMIT) はコミットされません。この場合、READ UNCOMMITED レベルで読み取られた a の値は現在の値 2 ですが、READ COMMITED レベルで読み取られた値は最後の送信後の値、つまり a が 1 のままです。a の値が 2 になるためには、変更スレッドが a の値を 2 に変更し、トランザクションがコミットされた後に a の値が読み取られる必要があります。このレベルによってもたらされる問題は、反復不可能な読み取りです。つまり、前回読み取った a の値は 1 だったが、変更スレッドがトランザクションをコミットしたため、a の値は 2 に変わり、今回読み取った値は 2 だった、つまり、同じ読み取り操作を 2 回実行して得られた値は異なるということです。
非反復読み取りとダーティ読み取りの違いは、ダーティ読み取りは別の未完了のトランザクションの実行中にデータを読み取るトランザクションであるのに対し、非反復読み取りは、あるトランザクションの実行中に別のトランザクションが現在のトランザクションによって読み取られているデータをコミットして変更する場合である点です。

繰り返し読む

REPEATED READ は、READ COMMITED に基づいていくつかの制限ルールを追加します。これは、MySQL データベースのデフォルトの分離レベルでもあります。簡単に言えば、トランザクションの実行中は、他のトランザクションが対応するデータを変更することを禁止します。これにより、トランザクションの実行中にクエリされたデータの一貫性が確保され、ダーティ リードや非反復リードの問題が解決されます。ただし、これにより「ファントム リード」という新しい問題が発生します。
「ファントム リード」とは、トランザクションの実行中に対応するデータの変更が禁止されているにもかかわらず、他のトランザクションがデータを挿入できることを意味します。このとき、最初のトランザクションは、あたかも錯覚が起こったかのように、何らかの追加データが「不可解に」現れることに気付きます。ファントム リードと非反復読み取りはどちらも、コミットされた別のトランザクションを読み取ります (ダーティ リードとは異なります)。違いは、非反復読み取りは同じデータ項目をクエリするのに対し、ファントム リードはデータのバッチ全体 (データの数など) をクエリすることです。

シリアル化可能

これは最も厳格な分離レベルです。トランザクションを強制的に連続して実行することで、ファントム リードの問題を回避します。ただし、この分離レベルは非常にコストがかかるため、あまり使用されません。

さまざまな分離レベルと発生する可能性のある問題の関係は次のとおりです。

分離レベルダーティリード繰り返し不可能な読み取りファントムリードロック
コミットされていない読み取りはいはいはいいいえ
コミットされた読み取りいいえはいはいいいえ
繰り返し読むいいえいいえはいいいえ
シリアル化可能いいえいいえいいえはい

MVCC

データの一貫性と正確性を確保するために、各 SQL 操作で行レベルのロックを追加する必要がある場合、信頼性は非常に高くなりますが、結果として生じるシステム オーバーヘッドと検索効率の低下も明らかです。そのため、この矛盾を解決するために MVCC が作成されました。
まず、MVCC はテーブルの各行の後ろに 2 つの隠し列を保存します。1 つは行の作成時刻を保存するためのもので、もう 1 つは行の有効期限 (削除) 時刻を保存するためのものです。この時間値は実時間ではなく、システムのバージョン番号です。トランザクションの開始時のシステム バージョン番号がトランザクション バージョン番号として使用され、照会されたレコードの各行のバージョン番号と比較されます。

  • INSERT: 新しく挿入された各行の行バージョン番号として現在のシステム バージョン番号を保存します。
  • DELETE: 削除された各行の行削除バージョン番号として現在のシステム バージョン番号を保存します。
  • 更新: 更新は、実際には、新しいデータを挿入し、元のデータを削除するプロセスとして理解する必要があります。つまり、現在のシステム バージョン番号を新しく挿入されたデータの行バージョン番号として保存し、現在のシステム バージョン番号を削除されたデータの削除バージョン番号として保存します。
  • SELECT: 次の条件を満たす行のみをクエリします。

a. 行バージョン番号がトランザクションバージョン番号以下である
b. 削除バージョン番号が未定義か、トランザクションバージョン番号より大きい

これら 2 つのバージョン番号を保存すると、ほとんどの操作をロックせずに正しく実行できるようになり、パフォーマンスと効率が確保されます。
MVCC は、READ COMMITED と REPEATABLE READ の 2 つの分離レベルでのみ機能することに注意してください。

以上がMySQLデータベース分離レベルとMVCCの詳細な説明です。MySQLデータベース分離レベルとMVCCの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL トランザクション分離レベルと MVCC の詳細な説明
  • MySQL MVCCメカニズム原理の詳細な説明
  • MySQLのMVCCマルチバージョン同時実行制御の実装
  • MySQL における楽観的ロック、悲観的ロック、MVCC の包括的な分析
  • MySQL の簡単な分析 - MVCC
  • MySQL マルチバージョン同時実行制御 MVCC の実装
  • MySQL の分離レベル、ロック、MVCC の紹介
  • MySQL マルチバージョン同時実行制御メカニズム (MVCC) ソースコードの詳細な説明

<<:  ウェブページコンテンツの閲覧設計手法に関する議論

>>:  MySQLクエリトランザクション処理へのノード接続の実装

推薦する

Vue の新しいおもちゃ VueUse の具体的な使い方

目次序文VueUseとは使いやすいおなじみの手ぶれ補正やスロットル機能もありますグローバル状態を共有...

Vue-cliフレームワークはタイマーアプリケーションを実装します

技術的背景このアプリケーションは vue-cli フレームワークを使用し、カスタム コンポーネント ...

MySQL マルチマスターと 1 スレーブのデータバックアップ方法のチュートリアル

概要いずれかのデータベースに対する操作は他のデータベースに自動的に適用され、2 つのデータベースのデ...

Nginx で Basic Auth ログイン認証を設定する方法

nginx でファイルサーバーを構築することもありますが、これは一般に公開されていますが、サーバーが...

CSSでよく使われるフォントスタイルを設定することで様々なフォントの変更が可能(例詳細説明)

CSS フォント プロパティは、テキストのフォント ファミリ、サイズ、太字、スタイル (斜体など)...

Nginxはctxを使用してデータ共有とコンテキスト変更機能を実現します。

環境: init_worker_by_lua、set_by_lua、rewrite_by_lua、a...

js で継承を実装する 5 つの方法

コンストラクタの借用この手法の基本的な考え方は単純です。サブタイプ コンストラクター内からスーパータ...

CSS の 4 つのインポート方法と優先順位の簡単な分析

第一に: CSSを導入する4つの方法CSS を導入する方法には、インライン スタイル、埋め込みスタイ...

docker のインストールが完了し、bridge-nf-call-iptables が無効であると報告される問題を解決します

Centos マシンで docker のインストールが完了したら、docker info コマンドを...

HTML と CSS に関する基本的なメモ (フロントエンドでは必読)

HTMLに触れた当初はレイアウトにいつもテーブルを使っていましたが、とても面倒で見た目も悪かったの...

Reactで例外を適切にキャプチャする方法

目次序文エラー境界エラー境界を超えてトライ/キャッチwindow.onerror、エラーイベント未処...

Docker で Elasticsearch Kibana と ik Word Segender をデプロイする詳細な説明

esインストール docker pull elasticsearch:7.4.0 # -d : バッ...

ウェブサイトを構築するときは、UTF-8 または GB2312 エンコードを使用する必要がありますか?

外国のウェブサイトを開くと文字化けした文字が表示されることが多く、また、英語以外の外国のウェブサイト...

HTML 固定タイトル列、タイトル ヘッダー テーブル固有の実装コード

コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC "...