使用 ODBC 連接數據庫,Grid 控件顯示數據,需在數據變更時自動更新界面,避免輪詢帶來的延遲與資源浪費。
| 方案 | 原理 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| 定時器輪詢 | `SetTimer` 定期 `SELECT` | 實現簡單,兼容所有 DB | 有延遲,頻繁查詢負載大 | 數據變更頻率低、實時性要求不高 |
| 數據庫觸發器 + 通知機制 | SQL Server `SqlDependency` / Oracle `DBMS_ALERT` / PostgreSQL `LISTEN/NOTIFY` | 真正推送,零延遲 | 依賴特定數據庫版本,ODBC 需額外封裝 | 高實時性、數據庫支持通知 |
| 中間件消息隊列 | 業務寫入 DB 同時發消息到 RabbitMQ/Kafka,客戶端訂閱 | 解耦、可擴展、跨平台 | 架構複雜,引入額外組件 | 分布式系統、多客戶端同步 |
| UDF/擴展存儲過程回調 | 數據庫觸發器調用擴展 DLL 發送 Socket 通知 | 輕量、無中間件 | 侵入數據庫,維護困難,安全風險 | 老系統改造、極簡部署 |
| 應用層緩存 + 失效廣播 | Redis/Memcached 做緩存,更新時發布失效事件 | 高性能、支持集群 | 引入緩存一致性問題 | 高併發讀多寫少 |
// 定時器回調
void OnTimer(UINT_PTR nIDEvent) {
static long lastVersion = -1;
long currVersion = GetDBVersion(); // 輕量查詢
if (currVersion != lastVersion) {
lastVersion = currVersion;
RefreshGrid(); // 重新填充數據
}
}
// 輕量版本查詢
long GetDBVersion() {
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly, _T("SELECT ISNULL(MAX(version),0) FROM sys_table_version"));
long v = 0; rs.GetFieldValue(0, v); rs.Close();
return v;
}
根據系統規模、實時性要求、技術棧選擇最經濟的方案,「過度設計」同樣是技術債。