MFC工程需要使用Mysql數據庫中遇到的問題記錄下。
1、首先去官網下載下Mysql安裝包,安裝下Mysql。
我在這邊下載的是mysql-installer-community-5.7.16.0.msi,因為是默認安裝,所以會根據系統是64位還是32位,來安裝64位的mysql或者32位的mysql。
我的操作系統是64位的,所以安裝后的mysql也是64位的,而我的MFC工程是32位的,所以安裝目錄得到的libmysql.lib文件使用。
解決方法:把64位的mysqlserver卸載,然后安裝32位的mysqlserver。直接remove就行,卸載完,同樣在這個界面Add就行。因為我的電腦已經做過這個操作了,所以顯示的mysqlserver已經x86了。
2、到mysqlserver目錄里得到libmysql.lib文件和include頭文件,自己的MFC工程引入即可。
3、使用MySQL有如下幾個步驟
- 通過調用 mysql_library_init()來初始化MySQL庫。
- 通過調用 mysql_init()來初始化一個連接句柄。
- 通過調用mysql_real_connect()來連接服務器。
- 使用SQL語句操作數據庫,並處理這些結果。
- 通過調用mysql_close()來關閉MySQL服務器的連接。
- 通過調用 mysql_library_end()來終止使用MySQL庫。
4、假如我們使用的database,是需要自己先創建,應該先用mysql_real_connect連接什么。
我們可以先連接默認的database:mysql,然后去創建我們需要的database,然后再切換過去。
bool MySQLServer::createDatabase(LPCTSTR dbname) { std::string queryStr = "create database if not exists "; queryStr += dbname; queryStr += " DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;"; if (0 == mysql_query(&mysqlInstance, queryStr.c_str())) { queryStr = "use "; queryStr += dbname; if (0 == mysql_query(&mysqlInstance, queryStr.c_str())) { return true; } } errorIntoMySQL(); return false; }
5、mysql斷開后如何自動連接?
mysql默認的是連接時長是8小時,如果8小時內,沒有數據進行交互,就會斷開連接,所以我們希望斷開后,能夠自動重連。
在database連接之后,調用下面的setReconnect函數,設置下重連。
bool MySQLServer::setReconnect() { char reconnect = 1; mysql_options(&mysqlInstance, MYSQL_OPT_RECONNECT, (char *)&reconnect); return true; }
6、對於多線程的查詢和寫入執行等操作時,一定要加鎖操作,否則會有崩潰風險
如寫入操作:
//寫入數據 bool MySQLServer::mysql_execsql(LPCTSTR queryStr) { m_DataBaseMutex.lock(); if (0 == mysql_query(&mysqlInstance, queryStr)) { m_DataBaseMutex.unlock(); return true; } else { errorIntoMySQL(); } m_DataBaseMutex.unlock(); return false; }
查詢操作:
//讀取數據 int MySQLServer::readDatafromDB(LPCTSTR queryStr, Json::Value & result) { m_DataBaseMutex.lock(); if (0 != mysql_query(&mysqlInstance, queryStr)) { errorIntoMySQL(); m_DataBaseMutex.unlock(); return -1; } MYSQL_RES *sqlResult = NULL; sqlResult = mysql_store_result(&mysqlInstance); int row = (int)mysql_num_rows(sqlResult); int field = (int)mysql_num_fields(sqlResult); MYSQL_FIELD* fieldArray = mysql_fetch_field(sqlResult); MYSQL_ROW lineData = NULL; lineData = mysql_fetch_row(sqlResult); int row_no = 0; std::string temp; while (NULL != lineData) { for (int i = 0; i<field; i++) { if (lineData[i]) { temp = lineData[i]; result[row_no][fieldArray[i].name] = temp; } else { temp = ""; result[row_no][fieldArray[i].name] = temp; } } row_no++; lineData = mysql_fetch_row(sqlResult); } mysql_free_result(sqlResult); m_DataBaseMutex.unlock(); return row; }
7、如果涉及到多線程的頻繁查詢和寫入的話,最好創建多個連接,每個線程操作一個連接,否則也會有崩潰的風險