程序员必备!这是即将写入MySQL源码的官方bug解决方案
作者:周信静 , 毕业于浙江大学 , 目前在CDB/CynosDB数据库内核团队参与TXSQL云数据库内核研发工作 , 参与了热点行更新以及一系列性能优化工作 , 并修复了多个MySQL官方bug 。
1背景InnoDB的自适应哈希索引(Adpative Hash Index , 以下简称AHI) , 是一种建立在B树索引结构上的索引结构 , 目的是为了进一步降低BTree的查询代价 。
在B树中搜索一个记录时 , 需要从根节点下降到叶子结点 , 同时在每个节点中还需要使用二分查找定位 。 而AHI对此的改进在于它对BTree索引频繁访问的叶子的行记录建立哈希索引 , 这样在执行B树查询时 , 通过AHI就可能能定位到叶子结点上的记录位置 , 避免B树根节点到叶子结点的下降过程 , 减少了CPU开销 。
由于AHI的构建是一个自适应且动态的过程 , 需要根据查询负载访问模式的变更、页面的换入和淘汰等情况做AHI对应清理或者重建 , 所以本质上来说AHI也是一个cache , 具体的构建逻辑网络上也有很多文章讲解 , 不是本文讨论的重点 。
【程序员必备!这是即将写入MySQL源码的官方bug解决方案】本文要讨论的是一个鲜为人知的AHI构建锁冲突问题以及相应优化 。
2问题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变化的角度 , 可以有如下图所示的分析:
文章插图
3优化我们注意到 , 对于一个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也是能够正确处理查询的 。
那么很自然的 , 我们可以想到如下的优化方式:
1. 当我们在BTree查询路径上经过分析后决定要对某一页构建AHI索引时 , 我们首先看一下该BTree所对应的hash table的锁是否被其他线程拿住了写锁;
2. 如果被拿住了写锁 , 我们取消这次针对页的AHI索引构建任务 , 等待下次再次访问到该页时再尝试去构建 , fallback到普通的BTree查询 。
4具体实现从实现角度来说 , 其实非常简单:在btr_search_info_update_slow根据统计信息判断要对一页的记录建立AHI索引时 , 我们加入一个条件判断:如果当前有并发AHI构建线程拿住了hash table的X锁 , 我们直接返回即可 。
代码只有几行 , 大致如下:
文章插图
有人可能会担心这样直接跳过会不会影响代码正确性?
答案是否定的 , 因为我们这里没有清除该页面关于AHI的任何统计信息 , 只是推迟了构建时机 , 即推迟到hash table锁冲突不严重的时候再进行 。
5效果应用上述的优化后 , 我们重新执行上述实验 , 得到如下的结果图:
文章插图
其中 , 红线(开启AHI+Contention Avoidance优化)是我们实现上述优化后结果 , 经过100s左右的预热后 , 性能稳定 , 锁瓶颈消失 。
- 当初|这是我的第一部华为手机,当初花6799元买的,现在“一文不值”?
- 现状|程序员现状揭秘:平均年薪20.36万,Java人才需求量最大
- 联网时代|34岁转行做程序员是否还有成功的机会
- 政治目|瑞典限制华为引商界巨鳄不满:这是想步澳大利亚等国后尘?
- 智慧城市|被汽车物联网控制的未来,这是我们向往的新生活吗?
- 华为|瑞典限制华为恐遭反制,这是要步澳大利亚的后尘?
- 最惨|这是 iPhone 12 被黑最惨的一次!
- 运营|淘宝这是要变成“小淘书”了么?
- 程序员学英语第1天——JavaScript 程序测试的介绍1
- 这些错误,程序员经常会犯,你了解过吗?
