1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

control Cache_flip_event_log lifetime with reference count

If online alter fails, TABLE_SHARE can be freed while concurrent
transactions still have row events in their online_alter_cache_data.
On commit they try'll to flush them, writing to TABLE_SHARE's
Cache_flip_event_log, which is already freed.
This causes a crash in main.alter_table_online_debug test
This commit is contained in:
Nikita Malyavin
2023-08-11 02:13:45 +04:00
committed by Sergei Golubchik
parent 62a1e282d0
commit 8f6f219a68
4 changed files with 51 additions and 13 deletions

View File

@ -11795,7 +11795,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
#ifdef HAVE_REPLICATION
if (online)
{
from->s->online_alter_binlog= new (&from->s->mem_root) Cache_flip_event_log();
from->s->online_alter_binlog= new Cache_flip_event_log();
if (!from->s->online_alter_binlog)
DBUG_RETURN(1);
from->s->online_alter_binlog->init_pthread_objects();
@ -11803,7 +11803,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (error)
{
from->s->online_alter_binlog->cleanup();
from->s->online_alter_binlog->release();
from->s->online_alter_binlog= NULL;
goto err;
}
@ -12014,6 +12014,19 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
else if (online) // error was on copy stage
{
/*
We can't free the resources properly now, as we can still be in
non-exclusive state. So this s->online_alter_binlog will be used
until all transactions will release it.
Once the transaction commits, it can release online_alter_binlog
by decreasing ref_count.
online_alter_binlog->ref_count can be reached 0 only once.
Proof:
If share exists, we'll always have ref_count >= 1.
Once it reaches destroy(), nobody can acquire it again,
therefore, only release() is possible at this moment.
*/
from->s->tdc->flush_unused(1); // to free the binlog
}
#endif