重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
本文简述下之前我们线上频繁碰到的“UNABLE TO PURGE A RECORD”的原因
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册、网络空间、营销软件、网站建设、尼开远网站维护、网站推广。
###################################################
线上实例错误日志中偶尔出现 “UNABLE TO PURGE A RECORD”,从官方bug系统来看,很多用户都遇到了类似的问题。
当change buffer模块以如下序列来缓存索引操作时:
当读入物理页时,需要进行ibuf merge,当执行到IBUF_OP_DELETE时,发现记录并没有被标记删除,导致错误日志报错。
显然上述的操作序列是不合理的,正确的序列应该是IBUF_OP_DELETE_MARK,IBUF_OP_DELETE,IBUF_OP_INSERT。
为了理清逻辑,我们简单的理一下相关代码
注意IBUF_OP_DELETE是由第一步的标记删除操作触发,Purge线程发起;在每个buffer pool的控制结构体中,有一个成员buf_pool->watch[BUF_POOL_WATCH_SIZE],BUF_POOL_WATCH_SIZE的值为purge线程个数,用于辅助Purge操作。
假定内存中没有对应的Page,Purge线程会做如下几件事儿:
如果不在内存中,则将page no等信息存储到watch数组中,并插入page hash(buf_pool_watch_set)。如果随后page被读入内存,就会删除watch标记。
解决
如果记录所在的page被设置了一个sentinel,那么对该page的并发插入操作就不应该缓存到change buffer中,而是直接去尝试读取物理页。
https://github.com/mysql/mysql-server/commit/ec369cb4f363161dfbbbd662b20763b54808b7d1