MySQLのkillがスレッドをkillできない理由

MySQLのkillがスレッドをkillできない理由

背景

日常の使用において、MySQL で個別または大量の接続が蓄積されることが時々あります。このような場合、通常は、kill コマンドを使用してこれらの蓄積された接続を強制的に強制終了し、接続数とデータベース サーバーの CPU リソースをできるだけ早く解放することを検討します。

問題の説明

実際に kill コマンドを使用すると、接続はすぐには終了せず、プ​​ロセス リストにはまだ表示されますが、表示されるコマンドは一般的なクエリや実行ではなく、Killed になります。例えば:

mysql> プロセスリストを表示します。
+----+------+--------------------+---------+--------+------+--------------+--------------------------------+
| ID | ユーザー | ホスト | db | コマンド | 時間 | 状態 | 情報 |
+----+------+--------------------+---------+--------+------+--------------+--------------------------------+
| 31 | root | 192.168.1.10:50410 | sbtest | クエリ | 0 | 開始 | プロセスリストを表示 |
| 32 | root | 192.168.1.10:50412 | sbtest | クエリ | 62 | ユーザー sleep | select sleep(3600) from sbtest1 |
| 35 | root | 192.168.1.10:51252 | sbtest | 強制終了 | 47 | データ送信中 | select sleep(100) from sbtest1 |
| 36 | root | 192.168.1.10:51304 | sbtest | クエリ | 20 | データを送信中 | select sleep(3600) from sbtest1 |
+----+------+--------------------+---------+--------+------+--------------+--------------------------------+

原因分析

疑問がある場合は、まず公式ドキュメントを参照してください。以下は公式ドキュメントからの抜粋です。

KILL を使用すると、スレッド固有の kill フラグがスレッドに設定されます。ほとんどの場合、kill フラグは特定の間隔でのみチェックされるため、スレッドが終了するまでに多少時間がかかることがあります。SELECT 操作中、ORDER BY および GROUP BY ループでは、行のブロックを読み取った後にフラグがチェックされます。kill フラグが設定されている場合、ステートメントは中止されます。
テーブルのコピーを作成する ALTER TABLE 操作では、元のテーブルからコピーされた行がいくつか読み取られるたびに、定期的に kill フラグがチェックされます。kill フラグが設定されている場合、ステートメントは中止され、一時テーブルは削除されます。
KILL ステートメントは確認を待たずに戻りますが、kill フラグ チェックによって、かなり短い時間内に操作が中止されます。必要なクリーンアップを実行するために操作を中止するのにも、ある程度の時間がかかります。
UPDATE または DELETE 操作中、各ブロックの読み取り後、および各行の更新または削除後に、kill フラグがチェックされます。kill フラグが設定されている場合、ステートメントは中止されます。トランザクションを使用していない場合、変更はロールバックされません。
GET_LOCK() は中止され、NULL を返します。
スレッドがテーブル ロック ハンドラー (状態: ロック) 内にある場合、テーブル ロックはすぐに中止されます。
スレッドが書き込み呼び出しで空きディスク領域を待機している場合、書き込みは「ディスクがいっぱいです」というエラー メッセージとともに中止されます。

公式ドキュメントの最初の段落には、kill のメカニズムが明確に記載されています。接続されたスレッドに対してスレッド レベルの kill マークが設定され、次の「マーク検出」まで有効になりません。これは、次の「マーク検出」が間に合わなかった場合、問題で説明した現象が発生する可能性があることも意味します。

公式ドキュメントには、いくつかのシナリオがリストされています。公式の説明に基づいた、よくある問題のシナリオをいくつか示します。

  • SELECT ステートメントで order by および group by を実行するときに、サーバーの CPU リソースが不足していると、データのバッチの読み取り/取得にかかる時間が長くなり、次の「マーク検出」の時間に影響します。
  • 大量のデータに対して DML 操作を実行する場合、kill などの SQL ステートメントはトランザクションのロールバックをトリガーします (InnoDB エンジン)。ステートメントは強制終了されますが、ロールバック操作には非常に長い時間がかかります。
  • キル変更操作中にサーバーの負荷が高い場合、データのバッチ操作にかかる時間が長くなり、次の「マーク検出」の時間に影響します。
  • 実際、kill のメカニズムを参照して帰納的に説明すると、SQL ステートメントの通常の実行をブロック/遅くする動作があると、次の「マーク検出」が延期されるか実行できなくなり、最終的に kill 操作が失敗することになります。

