InnoDB表的限制 对InnoDB表的限制在本节中的以下主题下进行描述:
最大值和最小值
一个表最多可以包含1017列。虚拟生成的列包含在此限制中。
一个表最多可以包含64个辅助索引。
索引键前缀长度限制是使用DYNAMIC或COMPRESSED行格式的InnoDB表的3072字节。
索引键前缀长度限制是使用REDUNDANT或COMPACT行格式的InnoDB表的767字节。例如,在TEXT或VARCHAR列上,如果假设utf8mb4字符集和每个字符最多4个字节,则列前缀索引可能超过191个字符,从而达到此限制。
尝试使用超过限制的索引键前缀长度将返回错误。
应用于索引键前缀的限制也适用于全列索引键。
如果通过在创建MySQL实例时指定innodb_page_size选项将InnoDB页面大小减少到8KB或4KB,则索引键的最大长度将根据16KB页面大小的3072字节的限制按比例降低。也就是说,当页面大小为8KB时,最大索引键长度是1536字节,当页面大小为4KB时,最大索引键长度是768字节。
多列索引最多允许16列。超过限制将返回一个错误。 错误1070(42000):指定的关键部件太多;最多允许16个部件
除了可变长度列(VARBINARY、VARCHAR、BLOB和TEXT)之外,对于4KB、8KB、16KB和32KB页面大小,最大行长度略小于页面的一半。例如,默认的innodb_page_size为16KB的最大行长度约为8000字节。对于64KB的InnoDB页面大小,最大行长度约为16000字节。LONGBLOB和LONGTEXT列必须小于4GB,总行长度(包括BLOB和TEXT列)必须小于4GB。
如果一行小于半页长,则所有行都本地存储在页中。如果超过半页,则选择可变长度列进行外部页外存储,直到该行适合于半页内,如第15.11.2节“文件空间管理”所述。
尽管InnoDB在内部支持大于65535字节的行大小,但是MySQL本身对所有列的组合大小强加了65535的行大小限制:
创建表t(VARCHAR(8000),b VARCHAR(10000), ->c VARCHAR(10000),d VARCHAR(10000),e VARCHAR(10000), ->f VARCHAR(10000),g VARCHAR(10000))引擎=InnoDB; 错误1118(42000):行大小太大。用于 使用的表类型(不计算BLOB)是65535。你必须换一些 到TEXT或BLOB的列
在一些较老的操作系统中,文件必须小于2GB。这不是InnoDB本身的限制,但是如果您需要大的表空间,那么可以使用几个较小的数据文件而不是一个大的数据文件来配置它。 InnoDB日志文件的组合大小可以达到512GB。 最小表空间大小略大于10MB。最大表空间大小取决于InnoDB页面大小。
InnoDB页面大小:最大表空间大小
4KB 16TB
8kb 32TB
16KB 64 TB
12KB 128TB
64KB 256TB
最大表空间大小也是表的最大大小。
InnoDB中的默认页面大小是16KB。在创建MySQL实例时,可以通过配置innodb_page_size选项来增加或减少页面大小。
支持32KB和64KB页面大小,但是对于大于16KB的页面大小,不支持ROW_FORMAT=COMPRESSED。对于32KB和64KB页面大小,最大记录大小为16KB。对于innodb_page_size=32KB,扩展大小是2MB。对于innodb_page_size=64KB,扩展大小为4MB。
使用特定InnoDB页面大小的MySQL实例不能使用来自使用不同页面大小的实例的数据文件或日志文件。
对InnoDB表的限制
分析表通过对每个索引树执行随机跳转并相应地更新索引基数估计,来确定索引基数(如SHOW INDEX输出的基数列中所示)。因为这些只是估计,所以重复运行分析表可以产生不同的数字。这使得分析表在InnoDB表上更快,但是不能100%准确,因为它没有考虑所有行。
通过打开innodb_stats_persistent配置选项,可以使AnalyYZE TABLE收集的统计数据更加精确和稳定。当启用该设置时,在索引列数据的主要更改之后运行AnalyYZE TABLE非常重要,因为统计信息不会定期重新计算(例如在服务器重新启动之后)。
如果启用了持久统计设置,则可以通过修改innodb_stats_persistent_sample_pages系统变量来更改随机跳转的数量。如果禁用持久统计设置,则改为修改innodb_stats_._sample_pages系统变量。
MySQL在连接优化中使用索引基数估计。如果连接没有以正确的方式优化,请尝试使用AnalyYZETaBLE。在少数情况下,AnalyYZETABLE不能为特定的表生成足够好的值,您可以在查询中使用FORCE INDEX来强制使用特定的索引,或者设置max_seeks_for_key系统变量以确保MySQL更喜欢索引查找而不是表扫描。
如果在表上运行语句或事务,并且在同一表上运行AnalyYZE TABLE,然后执行第二个AnalyYZE TABLE操作,则阻塞第二个AnalyYZE TABLE操作,直到语句或事务完成为止。之所以出现这种行为,是因为分析表将当前加载的表定义标记为在分析表完成运行时过时。新的语句或事务(包括第二个AnalyYZE TABLE语句)必须将新的表定义加载到表缓存中,直到当前运行的语句或事务完成并清除旧的表定义为止,表缓存才会发生。不支持加载多个并发表定义。
除了表保留的物理大小之外,SHOW TABLE STATUS没有给出关于InnoDB表的准确统计数据。行计数只是SQL优化中使用的粗略估计。
InnoDB不保持表中行的内部计数,因为并发事务可能同时看到不同数量的行。因此,SELECT COUNT(*)语句只对当前事务可见的行进行计数。
在Windows上,InnoDB总是以小写字母在内部存储数据库和表名。若要将二进制格式的数据库从Unix移动到Windows或从Windows移动到Unix,请使用小写字母名称创建所有数据库和表。
AUTO_INCREMENT列ai_col必须定义为索引的一部分,以便可以对表执行与索引SELECT MAX(ai_col)查找等效的查找以获得最大列值。通常,这是通过将列作为某些表索引的第一列来实现的。
InnoDB在与AUTO_INCREMENT列关联的索引末尾设置排他锁,同时初始化表上先前指定的AUTO_INCREMENT列。
对于innodb_autoinc_lock_mode=0,InnoDB使用特殊的AUTO-INC表锁定模式,其中在访问自动递增计数器时,锁定被获得并保持在当前SQL语句的末尾。当保持AUTO-INC表锁时,其他客户端不能插入到表中。对于innodb_autoinc_lock_mode=1的“大容量插入”也会出现相同的行为。表级AUTO-INC锁不与innodb_autoinc_lock_mode=2一起使用。
当AUTO_INCREMENT整数列用完值时,后续INSERT操作将返回一个复制键错误。这是MySQL的一般行为。
DELETE FROM tbl_name不重新生成表,而是逐行删除所有行。
级联的外键操作不激活触发器。
不能创建具有与内部InnoDB列的名称匹配的列名的表(包括DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR和DB_MIX_ID)。此限制适用于任何字母情况下名称的使用。
锁定和事务
如果innodb_table_locks=1(默认值),LOCK TABLES在每个表上获取两个锁。
除了MySQL层上的表锁之外,它还获取InnoDB表锁。4.1.2之前的MySQL版本没有获取InnoDB表锁;可以通过设置innodb_table_locks=0来选择旧的行为。
如果没有获取InnoDB表锁,即使表的一些记录被其他事务锁定,LOCK TABLES也会完成。 在MySQL 8.0中,innodb_table_locks=0对于用LOCK TABLES显式锁定的表没有影响……写。
它确实对通过LOCK TABLES锁定用于读或写的表有影响……隐式写入(例如,通过触发器)或锁表……读。
当事务被提交或中止时,事务持有的所有InnoDB锁将被释放。因此,在autocommit=1模式下对InnoDB表调用LOCK TABLES没有多大意义,因为获得的InnoDB表锁将立即释放。
因为LOCK TABLES执行隐式的COMMIT和UNLOCK TABLES,所以不能在事务的中间锁定其他表。