Mysql 上級 (1) Mysql の実行プロセスとアーキテクチャ

クエリはどのように実行されるのでしょうか?

select id from student;

上記の単純なクエリ ステートメントは、student テーブルの ID をクエリします。では、Mysql はこのステートメントを、データを取得してクライアントに返すために必要な命令にどのように変換するのでしょうか? 大まかなフローチャートはこちら

画像-20220713165549179

まず、データはMysqlサーバー側に保存されます。アプリケーションまたはツールはクライアントです。データベースを読み取るための最初のステップは、データベースとの接続と通信を確立することです。では、クライアントはどのようにサーバーと通信するのでしょうか?

同意書

Mysql は、TCP/IP プロトコル、Unix ソケット プロトコル、共有メモリ プロトコル、名前付きパイプ プロトコルなどのさまざまな通信プロトコルをサポートし、同期/非同期モードを使用でき、長い接続/短い接続をサポートします。

通信タイプ: 同期または非同期

同期する

1. 同步通信依赖于被调用方,受限于被调用方的性能,也就是是说,应用操作数据库,线程会阻塞,等待数据返回
2. 一般只能做到一对一,很难做到一对多的通信

非同期

  1. 非同期によりアプリケーションのブロックや待機を回避できますが、SQL の実行時間を計算することはできません。
  2. 非同期で同時実行性がある場合、データの混乱を避けるために各 SQL 実行で個別のリンクを確立する必要がありますが、これはサーバーに大きな負荷をもたらします (接続はスレッドであり、スレッドの切り替えにより多くの CPU リソースが消費されます)。また、コーディングが複雑になるため (追記: 最近、会社の Node.js プロジェクト (非同期 io) に圧倒されています)、一般的には推奨されません。非同期を使用する場合は、接続を作成するのではなく、接続プールから接続を取得するためにキューイングを使用する必要があります。

一般に、データベースへの接続には同期接続を使用します。

接続モード: ロング接続またはショート接続

Mysql は長い接続と短い接続の両方をサポートしていますが、一般的に言えば、これは長い接続であり、この長い接続はクライアントの接続プールに入れられます。

サーバー側では、show status コマンドを使用して、Mysql が現在持っている接続数を表示できます。

show global status like 'Thread%'

画像-20220713172916527

接続またはセッションが生成されるたびに、それを処理するためにサーバー側でスレッドが作成されます。

分野 意味
スレッドキャッシュ済み キャッシュ内のスレッド接続の数
スレッド接続済み 現在の開いている接続の数
スレッド作成数 接続を処理するために作成されたスレッドの数
スレッド実行中 非スリープ状態の接続数。通常は同時接続数を指します。

長時間接続を維持するとメモリが消費されます。接続が長時間非アクティブな場合、Mysql サーバーは自動的に切断されます。デフォルトの時間は 8 時間 28800 秒です。

show global variables like 'wait_timeout' --非交互式超时时间,如JDBC程序
show global variables like 'interactive_timeout' --交互式超时时间,如数据库工具navicat

画像-20220713174022203

Mysql サービスで許可される接続の最大数はデフォルトで 15 で、最大値は 10,000 に設定できます。

show variables like 'max_connections'

画像-20220713183251988

**パラメータ レベルの説明: **Mysql のパラメータはセッション レベルとグローバル レベルに分割されており、現在のセッションとグローバルで有効ですが、すべてのパラメータに 2 つのレベルがあるわけではありません。たとえば、max_connections にはグローバル レベルのみがあります。パラメータがない場合、デフォルトはクエリと変更を含むセッション レベルです。たとえば、パラメータを変更した後、クエリはこのウィンドウでは有効になりますが、他のウィンドウでは有効になりません。これが一般的な方法です。変更トランザクションを送信するには

show variables like 'autocommit';
set autocommit = on; --默认为session级别,只在当前窗口有效

同意書

  1. TCP/IPプロトコル

通常、私たちはこのプロトコルを通じて MySQL に接続し、さまざまな主要なプログラミング言語がこのプロトコルに従って接続モジュールを実装しています。mysql -h xx.xx.xx.xx -u root -p

  1. Unixソケットプロトコル

