この記事では、SQL 更新ステートメントを実行するプロセスを紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。
これまで、クエリ ステートメントの実行プロセスを体系的に理解し、実行プロセスに関与する処理モジュールを紹介しました。クエリ ステートメントの実行プロセスは、通常、コネクタ、アナライザー、オプティマイザー、エグゼキューターなどの機能モジュールを経由して、最終的にストレージ エンジンに到達することをまだ覚えていると思います。
それでは、更新ステートメントの実行フローはどのようなものでしょうか?
以前、DBA の同僚から、MySQL は半月以内でいつでも元の状態に復元できるという話をよく聞いたことがあるかもしれません。驚くと同時に、これがどのように行われるのかについても興味があるかもしれません。
テーブルの更新ステートメントから始めましょう。次はこのテーブルの作成ステートメントです。このテーブルには主キー ID と整数フィールド c:# があります。 ##
mysql> create table T(ID int primary key, c int);行 ID=2 の値に 1 を加算する場合、SQL ステートメントは次のように記述します。
mysql> update T set c=c+1 where ID=2;SQL の基本的な実行リンクを紹介しました。この写真をもう一度見て、確認することもできます。まず、クエリ ステートメントと更新ステートメントについても同じ一連のプロセスが実行されることは確実に言えます。 #ステートメントを実行する前にデータベースに接続する必要があります。これはコネクタの役割です。 テーブルに更新があると、このテーブルに関連するクエリ キャッシュが無効になると前に述べたので、このステートメントはテーブル T のキャッシュされた結果をすべてクリアします。このため、通常はクエリ キャッシュの使用を推奨しません。 次に、アナライザーは字句解析と構文解析を通じて、これが更新ステートメントであることを認識します。オプティマイザはインデックス ID を使用することを決定します。その後、エグゼキュータは実際にこの行を実行し、検索し、更新する責任を負います。 クエリ プロセスとは異なり、更新プロセスには、今日説明する主役である REDO ログ (REDO ログ) と binlog (アーカイブ ログ) という 2 つの重要なログ モジュールも含まれます。 MySQL に触れる場合、この 2 つの単語は絶対に避けて通ることはできません。以下のコンテンツでも引き続きこの 2 つの単語を強調していきます。ただし、そうは言っても、REDO ログと binlog の設計には興味深い側面が数多くあり、これらの設計アイデアは独自のプログラムでも使用できます。 重要なログ モジュール: やり直しログ記事「Kong Yiji」をまだ覚えているかどうかはわかりません。ホテルの支配人は、ゲストの信用記録を記録するために特別に使用されるピンクのボードを持っています。 。クレジットで支払う人が少ない場合は、顧客の名前と口座をボードに書くことができます。しかし、クレジットアカウントを持つ人が多すぎると、ファンボードがそれらを追跡できない場合が常に発生するため、店主はクレジットアカウントを記録するための専用の台帳を持っている必要があります。 誰かが信用を作りたい、または借金を返済したい場合、店主には通常 2 つの方法があります。
これと同様に、InnoDB の REDO ログはサイズが固定されています。たとえば、各ファイルのサイズが 1 GB の 4 つのファイルのセットとして構成できます。この場合、この「ピンクのボード」には合計 4 GB の操作を記録できます。以下の図のように、最初から書き始めて、最初に戻ってループして書きます。
write pos はカレントレコードの位置です書き込み中は逆方向(時計回り)に移動しますファイルNo.3の最後まで書き込んだ後先頭に戻りますファイルNo.0のチェックポイントは消去する現在位置であり、前方に移動してループします。レコードを消去する前に、レコードをデータ ファイルに更新する必要があります。
書き込み pos とチェックポイントの間のスペースは、新しい操作を記録するために使用できる「ピンクのボード」の空の部分です。書き込み pos がチェックポイントに追いついた場合、「ピンクのボード」がいっぱいであることを意味します。現時点では、新しい更新は実行できません。チェックポイントを進めるには、まず停止していくつかのレコードを消去する必要があります。
REDO ログを使用すると、InnoDB はデータベースが異常に再起動した場合でも、以前に送信されたレコードが失われないことを保証できます。この機能はクラッシュ セーフと呼ばれます。
クラッシュセーフの概念を理解するには、以前の信用記録の例を思い浮かべてください。信用記録がピンクのボードに記録されているか台帳に記載されていれば、店主が数日間突然営業を停止するなど、後で忘れてしまったとしても、台帳のデータから信用口座を明らかにすることができ、営業再開後のピンクボード。
前に述べたように、MySQL 全体には実際には 2 つの部分があります。1 つはサーバー層で、主に MySQL の機能レベルで処理を行います。エンジン層もあり、ストレージに関連する特定の問題を担当します。上で説明したピンクのボードの REDO ログは InnoDB エンジンに固有のログであり、サーバー層にも binlog (アーカイブ ログ) と呼ばれる独自のログがあります。
なぜログが 2 つあるのかと疑問に思われると思います。
MySQL には最初から InnoDB エンジンがなかったからです。 MySQL 独自のエンジンは MyISAM ですが、MyISAM にはクラッシュセーフ機能がなく、binlog ログはアーカイブにのみ使用できます。 InnoDB は、他社によってプラグインの形で MySQL に導入されましたが、binlog のみに依存するとクラッシュ セーフ機能がないため、InnoDB は別のログ システム、つまり REDO ログを使用してクラッシュ セーフ機能を実現します。
2 つのログには次の 3 つの違いがあります。
これら 2 つのログの概念を理解した上で、この単純な更新ステートメントを実行するときのエグゼキューターと InnoDB エンジンの内部プロセスを見てみましょう。
この update ステートメントの実行フローチャートを示しますが、図中の明るいボックスは InnoDB 内で実行されることを示し、暗いボックスはエグゼキューターで実行されることを示します。
最後の 3 つのステップが少し「循環」しているように見えることに気づいたかもしれません。REDO ログの書き込みは、準備とコミットの 2 つのステップに分かれています。これは「2 つ」です。 -フェーズコミット」。
なぜ「2 段階の提出」が必要なのでしょうか?これは、2 つのログ間のロジックを一貫させるためです。この問題を説明するには、この記事の冒頭の質問から始める必要があります。「データベースを半月以内に任意の秒の状態に復元するにはどうすればよいですか?」
前に述べたように、binlog はすべての論理操作を記録し、「追記書き込み」の形式を採用します。 DBA が半月以内に復元できると約束した場合、バックアップ システムは確実に過去半月のすべてのバイナリ ログを保存し、データベース全体を定期的にバックアップします。ここでの「定期的」とは、システムの重要性に応じて、1 日に 1 回または週に 1 回にすることができます。
指定した秒に復元する必要がある場合、たとえば、ある日の午後 2 時にテーブルが正午に誤って削除されたことに気づき、データを取得する必要があるとします。
このようにすると、一時データベースは誤って削除される前のオンライン データベースと同じになります。その後、必要に応じて一時データベースからテーブル データを取り出し、オンライン データベースに復元できます。 。
さて、データ回復プロセスについての説明は終わりましたので、戻ってログに「2 段階の送信」が必要な理由について話しましょう。ここでは、矛盾による証明を使って説明することもできます。
引き続き、前の update ステートメントを例として使用します。 ID=2 の現在の行でフィールド c の値が 0 であると仮定し、更新ステートメントの実行中、最初のログが書き込まれた後、2 番目のログが書き込まれる前にクラッシュが発生したと仮定します。 ?
「2 フェーズ コミット」が使用されていない場合、データベースの状態が、ログを使用して復元されたライブラリの状態と一致しない可能性があることがわかります。
「この可能性は非常に低いのでしょうか? 一時ライブラリをいつでも復元する必要がある状況はないのでしょうか?」と思われるかもしれません。
実はいいえ、このプロセスは誤操作後にデータを回復するためだけに必要なわけではありません。容量を拡張する必要がある場合、つまり、システムの読み取り容量を増やすためにさらにバックアップ データベースを構築する必要がある場合、現在の一般的な方法は、完全バックアップを使用し、binlog を適用してこれを実現することです。オンラインのマスター データベースとスレーブ データベース間の不一致です。
簡単に言えば、REDO ログと binlog の両方を使用してトランザクションのコミット ステータスを表すことができ、2 フェーズ コミットは 2 つの状態の論理的な一貫性を保つことです。
関連する推奨事項: 「mysql チュートリアル 」
以上がSQL更新ステートメントを実行するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。