シミュレーションする

ここでは、パラメータ innodb_thread_concurrency を使用して、SQL ステートメントの通常の実行をブロックするシナリオをシミュレートします。

InnoDB 内で許可されるスレッドの最大数を定義します。値 0 (デフォルト) は、無制限の同時実行 (制限なし) として解釈されます。この変数は、高同時実行システムでのパフォーマンス チューニングを目的としています。

公式ドキュメントによると、このパラメータが低い値に設定されている場合、制限を超える InnoDB クエリはブロックされます。したがって、このシミュレーションでは、このパラメータは非常に低い値に設定されました。

mysql> '%innodb_thread_concurrency%' のような変数を表示します。
+---------------------------+-------+
| 変数名 | 値 |
+---------------------------+-------+
| innodb_thread_concurrency | 1 |
+---------------------------+-------+
セット内の 1 行 (0.00 秒)

次に、2 つのデータベース接続 (セッション 1 とセッション 2) を開き、それぞれでselect sleep(3600) from sbtest.sbtest1ステートメントを実行してから、3 番目の接続でセッション 2 のクエリを強制終了します。

セッション 1:
mysql> sbtest.sbtest1 から sleep(3600) を選択します。

セッション2:
mysql> sbtest.sbtest1 から sleep(3600) を選択します。
エラー 2013 (HY000): クエリ中に MySQL サーバーへの接続が失われました
マイSQL>

セッション3:
mysql> プロセスリストを表示します。
+----+------+--------------------+-------+--------+------+--------------+-----------------------------------------+
| ID | ユーザー | ホスト | db | コマンド | 時間 | 状態 | 情報 |
+----+------+--------------------+-------+--------+------+--------------+-----------------------------------------+
| 44 | root | 172.16.64.10:39290 | NULL | クエリ | 17 | ユーザー sleep | sbtest.sbtest1 から sleep(3600) を選択 |
| 45 | ルート | 172.16.64.10:39292 | NULL | クエリ | 0 | 開始 | プロセスリストを表示 |
| 46 | root | 172.16.64.10:39294 | NULL | クエリ | 5 | データを送信中 | select sleep(3600) from sbtest.sbtest1 |
+----+------+--------------------+-------+--------+------+--------------+-----------------------------------------+
セット内の 3 行 (0.00 秒)

mysql> 46 を強制終了します。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> プロセスリストを表示します。
+----+------+--------------------+-------+--------+------+--------------+-----------------------------------------+
| ID | ユーザー | ホスト | db | コマンド | 時間 | 状態 | 情報 |
+----+------+--------------------+-------+--------+------+--------------+-----------------------------------------+
| 44 | root | 172.16.64.10:39290 | NULL | クエリ | 26 | ユーザー sleep | sbtest.sbtest1 から sleep(3600) を選択 |
| 45 | ルート | 172.16.64.10:39292 | NULL | クエリ | 0 | 開始 | プロセスリストを表示 |
| 46 | root | 172.16.64.10:39294 | NULL | 強制終了 | 14 | データを送信中 | sbtest.sbtest1 から sleep(3600) を選択 |
+----+------+--------------------+-------+--------+------+--------------+-----------------------------------------+
セット内の 3 行 (0.00 秒)

マイSQL>

ご覧のとおり、kill コマンドが実行されると、セッション 2 の接続はすぐに切断されますが、セッション 2 によって開始されたクエリは MySQL に残っています。もちろん、 innodb_thread_concurrencyパラメータによって同様の問題が発生している場合は、 set globalコマンドを使用して上限値を直接増やすか、直接 0 に設定して解決できます。このパラメータの変更は、すべての接続に対してリアルタイムで有効になります。