このプロトコルを使用して MySQL に接続するには物理ファイルが必要であるため、通常、このプロトコルを使用して MySQL サーバーにログインします。ファイルの保存場所は構成ファイルで定義されます。デフォルトのアドレスは /var/lib/mysql です。 /mysql.sock、これは言及する価値があります。驚くべきことに、これはすべてのプロトコルの中で最も効率的です。

  1. 共有メモリプロトコル

ほとんどの人はこのプロトコルを知りませんし、Windows でのみ使用できるため、絶対に使用されません。このプロトコルを使用するには、起動時に構成ファイルで –shared-memory パラメーターを使用する必要があります。このプロトコルは、サーバーのみが存在できるため、他のプロトコルが正常に動作しないと疑う場合を除き、通常は役に立ちません。実際、Microsoft の SQL Sever もこのプロトコルをサポートしています。

  1. 名前付きパイププロトコル

このプロトコルは Windows でのみ使用できます。共有メモリと同様に、このプロトコルを使用すると、異なるポートが使用されている場合でも、ホスト上に存在できるサーバーは 1 つだけです。名前付きパイプは LAN 用に開発されたプロトコルです。メモリの一部は、あるプロセスによって別のプロセスに情報を渡すために使用されるため、あるプロセスの出力は別のプロセスの入力になります。2 番目のプロセスは、ローカル (最初のプロセスと同じコンピュータ上) またはリモート (ネットワーク接続されたコンピュータ上) にすることができます。このため、環境内に TCP/IP 環境が存在しないか無効になっている場合でも、それが Windows サーバーであっても、データベースは引き続き動作します。このプロトコルを使用するには、起動時に --enable-named-pipe オプションを追加する必要があります

コミュニケーションの方法

  • **シンプレックス:** 2 台のコンピュータが通信する場合、データ送信はリモコンと同様に一方向です。
  • **半二重:** 2 台のコンピュータ間でのデータ送信は双方向であり、あなたが私に送信することも、私があなたに送信することもできます。ただし、この通信接続では、同時に通信できるのは 1 台のサーバーのみです。 . データを送信します。つまり、データを同時に送信することはできません。データの送信を続けるには、送信されたデータを待つ必要があります。これは、人生におけるトランシーバーに似ています。
  • **全二重: **データ送信は双方向であり、携帯電話の通話と同様に同時に送信できます。

MySQL は半二重通信方式を使用します。接続では、クライアントがサーバーにデータを送信するか、サーバーがクライアントにデータを送信します。これら 2 つのアクションは同時に実行できないため、クライアントは SQL ステートメントをサーバーに送信します。 . 最後に、(1 つの接続内で) データを細かく分割して送信することはできず、SQL ステートメントがどんなに大きくても、一度に送信されます。クエリ内のステートメントが長すぎる場合、クエリ処理で問題が発生する可能性があります。このとき、max_allowed_packetMysql サーバー設定パラメータの値を調整する必要があり、値を増やすとエラーが報告されます。

画像-20220816152100900

一方、サーバーの場合は、すべてのデータが一度に送信されるため、目的のデータを取得したからといって操作を中断することはできず、このときネットワークとメモリを大量に消費します。そのため、プログラムでは、条件を満たすデータを一度にすべて見つけるには、最初にカウントしなければならない、データ量が多い場合には、そのような操作を際限なく避ける必要があります。バッチでクエリされます。

クエリキャッシュ

mysql8.0 では削除されているため使用は推奨されず、独立したキャッシュサーバーにキャッシュを引き渡して運用することをお勧めします。

語彙文法分析と前処理 (パーサー、プリプロセッサ)

mysql クエリが間違ったクエリ ステートメントを入力すると、サーバーは 1064 エラーを報告します。では、mysql は入力内容が間違っていることをどのようにして知るのでしょうか? これは主に、 Mysql のParser パーサーPreprocessor 前処理モジュールによって行われます。

画像-20220816153102331

