1. 程式人生 > >mysql中文亂碼解決方案

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)

已不亂碼