12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
ADADADADAD
mysql数据库 时间:2024-12-03 12:12:12
作者:文/会员上传
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
转载:http://mysqllover.com/?p=1264
参考:InnoDB Insert Buffer实现详解 http://hedengcheng.com/?p=94
MySQL5.6.23: fix “UNABLE TO PURGE A RECORD”本文简述下之前我
以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。
本文简述下之前我们线上频繁碰到的“UNABLETOPURGEARECORD”的原因
###################################################
线上实例错误日志中偶尔出现“UNABLETOPURGEARECORD”,从官方bug系统来看,很多用户都遇到了类似的问题。
当changebuffer模块以如下序列来缓存索引操作时:
当读入物理页时,需要进行ibufmerge,当执行到IBUF_OP_DELETE时,发现记录并没有被标记删除,导致错误日志报错。
显然上述的操作序列是不合理的,正确的序列应该是IBUF_OP_DELETE_MARK,IBUF_OP_DELETE,IBUF_OP_INSERT。
为了理清逻辑,我们简单的理一下相关代码
注意IBUF_OP_DELETE是由第一步的标记删除操作触发,Purge线程发起;在每个bufferpool的控制结构体中,有一个成员buf_pool->watch[BUF_POOL_WATCH_SIZE],BUF_POOL_WATCH_SIZE的值为purge线程个数,用于辅助Purge操作。
假定内存中没有对应的Page,Purge线程会做如下几件事儿:
首先查询bufferpool,看看page是否已经读入内存;如果不在内存中,则将pageno等信息存储到watch数组中,并插入pagehash(buf_pool_watch_set)。如果随后page被读入内存,就会删除watch标记。
判断该二级索引记录是否可以被Purge(row_purge_poss_sec,当该二级索引记录对应的聚集索引记录没有deletemark并且其trxid比当前的purgeview还旧时,不可以做Purge操作)随后,再插入IBUF_OP_DELETE类型的ibuf记录时,还会doublecheck下该page是否被设为sentinel(ibuf_insert_low,buf_pool_watch_occurred),如果未被设置,表明已经page已经读入内存,就可以直接去做purge,而无需缓存了。对于普通的操作类型,例如IBUF_OP_INSERT和IBUF_OP_DELETE_MARK,同样也会doublecheckpage是否读入了内存。在函数ibuf_insert中会调用buf_page_hash_get进行检查,如果page被读入内存,则不缓存操作,如果请求的Page被设为sentinel,则从buf_page_hash_get返回NULL,因此随后判定需要缓存操作。这也正是问题的所在:解决
如果记录所在的page被设置了一个sentinel,那么对该page的并发插入操作就不应该缓存到changebuffer中,而是直接去尝试读取物理页。
https://github.com/mysql/mysql-server/commit/ec369cb4f363161dfbbbd662b20763b54808b7d1
11-20
11-19
11-20
11-20
11-20
11-19
11-20
11-20
11-19
11-20
11-19
11-19
11-19
11-19
11-19
11-19