問題現象 最近、sysbench を使用して MySQL をテストしました。テストに長い時間がかかったため、準備 -> 実行 -> クリーンアップの順序でバックグラウンドで実行されるスクリプトを作成しました。実行後、ログを確認すると問題が見つかりました。MySQL サービスのエラー ログに次のようなエラーが複数ありました。
I/O エラーのように見えますが、MySQL プロセスはクラッシュせず、sysbench クライアントはエラーを報告しませんでした。 問題発見プロセス エラーの時間記録とスクリプト出力の各段階の時点の比較に基づいて、その時点でスクリプトによって実行されていたコマンドは次のとおりであると判定されました。
再度手動でテストケースを実行しましたが、同じ状況は再び発生しませんでした。ただし、スクリプトを実行すると、このエラー メッセージが引き続き表示されます。最初に疑われたのは、この問題は実行とクリーンアップの間の短い間隔によって引き起こされたということです。 100G のデータを実行するには時間がかかり、繰り返しコストも大きいため、まずはユースケースのデータ量を減らすようにしてください。 --table-size=4000000 を 2000000 に変更します。スクリプトを実行すると、この問題はトリガーされなくなります。最後に、トリガーを安定させ、再現時間を短縮するために、--table-size=3000000 を変更します。長い間隔によって問題が再現されないかどうかを確認するために、スクリプトは実行段階とクリーンアップ段階の間で 10 秒間スリープするように変更されました。確かに、このエラー メッセージはトリガーされませんでした。 5 秒間スリープするように変更すると、引き続きトリガーされる可能性がありますが、報告されるエラーの数は減少します。 問題調査 対応するバージョンの mysql5.7.22 のコードを確認すると、このエラーは fil0fil.cc ファイルの 5578 行目の fil_io() 関数の 1 か所でのみ発生することがわかりました。 gdb デバッグを直接使用し、この場所にブレークポイントを追加し、再現可能なスクリプトを実行して次のスタックを取得します。 (gdb) うーん #0 fil_io (type=...、sync=sync@entry=false、page_id=...、page_size=...、byte_offset=byte_offset@entry=0、len=16384、buf=0x7f9ead544000、message=message@entry=0x7f9ea8ce9c78)、mysql-5.7.22/storage/innobase/fil/fil0fil.cc:5580 #1 0x00000000010f99fa buf_read_page_low (err=0x7f9ddaffc72c、sync=<最適化出力>、type=0、mode=<最適化出力>、page_id=...、page_size=...、unzip=true)、mysql-5.7.22/storage/innobase/buf/buf0rea.cc:195 #2 0x00000000010fc5fa buf_read_ibuf_merge_pages (sync=sync@entry=false、space_ids=space_ids@entry=0x7f9ddaffc7e0、page_nos=page_nos@entry=0x7f9ddaffc7a0、n_stored=2)、mysql-5.7.22/storage/innobase/buf/buf0rea.cc:834 #3 0x0000000000f3a86c、ibuf_merge_pages (n_pages=n_pages@entry=0x7f9ddaffce30、sync=sync@entry=false)、mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2552 #4 0x0000000000f3a94a、ibuf_merge (sync=false、sync=false、n_pages=0x7f9ddaffce30)、mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2656 #5 ibuf_merge_in_background (full=full@entry=false)、mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2721 で #6 0x000000000102bcf4 srv_master_do_active_tasks () で、mysql-5.7.22/storage/innobase/srv/srv0srv.cc:2132 #7 srv_master_thread (arg=<最適化済み>)、mysql-5.7.22/storage/innobase/srv/srv0srv.cc:2383 #8 /lib64/libpthread.so.0 の start_thread() 内の 0x00007fa003eeddc5 #9 /lib64/libc.so.6 からの clone() で 0x00007fa002aab74d 明らかに、これは挿入バッファのマージ操作を実行しているバックグラウンド スレッドです。このとき、space->stop_new_ops が true であることがわかります。これは、処理対象のページが属するスペースが削除されていることを意味します。削除中のスペースに対して操作を行うのはなぜですか?これには、挿入バッファ機能、挿入バッファのマージ プロセス、およびテーブル削除プロセスを調査する必要があります。 挿入バッファの背景知識 挿入バッファは、補助インデックス ページがバッファ プールに存在しない場合に変更をキャッシュし、後で他の読み取り操作によってページがバッファ プールにロードされたときに変更をマージする特殊なデータ構造 (B+ ツリー) です。 MySQL がこの機能を導入した当初は、挿入操作のみをキャッシュできたため、挿入バッファと呼ばれていました。現在、これらの操作は INSERT、UPDATE、または DELETE (DML) であるため、変更バッファと呼ばれています (この記事では引き続き挿入バッファと説明しています)。ただし、ソース コードでは識別子として ibuf が引き続き使用されています。この機能は、同じページへの複数の更新をキャッシュし、それらを 1 回の更新操作にマージして、IO を削減し、ランダム IO をシーケンシャル IO に変換します。これにより、ランダム IO によるパフォーマンスの低下を回避し、データベースの書き込みパフォーマンスを向上させることができます。 関連する挿入バッファのマージロジック バッファ ページがバッファ プールに読み込まれると、挿入バッファのマージが実行されます。マージ プロセスが発生する主なシナリオはいくつかあります。
今回の問題は明らかに 2 番目のケースに属します。 InnoDB メイン スレッド (svr_master_thread) は、挿入バッファーに対して 1 秒ごとにマージ操作をアクティブに実行します。まず、過去 1 秒以内にサーバー上で何らかのアクティビティ (ページへのタプルの挿入、UNDO テーブルでの行操作など) があったかどうかを判断します。アクティビティがあった場合、マージするページの最大数は innodb_io_capacity 設定の 5% になります。そうでない場合、マージするページの最大数は innodb_io_capacity によって設定された値になります。 InnoDB メインスレッド (svr_master_thread) マージの主なプロセスは次のとおりです。
関連テーブルを削除するためのロジック
結論 状況は非常に明確です。メイン スレッドの ibuf (スペース、ページ) を取得するプロセスと削除操作を実行するプロセスの間には、相互排他性を保証するロックはありません。非同期 I/O が完了した後のマージ操作と削除操作のみが相互に排他的です。バックグラウンド スレッドが ibuf マージを開始し、ステップ 2 の検出を実行したが、ステップ 3 の検出をまだ実行しておらず、ユーザー スレッドがテーブルの削除を開始し、stop_new_ops フラグを設定したが、テーブルスペース キャッシュを削除するステップ 5 をまだ実行していない場合、このエラー メッセージが表示されます。 2 つのスレッド間の相互作用を次の図に示します。 予期しない事態が発生しない場合は、ブレークポイントに到達したときに、対応するテーブルの削除操作を実行しているスレッドが存在する必要があります。確かに、次のスタックが見つかります。 スレッド 118 (スレッド 0x7f9de0111700 (LWP 5234)): #0 0x00007fa003ef1e8e、pthread_cond_broadcast@@GLIBC_2.3.2 ()、/lib64/libpthread.so.0 から #1 0x0000000000f82f41 ブロードキャスト (this=0xd452ef8)、mysql-5.7.22/storage/innobase/os/os0event.cc:184 #2 が mysql-5.7.22/storage/innobase/os/os0event.cc:75 に設定されました (this=0xd452ef8) #3 os_event_set (イベント=0xd452ef8)、mysql-5.7.22/storage/innobase/os/os0event.cc:483 #4 0x00000000010ec8a4 シグナル内 (this=<最適化済み>)、mysql-5.7.22/storage/innobase/include/ut0mutex.ic:105 #5 終了 (this=<最適化済み>)、mysql-5.7.22/storage/innobase/include/ib0mutex.h:690 #6 終了 (this=<最適化済み>)、mysql-5.7.22/storage/innobase/include/ib0mutex.h:961 #7 buf_flush_yield (bpage=<最適化済み出力>、buf_pool=<最適化済み出力>)、mysql-5.7.22/storage/innobase/buf/buf0lru.cc:405 #8 buf_flush_try_yield (処理済み = <最適化済み>、bpage = <最適化済み>、buf_pool = <最適化済み>)、mysql-5.7.22/storage/innobase/buf/buf0lru.cc:449 #9 buf_flush_or_remove_pages (trx=<最適化済み>、flush=<最適化済み>、observer=<最適化済み>、id=<最適化済み>、buf_pool=<最適化済み>)、mysql-5.7.22/storage/innobase/buf/buf0lru.cc:632 #10 buf_flush_dirty_pages (buf_pool=<最適化出力>、id=<最適化出力>、observer=<最適化出力>、flush=<最適化出力>、trx=<最適化出力>)、mysql-5.7.22/storage/innobase/buf/buf0lru.cc:693 #11 buf_LRU_remove_pages の 0x00000000010f6de7 (trx=0x0、buf_remove=BUF_REMOVE_FLUSH_NO_WRITE、id=55、buf_pool=0x31e55e8)、mysql-5.7.22/storage/innobase/buf/buf0lru.cc:893 #12 buf_LRU_flush_or_remove_pages (id=id@entry=55、buf_remove=buf_remove@entry=BUF_REMOVE_FLUSH_NO_WRITE、trx=trx@entry=0x0)、mysql-5.7.22/storage/innobase/buf/buf0lru.cc:951 #13 0x000000000114e488 が fil_delete_tablespace (id=id@entry=55、buf_remove=buf_remove@entry=BUF_REMOVE_FLUSH_NO_WRITE) にあり、mysql-5.7.22/storage/innobase/fil/fil0fil.cc:2800 にあります #14 0x0000000000fe77bd、row_drop_single_table_tablespace (trx=0x0、is_encrypted=false、is_temp=false、filepath=0x7f9d7c209f38 "./sbtest/sbtest25.ibd"、tablename=0x7f9d7c209dc8 "sbtest/sbtest25"、space_id=55)、mysql-5.7.22/storage/innobase/row/row0mysql.cc:4189 #15 row_drop_table_for_mysql (name=name@entry=0x7f9de010e020 "sbtest/sbtest25"、trx=trx@entry=0x7f9ff9515750、drop_db=<最適化出力>、nonatomic=<最適化出力>、nonatomic@entry=true、handler=handler@entry=0x0)、mysql-5.7.22/storage/innobase/row/row0mysql.cc:4741 #16 0x0000000000f092f3、ha_innobase::delete_table (this=<最適化済み>、name=0x7f9de010f5e0 "./sbtest/sbtest25")、mysql-5.7.22/storage/innobase/handler/ha_innodb.cc:12539 #17 0x0000000000801a30 が ha_delete_table (thd=thd@entry=0x7f9d7c1f6910、table_type=table_type@entry=0x2ebd100、path=path@entry=0x7f9de010f5e0 "./sbtest/sbtest25"、db=db@entry=0x7f9d7c00e560 "sbtest"、alias=0x7f9d7c00df98 "sbtest25"、generate_warning=generate_warning@entry=true) にあります (mysql-5.7.22/sql/handler.cc:2586) #18 0x0000000000d0a6af が mysql_rm_table_no_locks (thd=thd@entry=0x7f9d7c1f6910、tables=tables@entry=0x7f9d7c00dfe0、if_exists=true、drop_temporary=false、drop_view=drop_view@entry=false、dont_log_query=dont_log_query@entry=false) にあります (mysql-5.7.22/sql/sql_table.cc:2546) #19 0x0000000000d0ba58、mysql_rm_table (thd=thd@entry=0x7f9d7c1f6910、tables=tables@entry=0x7f9d7c00dfe0、if_exists=<最適化されて出力>、drop_temporary=<最適化されて出力>)、mysql-5.7.22/sql/sql_table.cc:2196 #20 0x0000000000c9d90b、mysql_execute_command (thd=thd@entry=0x7f9d7c1f6910、first_level=first_level@entry=true)、mysql-5.7.22/sql/sql_parse.cc:3589 #21 0x0000000000ca1edd、mysql_parse (thd=thd@entry=0x7f9d7c1f6910、parser_state=parser_state@entry=0x7f9de01107a0)、mysql-5.7.22/sql/sql_parse.cc:5582 #22 0x0000000000ca2a20 が、dispatch_command (thd=thd@entry=0x7f9d7c1f6910、com_data=com_data@entry=0x7f9de0110e00、command=COM_QUERY) にあります (mysql-5.7.22/sql/sql_parse.cc:1458) #23 0x0000000000ca4377、do_command (thd=thd@entry=0x7f9d7c1f6910)、mysql-5.7.22/sql/sql_parse.cc:999 #24 0x0000000000d5ed00 が handle_connection (arg=arg@entry=0x10b8e910) にあり、mysql-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:300 にあります #25 0x0000000001223d74、pfs_spawn_thread (arg=0x10c48f40)、mysql-5.7.22/storage/perfschema/pfs.cc:2190 #26 /lib64/libpthread.so.0 の start_thread() で 0x00007fa003eeddc5 #27 0x00007fa002aab74d は /lib64/libc.so.6 からの clone() にあります 解決 buf_read_ibuf_merge_pages、buf_read_page_low、fil_io に新しいパラメータ ignore_missing_space を追加します。削除されるスペースを無視することを示します。デフォルト値は false で、ibuf_merge_pages が呼び出されると true に設定されます。 fil_io エラー報告領域では、パラメータが true であるかどうかもさらに判断されます。 true の場合、エラーは報告されず、他のプロセスは続行されます。 または、buf_read_ibuf_merge_pages が buf_read_page_low を呼び出すときに、IORequest::IGNORE_MISSING パラメータを直接渡します。 具体的なコードについては、MariaDB コミットを参照してください: 8edbb1117a9e1fd81fbd08b8f1d06c72efe38f44 影響を受けるバージョン 関連情報を確認してください。この問題は、Bug#19710564 を変更するときにテーブルスペースのバージョンを削除したときに発生しました。
最適化の提案 次のようにしてパフォーマンスを最適化できます。buf_read_ibuf_merge_pages にエラーのあるスペース ID を記録し、ループ中に次のページのスペース ID を判別し、スペース ID が同じ場合は、対応する ibuf レコードを直接削除します (現在割り当てられている最大スペース ID はシステム テーブルスペースに記録され、スペース ID は 0xFFFFFFF0UL より小さい 4 バイトを占めます。割り当てるときに、システム テーブルスペースに保存されている値を読み取り、一意になるように 1 を追加します)。 要約する 上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。 以下もご興味があるかもしれません:
|
>>: Vueのシンプルな状態管理ストアモードを理解する方法
目次序文列挙可能なプロパティ反復可能なオブジェクトforEachメソッドとmapメソッドチェーン呼び...
設定は非常にシンプルですが、毎回確認しないといけないので、記録だけ残しておきます。 1. インストー...
メタを使用して、ページの時間指定更新またはジャンプを実装します。 XML/HTML コードコンテンツ...
スレッドが同時に実行される場合、スレッドがリソースを競合してデータの曖昧さが生じるのを防ぐために、重...
この記事では、全選択と逆選択操作を実装するためのjQueryの具体的なコードを参考までに共有します。...
マージントップの崩壊とはmargin-top の崩壊は、CSS ボックス モデルで発生する現象です。...
最近、nginx をリバース プロキシとして使用し、docker で nginx を実行するシステム...
Flashにより、デザイナーや開発者はブラウザ上でリッチなコンテンツを提供し、動き、インタラクティブ...
目次1. グループクエリの概略図2. groupbyキーワード構文の詳細な説明3. 簡単なグループク...
通常の説明%はどのクライアントでも接続できることを意味しますlocalhostはローカルコンピュータ...
1.コマンドが見つかりません コマンドが見つかりません2. そのようなファイルまたはディレクトリは...
仮想マシンを初めて使用する方や、仮想マシンに Linux をインストールしたばかりの方は、システムが...
目次アレイ重複排除1. from() を新しい Set() メソッドに重ねる2. スプレッド演算子 ...
目次1. テレポート1.1 テレポートの紹介1.2 テレポートの使用1.3 プレビュー効果2. サス...
Yum (フルネームは Yellow dog Updater, Modified) は、Fedora...