たとえば、単純なクエリ ステートメントはselect name from user where id = 1、「=」を含む 8 つの記号に分割されます。次に、文法分析によって、引用符が閉じられているかどうかなど、SQL ステートメントの文法チェックが行われます。字句および文法分析が完了すると、Mysql は、定義された文法に従って SQL ステートメントを新しいデータ構造に解析します。解析ツリー (select_lex) と呼ばれるこのデータ構造を使用します。

画像-20220829162352256

字句構文は正しい SQL であるが、テーブル名またはフィールド名が存在しない場合、SQL ステートメントを解析するときに、プリプロセッサは、生成された解析ツリーをチェックして、パーサーが解析できないセマンティクスを解決します。テーブル名と列名が存在するか、名前と別名を確認し、曖昧さがないことを確認してください

クエリ オプティマイザーとクエリ実行プラン

オプティマイザーとは何ですか

解析木は実行者が認識できるデータ構造ですが、SQL文の実行方法は1つだけですか?それとも、データベースによって最終的に実行される SQL は、送信された SQL と同じですか? 答えは「いいえ」です。SQL ステートメントは複数の方法で実行でき、最終的には同じ結果を返します。これらは同等です。しかし、実行方法が非常にたくさんある場合、これらの実行方法はどのようにして取得されるのでしょうか? 結局どれを選ぶの?また、どのような基準で選びますか?

これは、MYSQL クエリ オプティマイザー モジュール (オプティマイザー) です。

クエリ オプティマイザーの目的は、解析ツリーに従ってさまざまな実行プラン (実行プラン) を生成し、最適な実行プランを選択することです。MySQL はコストベースのオプティマイザーを使用します。どの実行プランが最もコストが低いでしょうか? どちらかを使用してください。

-- 可以使用这个命令查看查询的开销
show status like "Last_query_cost"

オプティマイザーができること

MySQL のオプティマイザーはどのような最適化タイプを処理できますか? 簡単な例を 2 つ挙げます。

  1. 複数のテーブルに対して関連付けられたクエリを実行する場合、どのテーブルのデータが参照テーブルとして使用されます (どのテーブルが最初にアクセスされるか)。
  2. 利用可能なインデックスが複数ある場合にどのインデックスを選択するか。
  3. 1=1 などの恒等性の削除、不要な括弧の削除、式の計算、サブクエリや結合クエリの最適化など、クエリ条件の最適化。

それでは、オプティマイザーによって処理された後の結果は何でしょうか?MySQL はそれをどのように処理するのでしょうか?

オプティマイザの実行結果

オプティマイザは最終的に解析ツリーを実行プラン (execution_plans) に変換しますが、これもデータ構造です もちろん、MySQL がすべての実行プランをカバーしているわけではないため、この実行プランが必ずしも最適な実行プランであるとは限りません。SQL ステートメントの前に EXPLAIN を追加すると、実行計画情報を表示できます。キーは使用されるインデックスです。詳細な情報を取得したい場合は、次を使用することもできます。FORMAT = JSON

 explain select name from user_innodb where id = 1;
 explain format = json select name from user_innodb where id = 1;

画像-20220830163130696

ストレージエンジン

基本的な紹介

データをテーブルに保存する際には、ストレージ エンジンによって決定されるデータの保存構造も整理する必要があります。MySQL では、データベースが 1 つのストレージ エンジンのみを使用できるのではなく、作成する各テーブルでストレージ エンジンを指定できます。ストレージ エンジンはテーブル単位で使用され、ストレージ エンジンをテーブル タイプと呼ぶこともでき、ストレージ エンジンは次のことができます。作成後に変更することもできます。

データベース内の既存のテーブルのストレージ エンジンを表示する

show table status from <db>

画像-20220830172318269

デフォルトでは、各データベースにはフォルダーがあり、どのストレージ エンジンにもテーブル構造定義ファイルである frm ファイルがあります。ストレージ エンジンが異なれば、データの保存方法も異なり、生成されるファイルも異なります。innodb ストレージ エンジンは ibd で終わるファイルですが、メモリ ストレージ エンジンはそうではありません。myisam ストレージ エンジンには 2 つのファイルが含まれており、1 つは MYD で終わり、もう 1 つは MYI で終わります。

