1. 問題現象
最近出現程序在運行一段時間之後,新入到MySQL中的數據出現中文亂碼,每次重啓程序就會好,然後過段時間又會出現問題?
2. 解決方案
經過排查懷疑是因爲在程序入庫程序執行中途,出現過與MySQL自動重連的操作,在自動重連以後所有配置都會使用默認的,所以字符集也相應會變成默認,而不再是剛開始建立連接時使用的UTF-8。
在引擎中當前與MySQL建立連接時用到的主要API函數如下:
//1. 設置連接參數
int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)
//2. 設置字符集
ret = mysql_real_query(mysql, "SET NAMES UTF8;", (unsigned long) strlen ("SET NAMES UTF8;"));
//3. 與MySQL建立連接
MYSQL *mysql_real_connect (MYSQL *mysql,
const char *host,
const char *user,
const char *passwd,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long client_flag);
以上的第2步中使用命令行的方式設置字符集編碼後,如果中途出現自動重連的會恢復到默認字符集。所以修改爲如下API設置:
//2. 設置連接字符集
int mysql_set_character_set(MYSQL *mysql, char *csname)
3. 幾種設置字符集的方式和對比
mysql在C/C++中調用api設置連接mysql的編碼方式有以下幾種方法:1. mysqli_set_charset調用示例:
ret = mysql_set_character_set(mysql, "utf8");
說明:
推薦使用的設置方法,與mysql的連接斷開自動重連後仍能保持設置的編碼格式,並且影響mysql_real_escape_string函數功能,使mysql_real_escape_string函數使用設置的編碼格式轉義字符串。
但該函數在mysql5.0.5版本以後才支持,故版本太低者…。2. 執行sql語句:SET NAMES
調用示例:
ret = mysql_real_query(mysql, "SET NAMES UTF8;", (unsigned long) strlen ("SET NAMES UTF8;"));
說明:
使用sql語句執行,只能影響當前與數據庫的連接,斷開自動重連後編碼格式會重置爲默認的配置。3. 設置MYSQL_SET_CHARSET_NAME屬性
調用示例:
ret = mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8");
說明:
跟mysql_set_character_set類似,斷開自動重連後仍能保持設置的編碼格式,只是不會影響到mysql_real_escape_string函數。
並且在mysql5.0.5版本都可以使用,低版本可以使用該方法代替。
需要特別說明的是只有在調用mysql_real_connect連接數據庫之前修改該屬性纔會生效。