在高併發或長時間運行的查詢場景中,設定合理的查詢超時時間至關重要。MySQL 官方客戶端庫 libmysql 提供了 MYSQL_OPT_READ_TIMEOUT 選項,讓開發者能精確控制讀取操作的超時閾值。本文將深入解析其底層實現、PHP 中的調用方式,以及實際部署時需注意的重試機制陷阱。
在 libmysql 源碼中,mysql_options() 函數負責處理各類連接選項。透過 switch 語句可見,MYSQL_OPT_READ_TIMEOUT(值為 11)會直接將傳入的無符號整數賦值給 mysql->options.read_timeout:
case MYSQL_OPT_READ_TIMEOUT:
mysql->options.read_timeout = *(uint*) arg;
break;
這意味著在 C/C++ 層面,開發者只需調用 mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, &timeout) 即可生效。
PHP 的 mysqli 擴展完整暴露了 mysql_options,對應函數為 mysqli_options()。其內部會根據參數類型(字串或長整數)轉換後直接呼叫底層 C API。然而,mysqli 並未導出 MYSQL_OPT_READ_TIMEOUT 常數,開發者必須自行查閱 MySQL 源碼中的 enum mysql_option 定義,得知其值為 11。
<?php
$mysqli = mysqli_init();
// 直接使用常數值 11 設定讀取超時為 1 秒
$mysqli->options(11 /* MYSQL_OPT_READ_TIMEOUT */, 1);
$mysqli->real_connect('host', 'user', 'pass', 'db');
?>
實測發現,libmysql 內建重試邏輯:首次嘗試 + 2 次重試。因此,若設定 MYSQL_OPT_READ_TIMEOUT = 1,實際超時時間將達到 3 秒。這也是目前透過此選項所能達成的最小超時粒度。
雖然粒度較粗(最小 3 秒),但總比完全無法控制要好。若需毫秒級控制,建議在應用層實現異步查詢 + 超時取消機制。
mysqli::options(11, 秒數) 即可設定查詢讀取超時。