データベースデータファイルのディレクトリ

 show variables like 'datadir';
-- 默认目录为/var/lib/mysql

ストレージ エンジンの比較

このコマンドを使用して、データベースのストレージ エンジンのサポートを確認できます。

show engines;

画像-20220830180723914

ストレージ エンジンと、トランザクション、XA プロトコル、セーブポイントのサポートについて説明します。XA プロトコルは、分散トランザクション (ローカル リソース マネージャーとトランザクション マネージャーに分割) を実装するために使用されます。セーブポイントは、サブトランザクション (ネストされたトランザクション) を実装するために使用されます。セーブポイントを作成した後、セーブポイントが作成される前の操作に影響を与えることなく、トランザクションをこの時点までロールバックできます。

  • マイISAM

    MySQL に付属するストレージ エンジンは ISAM からアップグレードされています。公式 Web サイトのドキュメント https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html では、適用範囲は比較的小さく、テーブルレベルのロックにより読み取り/書き込みのパフォーマンスが制限されます。そのため、Web およびデータ ウェアハウスでは、構成において、通常、読み取り専用またはほとんど読み取り専用の作業に使用されます。

  • InnoDB

    MySQL 5.7 以降のデフォルトのストレージ エンジンは、頻繁に更新されるテーブルに適しており、同時読み取りと書き込み、またはトランザクション処理を伴うビジネス システムに適しています。InnoDB は、トランザクション セーフ (ACID 互換) の MySQL ストレージ エンジンで、コミット、ロールバック、ユーザー データを保護する機能、InnoDB 行レベル ロック (粗粒度ロックにアップグレードされていない)、Oracle スタイルの一貫した読み取りにより、マルチユーザーの同時実行性とパフォーマンスが向上し、InnoDB テーブルはディスク上のデータを配置してプライマリ ベースのクエリを最適化します。キー 、各 InnoDB テーブルにはクラスター化インデックスと呼ばれる主キー インデックスがあり、主キー検索の I/O を最小限に抑えるためにデータを整理します。データの整合性を確保するために、InnoDB は外部キーを使用して挿入、更新をチェックする FOREIGN KEY 制約をサポートしています。 、および削除して、関連テーブル間で不整合が発生しないようにします。公式 Web サイトのドキュメント https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html

    特徴

    1. トランザクションと外部キーをサポートしているため、データの整合性と一貫性がより高くなります。
    2. 行レベルのロックとテーブルレベルのロックをサポートします。
    3. 読み取りと書き込みの同時実行、読み取りをブロックせずに書き込み (MVCC) をサポートします。
    4. 特別なインデックス保存方法により IO が削減され、クエリ効率が向上します。
  • メモリ

    重要ではないデータをすぐに見つける必要がある環境での高速アクセスのために、すべてのデータを RAM に保存します。データをメモリに保存すると、読み取りと書き込みの速度は非常に高速になりますが、データベースが再起動またはクラッシュすると、すべてのデータが失われます。これは、テーブル内のデータをメモリに保存する一時テーブルの実行にのみ適しており、デフォルトでハッシュ インデックスが使用されます。

  • CSV(3ファイル)

    そのテーブルは、実際にはカンマ区切りの値を持つテキスト ファイルです。CSV テーブルを使用すると、同じ形式で読み書きするスクリプトやアプリケーションとデータを交換するために、データを CSV 形式でインポートまたはダンプできます。CSV テーブルにはインデックスがないため、通常は通常の操作中はデータを Innodb テーブルに保持し、インポートまたはエクスポート フェーズ中にのみ CSV テーブルを使用します。

    特徴:空白行は使用できず、インデックスはサポートされていません。形式は共通で直接編集できるため、異なるデータベース間でのインポートおよびエクスポートに適しています。

  • アーカイブ(2ファイル)

    これらのコンパクトなインデックスのないテーブルは、めったに参照されない大量の履歴情報、アーカイブ情報、またはセキュリティ監査情報を保存および取得するために使用されます。

    **機能:** インデックス、更新削除はサポートしていません。

