在調用微信介面的時候,如果遇到包含表情的暱稱或者訊息的時候,在將資料寫入到MySQL的時候會出現類似 Incorrect string value: '\xF0\x8F...' for column 'XXX' 的錯誤提示。原因是UTF-8編碼有可能是兩個、三個或四個位元組,而上述中的表情為Emoji表情,在iPhone手機中很常見,很多都是四個位元組的。但是MySQL 5.1.x不支援這樣四個位元組的utf-8編碼,只有5.5.x才支援,所以只能將MySQL升級到5.5.x。
1. 安裝MySQL
windows下面安裝MySQL 5.5.x非常簡單,這裡不再詳述。Linux下面因為從MySQL 5.5開始使用cmake來做config了,所以與之前版本的安裝方式不同,這裡說明一下不同的地方。
首先安裝基礎依賴庫:
LANG=C yum -y install gcc-c++ gperf ncurses-devel readline-devel libaio-devel
然後下載編譯安裝cmake:
wget http://www.cmake.org/files/v2.8/cmake-2.8.12.2.tar.gz tar xzvf cmake-2.8.12.2.tar.gz cd cmake-2.8.12.2 ./configure && make && make install
安裝完成之後可以執行 cmake -version 命令查看cmake是否正常安裝。
基礎工作做完之後就可以下載安裝mysql了,這裡以mysql-5.5.36為例:
wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.36.tar.gz tar xzvf mysql-5.5.36.tar.gz cd mysql-5.5.36 cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_READLINE=1 -DWITH_SSL=system -DWITH_ZLIB=yes -DENABLED_LOCAL_INFILE=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSETS=all make && make install
其中cmake的安裝選項可以在MySQL Source-Configuration Options進行詳細的查看,預設情況下MyISAM、MERGE、MEMORY和CSV引擎預設配置是按照的,所以上面只使用 WITH_INNOBASE_STORAGE_ENGINE=1 配置安裝了InnoDB引擎。
如果CentOS版本低於6.x的話可能在安裝的過程中出現下面的錯誤:
/root/downloads/mysql-5.5.32/vio/viossl.c: In function ‘ssl_do’:
/root/downloads/mysql-5.5.32/vio/viossl.c:175: 錯誤:‘SSL_OP_NO_COMPRESSION’ 未聲明 (在此函數內第一次使用)
/root/downloads/mysql-5.5.32/vio/viossl.c:175: 錯誤:(即使在一個函數內多次出現,每個未聲明的標識符在其
/root/downloads/mysql-5.5.32/vio/viossl.c:175: 錯誤:所在的函數內只報告一次。)
make[2]: *** [vio/CMakeFiles/vio.dir/viossl.c.o] 錯誤 1
make[1]: *** [vio/CMakeFiles/vio.dir/all] 錯誤 2
make: *** [all] 錯誤 2
這是mysql 5.5.32的一個bug,原因是無法在openssl-1.0.0及更低版本下編譯,如果不需要ssl可以去掉WITH_SSL配置項,也可以升級openssl的版本,另外更方便的方法可以在cmake之前打一個補丁:
wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.36.tar.gz tar xzvf mysql-5.5.36.tar.gz cd mysql-5.5.36 wget -c "http://bugs.mysql.com/file.php?id=19941&bug_id=68999" -O mysql-openssl.patch patch -p1 < mysql-openssl.patch
然後再進行上面的cmake操作。
最後初始化資料庫,先要確保是否建立了mysql使用者,如果沒有則使用下面命令進行建立
groupadd mysql useradd -s /sbin/nologin -M -g mysql mysql
設定目錄許可權並安裝資料庫
cd /usr/local/mysql chown -R mysql . chgrp -R mysql .
# 安裝資料庫,這裡的指令碼位置跟5.1.x有所不同
scripts/mysql_install_db --user=mysql chown -R root . chown -R mysql data
如果不是升級的話可以先使用mysql預設的設定檔,然後啟動mysql:
# 下面的檔案在5.5.x放到了support-files目錄下了 cp support-files/my-medium.cnf /etc/my.cnf cp support-files/mysql.server /etc/init.d/mysql chmod +x /etc/init.d/mysql /etc/init.d/mysql start # 修改root密碼 bin/mysqladmin -uroot password 123 history -c /etc/init.d/mysql restart # 開機啟動 cat >> /etc/rc.local < /etc/init.d/mysql start > EOF
2. 修改mysql 5.1.x的設定檔
如果是升級的話使用原來的設定檔之前需要做一些修改,常用的變化的配置項如下:
default-character-set 修改成了 character-set-server,在linux安裝的過程中已經指定了編碼,所以不需要在設定檔中進行設定,但是windows下需要進行設定
innodb_file_io_threads已經棄用,修改成了 innodb_read_io_threads 和 innodb_write_io_threads
skip-locking 已經棄用,修改成了 skip-external-locking
log-long-format 已經棄用,修改成了 log-short-format
log_slow_queries 已經棄用,修改成了 slow-query-log,並且該參數設定為1啟用慢查詢日誌,0為關閉,使用slow_query_log_file指定記錄檔的名稱,預設檔案名稱為host_name-slow.log
lower_case_table_name 已經棄用,建議修改成 lower_case_table_names
另外可以把以前的built-in檔案格式Antelope改為新的Barracuda格式:
innodb_file_format=Barracuda
linux下為了與windows保持一致,設定表名或欄位名的大小寫不敏感:
lower_case_table_names=1
3. 原有資料庫修複及升級
為了保證資料的完整性,在將舊的資料匯入到新資料庫中之後(為了方便管理,可以將舊的mysql資料庫合并到新的資料庫中,然後重新mysql server使其生效),需要使用mysql_upgrade命令升級修複資料庫,否則有可能會出現 "Cannot load from mysql.proc. The table is probably corrupted"錯誤。在mysql的bin目錄下執行下面的命令(參數及其含義請見 mysql_upgrade — Check and Upgrade MySQL Tables):
mysql_upgrade -P3300 -uroot -p --force
確保mysql的密碼輸入正確,否則會出現 FATAL ERROR: Upgrade failed 的錯誤。
這裡需要指出的是,如果在windows環境下執行上述命令會出現下面的錯誤:
Looking for 'mysql.exe' as: c:\mysql\bin\mysql.exeFATAL ERROR: Can't execute 'c:\mysql\bin\mysql.exe'
如果執行mysql命令則會出現 “unknown variable 'character-set-server=utf8'” 的錯誤,這個是mysql的一個bug,可以首先將mysql的設定檔my.ini中的character-set-server全部修改為舊的default-character-set,然後再執行上述命令,執行命令的時候確保mysql服務是啟動狀態,等到升級完成之後再把設定檔中的default-character-set替換為新的character-set-server。
最後解決最開始說的問題的方法是將表中對應的欄位編碼由utf-8升級為utf8mb4:
ALTER TABLE `table_name` CHANGE `colum_name` `colum_name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL ;