MySQL - 在InnoDB 中 Troubleshooting Row size too large (」 8126)

解決報錯

遇到報錯:

ERROR 1118 (42000): 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.
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

root cause:
MySQL的頁大小如果爲 16K,一個頁中至少要存兩行數據。那麼每一行的大小是不能超過 8126字節,超出的部分,會放在其他頁中,這個頁稱爲 溢出頁(overflow page),這些列稱爲 off-page columns。

當使用行格式爲 compact 時,碰到字段內容超過 767 字節 的內容時,會將前 767 字節放入主頁中,再存儲一個 20字節 的指針信息,將剩餘的部分放入到其他的數據頁中。

所以,在行格式爲 compact 時,blob列多於十個時,並且每一列的數據內容都多於 767字節。 這樣的話,每一行最小佔據的字節數量也會多於 8126。就會超過限制。

當然,如果設置 blob 多於 10 個列,每一列的數據沒有超過767,並且相加沒有超過 8126 字節,也是不會報錯的。

解決方案:
將表的 row_format 改爲 dynamic 即可。

實驗:

-- t1 十個列
MySQL [testdb]> create table t1(
    -> id int primary key
    -> , col1 longblob
    -> , col2 longblob
    -> , col3 longblob
    -> , col4 longblob
    -> , col5 longblob
    -> , col6 longblob
    -> , col7 longblob
    -> , col8 longblob
    -> , col9 longblob
    -> , col10 longblob
    -> ) charset=utf8 row_format=compact;
Query OK, 0 rows affected (0.04 sec)

MySQL [testdb]> insert into t1 values (1,
    -> repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000),
    -> repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000));
Query OK, 1 row affected (0.03 sec)

-- t2 多於十個列
MySQL [testdb]> create table t2(
    -> id int primary key
    -> , col1 blob
    -> , col2 blob
    -> , col3 blob
    -> , col4 blob
    -> , col5 blob
    -> , col6 blob
    -> , col7 blob
    -> , col8 blob
    -> , col9 blob
    -> , col10 blob
    -> , col11 blob) charset=utf8 row_format=compact;
Query OK, 0 rows affected (0.04 sec)

MySQL [testdb]> insert into t2 values (1,
    -> repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),
    -> repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),
    -> repeat('a',767));
ERROR 1118 (42000): 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.

-- 超過了,所以要將總和小於 8126
MySQL [testdb]> insert into t2 values (1, repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',735), repeat('a',735), repeat('a',735), repeat('a',735), repeat('a',735));
Query OK, 1 row affected (0.03 sec)

-- 這時候已經達到了極限的狀態,當我們再加列時,已經無法再擴展了。
[MySQL [testdb]> alter table t2 add column add_col1 varchar(10) not null default 'a';
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

-- 修改表的 行類型
MySQL [testdb]> alter table t2 row_format= dynamic;
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

MySQL [testdb]> alter table t2 add column add_col1 varchar(10) not null default 'a';
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章