mysql row size上限
mysql innodb 的 row size上限
背景
在專案使用中,出現了以下報錯:
Error Code: 1118 - Row size too large (> 8126).
Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help.
In current row format, BLOB prefix of 768 bytes is stored inline.
上面報錯,這就涉及到了row size的上限,也有可能會涉及到file format的設定。
一些上限
- 建立表報錯:maximum row size > 65535
- 建立表報錯:row size too large > 8126
- 插入資料報錯:row size too larget > 8126
這裡主要講第三種報錯,插入資料的時候觸發的報錯。先要理清file format和row format兩個概念。
個人理解修改這兩個引數都有可能解決掉問題。為啥是有可能,因為file format只是部分長欄位型別的設定。
File format
先解釋下file forma。這是用於varchat或者text欄位儲存資料的方案。file format有兩種,分別是Antelope和Barracuda。
Antelope模式
在MySQL 5.6之前的版本,預設file format是Antelope。
意思是,對於varchar和text欄位,會將內容的前768欄位放置在index record中,後面再接20個位元組的指標。
剩下內容會放置在BLOB page中。
假設有11個text欄位,每個欄位都是1000位元組。那麼在插入資料的時候,row size = (768+20)* 11 = 8668 > 8126,將會觸發row size too larget > 8126
報錯。
如果使用Antelope模式,不建議使用超過10個text或varchar欄位。
Barracuda模式
Barracude會將所有資料放在BLOB page中,在index record裡面只放20個位元組的指標。
設定切換
查詢File format設定:
show variables like "%innodb_file%";
my.cnf 設定
innodb_file_format = Barracuda #
innodb_file_per_table = 1
innodb_large_prefix = 1
Row format
innodb引擎的行格式(row format)有兩種。分別是compact和dynamic/compressed。
ALTER TABLE test ROW_FORMAT=COMPRESSED;
SHOW TABLE STATUS IN test_db;
這裡還是之說Antelope模式下使用text的問題。普通的數值型別,其實很難超8126的長度限制,就不說了。在Antelope模式下,text欄位的前768會儲存在index record中,會佔用row size的768+2個位元組。所以text/varchar欄位不能太多。除非確定不會太長。
# 驗證測試的sql
create table text2
(
text1 longtext,
text2 longtext,
text3 longtext,
text4 longtext,
text5 longtext,
text6 longtext,
text7 longtext,
text8 longtext,
text9 longtext,
text10 longtext,
text11 longtext
) ENGINE=InnoDB DEFAULT CHARSET=ascii;
insert into text2 values(
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000)
);
insert into text2 values(
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',197) # repeat('y',198) error
);
--------
create table text3
(
text1 longtext,
text2 longtext,
text3 longtext,
text4 longtext,
text5 longtext,
text6 longtext,
text7 longtext,
text8 longtext,
text9 longtext,
text10 longtext,
text11 longtext
) ENGINE=INNODB DEFAULT CHARSET=ascii ROW_FORMAT=COMPRESSED;
insert into text3 values(
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000),
repeat('y',1000)
);