From 02fe5e27d24c127dc31ad5a09987c4835cf651cc Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Thu, 26 Jul 2007 11:31:10 +0300 Subject: [PATCH 1/3] Bug #29571: INSERT DELAYED IGNORE written to binary log on the master but on the slave MySQL can decide to "downgrade" a INSERT DELAYED statement to normal insert in certain situations. One such situation is when the slave is replaying a replication feed. However INSERT DELAYED is logged even if there're no updates whereas the NORMAL INSERT is not logged in such cases. Fixed by always logging a "downgraded" INSERT DELAYED: even if there were no updates. --- mysql-test/r/rpl_insert_delayed.result | 20 ++++++++++++++++++ mysql-test/t/rpl_insert_delayed.test | 29 ++++++++++++++++++++++++++ sql/sql_insert.cc | 9 +++++--- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/rpl_insert_delayed.result b/mysql-test/r/rpl_insert_delayed.result index 38e2cddd650..ddf6e9c2165 100644 --- a/mysql-test/r/rpl_insert_delayed.result +++ b/mysql-test/r/rpl_insert_delayed.result @@ -29,3 +29,23 @@ id name 10 my name 20 is Bond drop table t1; +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +show binlog events limit 11,100; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +On slave +show binlog events limit 12,100; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/rpl_insert_delayed.test b/mysql-test/t/rpl_insert_delayed.test index 3f72f3a3625..141f36a694a 100644 --- a/mysql-test/t/rpl_insert_delayed.test +++ b/mysql-test/t/rpl_insert_delayed.test @@ -65,3 +65,32 @@ connection master; drop table t1; sync_slave_with_master; connection master; + +# +# Bug #29571: INSERT DELAYED IGNORE written to binary log on the master but +# on the slave +# +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); + +#must show two INSERT DELAYED +--replace_column 1 x 2 x 3 x 4 x 5 x +show binlog events limit 11,100; +select * from t1; + +sync_slave_with_master; +echo On slave; +#must show two INSERT DELAYED +--replace_column 1 x 2 x 3 x 4 x 5 x +show binlog events limit 12,100; +select * from t1; + + +# clean up +connection master; +drop table t1; +sync_slave_with_master; +connection master; + +--echo End of 5.0 tests diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 73f8c5e4418..618ba62ef19 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -560,6 +560,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, int error, res; bool transactional_table, joins_freed= FALSE; bool changed; + bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED); uint value_count; ulong counter = 1; ulonglong id; @@ -859,14 +860,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, transactional_table= table->file->has_transactions(); - if ((changed= (info.copied || info.deleted || info.updated))) + if ((changed= (info.copied || info.deleted || info.updated)) || + was_insert_delayed) { /* Invalidate the table in the query cache if something changed. For the transactional algorithm to work the invalidation must be before binlog writing and ha_autocommit_or_rollback */ - query_cache_invalidate3(thd, table_list, 1); + if (changed) + query_cache_invalidate3(thd, table_list, 1); if (error <= 0 || !transactional_table) { if (mysql_bin_log.is_open()) @@ -904,7 +907,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } - if (!transactional_table) + if (!transactional_table && changed) thd->no_trans_update.all= TRUE; } } From f98eb3a634577b6fdd6ec475f3e473b2a1276468 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Thu, 26 Jul 2007 16:59:21 +0300 Subject: [PATCH 2/3] Addendum to bug 29571: wait for INSERT DELAYED to finish on master --- mysql-test/r/rpl_insert_delayed.result | 3 +++ mysql-test/t/rpl_insert_delayed.test | 1 + 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/rpl_insert_delayed.result b/mysql-test/r/rpl_insert_delayed.result index ddf6e9c2165..6815a727fd7 100644 --- a/mysql-test/r/rpl_insert_delayed.result +++ b/mysql-test/r/rpl_insert_delayed.result @@ -32,10 +32,12 @@ drop table t1; CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; show binlog events limit 11,100; Log_name Pos Event_type Server_id End_log_pos Info x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; flush table t1 select * from t1; a 1 @@ -44,6 +46,7 @@ show binlog events limit 12,100; Log_name Pos Event_type Server_id End_log_pos Info x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; flush table t1 select * from t1; a 1 diff --git a/mysql-test/t/rpl_insert_delayed.test b/mysql-test/t/rpl_insert_delayed.test index 141f36a694a..09e0c5cc2e9 100644 --- a/mysql-test/t/rpl_insert_delayed.test +++ b/mysql-test/t/rpl_insert_delayed.test @@ -73,6 +73,7 @@ connection master; CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; # to wait for INSERT DELAYED to be done #must show two INSERT DELAYED --replace_column 1 x 2 x 3 x 4 x 5 x From 9c8262da33ba0840dd6abc645e4e06e58ed0a493 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 26 Jul 2007 20:52:53 +0400 Subject: [PATCH 3/3] BUG#28591: make the fix work for BDB tables too: - make ha_berkeley::cmp_ref() take into account that auto-generated PKs are stored in LSB-first order. - Remove the temporary code that made the bugfix work for innodb only --- mysql-test/r/bdb.result | 2 +- sql/ha_berkeley.cc | 6 +++++- sql/sql_select.cc | 1 - sql/table.cc | 3 +-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 91c385112b4..3356d23053f 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -136,8 +136,8 @@ update ignore t1 set id=1023 where id=1010; select * from t1 where parent_id=102 order by parent_id,id; id parent_id level 1008 102 2 -1010 102 2 1015 102 2 +1010 102 2 explain select level from t1 where level=1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref level level 1 const X Using index diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 2a5fe775ca6..fbfd5031656 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -2646,7 +2646,11 @@ ha_rows ha_berkeley::estimate_rows_upper_bound() int ha_berkeley::cmp_ref(const byte *ref1, const byte *ref2) { if (hidden_primary_key) - return memcmp(ref1, ref2, BDB_HIDDEN_PRIMARY_KEY_LENGTH); + { + ulonglong a=uint5korr((char*) ref1); + ulonglong b=uint5korr((char*) ref2); + return a < b ? -1 : (a > b ? 1 : 0); + } int result; Field *field; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2d9d261bb31..d82a0fdcf41 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12033,7 +12033,6 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, */ if (!on_primary_key && (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && - table->s->db_type == DB_TYPE_INNODB && table->s->primary_key != MAX_KEY) { on_primary_key= TRUE; diff --git a/sql/table.cc b/sql/table.cc index ce894e6910f..18a395d69af 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -782,8 +782,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) { field->part_of_key= share->keys_in_use; - if (share->db_type == DB_TYPE_INNODB && - field->part_of_sortkey.is_set(key)) + if (field->part_of_sortkey.is_set(key)) field->part_of_sortkey= share->keys_in_use; } }