加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

InnoDB Insert Buffer unable to purge a record

发布时间:2022-03-26 13:23:08 所属栏目:编程 来源:互联网
导读:MySQL5.6.23: fix UNABLE TO PURGE A RECORD 本文简述下之前我们线上频繁碰到的UNABLE TO PURGE A RECORD的原因 ################################################### 线上实例错误日志中偶尔出现 UNABLE TO PURGE A RECORD,从官方bug系统来看,很多用户都
      MySQL5.6.23: fix “UNABLE TO PURGE A RECORD”
     本文简述下之前我们线上频繁碰到的“UNABLE TO PURGE A RECORD”的原因
 
###################################################
 
      线上实例错误日志中偶尔出现 “UNABLE TO PURGE A RECORD”,从官方bug系统来看,很多用户都遇到了类似的问题。
  
     当change buffer模块以如下序列来缓存索引操作时:
 
记录被标记删除(IBUF_OP_DELETE_MARK)
随后插入相同记录–IBUF_OP_INSERT
Purge线程需要物理删除二级索引记录,操作被buffer–IBUF_OP_DELETE
  
     当读入物理页时,需要进行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线程会做如下几件事儿:
 
首先查询buffer pool,看看page是否已经读入内存;
如果不在内存中,则将page no等信息存储到watch数组中,并插入page hash(buf_pool_watch_set)。如果随后page被读入内存,就会删除watch标记。
 
判断该二级索引记录是否可以被Purge(row_purge_poss_sec,当该二级索引记录对应的聚集索引记录没有delete mark并且其trx id比当前的purge view还旧时,不可以做Purge操作)
  
随后,再插入IBUF_OP_DELETE类型的ibuf记录时,还会double check下该page是否被设为sentinel (ibuf_insert_low,buf_pool_watch_occurred),如果未被设置,表明已经page已经读入内存,就可以直接去做purge,而无需缓存了。
  
对于普通的操作类型,例如IBUF_OP_INSERT和IBUF_OP_DELETE_MARK,同样也会double check page 是否读入了内存。在函数ibuf_insert中会调用buf_page_hash_get进行检查, 如果page被读入内存,则不缓存操作,如果请求的Page被设为sentinel,则从buf_page_hash_get返回NULL,因此随后判定需要缓存操作。这也正是问题的所在:
标记删除记录,写入IBUF_OP_DELETE_MARK
Purge线程设置page对应的sentinel,完成合法性检查,准备调用ibuf_insert
插入相同记录,写入IBUF_OP_INSERT
Purge线程写入IBUF_OP_DELETE
解决
 
如果记录所在的page被设置了一个sentinel,那么对该page的并发插入操作就不应该缓存到change buffer中,而是直接去尝试读取物理页。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读