最近遊戲開始第二次內測,開始處理操作日誌,最開始把日誌放到同一個表裏面,發現一天時間,平均100玩家在線,操作記錄就超過13萬條,決定拆表,按照日期來保存日誌,每天的日誌存到一個表裏面,然後定期把老的數據導出來備份後刪掉。
具體思路是寫日誌的時候,根據當前的時間決定插入到當天的表裏面,如表不存在則創建一個新的表,表名裏面帶上當天的日期。這就涉及到需要在存儲過程裏面動態創建一個跟日期相關的表。mysql不是很熟悉,只會基本的語法,這種高級功能都需要上網查詢,呵呵。
最開始的想法,是想定義一個字符串變量,把表名拼好後來創建表,發現創建的表名是定義的變量名,只好重新想辦法。
經過查資料,並試驗了很多次,最後找到了實現的方法,需要先將sql語句拼出來,然後在使用PREPARE來處理就可以了。sql語句如下:
set @sql_create_table = concat(
'CREATE TABLE IF NOT EXISTS operrecord_', date_format(curdate(),'%y%m%d'),
"(
`oper_id` int(10) NOT NULL AUTO_INCREMENT,
`oper_role` int(11) NOT NULL,
`oper_type` varchar(30) NOT NULL DEFAULT '',
`oper_content` varchar(1000) NOT NULL DEFAULT '',
`oper_cls` int(10) NOT NULL DEFAULT '0',
`oper_date` datetime NOT NULL,
`oper_serverid` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`oper_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8");
PREPARE sql_create_table FROM @sql_create_table;
EXECUTE sql_create_table;
創建表之後,還需要插入數據,但是insert語句裏面也要使用動態表名,沒辦法還是需要和上面一樣的方法來處理,先拼sql語句,示例如下:(注:rId等是存儲過程傳入的參數)
set @sql_oper_revcord = concat(
"INSERT INTO operrecord_", date_format(curdate(),'%y%m%d'),
" (`oper_role`, `oper_type`, `oper_content`, `oper_cls`, `oper_serverid`, `oper_date`)
values (rId, type, content, cls, serverid, NOW())");
PREPARE sql_oper_revcord FROM @sql_oper_revcord;
EXECUTE sql_oper_revcord;
執行的時候發現會報錯,找不到rId這個字段,網上說應該給rId加上引號如('rId')也不行,繼續報錯數據類型不匹配。
想了想,應該把rId這些傳人的參數聲明爲局部參數,再次測試果然成功了,另外需要注意的是表字段在字符串裏面需要加上(`xxx`)才行。正確的sql語句如下:
set @rId = rId, @type = type, @content = content, @cls = cls, @serverid = serverid;
set @sql_oper_revcord = concat(
"INSERT INTO operrecord_", date_format(curdate(),'%y%m%d'),
" (`oper_role`, `oper_type`, `oper_content`, `oper_cls`, `oper_serverid`, `oper_date`)
values (@rId, @type, @content, @cls, @serverid, NOW())");
PREPARE sql_oper_revcord FROM @sql_oper_revcord;
EXECUTE sql_oper_revcord;
記下這編文章,以作備忘。也希望能幫到其它遇到此問題的同學。