MySQL 5.0.2+ 透過 C API mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE, CURSOR_TYPE_READ_ONLY) 實作伺服器端游標,允許結果集留在伺服器端按需取回,減少網路傳輸。
| 限制項目 | 說明 | 影響 |
|---|---|---|
| 唯讀 | 不可透過游標 UPDATE/DELETE WHERE CURRENT OF | 需另行發送 DML 語句 |
| 不可持久 | COMMIT/ROLLBACK 後自動關閉 | 跨事務不可重用 |
| 不敏感 | 結果集建立後不反映後續資料變更 | 類似 INSENSITIVE 游標 |
| 不可捲動 | 僅支援 FETCH NEXT,無 ABSOLUTE/RELATIVE/PRIOR | 單向流式讀取 |
| 無名稱 | 以預處理語句句柄識別,無 DECLARE CURSOR name | 應用層管理句柄對應 |
| 單語句單游標 | 一個預處理語句僅能開啟一個游標 | 多游標需準備多個語句 |
| 不支援語句類型 | CHECK TABLE、HANDLER READ、SHOW BINLOG EVENTS 等 | 此類語句無法使用游標 |
| 預處理模式限制 | 若語句不支援預處理,則無法使用游標 | 需確認語句可 PREPARE |
LIMIT 1000000, 20 → 游標定位後僅傳輸 20 行。mysql_stmt_fetch_column() 按需取欄位,進一步減少傳輸。MYSQL_STMT *stmt = mysql_stmt_init(mysql);
mysql_stmt_prepare(stmt, "SELECT id, data FROM big_table WHERE category=?", strlen(...));
mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)CURSOR_TYPE_READ_ONLY);
mysql_stmt_bind_param(stmt, &bind_param);
mysql_stmt_execute(stmt);
mysql_stmt_bind_result(stmt, &bind_result);
while (mysql_stmt_fetch(stmt) == 0) {
// 處理單行
}
mysql_stmt_close(stmt);
| 方案 | 優點 | 缺點 |
|---|---|---|
| 伺服器端游標 | 減少網路傳輸、客戶端記憶體低 | 功能受限、需 C API、連線佔用久 |
| LIMIT/OFFSET 分頁 | 簡單、通用 | 深分頁效能差 (全掃描+排序) |
| Keyset Pagination | 高效、無深分頁問題 | 需唯一排序鍵、不支援隨機跳頁 |
| 應用層快取 | 極快 | 資料陈舊、一致性複雜 |
伺服器端游標是特定場景 (大結果集流式讀取) 的優化工具,非通用替代方案。受限於唯讀、單向、非持久等特性,現代應用多採用 Keyset Pagination + 應用層快取 組合,僅在 ETL/報表等後台批次作業考慮游標。