天天看点

bug#66718 Assert from DROP TABLE concurrent with ibuf merges

http://bugs.mysql.com/bug.php?id=66718

assert from drop table concurrent with ibuf merges

a.原因:

master线程发起的ibuf merge和用户线程的drop table操作可能存在竞争。

1.master线程请求文件page io,读入内存之前,会调用buf_page_init_for_read->fil_tablespace_deleted_or_being_deleted_in_mem

如果这时候该表尚未标记为删除,那么则认为可以继续读文件page。

2.用户线程调用fil_delete_tablespace

>设置space->stop_ibuf_merges = true

>确认space->n_pending_ibuf_merges == 0  

设置space->is_being_deleted = true;

>确认space->chain->n_pending为0  并且 space->n_pending_flushes = 0

继续下面的逻辑

3.master线程继续调用函数fil_io -> fil_node_prepare_for_io会递增node->n_pending++

4.用户线程继续往下走,调用

fil_delete_tablespace->fil_space_free->fil_node_free

在这里会做断言:

ut_a(node->n_pending == 0);

不过在percona版本中,断言处就不太一样,而是:

ut_a(node->n_pending == 0 || space->is_being_deleted);

因为在free node之前,我们已经设置了space->is_being_deleted为true,因此不会触发断言错误。

b.总结:

根据bug描述及分析,这个bug不影响我们的线上mysql版本。

c.其他:

我们已经确保space->n_pending_ibuf_merges为0了,为什么还会有对该表的ibuf merge呢?

对n_pending_ibuf_merges计数器操作的函数:fil_inc_pending_ibuf_merges及fil_decr_pending_ibuf_merges

我们来看看,在何时会递增这个计数器。

ibuf_merge_or_delete_for_page //每次读入一个索引页时,都会去尝试merge这个索引页上在内存中缓存的操作,如果该page上没有ibuf,或者表正在被删除,则不修改计数器,否则对计数+1,当执行完相关流程后,再调用fil_decr_pending_ibuf_merges进行-1.

计数器只在函数ibuf_merge_or_delete_for_page中做了修改。

请求文件页操作在调用ibuf_merge_or_delete_for_page之前,由master线程发起(用户线程无法和ddl并发)

d.todo

除了这个bug。另外一个去年春节发生,年底才fix的bug,也需要去跟踪(http://bugs.mysql.com/bug.php?id=66819)

这些都和insert buffer(或者称为change buffer)相关,后续会对这个模块的代码做分析