当前位置: 首页 > 网络应用技术

MySQL深度潜水|分析性能架构内存管理

时间:2023-03-05 20:01:38 网络应用技术

  简介:本文主要是通过阅读PFS引擎的内存管理源代码,解释PFS内存分配和发布的原理,对某些问题的深入分析以及一些改进的想法。

  MySQL性能架构(PFS)是由MySQL提供的强大性能监视诊断工具,该工具提供了一种特殊的方法,可以在Runtime.pfs期间检查服务器的内部执行。pfs通过监视服务器中的注册事件来收集信息。从理论上讲,事件可以是服务器内的活动或资源职业,例如函数调用,呼叫等待,SQL查询或排序状态,或IT ICMEMORY RESISIONS职业。

  PFS存储在Performance_Schema存储引擎中,Performance_Schema Storage Engine是一种内存表引擎,也就是说,所有收集的诊断信息都将存储在内存中。诊断信息的收集和存储将带来一定数量的额外开销。为了尽可能地影响业务,PF的性能和内存管理也非常重要。本文主要是通过阅读PFS引擎内存管理的源代码,解释PFS内存分配和发布的原理,在对某些问题和一些改进想法的深度分析中。本文的源代码分析基于MySQL -8.0.24版本。

  PFS内存管理有几个关键功能:

  1核心数据结构

  PFS_BUFFER_SCALABLE_CONTAINER是PFS内存管理的核心数据结构。总体结构如下所示:

  容器包含多个付款,每个页面都有固定数量的记录。每个记录对应于一个事件对象,例如pfs_thread。每个页面中的记录次数均已固定,但是页面的数量随加载的增加而增加。

  2分配页面选择策略

  PFS_BUFFER_SCALABLE_CONTAINER是PFS内存管理的核心数据结构,涉及内存分布的关键数据结构如下:

  首先,m_pages是一个数组。每个页面都有免费记录。整个页面也可能很忙。MySQL使用相对简单的策略。尝试尝试每个页面是否免费,直到分发成功为止。如果所有页面都不成功,将创建新页面以扩展到页面数量的上限为止。

  并非每次您开始查看第一页时旋转训练,而是使用原子变量M_onotonic记录的位置开始位置。M_Monotonic无法在每个页面中添加1个。

  核心简化代码如下:

  让我们详细分析下一个环形培训页面策略的问题,因为M_Momotonic原子变量的积累是并发的,这将导致某些页面跳过旋转培训,这加剧了扩展新页面的机会。

  例如,一个极端的例子更容易解释问题。假设总共有4页,第一页和4页已满记录,第二和3付款可用于记录。

  当同时达到4个线程时,分配请求和m_monotonic = 0。

  monotonic = m_onotonic.m_size_t.load();

  目前,所有线程都尝试从第一页分配记录(因为第一页不可记录),然后尝试尝试下一页

  单调= m_onotonic.m_size_t ++;

  目前,问题出现了,因为原子变量++返回最新值,而4个线程++成功具有序列。在第一个++线程之后,单调值为2,第二个++线程3,推入第二类。在这样,我看到了第三个和第4个线程跳过Page2和page3,这导致线程失败结束在旋转训练到创建新页面的过程中,但是此时,Page2和Page 3可以免费记录。

  尽管以上示例非常极端,但在MySQL访谈中,同时申请PFS内存可能会导致页面的一部分非常容易出现。

  3页记录选择策略

  PFS_BUFFER_DEFAULT_ARAY是每个页面的管理类,可维护一组记录。

  关键数据结构如下:

  每个页面实际上都是固定的长度数组。每个记录对象都有3个免费,肮脏,分配,免费的免费状态,意味着可以使用免费记录,分配已成功分配,而Dirty是中间状态,表明它已经被占据了成功。

  选择记录的本质是搜索和抓住国家状态的过程。

  核心简化代码如下:

  选择记录的主要过程基本上与选择页面的选择相似。区别在于页面中的记录数是固定的,因此没有扩展逻辑。

  当然,相同的选择策略将存在相同的问题。这里的m_monotonic原子变量++是多线程。如果在同一并发场景中会有记录,则将选择它。

  因此,即使没有跳过页面选择,页面中的记录也有机会被跳过而没有选择。积雪更糟,甚至加剧了记忆的增长。

  4 pfs_lock

  每个记录都有一个PFS_LOCK,以维持其在页面和版本信息中的分布状态。

  关键数据结构:

  struct pfs_lock {std :: atomic m_version_state;}

  pfs_lock使用1 32 -bit Unsigned Integer来保存版本+状态信息。格式如下:

  状态低2个字节表示分布状态。

  状态pfs_lock_free = 0x00状态pfs_lock_dirty = 0x01状态pfs_lock_allocated = 0x11

  版本初始版本为0。每次分发成功时,1可以指示记录的数量成功分布。查看状态迁移代码:

  状态迁移过程最好理解。dirty_to_allocated和分配_to_free的逻辑的逻辑更简单,因为只有当记录状态免费时,其状态迁移是同时存在的。

  版本的增长是状态变为pfs_lock_allocated的时候

  5 PFS内存发布

  PFS内存版本相对简单,因为每个记录其记录的容器和页面,调用Deallocation接口,并最终将状态放置为免费。

  底层将输入pfs_lock以更新状态:

  早些时候,我们分析了页面和记录都有机会进行跳过旋转训练的问题。即使是在缓存中有免费的成员也会具有不成功的分布,从而产生更多页面并占据更多内存。主要问题是,一旦分配了这些内存,就不会发布这些内存。

  为了提高PFS的主动命中率并尝试避免上述问题,有以下想法:

  另一方面,每个搜索都从成功分配上次分配的位置开始,因此它不可避免地会导致并发访问的冲突,因为每个人都从相同的位置开始。重复冲突。

  总结如下:

  每次淡化从最近分配的索引开始,或者开始找到随机位置

  每个分配严格训练所有页面或记录

  PFS内存发布的最大问题是,一旦创建了内存,直到关闭之前才发布。阶段。

  实现定期检测和回收记忆的效率而不影响记忆分布的效率更为复杂。

  主要需要考虑以下几点:

  该版本必须基于页面,即,必须保证发行版中的所有记录是免费的,并且有必要确保不再将免费页面分配给内存分配。回收,但是每个页面都可能很忙。如何更好地协调如何在这种情况下设置阈值,并避免频繁的分销+发布问题。

  为了响应PFS内存释放的优化,PolardB已开发并提供了常规回收PFS存储器的特征。鉴于该空间的限制,在以下内容中引入了。

  Polardb是由阿里巴巴独立开发的基于云的分布式关系数据库。2020年,他进入了Gartner全球数据库领导者限制,并赢得了中国电子协会在2020年授予的科学和技术进步的一等奖。Polardb基于云本地分布式数据库体系结构,并提供了大规模的在线交易处理能力。它具有用于复杂查询的并行处理功能。它已经达到了云本机分布数据库领域的国际领先水平,并被广泛认可。在阿里巴巴集团的最佳实践中,Polardb在2020年也完全支持Tmall Double Eleven,并刷新了数据库处理峰值记录有1.4亿英镑。有志向加入我们的人。请提交到zetao.wzt@alibaba-inc.com,并期待与您创建世界一流的下一代云本机分布关系数据库。

  参考:[1] mySQL性能schemahttps://dev.mysql.com/doc/refman/8.0/en/performance-schema.html

  [2] MySQL·最佳实践·您今天是否在并行进行?--- Insight Polardb 8.0并行查询http://mysql.taobao.org/monthly/2019/11/01/

  [3]源代码mysql/mysql-server 8.0.24https://github.com/mysql/mysql-mysql-server/mysql-8.0.24

  资料来源:阿里巴巴云