ストレージ エンジンが異なれば提供する機能も異なり、ストレージ メカニズム、インデックス付け方法、ロック レベル、その他の機能も異なります。

さまざまなビジネス シナリオでは、データベースの要件に応じて、ニーズを満たすさまざまなストレージ エンジンを選択できます。これが、mysql が非常に多くのストレージ エンジンをサポートする理由です。

ストレージ エンジンの選び方

データの一貫性に対する高い要件があり、トランザクションをサポートする必要がある場合は、InnoDB を選択できます。

データ クエリが多く更新が少なく、クエリのパフォーマンス要件が比較的高い場合は、MyISAM を選択できます。

クエリ用の一時テーブルが必要な場合は、[メモリ] を選択できます。

すべてのストレージ エンジンが要件を満たせない場合は、公式 Web サイトの内部マニュアルでストレージ エンジンを開発できます。

更新SQLはどのように実行されるのでしょうか?

更新プロセスとクエリプロセスの違いは何ですか? 基本的なプロセスは同じです。つまり、パーサー、オプティマイザーによって処理され、最終的にエグゼキューターに渡される必要があります。違いは、適格なデータを取得した後の操作にあります

バッファプール

まず、Innodb の場合、データはディスク上に配置されますが、データを操作するには、ストレージ エンジンがディスク上のデータをメモリにロードしてから動作する必要があります。

ここで疑問があります。一度にディスクからメモリにロードするデータの量はどれくらいで、必要なだけ取り込めるのでしょうか? ディスク I/O 操作はメモリ操作に比べて非常に時間がかかり、必要なデータがディスク上の別の場所に分散している場合、多くの I/O 操作が発生することになります。

したがって、オペレーティング システムとストレージ エンジンの両方には、ディスク上のデータが読み取られると、その近くの場所もすぐに読み取られる可能性が高い、先読みの概念があり、これを局所性原則と呼びます。このようにして、必要なだけ読み取るのではなく、読み取るたびにさらに多くのデータを読み取るだけです。

InnoDB では、ディスクからメモリにデータを読み取るための最小単位をページと呼びます。これはオペレーティング システムのページに似ています。オペレーティング システムのページ サイズは通常 4K ですが、InnoDB のページ サイズは 16Kb です。は論理ユニットです。この値のサイズを変更する必要がある場合は、ソース コードを変更し、再コンパイルしてインストールする必要があります。

データ ページの操作では、毎回ディスクを直接操作してディスクからメモリにロードすると考えますが、これでは遅くなりますか? これらのページをキャッシュしてデータのロードを高速化することはできますか。

InnoDB はバッファ プール テクノロジを使用します。つまり、ディスクから読み取られたページをメモリ領域に配置します。次回同じページを読み取るときは、まずそのページがこのメモリ領域にあるかどうかを確認します。メモリ領域にある場合は、直接読み取ります。その後、再度ディスクからロードせずに動作します。このメモリ領域はバッファプールと呼ばれます。

データを変更するときは、まずメモリ バッファ プール内のページを変更します。メモリ内のデータ ページがディスク データと一致しない場合、それらをダーティ ページと呼びます。ダーティ ページはいつディスクに同期されますか?

InnoDB には、バッファ プールのデータをディスクに書き込み、時々複数の変更を一度にディスクに書き込むための特別なバックグラウンドがあります。このアクションはダーティと呼ばれます。

InnoDB のメモリ構造とディスク構造

画像-20230506170646449

