MySQL row_format引發的案例一則

背景知識:
InnoDB存儲引擎和大多數數據庫一樣,記錄是以行的形式存儲的,這意味着頁中保存着表中一行行的數據。另外MYSQL對每個頁存放的記錄數又有硬性的規定,最少2行,最多16KB/2 - 200,即7992行。
在InnoDB 1.0.X之前,InnoDB存儲引擎提供了Compact和Redundant兩種格式來存放行記錄數據。Redundant是mysql5.0版本之前的行記錄存儲方式,之後仍然支持這個格式是爲了兼容之前版本的格式,5.1之後很少用到了,因爲Compact的結構設計比它好得多,compact格式消耗的磁盤空間和備份耗時更小,Redundant相比之下大了一些。compact格式更適用於大多數的業務場景。

在InnoDB 1.0.X版本開始又引入了新的文件格式(file format),
以前支持Compact和Redundant格式稱爲Antelope文件格式,
新引入的文件格式稱爲Barracuda文件格式。
Barracuda文件格式下擁有兩種新的行記錄格式:Compressed和Dynamic,
同時,Barracuda文件格式也包括了Antelope所有的文件格式。
這樣Barracuda文件格式支持4種row_format:

Redundant、Compact、Compressed、Dynamic

而Antelope文件格式只支持2種row_format:

Redundant、Compact

參數innodb_file_format用來指定文件格式,可以通過下面的方式來查看當前所使用的InnoDB存儲引擎的文件格式:

show variables like 'innodb_file_format';

現在基本上都是Barracuda

Dynamic和Compact基本是類似的,但是它們在行溢出數據的處理上卻完全不同:

compact格式下,溢出列存儲前768字節,而dynamic格式下,溢出的列只存儲前20字節,一旦發生了行溢出,
dynamic其實就存儲一個指針,數據都放在溢出頁裏,dynamic代表將長字段(發生行溢出)完全off-page存儲。

Row_format 引發異常的一個案例:
前幾天生產MYSQL遇到的一個問題,在錄入數據時,整行數據完全錄不進去,報以下錯:

Cause:java.sql.SQLException: com.taobao.tddl.common.exception.TddlException:java.sql.SQLException:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:Row size too large (> 8126). Changing
some columns to TEXT or BLOB or usingROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED
may help. In current row format,BLOB prefix of 768 bytes is stored inline.; nested exception
iscom.ibatis.common.jdbc.exception.NestedSQLException:  

該表是一個產品介紹詳情表,有20多個TEXT 字段,剛好碰到了一個產品,每個字段錄入的數據都很長,
而mysql 中有了個限制,一個頁(這裏pagesize 是16K)必須至少存2行,也就是說每行的存儲長度必須小於等於8192,而這麼多 TEXT 字段,一行肯定是存不下來,也就是會發生溢出,而即例發生溢出,每個列仍然會存儲前768字節(該表的row_formart 是compact),字段一多還是超過了8192,於是就報錯,插不進了。
最後將表的row_format 改爲 dynamic 得以解決。alter table … row_format=dynamic;

所以,如果大家遇到一些表TEXT 或 VARCHAR 大字段很多,又不好拆解時,可能需要考慮下溢出後列的長度了,如果溢出後列的長度還是太大,則要看一下表的 row_format :

show table status like '%xxx%'\G  

必要時需要將其實設置爲 dynamic 如:

create table test(id int,name text,...... ) row_format=dynamic;
或
alter table test row_format=dynamic;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章