MySQL 5.7 で導入された Optimizer Hint を使うと 特定のクエリの実行時間に制限を設けることができる。
mysql> SELECT /*+ MAX_EXECUTION_TIME(1500) */ SLEEP(10);
+-----------+
| SLEEP(10) |
+-----------+
| 1 |
+-----------+
1 row in set (1.50 sec)
MySQL 5.7 より前のバージョンでアプリ側でどうにかできないの? ってのを試してみたコードがこちら。(エラー制御は省略)
<?php
function connect_db() {
return new mysqli("127.0.0.1", "user", "pass", "db");
}
$conn->query("SELECT SLEEP(10)", MYSQLI_ASYNC); // 即時に制御が返る
$links = $errors = $rejects = [$conn];
if (0 < mysqli::poll($links, $errors, $rejects, 1, 500000)) { // 1.5 秒タイムアウトを設定
// 制限時間内に結果が返る場合
$result = $conn->reap_async_query();
} else {
// タイムアウトした場合
$kill_conn = connect_db();
$kill_conn->query("KILL QUERY {$conn->thread_id}");
$kill_conn->close();
}
php 5.3.0 以上で、mysqlnd 版の mysqili 拡張が利用できる環境である必要があります。(php 5.4 以降なら大体の環境で使えるんじゃないかな)
注意点としては、kill するためのコネクションを別に用意する必要があるところ。
上記の例ではタイムアウトするたびにつなぎに行ってしまうけど、kill 専用の持続的接続を用意しておけば、無駄なコネクションも抑制できるかな。