IT人每天都要面對突發狀況,就算是再有經驗的IT專才也不能幸免。正所謂“我今日真係學咗好多嘢”,今次要記錄一下發生在MySQL的小狀況。
有天收到客戶的電郵,說在我們自家製的小型CMS上有一項記錄不能更新資料。在檢查時發現用來測試的記錄能夠順利更新,但在客戶所說的那一項卻不能,而前端沒有回報有任何錯誤。
之後用MySQL Workbench連到DB Server嘗試直接修改,結果出現了“Error 1118: row size too large (> 8126)”的錯誤信息。總算有點頭緒了。🤨
Google一下後了解到這是和Innodb的Row size上限有關。在MySQL 5.6以前,Innodb預設的File format是最原始的Antelope,它會把VARCHAR和TEXT之類的彈性長度Column的頭768 bytes放在Index record中作快速搜尋之用,而Innodb的預設Row size limit大約是8KB,所以當table裡面有很多BLOB或TEXT column,這8KB就會很快用完而產生row size too large的問題。
因為專案還在進行中,所以最後決定採用了將File format轉為Barracuda的方案。Barracuda是最新的Innodb file format,支援Compressed和Dynamic兩種row format,而我今次所選用的Compressed會為index page作壓縮處理從而解決Row size過大的問題。
首先檢查MySQL的版本,因為在5.7之後Barracuda已經成為預設,所以如果你的MySQL版本是5.6或以下,首先進到MySQL CLI執行以下指令:
mysql> show variables like "%innodb_file%";
畫面將會列出有關innodb的系統變數,如果出現了Antelope:
+--------------------------+----------+ | Variable_name | Value | +--------------------------+----------+ | innodb_file_format | Antelope | | innodb_file_format_check | ON | | innodb_file_format_max | Antelope | | innodb_file_per_table | OFF | +--------------------------+----------+
那就要執行以下三行指令:
SET GLOBAL innodb_file_format = Barracuda; SET GLOBAL innodb_file_format_max = Barracuda; SET GLOBAL innodb_file_per_table="ON";
完成後再檢查一次innodb系統變數:
+--------------------------+-----------+ | Variable_name | Value | +--------------------------+-----------+ | innodb_file_format | Barracuda | | innodb_file_format_check | ON | | innodb_file_format_max | Barracuda | | innodb_file_per_table | ON | +--------------------------+-----------+
另外還需要在my.cnf中加入以下的設定:
innodb_file_format = Barracuda innodb_file_per_table = 1 innodb_large_prefix = 1
完成後restart MySQL的服務便可。
下一步是更新table的row format,進到MySQL CLI後執行:
mysql> ALTER TABLE test_table ROW_FORMAT=COMPRESSED; /* 請修改test_table成為你的table名字 */
然後執行以下指令查看table狀態:
mysql> SHOW TABLE STATUS IN test_db\G /* 請修改test_db成為你的table所在的database名字 */ *************************** 1. row *************************** Name: test_table Engine: InnoDB Version: 10 Row_format: Compressed
Row format已經成功轉為Compressed,之後就可以測試一下以確認不再出現row size too large的問題。