2008-07-23 18:56:39 +02:00
|
|
|
# ==== Purpose ====
|
|
|
|
#
|
|
|
|
# Verify that INSERT DELAYED in mixed or row mode writes events to the
|
|
|
|
# binlog, and that AUTO_INCREMENT works correctly.
|
|
|
|
#
|
|
|
|
# ==== Method ====
|
|
|
|
#
|
|
|
|
# Insert both single and multiple rows into an autoincrement column,
|
|
|
|
# both with specified value and with NULL.
|
|
|
|
#
|
|
|
|
# With INSERT DELAYED, the rows do not show up in the table
|
|
|
|
# immediately, so we must do source include/wait_until_rows_count.inc
|
|
|
|
# between any two INSERT DELAYED statements. Moreover, if mixed or
|
|
|
|
# row-based logging is used, there is also a delay between when rows
|
|
|
|
# show up in the table and when they show up in the binlog. To ensure
|
|
|
|
# that the rows show up in the binlog, we call FLUSH TABLES, which
|
|
|
|
# waits until the delayed_insert thread has finished.
|
|
|
|
#
|
|
|
|
# We cannot read the binlog after executing INSERT DELAYED statements
|
|
|
|
# that insert multiple rows, because that is nondeterministic. More
|
|
|
|
# precisely, rows may be written in batches to the binlog, where each
|
|
|
|
# batch has one Table_map_log_event and one or more
|
|
|
|
# Write_rows_log_event. The number of rows included in each batch is
|
|
|
|
# nondeterministic.
|
|
|
|
#
|
|
|
|
# ==== Related bugs ====
|
|
|
|
#
|
|
|
|
# BUG#20627: INSERT DELAYED does not honour auto_increment_* variables
|
|
|
|
# Bug in this test: BUG#38068: binlog_stm_binlog fails sporadically in pushbuild
|
|
|
|
|
|
|
|
|
2006-08-30 10:22:43 +03:00
|
|
|
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
|
|
|
|
2008-07-23 18:56:39 +02:00
|
|
|
let $table=t1;
|
|
|
|
let $count=0;
|
2006-09-23 15:24:45 +03:00
|
|
|
|
2008-07-23 18:56:39 +02:00
|
|
|
insert delayed into t1 values (207);
|
|
|
|
inc $count;
|
2006-09-23 15:24:45 +03:00
|
|
|
--source include/wait_until_rows_count.inc
|
2008-07-23 18:56:39 +02:00
|
|
|
|
2006-08-30 10:22:43 +03:00
|
|
|
insert delayed into t1 values (null);
|
2006-09-23 15:24:45 +03:00
|
|
|
inc $count;
|
|
|
|
--source include/wait_until_rows_count.inc
|
|
|
|
|
2006-08-30 10:22:43 +03:00
|
|
|
insert delayed into t1 values (300);
|
2006-09-23 15:24:45 +03:00
|
|
|
inc $count;
|
|
|
|
--source include/wait_until_rows_count.inc
|
|
|
|
|
2008-07-23 18:56:39 +02:00
|
|
|
# It is not enough to wait until all rows have been inserted into the
|
|
|
|
# table. FLUSH TABLES ensures that they are in the binlog too. See
|
|
|
|
# comment above.
|
|
|
|
FLUSH TABLES;
|
2007-03-29 21:38:03 +02:00
|
|
|
source include/show_binlog_events.inc;
|
2006-09-27 13:05:29 +03:00
|
|
|
|
Fixing problems I identified in my auto_increment work pushed in July
(as part of the auto_increment cleanup of WL#3146; let's not be
sad, that monster push still removed serious bugs):
one problem with INSERT DELAYED (unexpected interval releases),
one with stored functions (wrong auto_inc binlogging).
These bugs were not released.
mysql-test/extra/binlog_tests/binlog_insert_delayed.test:
more tests of binlogging of INSERT DELAYED: with multi-row INSERTs.
I identified why sleeps are needed to get a repeatable row-based
binlogged: because without sleeps rows sometimes get groupped
and so generate different row based events.
mysql-test/extra/rpl_tests/rpl_foreign_key.test:
don't forget to drop tables on slave too, otherwise it leaves
an orphan innodb table leading to rpl_insert_id failing sometimes
(like in pushbuild "sapsrv2 -max").
mysql-test/extra/rpl_tests/rpl_insert_id.test:
testing that if some statement does not update any row, it does
not pollute the auto_inc binlog variables of the next statement;
the test has to use stored procedures because with plain statements,
mysql_reset_thd_for_next_command() does the resetting (and thus
there is no problem); mysql_reset_thd_for_next_command() is not
called inside routines.
mysql-test/r/binlog_row_binlog.result:
result additions
mysql-test/r/binlog_statement_insert_delayed.result:
result additions
mysql-test/r/binlog_stm_binlog.result:
result additions
mysql-test/r/rpl_insert_id.result:
result additions
mysql-test/r/rpl_loaddata.result:
With the change to log.cc reverted, the result changes and is better:
the change to log.cc had caused some INSERT_ID events to disappear
though they were necessary (but testsuite could not catch that because
it's single-threaded).
mysql-test/r/rpl_ndb_insert_ignore.result:
NDB is now like other engines regarding INSERT IGNORE: autoincrement
values which caused a duplicate key are re-used for next row, not lost.
rpl_ndb_insert_ignore.result is now identical to rpl_insert_ignore.result.
sql/log.cc:
LOAD DATA INFILE is binlogged as several events, and the last of them must
have the auto_inc id. So it's wrong to reset the auto_inc id after every
binlog write (because then it's lost after the first event of LOAD
DATA INFILE and so missing for the last one)/
Another problem: MYSQL_LOG::write() is not always called (for example
if no row was updated), so we were missing reset in some cases.
sql/sp_head.cc:
SELECT func1(),func2() generates two binlog events, so needs to
clear auto_increment binlog variables after each binlog event
(it would be more natural to clear them in the log write code,
but LOAD DATA INFILE would suffer from this see the cset comment
for log.cc). Without the clearing, the problem is:
> exec func1()
>> call cleanup_after_query() (which does not clear our vars here)
>> binlog SELECT func1()
<
> exec func2()
and so SELECT func2() is binlogged with the auto_inc of SELECT func1().
sql/sql_class.cc:
after every statement we should clear auto_inc variables used for
binlogging, except if this was a function/trigger (in which case
it may be "INSERT SELECT func()", where the cleanup_after_query()
executed in func() should not reset the auto_inc binlog variables
as they'll be necessary when binlogging the INSERT SELECT later).
sql/sql_insert.cc:
- as INSERT DELAYED uses the same TABLE object as the delayed_insert
system thread, we should not call ha_release_auto_increment()
from INSERT DELAYED (and btw it's logical as we reserve nothing
as we don't perform the insert). Calling the function caused us to
release values being used by the delayed_insert thread.
So I do the call only if this is a non-DELAYED INSERT.
- Assuming two INSERT DELAYED which get grouped by the delayed_insert
thread, the second may use values reserved by the first, which is ok
per se, but is a problem in statement-based binlogging:
the 2nd INSERT gets binlogged with the "interval start" value
of the first INSERT (=> duplicate error in slave).
- no reason to ha_release_auto_increment() after every inserted row
in INSERT SELECT; more efficient to do it only when the statement ends
sql/sql_parse.cc:
a comment
2006-09-12 15:42:13 +02:00
|
|
|
insert delayed into t1 values (null),(null),(null),(null);
|
2006-09-23 15:24:45 +03:00
|
|
|
inc $count; inc $count; inc $count; inc $count;
|
|
|
|
--source include/wait_until_rows_count.inc
|
|
|
|
|
Fixing problems I identified in my auto_increment work pushed in July
(as part of the auto_increment cleanup of WL#3146; let's not be
sad, that monster push still removed serious bugs):
one problem with INSERT DELAYED (unexpected interval releases),
one with stored functions (wrong auto_inc binlogging).
These bugs were not released.
mysql-test/extra/binlog_tests/binlog_insert_delayed.test:
more tests of binlogging of INSERT DELAYED: with multi-row INSERTs.
I identified why sleeps are needed to get a repeatable row-based
binlogged: because without sleeps rows sometimes get groupped
and so generate different row based events.
mysql-test/extra/rpl_tests/rpl_foreign_key.test:
don't forget to drop tables on slave too, otherwise it leaves
an orphan innodb table leading to rpl_insert_id failing sometimes
(like in pushbuild "sapsrv2 -max").
mysql-test/extra/rpl_tests/rpl_insert_id.test:
testing that if some statement does not update any row, it does
not pollute the auto_inc binlog variables of the next statement;
the test has to use stored procedures because with plain statements,
mysql_reset_thd_for_next_command() does the resetting (and thus
there is no problem); mysql_reset_thd_for_next_command() is not
called inside routines.
mysql-test/r/binlog_row_binlog.result:
result additions
mysql-test/r/binlog_statement_insert_delayed.result:
result additions
mysql-test/r/binlog_stm_binlog.result:
result additions
mysql-test/r/rpl_insert_id.result:
result additions
mysql-test/r/rpl_loaddata.result:
With the change to log.cc reverted, the result changes and is better:
the change to log.cc had caused some INSERT_ID events to disappear
though they were necessary (but testsuite could not catch that because
it's single-threaded).
mysql-test/r/rpl_ndb_insert_ignore.result:
NDB is now like other engines regarding INSERT IGNORE: autoincrement
values which caused a duplicate key are re-used for next row, not lost.
rpl_ndb_insert_ignore.result is now identical to rpl_insert_ignore.result.
sql/log.cc:
LOAD DATA INFILE is binlogged as several events, and the last of them must
have the auto_inc id. So it's wrong to reset the auto_inc id after every
binlog write (because then it's lost after the first event of LOAD
DATA INFILE and so missing for the last one)/
Another problem: MYSQL_LOG::write() is not always called (for example
if no row was updated), so we were missing reset in some cases.
sql/sp_head.cc:
SELECT func1(),func2() generates two binlog events, so needs to
clear auto_increment binlog variables after each binlog event
(it would be more natural to clear them in the log write code,
but LOAD DATA INFILE would suffer from this see the cset comment
for log.cc). Without the clearing, the problem is:
> exec func1()
>> call cleanup_after_query() (which does not clear our vars here)
>> binlog SELECT func1()
<
> exec func2()
and so SELECT func2() is binlogged with the auto_inc of SELECT func1().
sql/sql_class.cc:
after every statement we should clear auto_inc variables used for
binlogging, except if this was a function/trigger (in which case
it may be "INSERT SELECT func()", where the cleanup_after_query()
executed in func() should not reset the auto_inc binlog variables
as they'll be necessary when binlogging the INSERT SELECT later).
sql/sql_insert.cc:
- as INSERT DELAYED uses the same TABLE object as the delayed_insert
system thread, we should not call ha_release_auto_increment()
from INSERT DELAYED (and btw it's logical as we reserve nothing
as we don't perform the insert). Calling the function caused us to
release values being used by the delayed_insert thread.
So I do the call only if this is a non-DELAYED INSERT.
- Assuming two INSERT DELAYED which get grouped by the delayed_insert
thread, the second may use values reserved by the first, which is ok
per se, but is a problem in statement-based binlogging:
the 2nd INSERT gets binlogged with the "interval start" value
of the first INSERT (=> duplicate error in slave).
- no reason to ha_release_auto_increment() after every inserted row
in INSERT SELECT; more efficient to do it only when the statement ends
sql/sql_parse.cc:
a comment
2006-09-12 15:42:13 +02:00
|
|
|
insert delayed into t1 values (null),(null),(400),(null);
|
2006-09-23 15:24:45 +03:00
|
|
|
inc $count; inc $count; inc $count; inc $count;
|
|
|
|
--source include/wait_until_rows_count.inc
|
|
|
|
|
2006-08-30 10:22:43 +03:00
|
|
|
select * from t1;
|
|
|
|
drop table t1;
|