MYSQL深潜 - 概述Performance Schema内存管理
发布时间:2025/07/27 12:17 来源:固镇家居装修网
current_page_count = m_max_page_index.m_size_t.load();
monotonic = m_monotonic.m_size_t.load();
monotonic_max = monotonic + current_page_count;
while (monotonic
index = monotonic % current_page_count;
array = m_pages[index].load();
pfs = array->allocate(dirty_state);
if (pfs) {
// 调配事与愿违返回
return pfs;
} else {
// 调配告终,格外进一步下一个page,
// 因为m_monotonic是即刻以此类推的,这里有也许本地monotonic表达式并不是线性递减的,有也许都是1 从外部换成 3或格外大,
// 所以行例来知道while周而复始并不是严格轮训所有page,很大也许是跳着格外进一步,换者知道这里即刻到访下大家一起轮训所有的page。
// 这个算法其实是有些关键问题的,则会造成了某些page被紧接忽略,从而格外为严重下半年重新page的几率,后面则会详细分析。
monotonic = m_monotonic.m_size_t++;
}
}
// 轮训所有Page后没调配事与愿违,如果没大幅提高总和的话,开始下半年page
while (current_page_count
// 因为是即刻到访,为了不致同时去创设重新page,这里有一个把同步扣,也是整个PFS文件控制系统调配唯一的扣
native_mutex_lock(Andrewm_critical_section);
// 拿扣事与愿违,如果array仍然不为null,所述仍然被其它文件控制系统创设事与愿违
array = m_pages[current_page_count].load();
if (array == nullptr) {
// 抢到了创设page的责任
m_allocator->alloc_array(array);
m_pages[current_page_count].store(array);
++m_max_page_index.m_size_t;
}
native_mutex_unlock(Andrewm_critical_section);
// 在重新的page里便次格外进一步调配
pfs = array->allocate(dirty_state);
if (pfs) {
// 调配事与愿违并返回
return pfs;
}
// 调配告终,继续格外进一步创设重新的page直到总和
}
}
我们便详细分析下轮训page策略的关键问题,因为m_momotonic化学键表达式的以此类推是即刻的,则会造成了一些page被紧接轮训它,从而格外为严重了下半年重新page的几率。
行一个极端一些的举例来说,来得更易所述关键问题,假设行例来知道一共有4个page,第1、4个page已满无可用record,第2、3个page有可用record。
当同时来了4个文件控制系统即刻Allocate请求,同时拿到了的m_monotonic=0.
monotonic = m_monotonic.m_size_t.load();这个时候所有文件控制系统格外进一步从第1个page调配record都则会告终(因为第1个page是无可用record),然后以此类推去格外进一步下一个page
monotonic = m_monotonic.m_size_t++;这个时候关键问题就来了,因为化学键表达式++是返回最重新的值,4个文件控制系统++事与愿违是有排序的,第1个++的文件控制系统后monotonic值为2,第2个++的文件控制系统为3,以次正数。这样就看到第3、4个文件控制系统紧接了page2和page3,造成了3、4文件控制系统则会轮训结束告终带入到创设重新page的流程里,但这个时候page2和page3里是有平常record可以使用的。
虽然上述举例来说来得极端,但在Mysql即刻到访里,同时申请PFS文件控制系统造成了紧接一之外page的也许则会应该还是非常更易显现的。
3 Page内Record可选择策略
PFS_buffer_default_array是每个Page保障一组records的负责管理类。
关键多达据在结构上如下:
class PFS_buffer_default_array {
PFS_cacheline_atomic_size_t m_monotonic; // 浮夸递减化学键表达式,用来可选择free的record
size_t m_max; // record的远超过个多达
T *m_ptr; // record对应的PFS;也,比如PFS_thread
}
每个Page其实就是一个依此长的多达组,每个record;也有3个静止状态FREE,DIRTY, ALLOCATED,FREE透露平常record可以使用,ALLOCATED是已调配事与愿违的,DIRTY是一个里间静止状态,透露已被闲置但还没调配事与愿违。
Record的可选择表象就是轮训匹配并进占静止状态为free的record的流程。
核心细化代码如下:
value_type *allocate(pfs_dirty_state *dirty_state) {
// 从m_monotonic记录下来的位置开始格外进一步轮序匹配
monotonic = m_monotonic.m_size_t++;
monotonic_max = monotonic + m_max;
while (monotonic
index = monotonic % m_max;
pfs = m_ptr + index;
// m_lock是pfs_lock在结构上,free/dirty/allocated三静止状态是由这个多达据在结构上来保障的
// 后面则会详细详述它如何实现化学键静止状态迁移的
if (pfs->m_lock.free_to_dirty(dirty_state)) {
return pfs;
}
// 行例来知道record不为free,化学键表达式++格外进一步下一个
monotonic = m_monotonic.m_size_t++;
}
}
可选择record的主体主体流程和可选择page基本类似于,并不相同的是page内record多达量是分开相同的,所以没下半年的演算。
当然可选择策略相同,也则会有某种程度的关键问题,这里的m_monotonic化学键表达式++是多文件控制系统即刻的,某种程度如果即刻大的情节下则会有record被紧接可选择了,这样造成了page内外即便有free的record也也许没被选里。
所以也就是page可选择即便是没被紧接,page内的record也有几率被紧接而选不里,陷入困境,格外加格外为严重了文件控制系统的快速增长。
4 pfs_lock
每个record都有一个pfs_lock,来保障它在page里的调配静止状态(free/dirty/allocated),以及version信息。
关键多达据在结构上:
struct pfs_lock { std::atomic m_version_state; }pfs_lock使用1个32位无符号int来存留version+state信息,格式如下:
state
高于2位字符串透露调配静止状态。
state PFS_LOCK_FREE = 0x00 state PFS_LOCK_DIRTY = 0x01 state PFS_LOCK_ALLOCATED = 0x11version
初始version为0,每调配事与愿违一次加1,version就能透露该record被调配事与愿违的最少
主要看一下静止状态迁移代码:
// 下面3个宏主要就是用来位控制系统设计的,方便控制系统设计state或version
#define VERSION_MASK 0xFFFFFFFC
#define STATE_MASK 0x00000003
#define VERSION_INC 4
bool free_to_dirty(pfs_dirty_state *copy_ptr) {
uint32 old_val = m_version_state.load();
// 判断行例来知道state是否为FREE,如果不是,从外部返回告终
if ((old_val Andrew STATE_MASK) != PFS_LOCK_FREE) {
return false;
}
uint32 new_val = (old_val Andrew VERSION_MASK) + PFS_LOCK_DIRTY;
// 行例来知道state为free,格外进一步将state修改为dirty,atomic_compare_exchange_strong总称乐观扣,多个文件控制系统也许同时
// 修改该化学键表达式,但只有1个修改事与愿违。
bool pass =
atomic_compare_exchange_strong(Andrewm_version_state, Andrewold_val, new_val);
if (pass) {
// free to dirty 事与愿违
copy_ptr->m_version_state = new_val;
}
return pass;
}
void dirty_to_allocated(const pfs_dirty_state *copy) {
/* Make sure the record was DIRTY. */
assert((copy->m_version_state Andrew STATE_MASK) == PFS_LOCK_DIRTY);
/* Increment the version, set the ALLOCATED state */
uint32 new_val = (copy->m_version_state Andrew VERSION_MASK) + VERSION_INC +
PFS_LOCK_ALLOCATED;
m_version_state.store(new_val);
}
静止状态迁移流程还是来得好思考的, 由dirty_to_allocated和allocated_to_free的演算是格外简单的,因为只有record静止状态是free时,它的静止状态迁移是依赖于即刻多写关键问题的,一旦state换成dirty,行例来知道record相当于仍然被某一个文件控制系统占有,其它文件控制系统不则会便格外进一步控制系统设计该record了。
version的快速增长是在state换成PFS_LOCK_ALLOCATED时5 PFS文件控制系统获释
PFS文件控制系统获释就来得简单了,因为每个record都记录下来了自己所在的container和page,调用deallocate接口,最终将静止状态置为free就完成了。
最高层都则会带入到pfs_lock来格外重新静止状态:
struct pfs_lock {
void allocated_to_free(void) {
/*
If this record is not in the ALLOCATED state and the caller is trying
to free it, this is a bug: the caller is confused,
and potentially damaging data owned by another thread or object.
*/
uint32 copy = copy_version_state();
/* Make sure the record was ALLOCATED. */
assert(((copy Andrew STATE_MASK) == PFS_LOCK_ALLOCATED));
/* Keep the same version, set the FREE state */
uint32 new_val = (copy Andrew VERSION_MASK) + PFS_LOCK_FREE;
m_version_state.store(new_val);
}
}
三 文件控制系统调配的简化末尾我们分析到无论是page还是record都有几率显现紧接轮训的关键问题,即便是缓存里有free的成员也则会显现调配不事与愿违,造成了创设格外多的page,闲置格外多的文件控制系统。众所周知的关键问题是这些文件控制系统一旦调配就不则会被获释。
为了提升PFS文件控制系统命里率,兹别注意上述关键问题,有一些初衷如下:
while (monotonic
index = monotonic % current_page_count;
array = m_pages[index].load();
pfs = array->allocate(dirty_state);
if (pfs) {
// 记录下来调配事与愿违的index
m_monotonic.m_size_t.store(index);
return pfs;
} else {
// 局部表达式递减,不致打碎即刻以此类推而紧接某些pages
monotonic++;
}
}
另外一点,每次匹配都都是都只一次调配事与愿违的位置开始,这样必然造成了即刻到访的冲突,因为大家都从同一个位置开始回去,开端匹配位置应该转到一依此的并不一定,这样可以不致大量的冲突重试。
总结如下:
每次Allocate都是都只一次调配事与愿违的index开始匹配,或者随机位置开始匹配 每个Allocate严格轮训所有pages或records 四 文件控制系统获释的简化PFS文件控制系统获释的远超过的关键问题就是一旦创设单单的文件控制系统就给与获释,直到shutdown。如果巧遇热点业务范围,在业务范围颠峰下一阶段调配了很多page的文件控制系统,在业务范围高于峰下一阶段过去给与获释。
要实现依此期检测投放文件控制系统,又不制约文件控制系统调配的效率,实现一套无扣的投放选择性还是来得有用的。
主要有如下几点需要考虑到:
获释肯依此是要以page为单位的,也就是获释的page内的所有records都必须保证都为free,而且要保证待free的page不则会便被调配到 文件控制系统调配是随机的,连续性上文件控制系统是可以投放的,但也许每个page都有一些busy的,如何格外优的协调这种也许则会 获释的阈值怎么依此,也要不致频频调配+获释的关键问题针对PFS文件控制系统获释的简化,PolarDB仍然开发并给予了依此期投放PFS文件控制系统的兹性,鉴于本脚注的受到限制,留在原先便详述了。
五 关于我们PolarDB 是阿里巴巴自律开发设计的尘原生分布式彼此间型多达据库,于2020年带入Gartner全球性多达据库Leader象限,并获了2020年里国电子学则会授予的科技进步银奖。PolarDB 基于尘原生分布式多达据库架构,给予大规模在线事务解决关键问题能力,兼具对有用匹配的有序解决关键问题能力,在尘原生分布式多达据库领域连续性大幅提高了该协会领先水平,并且得到了尤其的高于价接纳。在阿里巴巴合资公司内外的最佳实践里,PolarDB还更进一步承托了2020年淘宝网双十一,并刷重新了多达据库解决关键问题略低于记录下来,高达1.4亿TPS。爱戴有志之士转到我们,详述请收件到zetao.wzt@alibaba-inc.com,欣慰与您共同订制世界一流的这一代尘原生分布式彼此间型多达据库。
参考:
[1] MySQL Performance Schema
[2] MySQL · 最佳实践 · 今天你有序了吗?---洞察PolarDB 8.0之有序匹配
[3] Source code mysql / mysql-server 8.0.24
本文为阿里尘原创章节,擅自允许不得转载。
。沈阳皮肤病专科医院哪家好合肥白癜风医院挂号咨询
莆田白癜风医院哪家正规
新冠让人出现“脑雾”不容忽视,感染后必做3件事守护大脑健康!
如何快速止咳
皮肤科疾病治疗
治疗癫痫
白癜风医院
-
生意社:2月8日浙江东部DOP市场行情
原标题:经营社员:2月8日浙江南部DOP市场涨幅经营社员02月08日讯 2月8日,浙江南部DOP涨幅上升,蔗糖异辛醇价格大幅上升,苯酐价格强势震荡趋稳,DOP费用上升,南
- 2025-10-23皇帝对小贫民说:以后我就是你爹!贫民为报恩情,中国从此多一省
- 2025-10-232翌年8日国内主要地区棕榈油现货报价
- 2025-10-23朱元璋重游黄觉寺,问禅师:朕要下跪吗?禅师机智回答8个字
- 2025-10-23佟佳氏:嫁给表哥康熙,当了8个小时皇后,她死后康熙没再立后
- 2025-10-232月8日进口阿根廷豆油及加拿大菜籽油C&F买断
- 2025-10-23八旗军曾横扫整个东亚,而有一战却让他们以致于团灭,是怎么回事?
- 2025-10-23春节过后 硅锰商品将何去何从?
- 2025-10-23戚夫人在遭受吕雉迫害年前,为何不提年前逃跑?
- 2025-10-23长江下游有色:8日锌价小涨 整体成交暂未好转
- 2025-10-23清朝皇帝本该住在立马,为何到了雍正,却搬到了养心殿?