1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-17262: mysql crashed on galera while node rejoined cluster (#895)

This patch contains a fix for the MDEV-17262/17243 issues and
new mtr test.

These issues (MDEV-17262/17243) have two reasons:

1) After an intermediate commit, a transaction loses its status
of "transaction that registered in the MySQL for 2pc coordinator"
(in the InnoDB) due to the fact that since version 10.2 the
write_row() function (which located in the ha_innodb.cc) does
not call trx_register_for_2pc(m_prebuilt->trx) during the processing
of split transactions. It is necessary to restore this call inside
the write_row() when an intermediate commit was made (for a split
transaction).

Similarly, we need to set the flag of the started transaction
(m_prebuilt->sql_stat_start) after intermediate commit.

The table->file->extra(HA_EXTRA_FAKE_START_STMT) called from the
wsrep_load_data_split() function (which located in sql_load.cc)
will also do this, but it will be too late. As a result, the call
to the wsrep_append_keys() function from the InnoDB engine may be
lost or function may be called with invalid transaction identifier.

2) If a transaction with the LOAD DATA statement is divided into
logical mini-transactions (of the 10K rows) and binlog is rotated,
then in rare cases due to the wsrep handler re-registration at the
boundary of the split, the last portion of data may be lost. Since
splitting of the LOAD DATA into mini-transactions is technical,
I believe that we should not allow these mini-transactions to fall
into separate binlogs. Therefore, it is necessary to prohibit the
rotation of binlog in the middle of processing LOAD DATA statement.

https://jira.mariadb.org/browse/MDEV-17262 and
https://jira.mariadb.org/browse/MDEV-17243
This commit is contained in:
sysprg
2019-03-18 06:39:51 +01:00
committed by Jan Lindström
parent 5e044f78c0
commit 26432e49d3
13 changed files with 295 additions and 20 deletions

View File

@@ -6413,8 +6413,25 @@ err:
update_binlog_end_pos(offset);
signal_update();
/*
If a transaction with the LOAD DATA statement is divided
into logical mini-transactions (of the 10K rows) and binlog
is rotated, then the last portion of data may be lost due to
wsrep handler re-registration at the boundary of the split.
Since splitting of the LOAD DATA into mini-transactions is
logical, we should not allow these mini-transactions to fall
into separate binlogs. Therefore, it is necessary to prohibit
the rotation of binlog in the middle of processing LOAD DATA:
*/
#ifdef WITH_WSREP
if (!thd->wsrep_split_flag)
{
#endif /* WITH_WSREP */
if ((error= rotate(false, &check_purge)))
check_purge= false;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
}
}
}
@@ -7139,8 +7156,25 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd)
!(error= flush_and_sync(0)))
{
signal_update();
/*
If a transaction with the LOAD DATA statement is divided
into logical mini-transactions (of the 10K rows) and binlog
is rotated, then the last portion of data may be lost due to
wsrep handler re-registration at the boundary of the split.
Since splitting of the LOAD DATA into mini-transactions is
logical, we should not allow these mini-transactions to fall
into separate binlogs. Therefore, it is necessary to prohibit
the rotation of binlog in the middle of processing LOAD DATA:
*/
#ifdef WITH_WSREP
if (!thd->wsrep_split_flag)
{
#endif /* WITH_WSREP */
if ((error= rotate(false, &check_purge)))
check_purge= false;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
}
offset= my_b_tell(&log_file);
@@ -7906,6 +7940,20 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
mark_xids_active(binlog_id, xid_count);
}
/*
If a transaction with the LOAD DATA statement is divided
into logical mini-transactions (of the 10K rows) and binlog
is rotated, then the last portion of data may be lost due to
wsrep handler re-registration at the boundary of the split.
Since splitting of the LOAD DATA into mini-transactions is
logical, we should not allow these mini-transactions to fall
into separate binlogs. Therefore, it is necessary to prohibit
the rotation of binlog in the middle of processing LOAD DATA:
*/
#ifdef WITH_WSREP
if (!leader->thd->wsrep_split_flag)
{
#endif /* WITH_WSREP */
if (rotate(false, &check_purge))
{
/*
@@ -7925,6 +7973,9 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, errno);
check_purge= false;
}
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
/* In case of binlog rotate, update the correct current binlog offset. */
commit_offset= my_b_write_tell(&log_file);
}