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

MySQL 使用者自訂變數深度解析:會話變數在高併發計數器的實戰應用

     編輯:MySQL 綜合教學

MySQL 使用者自訂變數深度解析:會話變數在高併發計數器的實戰應用

從變數分類、作用域、賦值語法到實戰案例,完整解析 MySQL 使用者自訂會話變數 (@var) 在解決主從同步延遲導致計數器不準問題中的應用。

MySQL 變數分類體系

大類子類作用域生命週期典型用途
使用者自訂局部變數BEGIN...END 區塊存儲過程調用期間存儲過程邏輯暫存
會話變數 (@var)當前連線連線斷開釋放跨 SQL 傳值、計數器
系統變數會話變數當前連線連線期間調整當前連線行為 (sql_mode 等)
全域變數全伺服器啟動至關機 (重啟失效)伺服器級配置

使用者自訂會話變數 (@var) 核心語法

宣告與賦值

SET @a = 1, @b = 2;
SET @c := @a + @b;  -- 非 SET 語句必須用 :=
SELECT @c;  -- 3

查詢

SELECT @a;
SELECT @@session.var_name;  -- 系統會話變數用 @@
SHOW SESSION VARIABLES LIKE '%var%';

三大避坑指南

  1. 同一非 SET 語句中勿同時賦值與使用
    -- ❌ 不穩定
    SELECT @a, @a:=@a+1 FROM t;
    -- ✅ 分離
    SET @a = @a + 1;
    SELECT @a;
    原因:運算順序未定義,且回傳型別由語句開始時決定
  2. 變數值在發送給客戶端時才計算
    -- ❌ HAVING 引用同 SELECT 定義的別名失效
    SELECT (@aa:=id) AS a, (@aa+3) AS b FROM t HAVING b=5;
    -- 原因:HAVING 執行時 @aa 仍為上一語句結果
  3. 型別隱性轉換:未初始化變數為字串 NULL,賦值浮點數不保留精度,時空間型別轉二進位串

實戰案例:超級話題積分系統計數器修正

問題背景

  • 用戶第 N 次互動 (轉發/評論/簽到) 獲得 N 相關積分
  • 高併發下,從庫讀取計數器值因主從延遲偏小 → 積分少算
  • 原邏輯:從庫 SELECT 計數 → PHP 計算積分 → 更新計數與積分 (兩階段非原子)

解決方案:單一 UPDATE 回傳新值

-- 存儲過程 / 直接 SQL
UPDATE super_topic_counter 
SET counter = @counter := counter + 1 
WHERE uid = ? AND topic_id = ? AND action_type = ?;

SELECT @counter;  -- 取得遞增後的新值,用於積分計算

關鍵優勢

  • 主庫執行,讀取最新值,無主從延遲問題
  • 單一語句原子遞增,避免競態條件
  • 會話變數 @counter 暫存新值,同一連線立即 SELECT 取得
  • 無需額外鎖/交易,效能極佳

補充:變數儲存位置

使用者自訂會話變數儲存在 伺服器端連線執行緒記憶體 中 (非客戶端),連線斷開自動釋放。這保證了同一連線內多語句間的可見性。

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