昨天把mysql里所有table的varchar字段的字符集,批量換成了utf8mb4/utf8mb4_unicode_ci ,以便能保存一些emoji火星文 , 結果有一個sql語句執行時,報錯如下:
Illegalmixofcollations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT)foroperation '=
觀察了一下,這個sql使用了一個自定義的function,這個函數的入口參數為varchar,類似如下:
CREATE FUNCTION `f_xxx`( p_ref_type VARCHAR(50) , ... )
問題就在這里,把p_ref_type的參數類型改成:
CREATE FUNCTION `f_xxx`( p_ref_type VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, ... )
就ok了。
當然,如果不想改function,還有一種一勞永逸的解決辦法:(需要停機)
出錯信息的意思是 utf8-unicode-cli與utf-general-cli 不能混用,可以用
show create function f_xxx\G 查看下結構,重點觀察下最后幾行:
... END character_set_client: utf8mb4 collation_connection: utf8mb4_unicode_ci Database Collation: utf8_general_ci 1 row in set (0.00 sec)
這里可以看出,collation_connnection 與 Database Collation所用的字符集不一致,要想辦法弄成一致,可以再用:
SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';
查看mysql的相關系統變量:
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
| collation_connection | utf8mb4_general_ci |
| collation_database | utf8mb4_general_ci |
| collation_server | utf8mb4_general_ci |
大概輸出是這樣的,注意最后3行,確認mysql實例的編碼后,可以調整database的編碼:
ALTER DATABASE `數據庫名` character set utf8mb4 COLLATE utf8mb4_general_ci ;
考慮到,有些表或字段在創建時,可能也指定了其它編碼,可以用:
./mysqldump -u用戶名 -p -d --add-drop-table 數據庫名 > 導出的文件名
注:為防止操作期間有人操作數據庫,最好將所有應用暫時停機,保證操作期間db沒人向其寫入數據 。
導出表結構的sql,然后用文本編碼工具,批量把指定字符集的字符串給批量清空,即:清除所有指定字符集的DDL語句,全部默認用database本身的字符集
接下來用
./mysqldump -u用戶名 -p -t 數據庫名 > 導出的文件名
導出所有數據
最后,干掉所有table,然后mysql命令行下
source 修改好以后的數據庫表結構.sql
source 數據.sql
將所有表重建,然后導入數據,進行恢復,最終目標是將整個db,包括所有表及字段的字符集大換血了