设为首页 收藏本站
查看: 1236|回复: 0

[经验分享] MySQL源码:为什么INNODB数据页面中最少存储2条记录?

[复制链接]

尚未签到

发表于 2015-6-19 09:50:45 | 显示全部楼层 |阅读模式
  写在前面:我一直认为数据库中已经规定,一个页面中至少要存储2条记录,但是前几天碰到一个问题:为什么INNODB数据页面中最少存储2条记录?一下子把我问住了,知道是这样,但从没有问过自己这是为什么,所以我一直想这个问题,现在刨根问底,终于知道为什么了,下面就把这个问题的原因说一下吧。
  在INNODB中,底层数据的存储是通过B+树实现的,一个页面的大小一般设置为16K,不同页面之间通过父子、兄弟挂链,形成B+树结构。
  为了说明为什么一个数据页面至少要存储2条记录,下面就先简单叙述一下B树的一个记录插入过程,下面图示中的方框用来表示一个页面,左边和右边的小方框表示最小虚记录及最大虚记录,下面是表示内节点中的KEY指针,每一个KEY都会有一个指针指向其叶子节点的位置,对于叶子节点,这个是没有的。下面假设插入数据的顺序是2-1-3-1.5。
  假设一个页面中可以存储3条记录,下就面插入过程图示说明:

  现在根页面已经插入满了,此时如果再继续插入,则需要将根页面分裂(根节点的分裂),此时创建一个新的叶子节点,然后将原根页面的全部记录复制到新页面中,新根页面的最小虚记录要指向原来的根页面(新叶子节点),同时将原根页面中的记录全部删除,结果是这样的:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D1.jpg
  然后继续向原页面(新的叶子节点)插入数据1.5,因为还是插入不成功(因为页面还是满的),则继续分裂,但此时的分裂是叶子节点的分裂,此时再创建一个空的叶子节点页面,并且将被分裂页面的数据的一部分移动到新页面中,同时将新页面及被分裂叶子页面之间形成链表,另外,还需要在新建叶子节点中找到最左边的记录,根据这条记录创建一个其父节点中的关系字KEY值,同时让这个KEY键中的指针指向这个新的叶子节点,操作后如下:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D2.jpg
  那么此时就可以向重新搜索插入位置,那么找到的是已经有1这条记录的页面,此时页面不满,可以插入成功,那么到现在为止,分裂已经成功。现在的图示如下:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D31.jpg
  那么上面说了插入过程,现在反回来解释为为什么一个页面中必须至少要2条记录了,假设在极端情况下,每一个页面中只能插入一条记录,那么在如下情况下,就必须要进行分裂了:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D4.jpg
  此时再向叶子节点插入数据1,结果还是插入不进去,此时分裂叶子节点,创建新页面,新增一个2节点的右兄弟,而此时因为插入的是1,比2小,所以需要将2的数据复制到新的叶子页面中,所以插入1之后的结果如下:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D5.jpg
  
  此时1已经插入完成,再插入3,通过B树的搜索,找到了插入位置为叶子节点2里面,但是因为只能插入一个记录,所以这个节点再分裂,因为插入的3比2大,直接将3写入新叶子节点即可,结果如下:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D6.jpg
  此时还是同样的道理,需要将3这个节点在内节点中创建索引键指针,将3插入到根页面中,但是根页面中2已经存在了,再不能插入更多的数据记录,根页面再次分裂,同样的道理,创建一个新的根页面,然后再次向分裂页面插入数据3,还是插入不成功,再次分裂内节点,然后3可以顺利插入完成,那么此时的情况是下面这样的:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D7.jpg
  看看这个图,是不是觉得很怪,怎么这么多节点其实只有三个记录,是的,如果一个页面只能插入一条记录的话就是这样的,所以这也是为什么做了限制的原因了。
  但是还有一种情况,现在将范围扩大一些,如果KEY的大小限制了,一个内节点页面中至少要存储2条记录(这里假设就是存储2条记录),而叶子节点中只能存储一条记录,那么此时的结果其实就是一个非常冗余的具有B树结构的双链表,比如插入顺序为1,2,3,4的话:
http://rrdba.cn/wp-content/uploads/2012/11/%E6%9C%AA%E5%91%BD%E5%90%8D8.jpg
  总结:这个问题在数据库中是这样的解释,但归根到底,其实还是B+树的特性,如果不存储至少2条记录,则这个B+树是没有意义的,形不成一个有效的索引,所以这也是一种解释吧。
  上面的叙述大致原理是这样的,但是如果有些细节不正确地方,请指点或者提出来。
  那么至于记录超长时,在INNODB中的处理方式是什么,这个问题后面可以继续做一些叙述,这个问题先就这样吧。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-78778-1-1.html 上篇帖子: mysql远程连接命令 下篇帖子: MySQL当批量插入遇上唯一索引
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表