首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL mysql-udf-http 效能實測:觸發器 + HTTP 呼叫同步 Memcached 的代價與替代方案

     編輯:MySQL 綜合教學

嘗試在 MySQL 觸發器中透過 mysql-udf-http 呼叫外部 HTTP 服務同步 Memcached,聽起來很美好——資料庫層自動完成緩存更新,應用層零侵入。但實測數據揭示了殘酷真相:單次 HTTP 呼叫延遲 9ms 起跳,千次寫入耗時 9 秒,效能不可接受。本文完整記錄測試環境、程式碼、數據分析與替代架構建議。

一、測試環境

  • OS:Linux 2.6.18 (虛擬機),376MB RAM
  • MySQL:5.1.26-rc-log,MyISAM 表
  • Memcached:192.168.0.134:11211
  • UDF:mysql-udf-http (提供 http_get(), http_post(), http_put())
  • PHP 版本:5.x (CGI 模式)

二、基準測試:直連 vs 觸發器

操作方式1000 次耗時單次平均
MySQL INSERTPHP 直連 mysql_query0.9 秒0.9 ms
Memcached SETPHP 直連 Memcache::set0.8 秒0.8 ms
MySQL INSERT + 觸發器 HTTP PUT觸發器呼叫 http_put()9 秒9 ms
觸發器純 SQL INSERT (同庫另一表)觸發器 INSERT INTO tmp...0.7 秒0.7 ms

三、程式碼關鍵片段

1. 觸發器定義

CREATE TRIGGER `mytable_insert` AFTER INSERT ON `mytable`
FOR EACH ROW
BEGIN
  SET @tt_resu = http_put(
    CONCAT('https://192.168.0.134/mem_ss.php?type=post&id=', NEW.id, '&data=', NEW.addtime),
    11  -- timeout 秒
  );
END;

2. PHP 接收端 (mem_ss.php)

$mem = new Memcache();
$mem->connect('192.168.0.134', 11211);
$mem->set($_GET['id'], $_GET['data'], 0, 3600);
$mem->close();

四、效能剖析:為什麼這麼慢?

  1. 同步阻塞:觸發器執行 http_put() 時,MySQL 執行緒完全阻塞等待 HTTP 回應,無法並行。
  2. 連線建立開銷:PHP 端每次 new Memcache()->connect() + close(),TCP 三次握手 + Memcached 協議交換 ≈ 2-3ms。
  3. HTTP 協議開銷:Request/Response 標頭、URL 解析、PHP 解釋器啟動(CGI 模式每請求 fork 進程)。
  4. 無連線池:UDF 內部無 HTTP 連線池、無 Keep-Alive、無非同步機制。
  5. 序列化成本:CONCAT() 組裝長 URL、PHP 端 $_GET 解析。

五、優化嘗試與結果

優化手段預期效果實測結果
PHP 端改用持久連線 pconnect省去 TCP 握手無顯著改善(CGI 模式進程隔離,持久連線無效)
改用 FastCGI (PHP-FPM)復用進程、支援持久連線單次降至 ~4ms,仍偏高
UDF 改用 libcurl 非同步 + 批次非阻塞、批次發送需重寫 UDF,屬架構級重構
改用 MySQL 8.0 HTTP() UDF (企業版)原生支援、連線池需商業授權

六、生產可用的替代架構

方案 A:應用層雙寫(最簡單、可控)

// 應用程式碼
db.execute("INSERT INTO mytable ...");
memcache.set(key, value);  // 同步或非同步佇列

優點:延遲可控、易除錯、可重試。缺點:應用層耦合、需事務性保證時複雜。

方案 B:Binlog 異步同步 (CDC) —— 推薦


[MySQL Binlog] → [Canal / Debezium / Maxwell] → [Kafka / RocketMQ] → [Consumer] → [Memcached/Redis]
  • 完全解耦,資料庫零侵入
  • 毫秒級延遲,支援重試、冪等、順序保證
  • 可同時同步多個下游(緩存、搜尋、數倉)

方案 C:MySQL 8.0 原生 INVOKER + 元件 (企業版)

支援在觸發器/預存程序中安全呼叫外部 REST/gRPC,內建連線池、超時、重試、熔斷。

方案 D:資料庫層異步事件表 + 輪詢器


CREATE TABLE sync_queue (id BIGINT AUTO_INCREMENT, payload JSON, status TINYINT, created_at TIMESTAMP);
-- 觸發器只寫入隊列(極快)
CREATE TRIGGER ... AFTER INSERT ON mytable FOR EACH ROW
  INSERT INTO sync_queue (payload) VALUES (JSON_OBJECT('id', NEW.id, 'data', NEW.addtime));
-- 獨立 Worker 輪詢處理

優點:資料庫內完成、無外部依賴、可重試。缺點:需額外 Worker 進程、延遲取決於輪詢間隔。

七、結論與建議

  1. 不要在觸發器中做網路 I/O(HTTP、RPC、檔案寫入),會嚴重拖垮資料庫吞吐量、增加鎖持有時間、引發連鎖阻塞。
  2. mysql-udf-http 適合極低頻、非核心路徑的管理類操作(如發送告警、觸發重建索引任務),不適合高頻寫入路徑。
  3. 緩存同步採用 CDC (Binlog) 架構 是業界標準解法,成熟開源組件豐富(Canal、Debezium、Maxwell)。
  4. 若必須資料庫層觸發,請用異步隊列表 + 獨立 Worker模式,將耗時操作剝離出關鍵路徑。

技術選型的本質是權衡。看似優雅的「資料庫自動同步緩存」,若犧牲了寫入效能與穩定性,便得不償失。下一篇我們將探討 MySQL 慢查詢日誌分析與優化實戰,敬請期待。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved