本文是对row_format为compact时,varchar长度的一个探讨。 《MySQL技术内幕 InnoDB存储引擎》中姜承尧提到MySQL varchar最大长度65535是指所有的varchar长度累加必须小于65535,这篇文章对这个进行一个探讨,发现65535中应该包含了所有字段的长度、变长字段长度标示位、NULL标示位的累计。在此感谢姜承尧的《MySQL技术内幕 InnoDB存储引擎》,对很多东西有了一个更清晰的了解。

注:下面的测试是 character_set=utf8 utf8下面一个字符占3个字节,因此最大是65535/3=21845,但是21845之后没有地方存储长度信息,所以单列的最大长度是21844

Every table (regardless of storage engine) has a maximum row size of 65,535 bytes。可以通过下面的测试有个了解。

show table status like "test";
Row_format:Compact

CREATE TABLE `test` (
  `c1` varchar(21844) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

mysql> alter table test modify column c1 varchar(21844) not null; 
Query OK, 7 rows affected (0.07 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> alter table test modify column c1 varchar(21845) not null; 
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql> select 21844*3+2;
+-----------+
' 21844*3+2 '
+-----------+
'     65534 '
+-----------+
1 row in set (0.00 sec)

因为null标示位占用了一个字节,所以可以去掉not null限制。

mysql> alter table test modify c1 varchar(21844) COLLATE utf8_bin; 
Query OK, 7 rows affected (0.08 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> alter table test add column i1 int not null;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

mysql> alter table test modify column c1 varchar(21843) not null;   
Query OK, 7 rows affected (0.08 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> alter table test add column i1 int not null;              
Query OK, 7 rows affected (0.08 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> alter table test add column i2 int not null; 
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

mysql> select 21843*3+2+4;
+-------------+
' 21843*3+2+4 '
+-------------+
'       65535 '
+-------------+
1 row in set (0.00 sec)

这个时候去掉not null就不可以了

mysql> alter table test modify column c1 varchar(21843);           
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

参照如下: 1,http://dev.mysql.com/doc/refman/5.0/en/column-count-limit.html 2,MySQL技术内幕 InnoDB存储引擎