Commit 90247658 authored by Jacob Mathew's avatar Jacob Mathew

MDEV-14019: Spider + binlog_format = ROW => CRASH

The crash occurs when inserting into, updating or deleting from Spider system
tables.  These operations do not go through the normal insert, update or
delete logic, so binary logging of the row is not properly set up and leads
to the crash.

The fix for this problem uses the same strategy as is used for the servers
system table that contains entries for the servers created with CREATE SERVER.
Binary logging is now temporarily disabled on insert, update and delete
operations on Spider system tables.

Author:
  Jacob Mathew.

Reviewer:
  Kentoku Shiba.
parent aec4734f
......@@ -35,6 +35,86 @@
extern handlerton *spider_hton_ptr;
/**
Insert a Spider system table row.
@param table The spider system table.
@param do_handle_error TRUE if an error message should be printed
before returning.
@return Error code returned by the write.
*/
inline int spider_write_sys_table_row(TABLE *table, bool do_handle_error = TRUE)
{
int error_num;
THD *thd = table->in_use;
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
error_num = table->file->ha_write_row(table->record[0]);
reenable_binlog(thd);
if (error_num && do_handle_error)
table->file->print_error(error_num, MYF(0));
return error_num;
}
/**
Update a Spider system table row.
@param table The spider system table.
@return Error code returned by the update.
*/
inline int spider_update_sys_table_row(TABLE *table)
{
int error_num;
THD *thd = table->in_use;
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
error_num = table->file->ha_update_row(table->record[1], table->record[0]);
reenable_binlog(thd);
if (error_num)
{
if (error_num == HA_ERR_RECORD_IS_THE_SAME)
error_num = 0;
else
table->file->print_error(error_num, MYF(0));
}
return error_num;
}
/**
Delete a Spider system table row.
@param table The spider system table.
@param record_number Location of the record: 0 or 1.
@param do_handle_error TRUE if an error message should be printed
before returning.
@return Error code returned by the update.
*/
inline int spider_delete_sys_table_row(TABLE *table, int record_number = 0,
bool do_handle_error = TRUE)
{
int error_num;
THD *thd = table->in_use;
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
error_num = table->file->ha_delete_row(table->record[record_number]);
reenable_binlog(thd);
if (error_num && do_handle_error)
table->file->print_error(error_num, MYF(0));
return error_num;
}
#if MYSQL_VERSION_ID < 50500
TABLE *spider_open_sys_table(
THD *thd,
......@@ -983,11 +1063,8 @@ int spider_insert_xa(
table->use_all_columns();
spider_store_xa_bqual_length(table, xid);
spider_store_xa_status(table, status);
if ((error_num = table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_write_sys_table_row(table)))
DBUG_RETURN(error_num);
}
} else {
my_message(ER_SPIDER_XA_EXISTS_NUM, ER_SPIDER_XA_EXISTS_STR, MYF(0));
DBUG_RETURN(ER_SPIDER_XA_EXISTS_NUM);
......@@ -1017,11 +1094,8 @@ int spider_insert_xa_member(
}
table->use_all_columns();
spider_store_xa_member_info(table, xid, conn);
if ((error_num = table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_write_sys_table_row(table)))
DBUG_RETURN(error_num);
}
} else {
my_message(ER_SPIDER_XA_MEMBER_EXISTS_NUM, ER_SPIDER_XA_MEMBER_EXISTS_STR,
MYF(0));
......@@ -1051,11 +1125,8 @@ int spider_insert_tables(
SPIDER_LINK_STATUS_NO_CHANGE ?
share->alter_table.tmp_link_statuses[roop_count] :
SPIDER_LINK_STATUS_OK);
if ((error_num = table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_write_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
DBUG_RETURN(0);
......@@ -1077,11 +1148,8 @@ int spider_log_tables_link_failed(
if (table->field[3] == table->timestamp_field)
table->timestamp_field->set_time();
#endif
if ((error_num = table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_write_sys_table_row(table)))
DBUG_RETURN(error_num);
}
DBUG_RETURN(0);
}
......@@ -1115,11 +1183,8 @@ int spider_log_xa_failed(
if (table->field[20] == table->timestamp_field)
table->timestamp_field->set_time();
#endif
if ((error_num = table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_write_sys_table_row(table)))
DBUG_RETURN(error_num);
}
DBUG_RETURN(0);
}
......@@ -1148,14 +1213,8 @@ int spider_update_xa(
store_record(table, record[1]);
table->use_all_columns();
spider_store_xa_status(table, status);
if (
(error_num = table->file->ha_update_row(
table->record[1], table->record[0])) &&
error_num != HA_ERR_RECORD_IS_THE_SAME
) {
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_update_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
DBUG_RETURN(0);
......@@ -1188,14 +1247,8 @@ int spider_update_tables_name(
store_record(table, record[1]);
table->use_all_columns();
spider_store_tables_name(table, to, strlen(to));
if (
(error_num = table->file->ha_update_row(
table->record[1], table->record[0])) &&
error_num != HA_ERR_RECORD_IS_THE_SAME
) {
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_update_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
roop_count++;
}
......@@ -1239,11 +1292,8 @@ int spider_update_tables_priority(
SPIDER_LINK_STATUS_NO_CHANGE ?
alter_table->tmp_link_statuses[roop_count] :
SPIDER_LINK_STATUS_OK);
if ((error_num = table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_write_sys_table_row(table)))
DBUG_RETURN(error_num);
}
roop_count++;
} while (roop_count < (int) alter_table->all_link_count);
DBUG_RETURN(0);
......@@ -1259,14 +1309,8 @@ int spider_update_tables_priority(
spider_store_tables_connect_info(table, alter_table, roop_count);
spider_store_tables_link_status(table,
alter_table->tmp_link_statuses[roop_count]);
if (
(error_num = table->file->ha_update_row(
table->record[1], table->record[0])) &&
error_num != HA_ERR_RECORD_IS_THE_SAME
) {
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_update_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
}
while (TRUE)
......@@ -1284,11 +1328,8 @@ int spider_update_tables_priority(
table->file->print_error(error_num, MYF(0));
DBUG_RETURN(error_num);
}
if ((error_num = table->file->ha_delete_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_delete_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
roop_count++;
}
......@@ -1324,14 +1365,8 @@ int spider_update_tables_link_status(
store_record(table, record[1]);
table->use_all_columns();
spider_store_tables_link_status(table, link_status);
if (
(error_num = table->file->ha_update_row(
table->record[1], table->record[0])) &&
error_num != HA_ERR_RECORD_IS_THE_SAME
) {
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_update_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
DBUG_RETURN(0);
......@@ -1358,11 +1393,8 @@ int spider_delete_xa(
MYF(0));
DBUG_RETURN(ER_SPIDER_XA_NOT_EXISTS_NUM);
} else {
if ((error_num = table->file->ha_delete_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_delete_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
DBUG_RETURN(0);
......@@ -1389,7 +1421,7 @@ int spider_delete_xa_member(
DBUG_RETURN(0);
} else {
do {
if ((error_num = table->file->ha_delete_row(table->record[0])))
if ((error_num = spider_delete_sys_table_row(table, 0, FALSE)))
{
spider_sys_index_end(table);
table->file->print_error(error_num, MYF(0));
......@@ -1424,11 +1456,8 @@ int spider_delete_tables(
if ((error_num = spider_check_sys_table(table, table_key)))
break;
else {
if ((error_num = table->file->ha_delete_row(table->record[0])))
{
table->file->print_error(error_num, MYF(0));
if ((error_num = spider_delete_sys_table_row(table)))
DBUG_RETURN(error_num);
}
}
roop_count++;
}
......@@ -2305,7 +2334,7 @@ int spider_sys_replace(
char table_key[MAX_KEY_LENGTH];
DBUG_ENTER("spider_sys_replace");
while ((error_num = table->file->ha_write_row(table->record[0])))
while ((error_num = spider_write_sys_table_row(table, FALSE)))
{
if (
table->file->is_fatal_error(error_num, HA_CHECK_DUP) ||
......@@ -2357,13 +2386,11 @@ int spider_sys_replace(
last_uniq_key &&
!table->file->referenced_by_foreign_key()
) {
error_num = table->file->ha_update_row(table->record[1],
table->record[0]);
if (error_num && error_num != HA_ERR_RECORD_IS_THE_SAME)
if ((error_num = spider_update_sys_table_row(table)))
goto error;
DBUG_RETURN(0);
} else {
if ((error_num = table->file->ha_delete_row(table->record[1])))
if ((error_num = spider_delete_sys_table_row(table, 1, FALSE)))
goto error;
*modified_non_trans_table = TRUE;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment