導入 データベース理論についてさらに学んでいくうちに、さまざまな分離レベルによって起こり得る問題について学びました。理解を深めるために、これらの問題を MySQL データベースでテストし、再現しました。ダーティ リードと反復不可能なリードは、対応する分離レベルで簡単に再現できます。しかし、ファントム リードに関しては、繰り返し読み取り分離レベルでは発生しないことがわかりました。その時、MySQL がファントム リードに対処するために何かを行っているのではないかと考えました。 テスト: テストテーブル部門を作成します: テーブル「dept」を作成します( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) デフォルト NULL, 主キー (`id`) ) エンジン=InnoDB AUTO_INCREMENT=12 デフォルト文字セット=utf8 dept(name) に値("物流部門") を挿入します。
上記のプロセスによれば、トランザクション 1 の最初の選択では 1 つのデータが照会され、2 番目の選択では 2 つのデータ (トランザクション 2 によって送信されたデータを含む) が照会されることが予想されます。 しかし、実際のテストでは、2 番目の select は実際には 1 つのデータのみを照会して処理することがわかりました。ただし、データベース理論における繰り返し読み取りの実装 (排他ロックと共有ロック) によれば、これは当てはまりません。 実際の理由を理解する前に、物事の関連する理論を見直してみましょう。 データベースの原理理論 もの トランザクションとは、一般的に、実行されることや行われるべきことを指します。コンピュータ用語では、データベース内のさまざまなデータ項目にアクセスし、場合によっては更新するプログラム実行ユニットを指します。トランザクションは、トランザクションの開始から終了までの間に実行されるすべての操作で構成されます。リレーショナル データベースでは、トランザクションは一連の SQL ステートメントまたはプログラム全体になります。 私たちはなぜ物を持っているのでしょうか? データベース トランザクションは通常、データベースの読み取りまたは書き込みを行う一連の操作で構成されます。それは 2 つの目的のために存在します:
物事の特性 トランザクションには、原子性、一貫性、独立性、永続性という 4 つの特性があります。これら 4 つの特性は、ACID 特性と呼ばれることがよくあります。
物事間のいくつかの特性は同等の概念の集合ではありません。 一度に 1 つだけ存在する場合、それは自然に分離され、原子性が保証されている限り一貫性を実現できます。 同時実行性がある場合、一貫性を確保するために原子性と分離性を保証する必要があります。 同時データベーストランザクションの問題 トランザクションの分離を考慮しないと、次の問題が発生する可能性があります。
排他ロック、共有ロック 排他ロック。X ロック、書き込みロックとも呼ばれます。 共有ロックは、S ロック、読み取りロックとも呼ばれます。 読み取り/書き込みロックの関係は次のとおりです。
つまり、読み取り書き込みロックの関係は、複数の読み取りと単一の書き込みとして要約できます。 トランザクションの分離レベル トランザクションにはいくつかの分離レベルがあります。
MySQL における分離レベルの実装 上記の内容はデータベース理論のいくつかの概念を説明したものですが、MySQLやORACLEなどのデータベースでは、パフォーマンス上の理由から、上で紹介した理論に完全に従って実装されているわけではありません。 MVCC マルチバージョン同時実行制御 (MVCC) は、楽観的ロック理論に基づいて MySQL で分離レベルを実装する方法です。読み取りコミット分離レベルと反復可能読み取り分離レベルを実装するために使用されます。 実装(分離レベルは繰り返し読み取り) 実装方法について説明する前に、2 つの概念を紹介しましょう。
MySQL では、テーブル内の各レコードの後に 2 つのフィールドが追加されます。 バージョン番号の作成: データ行を作成するときに、現在のシステムバージョン番号を作成バージョン番号として割り当てます。 削除バージョン番号: データ行を削除すると、現在のシステムバージョン番号が削除バージョン番号として割り当てられます。 選択 選択中にデータを読み取るためのルールは、作成バージョン番号 <= 現在のトランザクション バージョン番号であり、削除バージョン番号は空または現在のトランザクション バージョン番号より大きいです。 作成バージョン番号 <= 現在のトランザクション バージョン番号により、取得されたデータには、後で開始されたトランザクションで作成されたデータが含まれないことが保証されます。これが、最初の例の後半で追加されたデータが見つからない理由です。 削除バージョン番号が空であるか、現在のトランザクション バージョン番号より大きいため、少なくともトランザクションが開始される前にはデータが削除されておらず、チェックアウトする必要があるデータであることが保証されます。 入れる 挿入時に、作成バージョン番号フィールドに現在のシステム バージョン番号を割り当てます。 アップデート 新しいレコードを挿入し、現在のトランザクション バージョン番号を行作成バージョン番号として保存し、現在のトランザクション バージョン番号を元々削除された行に保存します。実際、ここでの更新は削除と挿入を通じて実装されます。 消去 削除時には、コミットの実行時にデータが実際に削除されない場合でも、どのトランザクションでデータ行が削除されるかを示すために、現在のシステム バージョン番号が削除バージョン番号フィールドに割り当てられます。選択ルールに従ってデータを開いたとしても、データは見つかりません。 MVCC は本当にファントムリーディングを解決できるのでしょうか? 当初のテスト例と上記の理論的裏付けから、MySQL の MVCC によってファントム リードの問題が解決されたようです。シリアル リードは意味がないと思われるため、疑問を抱きながらテストを続けます。 事前テストデータ:
上記の結果に基づいて、次の結果が予想されます。
しかし実際のところ、私たちの経験では、 当初は最初のデータの部門を財務に変更することを希望していましたが、最終的には両方のデータが変更されました。この結果は、MySQL の繰り返し読み取り分離レベルはファントム読み取りの問題を完全に解決するわけではないが、データ読み取り時のファントム読み取りの問題を解決することを示しています。ただし、変更操作ではファントム リードの問題が依然として存在しており、これは MVCC のファントム リードに対するソリューションが完全ではないことを意味します。 スナップショット読み取りと現在の読み取り 上記のような状況が発生した場合、なぜそれが起こるのかを知る必要があります。いくつかの情報を調べた後、RR レベルでは、MVCC メカニズムによってデータが繰り返し可能になるものの、読み取るデータはデータベース内の最新のデータではなく、履歴データである可能性があることがわかりました。履歴データを読み取るこの方法はスナップショット読み取りと呼ばれ、データベースの最新バージョンを読み取る方法は現在の読み取りと呼ばれます。 スナップショット読み取りを選択 選択操作を実行すると、InnoDB はデフォルトでスナップショット読み取りを実行し、この選択の結果を記録します。このスナップショットのデータは、後続の選択で返されます。他のトランザクションがコミットされても、現在の選択のデータには影響しないため、繰り返し読み取りが実現されます。スナップショットは、select が初めて実行されたときに生成されます。つまり、A がトランザクションを開始し、その後何も操作を行わなかったとします。この時点で、B はデータを挿入してコミットします。この時点で、A は select を実行し、返されるデータには B によって追加されたデータが含まれます。スナップショットが生成され、後続の選択はスナップショットに基づいて行われるため、その後に他のトランザクションがコミットされても問題ありません。 現在の読書 データを変更する操作 (更新、挿入、削除) では、現在の読み取りモードが使用されます。これらの操作を実行すると、最新のレコードが読み取られ、他のトランザクションによって送信されたデータも照会できます。レコードを更新したいが、別のトランザクションでデータが削除されコミットされている場合、更新すると競合が発生するため、更新時には最新のデータを知る必要があります。まさにこのために、上でテストした状況が発生しました。 選択の現在の読み取りを手動でロックする必要があります。 select * from table where ? lock in share mode; 更新のために、? のテーブルから * を選択します。 説明すべき問題がある テスト開始当初は、begin 文を使うのはトランザクションを開始するためだと思っていました。そのため、上記の 2 番目のテストでは、トランザクション 1 が最初に開始されたため、トランザクション 2 で新しく追加されたデータがトランザクション 1 で見つかりました。このとき、これは以前の MVCC の選択ルールと矛盾していると思い、次のテストを行いました。 SELECT * FROM information_schema.INNODB_TRX //現在実行中のトランザクションを照会するために使用されます begin ステートメントを実行するだけでは、トランザクションは実際には開始されないことがわかります。 次に、begin の後に select ステートメントを追加します。 したがって、データの追加、削除、変更、チェックなどの操作が実行された後にのみ、トランザクションが実際に開かれることを理解することが重要です。 ファントムリードを解決する方法 明らかに、繰り返し読み取り分離レベルではファントム読み取りの問題を完全に解決することはできません。プロジェクトでファントム読み取りを解決する必要がある場合、次の 2 つの方法があります。
実際、上記の 2 つの方法は多くのプロジェクトで使用されていません。シリアル読み取りのパフォーマンスが悪すぎるため、ファントム読み取りでもまったく問題ないことがよくあります。 要約する 以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。 以下もご興味があるかもしれません:
|
<<: Dockerはrabbitmqのサンプルコードをインストールして実行します
>>: Vue-Routerのインストールと使用方法の詳細な説明
1 / Webプロジェクトファイルをwebappsディレクトリに直接コピーするこれは最も一般的に使...
目次1. Vueリスナー配列2. vueが配列の変更を監視できない状況1. Vueリスナー配列Vue...
1.MySQL UPDATE JOIN構文MySQL では、UPDATE ステートメントでJOIN句...
目次1. v-bind: 要素の属性にデータをバインドできる2. v-bind: は次のように省略で...
この記事では、例を使用して MySQL トリガーの構文とアプリケーションを説明します。ご参考までに、...
ネットワーク セキュリティは非常に重要なトピックであり、サーバーはネットワーク セキュリティにおける...
目次序文1. イントラネットDNS AレコードとMXレコードを構成する2. メールサーバの初期化設定...
最近、私は毎日論文提案に取り組んでいます。自分のスキルを発揮して、再びWebをデザインしたくてうずう...
背景webpackのバージョンを確認したいのですが、webpack -vを実行するとエラーが報告され...
目次基本設定エントリファイル main.jsアプリ.vue表紙ヘッダー検索バー本体当プロジェクトでは...
1. フレームセット、フレーム、iframeを使用して複数のウィンドウを実現する2. 画像上のマッ...
ご存知のとおり、私たちが毎日閲覧する Web ページ、Web サイト、または Web ページには独自...
CS: ... 1. <link type="text/css" href...
問題の説明: mysqladmin.exe を使用してコマンドを実行すると、次のエラー メッセージが...
前回の「最もシンプルなスイッチを実現するCSS」のように、HTML5とCSS3でほとんどの機能をすで...