MySQL 5.7 对buffer pool list scan的优化

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

worklog: http://dev.mysql.com/worklog/task/?id=7047
原作者Innam 跳槽到twitter后 将该特性合并到webscalesql: https://github.com/webscalesql/webscalesql-5.6/commit/c834781321d97b914c3712c663bd7209175a3fe2#diff-07468177c19cc3f32d25913fe731f936R1814

在该worklog中,主要对LRU LIST 和FLUSH List的扫描做了优化,通过设置Hazard Pointer的pointer的方式,避免多线程操作同一个buffer pool导致的回溯扫描list.该优化对buffer pool小于数据集的场景比较有益。用户线程驱逐获取空闲block,用户线程在同步checkpoint时做pre flush dirty page,以及page cleaner线程之间 都可能产生冲突。

新对象
通过如下几个指针作为hazard pointer,在需要扫描LIST时,存储下一个即将扫描的目标page,根据不同的目的:
flush_hp: 用作对FLUSH LIST BATCH操作
lru_hp: 用作对LRU LIST BATCH 操作
lru_scan_itr: 用作从LRU链表上替换驱逐一个干净的page,总是从上一次扫描结束的位置开始,而不是LRU尾部。
single_scan_itr: 用作从LRU上刷新或驱逐一个Page, 总是从上一次结束的位置开始,而不是LRU尾部
后两类的hp,在到达LRU->old时,会被重置到LRU尾部

初始化
在buf_pool_init_instance初始化每个bp instance时分配并初始化hp,每个bp instance都拥有自己的hp

更新hazard pointer
当某个线程对buffer pool中的page进行时,例如需要从LRU中移除Page时,如果当前的page被设置为hp,就要将hp更新为当前Page的前一个page

flush_hp: 如下函数中调整:buf_flush_remove, buf_flush_relocate_on_flush_list,每次batch flush list后清空
lru_hp: 在函数buf_LRU_adjust_hp中调整,buf_LRU_remove_block, buf_relocate,每次batch lru list后清空
lru_scan_itr/single_scan_itr, 对其adjust操作同样封装在buf_LRU_adjust_hp中,另外在LRUItr::start中有判断是否到达LRU->old,如果到达了,hp也会重新指向到LRU尾部。

几个主要的更改

buf_flush_LRU_list_batch
在调用函数该函数扫描page时,从尾部开始,依次通过bpage = buf_pool->lru_hp.get()来操作下一个,每操作依次page,更新lru_hp为PREV
而原始逻辑中,
当可以驱逐时,每次驱逐一个page, 都需要从LRU尾部重新开始扫描。
当不可以驱逐时,保存前一个page, 调用buf_flush_page_and_try_neighbors 会释放并重新获取buffer pool mutex,因此需要从page hash中再次确认prev page
——新的逻辑省略了查找page hash 以确认prev page存在的开销 (因为中间会release bp mutex)

buf_do_flush_list_batch
—同样的设置flush_hp上的page指针
—5.6原始版本中,当发现了指针被重置后,会从尾部重新扫描;而新的逻辑不会回溯链表。
从最差O(N^2) 到真正的O(N)

buf_flush_single_page_from_LRU
根据buf_pool->single_scan_itr扫描LRU
LRUItr是LRUHp的子类
增加新的行为:
—原始行为:
从LRU尾部开始,找一个脏页,flush it (buf_flush_ready_for_flush, buf_flush_page)
重新扫描LRU,从尾部开始,找到一个可替换的page,将其加入到free list
—现在的行为:直接在一次扫描中完成,省去一次扫描
如果发现可replace的page,直接放到free list上
否则如果发现脏页,flush it, 并加入到free list上

buf_flush_LRU_tail
—— 不再按照chunk by chunk的方式flush LRU
划分成chunk(每次从LRU上刷100个page)的原因是因为可能有用户线程可能在函数buf_LRU_get_free_block中等待flush结束,但新的逻辑中,用户线程不再需要等待batch flush操作结束。

buf_LRU_get_free_block
现在逻辑:
–不再判断buffer pool是否正在进行flush lru操作,因此无需 buf_flush_wait_batch_end
—尝试从LRU上释放一个空闲block到free list上 (会调用到buf_LRU_free_from_common_LRU_list),如果失败,则唤醒page cleaner线程

buf_LRU_free_from_common_LRU_list
通常为用户线程调用 (上层函数buf_LRU_scan_and_free_block)来获取一个空闲block
—原始逻辑:扫描LRU深度最大为srv_LRU_scan_depth
—现在逻辑:扫描LRU深度最大为BUF_LRU_SEARCH_SCAN_THRESHOLD(100)
使用lru_scan_itr来进行扫描,找到一个空闲的block 加入到free list 。根据官方worklog的解释,如果扫描了100个page都没有clean的,那么最好返回做一次single page flush


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
10天前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
14天前
|
缓存 监控 关系型数据库
如何优化MySQL查询速度?
如何优化MySQL查询速度?【10月更文挑战第31天】
43 3
|
17天前
|
缓存 关系型数据库 MySQL
如何优化 MySQL 数据库的性能?
【10月更文挑战第28天】
40 1
|
24天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
63 9
|
18天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
86 1
|
24天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
55 5
|
29天前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
51 1
|
29天前
|
缓存 关系型数据库 MySQL
一文彻底弄懂MySQL优化之深度分页
【10月更文挑战第24天】本文深入探讨了 MySQL 深度分页的原理、常见问题及优化策略。首先解释了深度分页的概念及其带来的性能和资源问题。接着介绍了基于偏移量(OFFSET)和限制(LIMIT)以及基于游标的分页方法,并分析了它们的优缺点。最后,提出了多种优化策略,包括合理创建索引、优化查询语句和使用数据缓存,帮助提升分页查询的性能和系统稳定性。
|
19天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
28天前
|
存储 监控 关系型数据库
MySQL并发控制与管理:优化数据库性能的关键
【10月更文挑战第17天】MySQL并发控制与管理:优化数据库性能的关键
119 0