総括する

MySQL の kill 操作は、想像どおりにデータベース接続を直接強制的に終了するわけではありません。終了信号を送信するだけです。SQL 自体の実行効率が遅すぎる場合、または他の要因 (サーバーの負荷が高い、大量のデータ ロールバックがトリガーされる) の影響を受けている場合は、この kill 操作では、問題のあるクエリを時間内に終了できない可能性があります。それどころか、プログラム側の接続が切断された後に再接続がトリガーされ、クエリの効率がさらに低下し、データベースのパフォーマンスがさらに低下する可能性があります。

上記は、MySQL kill がスレッドを強制終了できない理由の詳細です。MySQL kill スレッドの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Mysql は、デッドロック問題を解決するために kill コマンドを使用します (実行中の特定の SQL ステートメントを強制終了します)。
  • mysql show processlistはmysqlクエリプロセスを表示します。
  • MYSQL でプロセスを表示および終了する方法

<<:  Webデザイン: スクリプト素材でユーザーエクスペリエンスを再構築

>>:  CSS3 アニメーション – ステップ機能の説明

推薦する

JavaScript セレクター関数 querySelector および querySelectorAll

目次1. querySelectorは単一の要素を照会する1. ドキュメントインスタンスの呼び出し2...

テキスト ファイルの並べ替えに役立つ Awk コマンドラインまたはスクリプト (推奨)

Awk は、ソートを含む他の一般的なユーティリティによって実行できるいくつかのタスクを実行できる強...

CentOS 8.4 に Docker をインストールする詳細なチュートリアル

目次序文:システム要件:インストール環境:古いバージョンをアンインストールします: yum は具体的...

MySQL 5.7.19 Winx64 ZIP アーカイブのインストールと使用に関する問題の概要

今日はMySQLのインストール方法を学びましたが、その過程でいくつか問題が発生しました。関連記事をい...

HTML タグのカスタム属性に関する質問

以前の開発では、クラス、名前などの HTML のデフォルト属性を使用していました。 Huawei社の...

MySQL Bツリーインデックスとインデックス最適化の概要についての簡単な説明

MySQL の MyISAM エンジンと InnoDB エンジンはどちらもデフォルトで B+ ツリー...

Win10 インストール Linux システム チュートリアル ダイアグラム

Windows システムに仮想マシンをインストールするには、 VMware Workstationソ...

Docker ベースの Tomcat クラスタと Nginx ロード バランシングの展開の概要

目次前面に書かれた1. Ngixnイメージの作成2. Java Web (Tomcat) アプリケー...

docker compose を使用して fastDFS ファイル サーバーを構築する方法

前回の記事では、docker compose を使用して FastDfs ファイル サーバーをインス...

便利でシンプルなMySQL関数10個

関数0. 現在の時刻を表示するコマンド: select now()。機能: 現在の時刻を表示します。...

CSS3 border-radius 丸角の実装方法と使い方の詳しい説明

以前は、角を丸くするのは非常に面倒でしたが、CSS3 では、角を丸くするのは非常に簡単になり、bor...

JavaScript 事前分析、オブジェクトの詳細

目次1. 事前分析1. 変数の事前解析と関数の事前解析1. 変数の事前解析2. 機能事前分析2. 事...

ホバープロンプトにはvue2+elementuiを使用する

Vue2+elementui のホバー プロンプトは、外部と内部に分かれています。内部のものは el...

ウェブデザイナーが知っておくべき効率的なナビゲーションデザインの3つの原則

ウェブサイトのナビゲーションを設計することは、家の基礎を築くようなものです。基礎がしっかりしていなけ...

CSS フロート(float, clear)の人気の解説と体験談

私はかなり昔に CSS に触れましたが、フローティングについてはいつも混乱していました。私の理解が浅...