即将写入MySQL源码的官方bug解决之路
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了即将写入MySQL源码的官方bug解决之路,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4083字,纯文字阅读大概需要6分钟。
内容图文
作者 周信静,毕业于浙江大学,目前在CDB/CynosDB数据库内核团队参与TXSQL云数据库内核研发工作,参与了热点行更新以及一系列性能优化工作,并修复了多个MySQL官方bug。
Part1 背景
InnoDB的自适应哈希索引(Adpative Hash Index,以下简称AHI),是一种建立在B树索引结构上的索引结构,目的是为了进一步降低BTree的查询代价。
在B树中搜索一个记录时,需要从根节点下降到叶子结点,同时在每个节点中还需要使用二分查找定位。而AHI对此的改进在于它对BTree索引频繁访问的叶子的行记录建立哈希索引,这样在执行B树查询时,通过AHI就可能能定位到叶子结点上的记录位置,避免B树根节点到叶子结点的下降过程,减少了CPU开销。
由于AHI的构建是一个自适应且动态的过程,需要根据查询负载访问模式的变更、页面的换入和淘汰等情况做AHI对应清理或者重建,所以本质上来说AHI也是一个cache,具体的构建逻辑网络上也有很多文章讲解,不是本文讨论的重点。
本文要讨论的是一个鲜为人知的AHI构建锁冲突问题以及相应优化。
Part2 问题
TXSQL 5.7版本在跑sysbench时,我们观察到一个非常有意思的现象。
实验环境是这样的,2台96-core的机器,分别作为sysbench client和mysql server,我们配置buffer pool大小为200GB,同时生成一张120GB的sysbench table。
如下图所示,我们执行128并发的oltp_read_only负载时,观察到QPS首先有一个上升的坡,这段时间我们发现系统有大量的读IO,正在填充buffer pool,属于正常状态。
然后过了100s时突然出现了一个急剧的下降,在400s后开始系统QPS开始缓慢上升,直到800s后达到峰值。
通过perf工具抓取系统在QPS剧降时间点的状态,结果如下图:
分析堆栈,可以发现,大量CPU花费在在AHI的hash table的锁竞争上。
仔细分析不难发现,这个时候大多数页面基本上还没有建立AHI,然后多个线程同时需要对页面建立AHI索引,而这个构建过程需要对同一个AHI hash table加X锁,因此造成了大量等待。
从QPS变化的角度,可以有如下图所示的分析:
Part3 优化
我们注意到,对于一个BTree索引来说,其AHI构建是在BTree叶子结点定位完毕后发生的,对应调用链如下:
btr_cur_search_to_nth_level→ btr_search_info_update→ btr_search_info_update_slow→ btr_search_build_page_hash_index
在btr_search_info_update_slow中,根据统计信息作出决定,调用btr_search_build_page_hash_index把当前页面的记录加入AHI的hash table,这个过程需要独占hash table的X锁。
既然只能有一个线程对hash table进行修改,那么其他并发构建AHI线程等待这个hash table的X锁是相当不明智的,因为这样block住了查询的关键路径,同时只有一个线程在做这个构建工作。
同时我们又注意到AHI只是一个辅助cache,其实用BTree也是能够正确处理查询的。
那么很自然的,我们可以想到如下的优化方式:
-
当我们在BTree查询路径上经过分析后决定要对某一页构建AHI索引时,我们首先看一下该BTree所对应的hash table的锁是否被其他线程拿住了写锁;
- 如果被拿住了写锁,我们取消这次针对页的AHI索引构建任务,等待下次再次访问到该页时再尝试去构建,fallback到普通的BTree查询。
Part4 具体实现
从实现角度来说,其实非常简单:在btr_search_info_update_slow根据统计信息判断要对一页的记录建立AHI索引时,我们加入一个条件判断:如果当前有并发AHI构建线程拿住了hash table的X锁,我们直接返回即可。
代码只有几行,大致如下:
有人可能会担心这样直接跳过会不会影响代码正确性?
答案是否定的,因为我们这里没有清除该页面关于AHI的任何统计信息,只是推迟了构建时机,即推迟到hash table锁冲突不严重的时候再进行。
Part5 效果
应用上述的优化后,我们重新执行上述实验,得到如下的结果图:
其中,红线(开启AHI+Contention Avoidance优化)是我们实现上述优化后结果,经过100s左右的预热后,性能稳定,锁瓶颈消失。
Part6 灵感来源
其实在原始的AHI查询路径上已经有一个类似的优化了:
在btr_cur_search_to_nth_level中执行AHI查询前,如果发现AHI的hash table被其他线程X锁住了,直接fallback到BTree查询。
这里的优化考量是类似的:与其等待AHI的hash table的X锁,不如直接走btree搜索,代价很可能比等待X锁更低,并发度更高。
Part7 总结
该优化目前已经在TXSQL5.7最新版本中上线,将会有效缓解AHI构建的锁竞争问题,可能的场景包括不限于:系统启动、AHI开关刚开启、主备切换时,所有页面都还没有AHI记录,高并发可能导致大量的AHI构建工作。
同时经过我们验证,在官方MySQL的5.7和8.0最新版本中都存在该问题,因此我们也已经将这个优化思路贡献给了官方, https://bugs.mysql.com/bug.php?id=100512 ,目前正在评估,相信不久将合入主线。
即将写入MySQL源码的官方bug解决之路
标签:abc 树根 bugs 建立 search 行修改 osd 针对 缓解
本文系统来源:https://blog.51cto.com/14992250/2551638
内容总结
以上是互联网集市为您收集整理的即将写入MySQL源码的官方bug解决之路全部内容,希望文章能够帮你解决即将写入MySQL源码的官方bug解决之路所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。