mysql row size上限

mysql innodb 的 row size上限

背景

在項目使用中,出現瞭如下報錯:mysql

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的設置。sql

一些上限

  • 建立表報錯: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中。code

假設有11個text字段,每一個字段都是1000字節。那麼在插入數據的時候,row size = (768+20)* 11 = 8668 > 8126,將會觸發row size too larget > 8126報錯。
若是使用Antelope模式,不建議使用超過10個text或varchar字段。orm

Barracuda模式

Barracude會將全部數據放在BLOB page中,在index record裏面只放20個字節的指針。ci

設置切換

查詢File format設置:get

show variables like "%innodb_file%";

my.cnf 設置innodb

innodb_file_format = Barracuda #
innodb_file_per_table = 1
innodb_large_prefix = 1

Row format

innodb引擎的行格式(row format)有兩種。分別是compact和dynamic/compressed。table

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)
);
相關文章
相關標籤/搜索