前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >How does InnoDB behave without a Primary Key(11.InnoDB在没用主键情况下的行为)

How does InnoDB behave without a Primary Key(11.InnoDB在没用主键情况下的行为)

作者头像
冬天里的懒猫
发布2020-09-01 15:09:00
5990
发布2020-09-01 15:09:00
举报

今天下午,我和Arjen Lentz讨论了InnoDB在没有声明主键的情况下的行为,这个话题很有趣,也没有足够的文档证明,所以有必要写一个简短的帖子。

InnoDB聚集索引的背景

在InnoDB索引页的物理结构中,我描述了“在InnoDB中的任何内容都是索引”。这意味着InnoDB必须为每个表都有一个“聚簇索引”,这通常是主键。手册上说在聚集和二级索引: 如果表没有主键或合适的唯一索引,InnoDB内部会在一个包含行ID值的合成列上生成一个隐藏的聚集索引。这些行是按照InnoDB给表中的行分配的ID排序的。行ID是一个6字节的字段,在插入新行时单调地增加。因此,按行ID排序的行在物理上是按插入顺序排列的。

我之前假设这意味着将使用一个不可见的列和用于实现auto_increment的相同序列生成代码(它本身存在一些可伸缩性问题)。然而,实际上它们是完全不同的实现。

实现隐式的 Row IDs

这实际上是这样实现的,如手册所说,如果一个表声明没有主键和非空的唯一键,InnoDB会自动添加一个6字节(48位)的整数列ROW_ID到表中,并基于该列集群数据。该列不能被任何查询访问,也不能在内部用于任何事情,比如基于行的复制。 手册没有提到的是,所有使用这样的ROW_ID列的表共享相同的全局序列计数器(手册上说“单调递增”,但没有澄清),这是数据字典的一部分。所有行ID的最大使用值(从技术上说,是下一个要使用的ID)存储在第7页(类型SYS)的系统表空间(例如ibdata1)中,在数据字典头(字段DICT_HDR_ROW_ID)中。 这个全局序列计数器由dict_sys->互斥锁保护,甚至用于递增(与使用原子递增相反)。实现在include/dict0boot中。ic(删除多空行):

代码语言:javascript
复制
 38  UNIV_INLINE
39  row_id_t
40  dict_sys_get_new_row_id(void)
41  /*=========================*/
42  {
43          row_id_t        id;
44  
45          mutex_enter(&(dict_sys->mutex));
47          id = dict_sys->row_id;
49          if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) {
51                  dict_hdr_flush_row_id();
52          }
54          dict_sys->row_id++;
56          mutex_exit(&(dict_sys->mutex));
57  
58          return(id);
59  }

您可能还注意到,这段代码缺乏任何保护措施,以防止分配给行id的48位溢出。这是不必要的冗余代码,但即使是连续每秒100万次插入(这可能有点乐观;),也需要大约9年的时间来耗尽ID空间。我想应该是这样吧。

确保生成不冲突的id

计数器每生成第256个ID(上面定义的DICT_HDR_ROW_ID_WRITE_MARGIN)就刷新到磁盘,方法是修改SYS数据字典页面中的值,该值被记录到事务日志中。在启动时,InnoDB会将存储在磁盘上的DICT_HDR_ROW_ID增加至少256,最多511。这确保了生成的任何id都小于新的起始值,因此不会有任何冲突。

性能和竞争的影响

鉴于InnoDB中的其他代码受到了dict_sys->互斥锁的保护,我认为可以公平地说,任何具有隐式集群键(ROW_ID)的表都可能在删除(不相关的)表的操作中都会遇到插入卡顿。在具有隐式键的多个表中并行插入可能会受到性能限制,因为它将在共享互斥锁和共享计数器变量的缓存争用上序列化。此外,每生成第256个值,就会导致对SYS页面修改进行一次日志写入(和刷新),而不管事务是否已经提交(或将要提交)。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • InnoDB聚集索引的背景
  • 实现隐式的 Row IDs
  • 确保生成不冲突的id
  • 性能和竞争的影响
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档