天天看點

記mysql存儲過程給變量指派的坑

前言

最近在公司編寫存儲過程,碰到了一個問題,排查了很久,才解決,現記錄一下,給各位踩踩坑。

問題

SET cluster_value = CONCAT('{"Desc":"這是一個中文字元串"',NOW(), '","OtherStatus":0,"OneStatus":0}');
SELECT cluster_value;      

列印 cluster_value ,值為null

記mysql存儲過程給變量指派的坑

尋找原因,開始認為是以下幾個方面:

  1. cluster_value變量聲明的大小不夠
  2. 給cluster_value指派的sql語句格式錯誤
  3. cluster_value被其他sql語句影響

三點都驗證了一遍,發現仍然沒有問題,然後就想是不是字元串裡的内容有問題,于是繼續驗證,最終發現是隻要含有中文字元就有問題,修改成英文就正常。

瞬間,局勢就爽朗起來了呀!

于是上到mysql所在的伺服器,準備大刀闊斧的幹

解決方法

1. 使用 show variables like 'character%' 檢視資料庫編碼:

記mysql存儲過程給變量指派的坑

發現 character _set_server 的字元集是 latin1,需要将其換成 utf8mb4

2. 進入my.cnf 檔案(位置一般在mysql安裝的位置)中,在【mysqld】裡輸入character-set-server=utf8mb4

3. 重新開機mysql

4. 再次檢視編碼:

記mysql存儲過程給變量指派的坑

再次運作sql語句,cluster_value值即正常

原因猜想

存儲過程中定義參數時,無法定義其字元集,是以調用存儲過程的時候,會預設讀取全局變量character_set_server,而且還是隻讀取mysqld啟動時該全局變量的值作為存儲過程中預設的傳輸字元集。是以,如果資料表/字段使用系統預設的字元集(比如latin1)的話,調用存儲過程更新一些非英文的字元串字段時,就不會發生問題;但是,如果資料表/字段的字元集不是系統預設的字元集(比如預設是latin1,資料表使用的是utf8),就會出現問題。

這個問題看起來很小,但定位的時候老折磨了

繼續閱讀