メモリ構造には主にバッファ プール、変更バッファ、ログ バッファ AHI が含まれます。

  1. バッファプール

    ページ情報はバッファ プールにキャッシュされ、デフォルトのサイズは 128M ですが、変更および調整できます。

  2. (やり直し)ログバッファ

    フラッシュはリアルタイムではないため、BufferPool 内のダーティ ページがディスクにフラッシュされていない場合、データベースがダウンするか再起動され、データが失われます。メモリ内のデータには永続的な手段が必要です。この問題を回避するために、InnoDB はすべてのページ変更操作をログ ファイルに書き込みます。ディスクに同期されていないデータがある場合、データベースは起動時にこのログ ファイルから回復します (クラッシュ セーフを実現するため)。私たちが話しているトランザクション ACID の D (永続性) はそれとともに実装されています。

    このログ ファイルは、ディスクの REDO ログ (REDO ログと呼ばれます) であり、/var/lib/mysql/ ディレクトリの ib_logfile0 および ib_logfile1 に対応します。デフォルトでは 2 つのファイルがあり、それぞれ 48M です。show variables like 'innodb_log'

    1. ディスクにも書き込まれます。db ファイルに直接書き込むのではなく、最初にログを書き込んでからディスクに書き込むのはなぜですか? ログ ファイルへの書き込みとデータ ファイルへの書き込みの違いは何ですか?

      データはさまざまなセクターに分散されており、db ファイルへの書き込みにはランダム I/O であるディスク操作が必要ですが、ロギングはシーケンシャル I/O (継続的に書き込まれる) であり、シーケンシャル I/O の方が効率的であるため、ログ ファイルを変更すると、メモリ データのセキュリティを確保しながらディスクをフラッシュするタイミングを遅らせることができるため、システムのスループットが向上します。

    特徴:

    1. REDO ログは InnoDB ストレージ エンジンによって実装されますが、すべてのストレージ エンジンが備えているわけではありません。クラッシュ リカバリのサポートは InnoDB の機能です。
    2. REDOログとは、「特定のデータページにどのような変更が加えられたか」を記録する物理的なログです。
    3. REDO ログのサイズは固定されており、以前の内容は上書きされ、いっぱいになると、後続の変更のためのスペースを確保するために、バッファ プールとディスクの同期がトリガーされます。
  3. UNDOログ表領域

    アンドゥ ログ (アンドゥ ログまたはロールバック ログ) は、トランザクションが発生する前のデータの状態 (選択を除く) を記録し、データ変更時に例外が発生した場合に、アンドゥ ログを使用してロールバック操作を実装することができます (アトミック性を維持するため)。

    UNDO を実行すると、物理ページを操作するのではなく、データをトランザクション前の状態に論理的に復元するだけです。これはログの論理形式に属します。UNDO ログのデータは、デフォルトでシステム テーブルスペース Ibdata1 ファイルにあります。共有テーブルの弓矢は自動的に縮小されず、UNDO テーブルスペースも個別に作成できるためです。

これらのログを使用して、更新操作の流れを要約してみましょうupdate user set name = 'telangpu' where name = "baideng";

  1. トランザクションが開始されると、メモリ (バッファ プール) またはディスク (データ ファイル) がこのデータをフェッチし、サーバーのエグゼキュータに返します。
  2. サーバーのエグゼキュータは、このデータ行の値を telangpu に変更します。
  3. レコード名=baideng の元に戻すログ;
  4. レコード名=telangpu to redoログ
  5. ストレージ エンジン インターフェイスを呼び出して、メモリ バッファ プール内のデータを変更します。
  6. トランザクションのコミット

バックグラウンド スレッドが動作し、メモリ プール内のデータを更新し、変更されたデータをディスクに更新します。

ビンログ

Innodb アーキテクチャのログ ファイルを処理するために、Mysql のサーバー層には、すべてのストレージ エンジンで使用できる binlog と呼ばれるログ ファイルもあります。

binlog は、すべての DDL および DML ステートメントをイベントの形式で記録します。データではなく操作を記録します。binlog は、マスター/スレーブのレプリケーションとデータのリカバリに使用できます。REDO ログ ログとは異なり、binlog ログ ファイルは追加できます。固定サイズはありません。限界。

binlog 機能がオンになっている場合、binlog を SQL ステートメントにエクスポートし、すべての操作を再実行してデータ (アーカイブ) リカバリを実現できます。

おすすめ

転載: blog.csdn.net/Hong_pro/article/details/130533081