mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Don't crash with: UPDATE performance_schema.setup_instruments SET ENABLED="NO";
Don't log updates to performance schema in replication log. Ensure that we don't call ha_update after ha_index_or_rnd_end() is called on slave. .bzrignore: Ignore some generated files mysql-test/include/show_slave_status.inc: Ensure that ./ is removed from file names mysql-test/suite/perfschema/r/binlog_mix.result: Updated results mysql-test/suite/perfschema/r/binlog_row.result: Updated results mysql-test/suite/perfschema/r/binlog_stmt.result: Updated results mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result: Updated results mysql-test/suite/rpl/r/rpl_performance_schema.result: Ensure that we don't crash slave when we update performance schema mysql-test/suite/rpl/t/rpl_performance_schema.test: Ensure that we don't crash slave when we update performance schema sql/log_event.cc: Ensure that we don't call ha_update after ha_index_or_rnd_end() is called. Remove old code that is not needed anymore (like restarting read loop over all rows if no matcing row is found) Simplify code sql/log_event_old.cc: Ensure that we don't call ha_update after ha_index_or_rnd_end() is called. storage/myisam/ha_myisam.cc: More DBUG_PRINT storage/perfschema/ha_perfschema.h: Don't log updates to performance schema in replication log.
This commit is contained in:
@ -1135,3 +1135,5 @@ plugin/handler_socket/perl-Net-HandlerSocket/Makefile.PL
|
||||
libmysqld/libmysqld_exports_file.cc
|
||||
libmysqld/gcalc_slicescan.cc
|
||||
libmysqld/gcalc_tools.cc
|
||||
sql/share/errmsg.sys
|
||||
sql/share/mysql
|
||||
|
@ -69,6 +69,7 @@ while ($_show_slave_status_items)
|
||||
--let $_show_slave_status_name= `SELECT SUBSTRING_INDEX('$_show_slave_status_items', ',', 1)`
|
||||
--let $_show_slave_status_items= `SELECT LTRIM(SUBSTRING('$_show_slave_status_items', LENGTH('$_show_slave_status_name') + 2))`
|
||||
|
||||
--replace_regex /\.[\\\/]master/master/
|
||||
--let $_show_slave_status_value= query_get_value(SHOW SLAVE STATUS, $_show_slave_status_name, 1)
|
||||
--let $_show_slave_status_value= `SELECT REPLACE("$_show_slave_status_value", '$MYSQL_TEST_DIR', 'MYSQL_TEST_DIR')`
|
||||
--echo $_show_slave_status_name = '$_show_slave_status_value'
|
||||
|
@ -26,10 +26,6 @@ update performance_schema.setup_instruments set enabled='YES'
|
||||
and name not in ("wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock");
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
master-bin.000001 # Table_map # # table_id: # (performance_schema.setup_instruments)
|
||||
master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t2` /* generated by server */
|
||||
master-bin.000001 # Query # # use `test`; create table test.t1 (thread_id integer)
|
||||
@ -44,7 +40,3 @@ master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t2` /* generated by server */
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
master-bin.000001 # Table_map # # table_id: # (performance_schema.setup_instruments)
|
||||
master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
|
@ -26,10 +26,6 @@ update performance_schema.setup_instruments set enabled='YES'
|
||||
and name not in ("wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock");
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
master-bin.000001 # Table_map # # table_id: # (performance_schema.setup_instruments)
|
||||
master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t2` /* generated by server */
|
||||
master-bin.000001 # Query # # use `test`; create table test.t1 (thread_id integer)
|
||||
@ -44,7 +40,3 @@ master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t2` /* generated by server */
|
||||
master-bin.000001 # Query # # BEGIN
|
||||
master-bin.000001 # Table_map # # table_id: # (performance_schema.setup_instruments)
|
||||
master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
|
@ -20,12 +20,14 @@ insert into test.t1
|
||||
select thread_id from performance_schema.events_waits_current;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses the general log, slow query log, or performance_schema table(s). This is unsafe because system tables may differ on slaves.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Mixing self-logging and non-self-logging engines in a statement is unsafe.
|
||||
insert into test.t2
|
||||
select name from performance_schema.setup_instruments
|
||||
where name like "wait/synch/rwlock/sql/%"
|
||||
and name not in ("wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock");
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses the general log, slow query log, or performance_schema table(s). This is unsafe because system tables may differ on slaves.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Mixing self-logging and non-self-logging engines in a statement is unsafe.
|
||||
drop table test.t1;
|
||||
drop table test.t2;
|
||||
update performance_schema.setup_instruments set enabled='YES'
|
||||
|
@ -11,7 +11,7 @@ reset slave;
|
||||
start slave;
|
||||
include/wait_for_slave_param.inc [Last_IO_Errno]
|
||||
Last_IO_Errno = '1236'
|
||||
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the last event was read from './master-bin.000001' at 316, the last byte read was read from './master-bin.000001' at 335.''
|
||||
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the last event was read from 'master-bin.000001' at 316, the last byte read was read from 'master-bin.000001' at 335.''
|
||||
reset master;
|
||||
stop slave;
|
||||
reset slave;
|
||||
|
4
mysql-test/suite/rpl/r/rpl_performance_schema.result
Normal file
4
mysql-test/suite/rpl/r/rpl_performance_schema.result
Normal file
@ -0,0 +1,4 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
UPDATE performance_schema.setup_instruments SET ENABLED="NO";
|
||||
include/rpl_end.inc
|
10
mysql-test/suite/rpl/t/rpl_performance_schema.test
Normal file
10
mysql-test/suite/rpl/t/rpl_performance_schema.test
Normal file
@ -0,0 +1,10 @@
|
||||
--source include/master-slave.inc
|
||||
--source include/have_perfschema.inc
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
|
||||
UPDATE performance_schema.setup_instruments SET ENABLED="NO";
|
||||
|
||||
--sync_slave_with_master
|
||||
--source include/rpl_end.inc
|
||||
|
||||
# End of test case
|
@ -10127,6 +10127,10 @@ void issue_long_find_row_warning(Log_event_type type,
|
||||
|
||||
@note If the engine allows random access of the records, a combination of
|
||||
@c position() and @c rnd_pos() will be used.
|
||||
|
||||
Note that one MUST call ha_index_or_rnd_end() after this function if
|
||||
it returns 0 as we must leave the row position in the handler intact
|
||||
for any following update/delete command.
|
||||
*/
|
||||
|
||||
int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
@ -10216,7 +10220,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
{
|
||||
DBUG_PRINT("info",("ha_index_init returns error %d",error));
|
||||
table->file->print_error(error, MYF(0));
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Fill key data for the row */
|
||||
@ -10251,7 +10255,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
error= HA_ERR_KEY_NOT_FOUND;
|
||||
table->file->print_error(error, MYF(0));
|
||||
table->file->ha_index_end();
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -10281,15 +10285,15 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
/* Unique does not have non nullable part */
|
||||
if (!(table->key_info->flags & (HA_NULL_PART_KEY)))
|
||||
{
|
||||
table->file->ha_index_end();
|
||||
goto ok;
|
||||
error= 0;
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
KEY *keyinfo= table->key_info;
|
||||
/*
|
||||
Unique has nullable part. We need to check if there is any field in the
|
||||
BI image that is null and part of UNNI.
|
||||
Unique has nullable part. We need to check if there is any
|
||||
field in the BI image that is null and part of UNNI.
|
||||
*/
|
||||
bool null_found= FALSE;
|
||||
for (uint i=0; i < keyinfo->key_parts && !null_found; i++)
|
||||
@ -10301,8 +10305,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
|
||||
if (!null_found)
|
||||
{
|
||||
table->file->ha_index_end();
|
||||
goto ok;
|
||||
error= 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* else fall through to index scan */
|
||||
@ -10345,14 +10349,9 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
DBUG_PRINT("info",("no record matching the given row found"));
|
||||
table->file->print_error(error, MYF(0));
|
||||
table->file->ha_index_end();
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Have to restart the scan to be able to fetch the next row.
|
||||
*/
|
||||
table->file->ha_index_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -10360,14 +10359,12 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
/* We use this to test that the correct key is used in test cases. */
|
||||
DBUG_EXECUTE_IF("slave_crash_if_table_scan", abort(););
|
||||
|
||||
int restart_count= 0; // Number of times scanning has restarted from top
|
||||
|
||||
/* We don't have a key: search the table using rnd_next() */
|
||||
if ((error= table->file->ha_rnd_init_with_error(1)))
|
||||
{
|
||||
DBUG_PRINT("info",("error initializing table scan"
|
||||
" (ha_rnd_init returns %d)",error));
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
is_table_scan= true;
|
||||
@ -10383,8 +10380,14 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
switch (error) {
|
||||
|
||||
case 0:
|
||||
DBUG_DUMP("record found", table->record[0], table->s->reclength);
|
||||
break;
|
||||
|
||||
case HA_ERR_END_OF_FILE:
|
||||
DBUG_PRINT("info", ("Record not found"));
|
||||
table->file->ha_rnd_end();
|
||||
goto end;
|
||||
|
||||
/*
|
||||
If the record was deleted, we pick the next one without doing
|
||||
any comparisons.
|
||||
@ -10392,58 +10395,28 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
||||
case HA_ERR_RECORD_DELETED:
|
||||
goto restart_rnd_next;
|
||||
|
||||
case HA_ERR_END_OF_FILE:
|
||||
if (++restart_count < 2)
|
||||
{
|
||||
int error2;
|
||||
if ((error2= table->file->ha_rnd_init_with_error(1)))
|
||||
{
|
||||
error= error2;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DBUG_PRINT("info", ("Failed to get next record"
|
||||
" (rnd_next returns %d)",error));
|
||||
table->file->print_error(error, MYF(0));
|
||||
table->file->ha_rnd_end();
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
while (restart_count < 2 && record_compare(table));
|
||||
while (record_compare(table));
|
||||
|
||||
/*
|
||||
Note: above record_compare will take into accout all record fields
|
||||
which might be incorrect in case a partial row was given in the event
|
||||
*/
|
||||
|
||||
/*
|
||||
Have to restart the scan to be able to fetch the next row.
|
||||
*/
|
||||
if (restart_count == 2)
|
||||
DBUG_PRINT("info", ("Record not found"));
|
||||
else
|
||||
DBUG_DUMP("record found", table->record[0], table->s->reclength);
|
||||
table->file->ha_rnd_end();
|
||||
|
||||
DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0);
|
||||
goto err;
|
||||
}
|
||||
ok:
|
||||
|
||||
end:
|
||||
if (is_table_scan || is_index_scan)
|
||||
issue_long_find_row_warning(get_type_code(), m_table->alias.c_ptr(),
|
||||
is_index_scan, rli);
|
||||
|
||||
table->default_column_bitmaps();
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
if (is_table_scan || is_index_scan)
|
||||
issue_long_find_row_warning(get_type_code(), m_table->alias.c_ptr(),
|
||||
is_index_scan, rli);
|
||||
|
||||
table->default_column_bitmaps();
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -10516,6 +10489,7 @@ int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli)
|
||||
Delete the record found, located in record[0]
|
||||
*/
|
||||
error= m_table->file->ha_delete_row(m_table->record[0]);
|
||||
m_table->file->ha_index_or_rnd_end();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -10658,7 +10632,7 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli)
|
||||
m_curr_row= m_curr_row_end;
|
||||
/* this also updates m_curr_row_end */
|
||||
if ((error= unpack_current_row(rli)))
|
||||
return error;
|
||||
goto err;
|
||||
|
||||
/*
|
||||
Now we have the right row to update. The old row (the one we're
|
||||
@ -10678,6 +10652,8 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli)
|
||||
if (error == HA_ERR_RECORD_IS_THE_SAME)
|
||||
error= 0;
|
||||
|
||||
err:
|
||||
m_table->file->ha_index_or_rnd_end();
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -2218,6 +2218,10 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli,
|
||||
|
||||
@note If the engine allows random access of the records, a combination of
|
||||
@c position() and @c rnd_pos() will be used.
|
||||
|
||||
Note that one MUST call ha_index_or_rnd_end() after this function if
|
||||
it returns 0 as we must leave the row position in the handler intact
|
||||
for any following update/delete command.
|
||||
*/
|
||||
|
||||
int Old_rows_log_event::find_row(const Relay_log_info *rli)
|
||||
@ -2361,15 +2365,14 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
|
||||
/* Unique does not have non nullable part */
|
||||
if (!(table->key_info->flags & (HA_NULL_PART_KEY)))
|
||||
{
|
||||
table->file->ha_index_end();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
KEY *keyinfo= table->key_info;
|
||||
/*
|
||||
Unique has nullable part. We need to check if there is any field in the
|
||||
BI image that is null and part of UNNI.
|
||||
Unique has nullable part. We need to check if there is any
|
||||
field in the BI image that is null and part of UNNI.
|
||||
*/
|
||||
bool null_found= FALSE;
|
||||
for (uint i=0; i < keyinfo->key_parts && !null_found; i++)
|
||||
@ -2381,7 +2384,6 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
|
||||
|
||||
if (!null_found)
|
||||
{
|
||||
table->file->ha_index_end();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -2424,11 +2426,6 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Have to restart the scan to be able to fetch the next row.
|
||||
*/
|
||||
table->file->ha_index_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2462,8 +2459,10 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
|
||||
if (++restart_count < 2)
|
||||
{
|
||||
int error2;
|
||||
table->file->ha_rnd_end();
|
||||
if ((error2= table->file->ha_rnd_init_with_error(1)))
|
||||
DBUG_RETURN(error2);
|
||||
goto restart_rnd_next;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2489,6 +2488,7 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
|
||||
DBUG_PRINT("info", ("Record not found"));
|
||||
else
|
||||
DBUG_DUMP("record found", table->record[0], table->s->reclength);
|
||||
if (error)
|
||||
table->file->ha_rnd_end();
|
||||
|
||||
DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0);
|
||||
@ -2738,6 +2738,7 @@ int Delete_rows_log_event_old::do_exec_row(const Relay_log_info *const rli)
|
||||
Delete the record found, located in record[0]
|
||||
*/
|
||||
error= m_table->file->ha_delete_row(m_table->record[0]);
|
||||
m_table->file->ha_index_or_rnd_end();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -2874,6 +2875,8 @@ Update_rows_log_event_old::do_exec_row(const Relay_log_info *const rli)
|
||||
#endif
|
||||
|
||||
error= m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
|
||||
m_table->file->ha_index_or_rnd_end();
|
||||
|
||||
if (error == HA_ERR_RECORD_IS_THE_SAME)
|
||||
error= 0;
|
||||
|
||||
|
@ -1672,18 +1672,26 @@ int ha_myisam::index_init(uint idx, bool sorted)
|
||||
|
||||
int ha_myisam::index_end()
|
||||
{
|
||||
DBUG_ENTER("ha_myisam::index_end");
|
||||
active_index=MAX_KEY;
|
||||
//pushed_idx_cond_keyno= MAX_KEY;
|
||||
mi_set_index_cond_func(file, NULL, 0);
|
||||
in_range_check_pushed_down= FALSE;
|
||||
ds_mrr.dsmrr_close();
|
||||
return 0;
|
||||
#if !defined(DBUG_OFF) && defined(SQL_SELECT_FIXED_FOR_UPDATE)
|
||||
file->update&= ~HA_STATE_AKTIV; // Forget active row
|
||||
#endif
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int ha_myisam::rnd_end()
|
||||
{
|
||||
DBUG_ENTER("ha_myisam::rnd_end");
|
||||
ds_mrr.dsmrr_close();
|
||||
return 0;
|
||||
#if !defined(DBUG_OFF) && defined(SQL_SELECT_FIXED_FOR_UPDATE)
|
||||
file->update&= ~HA_STATE_AKTIV; // Forget active row
|
||||
#endif
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int ha_myisam::index_read_map(uchar *buf, const uchar *key,
|
||||
@ -1785,6 +1793,7 @@ void ha_myisam::position(const uchar *record)
|
||||
{
|
||||
my_off_t row_position= mi_position(file);
|
||||
my_store_ptr(ref, ref_length, row_position);
|
||||
file->update|= HA_STATE_AKTIV; // Row can be updated
|
||||
}
|
||||
|
||||
int ha_myisam::info(uint flag)
|
||||
|
@ -70,9 +70,13 @@ public:
|
||||
Without HA_FAST_KEY_READ, the optimizer reads all columns and never
|
||||
calls ::rnd_pos(), so it is guaranteed to return only thread <n>
|
||||
records.
|
||||
We use HA_HAS_OWN_BINLOGGING to stop changes to this table to
|
||||
be logged to slaves (as enabled performance tracking on all slaves
|
||||
is probably not what anyone wants)
|
||||
*/
|
||||
return HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
|
||||
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_NO_BLOBS;
|
||||
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
|
||||
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
|
||||
HA_HAS_OWN_BINLOGGING | HA_NO_BLOBS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user