mysql中文亂碼解決方案
一 問題描述
當往表裡插入中文資料時,報錯:
mysql> insert into t(id,nam) values(1,'丹丹');
ERROR 1366 (HY000): Incorrect string value:'\xE4\xB8\xB9\xE4\xB8\xB9' for column 'nam' at row 1
二 出錯原因
該表或者列的字符集與當前連線的字符集不同導致。
mysql> show create table t; CREATE TABLE `t` ( `id` int(11) DEFAULT NULL, `nam` varchar(300) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ----安裝完5.6.33後,預設字符集是: mysql> show variables like '%char%'; +--------------------------+----------------------------------+ | Variable_name | Value | +--------------------------+----------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql/share/charsets/ | +--------------------------+----------------------------------+
由於character_set_database值是latin1,因此預設建立的表字符集也是latin1。
但是character_set_client,character_set_connection,character_set_results是utf8,因此插入中文時會報錯。
/*
各引數含義如下:
*/
三 解決辦法
3.1 臨時方案
mysql> set names latin1; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%char%'; +--------------------------+----------------------------------+ | Variable_name | Value | +--------------------------+----------------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql/share/charsets/ | +--------------------------+----------------------------------+ 8 rows in set (0.01 sec) 再次插入就沒有再報錯了。 mysql> insert into t(id,nam) values(1,'丹丹'); Query OK, 1 row affected (0.02 sec) mysql> select * from t; +------+--------+ | id | nam | +------+--------+ | 1 | 丹丹 | +------+--------+ 但是set names latin1;命令是臨時性的。當退出該會話,重新登入時,又變回了utf8: mysql> select * from dan.t; +------+--------------+ | id | nam | +------+--------------+ | 1 | 丹丹 | +------+--------------+ 1 row in set (0.00 sec)
3.2 永久方案
修改配置檔案,把預設字符集改成utf8。再重新匯入資料。
3.2.1 備份字符集非utf8的表資料
#檢視下除了系統自帶的表外,有哪些表的字符集非utf8 mysql> select table_schema,table_name,TABLE_COLLATIONfrom information_schema.tables where table_schema notin('information_schema','performance_schema','mysql','test') andTABLE_COLLATION not like 'utf8%'; +--------------+------------+-------------------+ | table_schema | table_name |TABLE_COLLATION | +--------------+------------+-------------------+ | dan | t | latin1_swedish_ci | | dba | t | latin1_swedish_ci | | dba | t2 | latin1_swedish_ci | | jiao | t | latin1_swedish_ci | | sds | t | latin1_swedish_ci | +--------------+------------+-------------------+ #檢視下這幾個字符集為latin1的表所在的資料庫都有哪些表: mysql> selecttable_schema,table_name,TABLE_COLLATION from information_schema.tables where table_schemain ('dan','dba','jiao','sds'); +--------------+----------------+-------------------+ | table_schema | table_name | TABLE_COLLATION | +--------------+----------------+-------------------+ | dan | t | latin1_swedish_ci | | dba | t | latin1_swedish_ci | | dba | t2 | latin1_swedish_ci | | jiao | t | latin1_swedish_ci | | sds | EOS_DICT_ENTRY |utf8_general_ci | | sds | t | latin1_swedish_ci | +--------------+----------------+-------------------+
發現sds還有一個為utf8的表。所以需要單獨備份sds.t
#備份下其餘那幾個庫:
[root@slave2 mysql]# mysqldump -u root-psystem@123 --default-character-set=latin1 -B dba dan jiao > /download/bak/3.bak
#備份sds.t表
mysqldump -u root -psystem@123--default-character-set=latin1 sds t > /download/bak/sds_t.bak
/*
--default-character-set 表示設定以什麼字符集連線
備份檔案中會包含:SET NAMES latin1且表的插入語句不會出現亂碼,如:
INSERT INTO `t` VALUES (1,'丹丹');
如果備份時沒有指定選項--default-character-set,預設會使用utf8進行備份,則備份檔案中會包含SET NAMES utf8,且表插入語句會出現亂碼,如:
INSERT INTO `t` VALUES (1,'丹丹');
*/
3.2.2 修改備份檔案中的字符集
修改備份檔案,
將SET NAMES latin1改成SET NAMES utf8,
將DEFAULT CHARACTER SET latin1改成DEFAULT CHARACTERSET utf8,
將DEFAULT CHARSET=latin1改成DEFAULT CHARSET=utf8
cd /download/bak
sed -i 's/SET NAMES latin1/SET NAMESutf8/g' 3.bak
sed -i 's/DEFAULT CHARACTER SETlatin1/DEFAULT CHARACTER SET utf8/g' 3.bak
sed -i 's/DEFAULT CHARSET=latin1/DEFAULTCHARSET=utf8/g' 3.bak
由於sds_t.bak只備份了sds.t表,沒有備份資料庫,
沒有類似CREATE DATABASE /*!32312 IF NOT EXISTS*/ `sds` /*!40100 DEFAULTCHARACTER SET latin1 */;的語句
因此只需要修改SET NAMES latin1及表的字符集配置DEFAULT CHARSET=latin1。
sed -i 's/SET NAMES latin1/SET NAMESutf8/g' sds_t.bak
sed -i 's/DEFAULT CHARSET=latin1/DEFAULTCHARSET=utf8/g' sds_t.bak
3.2.3 修改配置檔案中的字符集
在[mysqld]下新增:
character_set_server=utf8
重啟mysql,發現已改變
mysql> show variables like '%char%';
+--------------------------+----------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir |/usr/local/mysql/share/charsets/ |
3.2.4 匯入資料
mysql -u root -psystem@123 < 3.bak
mysql -u root -psystem@123 sds <sds_t.bak
3.2.5 驗證
mysql> select * from dan.t;
+------+--------+
| id | nam |
+------+--------+
| 1 | 丹丹 |
+------+--------+
1 row in set (0.00 sec)
mysql> select * from sds.t;
+------+--------+
| id | name |
+------+--------+
| 1 | 焦焦 |
| 3 | 焦焦 |
| 5 | 焦焦 |
+------+--------+
3 rows in set (0.00 sec)
已不亂碼