使用 Sphinx/Coreseek PHP API 時,Query() 方法失敗僅回傳 false,不會直接輸出錯誤訊息。掌握 GetLastError() 方法是快速定位問題的關鍵。
$cl = new SphinxClient();
$cl->SetServer('localhost', 9312);
$res = $cl->Query($keyword, 'my_index');
// $res === false 表示失敗,但不知原因
var_dump($cl->GetLastError());
| 錯誤訊息 | 可能原因 | 解決方向 |
|---|---|---|
| connection to localhost:9312 failed | searchd 未啟動/端口錯誤/防火牆阻擋 | 檢查 service searchd status、netstat -ntlp | grep 9312、防火牆規則 |
| index 'my_index': search error: | 索引不存在/索引損壞/路徑錯誤 | 確認 sphinx.conf index 區塊名稱、indexer --all 重建 |
| per-query max_matches=1000 limit reached | 結果集超過 max_matches | 調大 searchd 設定 max_matches、或 SetLimits(0, 20, 10000) |
| client version is higher than daemon version | PHP API 版本與 searchd 版本不匹配 | 升級/降級 API 或 searchd 至相容版本 |
| received zero-size searchd response | searchd 崩潰/記憶體不足/OOM Killer | 檢查 searchd.log、系統 dmesg | grep -i kill、調大記憶體限制 |
| attr 'category_id' not found | 查詢使用的屬性未在索引定義中宣告 | 補上 sql_attr_uint = category_id 並重建索引 |
function sphinx_search($keyword, $index = '*') {
$cl = new SphinxClient();
$cl->SetServer('localhost', 9312);
$cl->SetConnectTimeout(1);
$cl->SetArrayResult(true);
$cl->SetLimits(0, 20, 1000);
$cl->SetMatchMode(SPH_MATCH_EXTENDED);
$res = $cl->Query($keyword, $index);
if ($res === false) {
$err = $cl->GetLastError();
error_log("Sphinx search failed: keyword='$keyword', index='$index', error=$err");
// 可選:拋出例外、回傳空陣列、降級到 DB LIKE 查詢
return [];
}
return $res['matches'] ?? [];
}
searchd 啟用 query_log,可見實際收到的查詢語句與耗時。indexer -c sphinx.conf --check idx_main 檢查索引完整性。tcpdump -i lo port 9312 -w sphinx.pcap 分析協議交互。sphinxapi.php。核心口訣:Query() 回傳 false → 立即呼叫 GetLastError() → 讀取錯誤字串 → 對照上表 → 定位解決。別讓「靜默失敗」拖慢排查速度。