InnoDB bugs found during research on InnoDB data storage(10.在研究InnoDB数据存储时发现的InnoDB bug)

黄丰
2023-12-01

在研究InnoDB的存储格式和构建innodb_ruby和innodb_diagrams项目的过程中,我和Davi Arnaut发现了很多InnoDB的bug。我想我应该提几个,因为它们相当有趣。
由于innodb_space实用程序使重要的内部信息以一种以前从未有过的方式可见,所以这些漏洞在很大程度上可以被发现。使用它来检查生产表提供了许多信息,可以继续寻找导致错误的原因。当我们最初查看由innodb_space数据生成的按页空闲空间的图形图时,我们非常惊讶地看到许多页面不到一半的填充(包括许多几乎为空的页面)。经过大量研究,我们找到了所有我们发现的异常现象的原因。

Bug #67718: InnoDB drastically under-fills pages in certain conditions

InnoDB在某些情况下会导致页填充不足,由于在插入过程中过于积极地尝试基于插入顺序来优化页面分割,InnoDB可能会让页面填充不足,每个页面只有一条记录。这在几个生产系统中被观察到,在两种情况下,我相信这在其他情况下很常见:

  • 1.Mostly-increasing keys Twitter使用snowflake以分布式方式生成ID。总的来说还不错。snowflake生成64位的递增id,其中包含一个时间戳组件。插入通常是通过队列和其他非即时机制进行的,因此IDs将发现它们进入数据库的方式略有混乱。
  • 2.Nearly-ordered keys 另一个模式有一个主键和一个副键,它们的顺序相似,但不完全相同。以任何一种顺序插入到表中以复制数据,最后几乎按另一个键排序。

这两种情况最终都会导致这个BUG的产生,导致生产数据库中出现严重不足的页面,消耗大量磁盘空间。

Bug #67963: InnoDB wastes 62 out of every 16384 pages

InnoDB偶尔需要分配一些内部记账页面;每256mib数据对应2个。为此,它分配一个区段(64个页面),分配所需的两个页面,然后将剩余的区段(62个空闲页面)添加到一个名为FREE_FRAG的区段列表中,该区段用于单页分配。几乎没有从该列表中分配页面,所以这些页面被浪费了。
这是相当微妙的,在任何大型InnoDB表中只浪费0.37%的磁盘空间,但尽管如此,这还是很有趣的,而且很容易修复。

Bug #68023: InnoDB reserves an excessive amount of disk space for write operations

InnoDB通过为写操作预留1%的表空间大小,试图确保写操作在到达某个点后总是能够成功。这是一个过多的数额;在一个生产系统中,每一个大表的1%都加起来了。这应该被限制在一个合理的数额。

Bug #68501: InnoDB fails to merge under-filled pages depending on deletion order

根据从页面中删除记录的顺序,InnoDB可能不会合并多个相邻的未填满的页面,这会浪费磁盘空间。

Bug #68545: InnoDB应该在目标页面满的时候检查左/右页面,以避免分裂

在插入操作期间,目前只有两种结果可能产生:

  • 1.记录与目标页相匹配,插入时不分割页。
  • 2.记录不适合放入目标页面,然后该页面被分成两个页面,每个页面上都有原始页面上的一半记录。页面被分割后,插入将发生在两个结果页面中的一个页面中。
    这忽略了在实践中非常常见的一种情况,即目标页已满,但它的一个或多个相邻页有空闲空间,甚至可能几乎为空。更明智的选择是考虑合并相邻的页面以在目标页面上腾出空闲空间,而不是分割目标页面,从而创建一个全新的半全页。

Bug #68546: InnoDB stores unnecessary PKV fields in unique SK non-leaf pages

即使可能有许多子页面具有相同的最小键值,辅助键中的非叶页也需要一个保证惟一的键。InnoDB将所有主键字段添加到键中,但当副键已经是唯一的时,这是不必要的。对于具有惟一的辅助键和较大的主键的系统,这会增加大量磁盘空间来存储不必要的字段。以一种兼容的方式修复这个问题会很复杂,而且大多数用户不会受到影响,所以我认为它不太可能被修复。

Bug #68868: Documentation for InnoDB tablespace flags for file format incorrect

正如我在《InnoDB如何意外地只保留了1位表格式》一文中所写的,据说InnoDB只保留了一个字段的6位来存储表格式(Antelope, Barracuda等),但是由于c#中的一个bug,只保留了1位。

 类似资料: