Commit adf9dadf authored by Michael Widenius's avatar Michael Widenius

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.
parent a2a6880c
......@@ -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;
......
include/master-slave.inc
[connection master]
UPDATE performance_schema.setup_instruments SET ENABLED="NO";
include/rpl_end.inc
--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,7 +10127,11 @@ 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:
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:
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(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,7 +2218,11 @@ 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,7 +2488,8 @@ 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);
table->file->ha_rnd_end();
if (error)
table->file->ha_rnd_end();
DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0);
DBUG_RETURN(error);
......@@ -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 @@ class ha_perfschema : public handler
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);
}
/**
......
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