MySQL 字符集與亂碼與collation設定的問題?

資料庫工作筆記發表於2023-10-30

來源:AustinDatabases


問題是這樣的,最近有同學問關於MySQL 的字元亂碼的問題,說從一個資料庫到另一個資料庫,配置相同,但是為什麼這個資料庫的中文就是中文,到另一個資料庫就是亂碼?

說到這個問題,我們先對MySQL的字符集的配置部分進行一個系統化的分析,這裡我們那下面的這些配置來詳細的說說字元和字元亂碼的問題

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 utf8mb3

character_set_client 這裡官方的解釋是,客戶端傳送的語句時所用的字符集,這裡的意思就是MySQL 或類MySQL的資料庫產品,會認為在接受到客戶端的發來的資訊後,客戶端的編碼是 utf8mb4 .

同時MySQL如何處理這些發來的資料要用 character_set_connection 中設定的透過character_set_connection 中設定的字符集來進行資料的處理,最後character_set_results 是最後一個環節,在資料處理完畢後,將資料返回給客戶端的字符集編碼。

character_set_database

character_set_server

character_set_system 

剩下的三個主要 character_set_database 引數控制了資料庫的預設的字符集合,character_set_server 為資料庫伺服器啟動時的預設字符集編碼,character_set_system 則是這裡唯一的一個變數,他為資料庫系統所在的作業系統的字符集這個是無法進行設定的,他與作業系統當前的字符集有關。

那麼什麼情況會導致輸入的資料的字元到了資料庫裡面是錯誤的

案例1  

JDBC中使用的指定的字符集不對,導致MySQL接受到的資料與預設客戶的字符集不對,導致的亂碼。這裡需要注意,在JDBC URL中需要使用connector/J 8.020 後的JDBC 才能支援utf8mb4 ,否則只能支援到utf8。

同理當character_set_results的字符集和JDBC的應用字符集設定的不同,也會導致傳回應用的字元是亂碼的情況。

String url = "jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf8mb4&autoReconnect=true&allowMultiQueries=true";

所以必須去確認JDBC 設定的字符集和你的MySQL的 character_set_client 和 character_set_result 的字符集是一致的。這裡稍微模擬一下,character_set_result 和 character_set_client 的字符集不一致導致的亂碼的問題。 

mysql> select * from test;
+----+--------+--------+
| id | name   | title  |
+----+--------+--------+
|  1 | 小李 | 嘩蠧 |
|  2 | 小李 | 嘩蠧 |
+----+--------+--------+
2 rows in set (0.00 sec)

mysql> set character_set_results = 'big5';
Query OK, 0 rows affected (0.00 sec)

mysql> 
mysql> 
mysql> 
mysql>  insert into test (name,title) values ('小李','嘩蠧');
Query OK, 1 row affected (0.00 sec)

mysql> 
mysql> 
mysql> select * from test;
+----+-------+-------+
| id | name  | title |
+----+-------+-------+
|  1 | ?ʡ剠| ???   |
|  2 | ?ʡ剠| ???   |
|  3 | ?ʡ剠| ???   |
+----+-------+-------+
3 rows in set (0.00 sec)

所以在此基礎上,需要正確設定這些引數,保證資料庫和客戶端在字符集設定上是一致的。

說完字符集,下面的說說字元比較規則的問題,字元在進行資料處理中需要進行時間,collation_connection 是MySQL伺服器的一個系統變數,用於指定當前連線字元比較的規則,字元比較規則包含字符集和校對規則,決定了在執行字元比較和排序時要使用的規則,我們可以透過show varaibles like '%coll%' 來調取當前與collation有關的值。

collation_connection utf8mb4_0900_ai_ci
collation_database utf8mb4_general_ci
collation_server utf8mb4_general_ci
default_collation_for_utf8mb4 utf8mb4_0900_ai_ci

default_collation_for_utf8mb4 是預設資料庫和表建立是的校對規則,另外需要注意的校對規則在資料庫建立後,不能隨意改變,這將產生與應用程式預想的一些業務處理邏輯相悖的結果。

我們舉一個簡單的例子
mysql> 
mysql> show variables like 'coll%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database   | utf8mb4_general_ci |
| collation_server     | utf8mb4_general_ci |
+----------------------+--------------------+
3 rows in set (0.00 sec)

mysql> select 'a' = 'A';
+-----------+
'a' = 'A' |
+-----------+
|         1 |
+-----------+
1 row in set (0.01 sec)

mysql> set collation_connection = utf8_bin;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select 'a' = 'A';
+-----------+
'a' = 'A' |
+-----------+
|         0 |
+-----------+
1 row in set (0.00 sec)

mysql> 

最後總結MySQL 的字符集和字元排序的問題,

1 弄清楚當前資料庫的字符集和字元排序的設定

2 出現亂碼去發現當前的資料的字符集和資料庫連結和結果的字符集與應用的設定是否匹配一致。

3  排序規則不能輕易變換,輕易變換後會可能會出現業務邏輯錯誤的問題。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027826/viewspace-2991740/,如需轉載,請註明出處,否則將追究法律責任。

相關文章