From 20108d6f4bb3003dfb7edec9e4319e89d86dbfa9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 Aug 2005 18:08:45 +0200 Subject: [PATCH 1/7] BUG#12542: All set statements should be executed by slave thd rpl_replicate_do.result: New test case sql_parse.cc: All SET statements should be executed by slave thd rpl_replicate_do.test: New test case mysql-test/t/rpl_replicate_do.test: Added test sql/sql_parse.cc: All SET commands should be executed by slave thd mysql-test/r/rpl_replicate_do.result: New test case --- mysql-test/r/rpl_replicate_do.result | 11 +++++ mysql-test/t/rpl_replicate_do.test | 18 +++++++ sql/sql_parse.cc | 73 +++++++++++++++++----------- 3 files changed, 74 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result index ca290d46fda..45ef6cb9b7b 100644 --- a/mysql-test/r/rpl_replicate_do.result +++ b/mysql-test/r/rpl_replicate_do.result @@ -29,3 +29,14 @@ drop table if exists t1,t2,t11; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master # 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1340 slave-relay-bin.000002 1384 master-bin.000001 Yes Yes test.t1 0 0 1340 1384 None 0 No # +create table t1 (ts timestamp); +set one_shot time_zone='met'; +insert into t1 values('2005-08-12 00:00:00'); +set one_shot time_zone='met'; +select * from t1; +ts +2005-08-12 00:00:00 +set one_shot time_zone='met'; +select * from t1; +ts +2005-08-12 00:00:00 diff --git a/mysql-test/t/rpl_replicate_do.test b/mysql-test/t/rpl_replicate_do.test index 98374240dd5..9bbaa9f0076 100644 --- a/mysql-test/t/rpl_replicate_do.test +++ b/mysql-test/t/rpl_replicate_do.test @@ -36,4 +36,22 @@ sync_with_master; --replace_column 1 # 33 # show slave status; +# +# BUG#12542 +# TEST: "SET ONE_SHOT should always be executed on slave" +# +# We could use any timezone different than server default in this test +# +connection master; +create table t1 (ts timestamp); +set one_shot time_zone='met'; +insert into t1 values('2005-08-12 00:00:00'); +set one_shot time_zone='met'; +select * from t1; +sync_slave_with_master; + +connection slave; +set one_shot time_zone='met'; +select * from t1; + # End of 4.1 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index caf76b19eb2..8e457b67f00 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -120,6 +120,9 @@ static bool end_active_trans(THD *thd) #ifdef HAVE_REPLICATION +/* + Returns true if all tables should be ignored +*/ inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) { return (table_rules_on && tables && !tables_ok(thd,tables) && @@ -1915,6 +1918,23 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) return 0; } +static void reset_one_shot_variables(THD *thd) +{ + thd->variables.character_set_client= + global_system_variables.character_set_client; + thd->variables.collation_connection= + global_system_variables.collation_connection; + thd->variables.collation_database= + global_system_variables.collation_database; + thd->variables.collation_server= + global_system_variables.collation_server; + thd->update_charset(); + thd->variables.time_zone= + global_system_variables.time_zone; + thd->one_shot_set= 0; +} + + /**************************************************************************** ** mysql_execute_command ** Execute command saved in thd and current_lex->sql_command @@ -1975,16 +1995,21 @@ mysql_execute_command(THD *thd) /* Skip if we are in the slave thread, some table rules have been given and the table list says the query should not be replicated. - Exception is DROP TEMPORARY TABLE IF EXISTS: we always execute it - (otherwise we have stale files on slave caused by exclusion of one tmp - table). + + Exceptions are: + - SET: we always execute it (Not that many SET commands exists in + the binary log anyway) + - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we + have stale files on slave caused by exclusion of one tmp table). */ - if (!(lex->sql_command == SQLCOM_DROP_TABLE && + if (!(lex->sql_command == SQLCOM_SET_OPTION) && + !(lex->sql_command == SQLCOM_DROP_TABLE && lex->drop_temporary && lex->drop_if_exists) && all_tables_not_ok(thd,tables)) { /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); + reset_one_shot_variables(thd); DBUG_VOID_RETURN; } #ifndef TO_BE_DELETED @@ -3309,6 +3334,7 @@ purposes internal to the MySQL server", MYF(0)); !db_ok_with_wild_table(lex->name))) { my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); + reset_one_shot_variables(thd); break; } #endif @@ -3344,6 +3370,7 @@ purposes internal to the MySQL server", MYF(0)); !db_ok_with_wild_table(lex->name))) { my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); + reset_one_shot_variables(thd); break; } #endif @@ -3384,6 +3411,7 @@ purposes internal to the MySQL server", MYF(0)); !db_ok_with_wild_table(db))) { my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); + reset_one_shot_variables(thd); break; } #endif @@ -3718,30 +3746,19 @@ purposes internal to the MySQL server", MYF(0)); break; } thd->proc_info="query end"; // QQ - if (thd->one_shot_set) - { - /* - If this is a SET, do nothing. This is to allow mysqlbinlog to print - many SET commands (in this case we want the charset temp setting to - live until the real query). This is also needed so that SET - CHARACTER_SET_CLIENT... does not cancel itself immediately. - */ - if (lex->sql_command != SQLCOM_SET_OPTION) - { - thd->variables.character_set_client= - global_system_variables.character_set_client; - thd->variables.collation_connection= - global_system_variables.collation_connection; - thd->variables.collation_database= - global_system_variables.collation_database; - thd->variables.collation_server= - global_system_variables.collation_server; - thd->update_charset(); - thd->variables.time_zone= - global_system_variables.time_zone; - thd->one_shot_set= 0; - } - } + + /* + Reset system variables temporarily modified by SET ONE SHOT. + + Exception: If this is a SET, do nothing. This is to allow + mysqlbinlog to print many SET commands (in this case we want the + charset temp setting to live until the real query). This is also + needed so that SET CHARACTER_SET_CLIENT... does not cancel itself + immediately. + */ + if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION) + reset_one_shot_variables(thd); + if (res < 0) send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); From f8aadb60947b6f94ffd6ddec77036091593b54a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Sep 2005 17:58:00 +0200 Subject: [PATCH 2/7] BUG#12542: Added comments sql/log_event.cc: Added comments sql/sql_parse.cc: Added comments --- sql/log_event.cc | 20 ++++++++++++++++++++ sql/sql_parse.cc | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 66c732e8cb0..b08439a20b8 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1008,6 +1008,16 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) #endif clear_all_errors(thd, rli); + /* + Note: We do not need to execute reset_one_shot_variables() if this + db_ok() test fails. + Reason: The db stored in binlog events is the same for SET and for + its companion query. If the SET is ignored because of + db_ok(), the companion query will also be ignored, and if + the companion query is ignored in the db_ok() test of + ::exec_event(), then the companion SET also have so we + don't need to reset_one_shot_variables(). + */ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { thd->set_time((time_t)when); @@ -1762,6 +1772,16 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, Create_file_log_event::exec_event() and then discarding Append_block and al. Another way is do the filtering in the I/O thread (more efficient: no disk writes at all). + + + Note: We do not need to execute reset_one_shot_variables() if this + db_ok() test fails. + Reason: The db stored in binlog events is the same for SET and for + its companion query. If the SET is ignored because of + db_ok(), the companion query will also be ignored, and if + the companion query is ignored in the db_ok() test of + ::exec_event(), then the companion SET also have so we + don't need to reset_one_shot_variables(). */ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8e457b67f00..94064d5ddfa 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1998,7 +1998,8 @@ mysql_execute_command(THD *thd) Exceptions are: - SET: we always execute it (Not that many SET commands exists in - the binary log anyway) + the binary log anyway -- only 4.1 masters write SET statements, + in 5.0 there are no SET statements in the binary log) - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we have stale files on slave caused by exclusion of one tmp table). */ From 7f98b2a04625a9255103db171e542e523aa0b161 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Sep 2005 11:14:47 +0200 Subject: [PATCH 3/7] mysqltest.test: Remove output from shells in result file mysql-test/r/mysqltest.result: Update test results mysql-test/t/mysqltest.test: Send output from failed command to /dev/null in order to avoid recording the output from different shells --- mysql-test/r/mysqltest.result | 7 ++----- mysql-test/t/mysqltest.test | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 80c54f589da..9175bdc7250 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -179,9 +179,7 @@ source database echo message echo message mysqltest: At line 1: Empty variable -sh: -c: line 0: syntax error near unexpected token `;' -sh: -c: line 0: `;' -mysqltest: At line 1: command ";" failed +mysqltest: At line 1: command "';' 2> /dev/null" failed mysqltest: At line 1: Missing argument in exec MySQL "MySQL" @@ -303,8 +301,7 @@ mysqltest: At line 1: First argument to dec must be a variable (start with $) mysqltest: At line 1: End of line junk detected: "1000" mysqltest: At line 1: Missing arguments to system, nothing to do! mysqltest: At line 1: Missing arguments to system, nothing to do! -sh: NonExistsinfComamdn: command not found -mysqltest: At line 1: system command 'NonExistsinfComamdn' failed +mysqltest: At line 1: system command 'NonExistsinfComamdn 2> /dev/null' failed test test2 test3 diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index ee2104d19b0..bfb1919e75c 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -424,7 +424,7 @@ echo ; # Illegal use of exec --error 1 ---exec echo "--exec ;" | $MYSQL_TEST 2>&1 +--exec echo "--exec ';' 2> /dev/null" | $MYSQL_TEST 2>&1 --error 1 --exec echo "--exec " | $MYSQL_TEST 2>&1 @@ -672,7 +672,7 @@ system echo "hej" > /dev/null; --error 1 --exec echo "system $NONEXISTSINFVAREABLI;" | $MYSQL_TEST 2>&1 --error 1 ---exec echo "system NonExistsinfComamdn;" | $MYSQL_TEST 2>&1 +--exec echo "system NonExistsinfComamdn 2> /dev/null;" | $MYSQL_TEST 2>&1 --disable_abort_on_error system NonExistsinfComamdn; From 7056f0b3f01f8ef73216c1e21a082e9fea8714fd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Sep 2005 11:47:24 +0200 Subject: [PATCH 4/7] ndb - bug #10987 make sure not to cut log to early (specificly not use LCP with maxGciStarted that has not yet completed) ndb/include/kernel/signaldata/SignalData.hpp: Add signal data printer for START_FRAG_REQ ndb/include/kernel/signaldata/StartFragReq.hpp: Add signal data printer for START_FRAG_REQ ndb/src/common/debugger/signaldata/SignalDataPrint.cpp: Add signal data printer for START_FRAG_REQ ndb/src/common/debugger/signaldata/StartRec.cpp: Add signal data printer for START_FRAG_REQ ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: Add maxGciStarted/Completed to event report bug: dont use LCP for calcKeepGci in maxGciSTarted is not completed --- ndb/include/kernel/signaldata/SignalData.hpp | 1 + .../kernel/signaldata/StartFragReq.hpp | 2 ++ .../debugger/signaldata/SignalDataPrint.cpp | 1 + .../common/debugger/signaldata/StartRec.cpp | 25 +++++++++++++++++++ ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 12 ++++++--- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/ndb/include/kernel/signaldata/SignalData.hpp b/ndb/include/kernel/signaldata/SignalData.hpp index f9d3a6faa64..b0cfbc1540c 100644 --- a/ndb/include/kernel/signaldata/SignalData.hpp +++ b/ndb/include/kernel/signaldata/SignalData.hpp @@ -215,5 +215,6 @@ GSN_PRINT_SIGNATURE(printSCAN_FRAGREQ); GSN_PRINT_SIGNATURE(printCONTINUEB_NDBFS); GSN_PRINT_SIGNATURE(printCONTINUEB_DBDIH); +GSN_PRINT_SIGNATURE(printSTART_FRAG_REQ); #endif diff --git a/ndb/include/kernel/signaldata/StartFragReq.hpp b/ndb/include/kernel/signaldata/StartFragReq.hpp index ec05c1ee366..ab17a147195 100644 --- a/ndb/include/kernel/signaldata/StartFragReq.hpp +++ b/ndb/include/kernel/signaldata/StartFragReq.hpp @@ -32,6 +32,8 @@ class StartFragReq { public: STATIC_CONST( SignalLength = 19 ); + friend bool printSTART_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16); + private: Uint32 userPtr; Uint32 userRef; diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp index a4cee38e06f..bd1dff074f9 100644 --- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp +++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp @@ -195,6 +195,7 @@ SignalDataPrintFunctions[] = { ,{ GSN_ACC_LOCKREQ, printACC_LOCKREQ } ,{ GSN_LQH_TRANSCONF, printLQH_TRANSCONF } ,{ GSN_SCAN_FRAGREQ, printSCAN_FRAGREQ } + ,{ GSN_START_FRAGREQ, printSTART_FRAG_REQ } ,{ 0, 0 } }; diff --git a/ndb/src/common/debugger/signaldata/StartRec.cpp b/ndb/src/common/debugger/signaldata/StartRec.cpp index 482e3cb0728..54830e533c5 100644 --- a/ndb/src/common/debugger/signaldata/StartRec.cpp +++ b/ndb/src/common/debugger/signaldata/StartRec.cpp @@ -17,6 +17,7 @@ #include #include +#include bool printSTART_REC_REQ(FILE * output, @@ -50,3 +51,27 @@ printSTART_REC_CONF(FILE * output, return true; } + +bool +printSTART_FRAG_REQ(FILE * output, + const Uint32 * theData, + Uint32 len, + Uint16 recBlockNo) +{ + StartFragReq* sig = (StartFragReq*)theData; + + fprintf(output, " table: %d frag: %d lcpId: %d lcpNo: %d #nodes: %d \n", + sig->tableId, sig->fragId, sig->lcpId, sig->lcpNo, + sig->noOfLogNodes); + + for(Uint32 i = 0; inoOfLogNodes; i++) + { + fprintf(output, " (node: %d startGci: %d lastGci: %d)", + sig->lqhLogNode[i], + sig->startGci[i], + sig->lastGci[i]); + } + + fprintf(output, "\n"); + return true; +} diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 669be2b48f0..ca066b588e7 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -9640,6 +9640,9 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal) } bool tableDone = reportLcpCompletion(lcpReport); + + Uint32 started = lcpReport->maxGciStarted; + Uint32 completed = lcpReport->maxGciCompleted; if(tableDone){ jam(); @@ -9673,7 +9676,9 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal) signal->theData[1] = nodeId; signal->theData[2] = tableId; signal->theData[3] = fragId; - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB); + signal->theData[4] = started; + signal->theData[5] = completed; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB); #endif bool ok = false; @@ -10790,7 +10795,9 @@ void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr, lcpNo = fmgReplicaPtr.p->nextLcp; do { ndbrequire(lcpNo < MAX_LCP_STORED); - if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID) { + if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID && + fmgReplicaPtr.p->maxGciStarted[lcpNo] <= coldgcp) + { jam(); keepGci = fmgReplicaPtr.p->maxGciCompleted[lcpNo]; oldestRestorableGci = fmgReplicaPtr.p->maxGciStarted[lcpNo]; @@ -10798,7 +10805,6 @@ void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr, return; } else { jam(); - ndbrequire(fmgReplicaPtr.p->lcpStatus[lcpNo] == ZINVALID); if (fmgReplicaPtr.p->createGci[0] == fmgReplicaPtr.p->initialGci) { jam(); /*------------------------------------------------------------------- From 21ce9ede3c6081b134421854a1776436e68985c4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Sep 2005 11:50:50 +0200 Subject: [PATCH 5/7] ndb - bug#12608 Always abort if node failure occured between startTransaction and commit (can later be improved by wl#2610) ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Always abort if node failure occured between startTransaction and commit --- ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 93b122b9a99..f0861d1f0cc 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -4404,7 +4404,7 @@ Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci) *------------------------------------------------------------------------*/ tabortInd = ZFALSE; setupFailData(signal); - if (tabortInd == ZFALSE) { + if (false && tabortInd == ZFALSE) { jam(); commitGciHandling(signal, Tgci); toCommitHandlingLab(signal); From f9d29cfeedeafea81e7cc368648b3179dc419349 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Sep 2005 11:55:41 +0200 Subject: [PATCH 6/7] ndb - fix printout related to bug#10987 ndb/src/common/debugger/EventLogger.cpp: Fix extended printout of LCP_FRAGMENT_COMPLETED --- ndb/src/common/debugger/EventLogger.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp index 97945394690..f7cef644c64 100644 --- a/ndb/src/common/debugger/EventLogger.cpp +++ b/ndb/src/common/debugger/EventLogger.cpp @@ -585,11 +585,13 @@ EventLogger::getText(char * m_text, size_t m_text_len, BaseString::snprintf(m_text, m_text_len, "%sTable ID = %u, fragment ID = %u has completed LCP " - "on Node %u", + "on Node %u maxGciStarted: %d maxGciCompleted: %d", theNodeId, theData[2], theData[3], - theData[1]); + theData[1], + theData[4], + theData[5]); break; case EventReport::TransReportCounters: // ------------------------------------------------------------------- From 8f0530d0150b0c1beb2a9531a5f97bbfa29c4b67 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Sep 2005 12:20:18 +0200 Subject: [PATCH 7/7] Removed redundant case in Makefile.am Makefile.am: Removed redundant case --- Makefile.am | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index 353a05eeb14..ee0353349ea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,12 +97,6 @@ tags: support-files/build-tags .PHONY: init-db bin-dist -# Test installation - -test: - cd mysql-test; \ - ./mysql-test-run && ./mysql-test-run --ps-protocol - # Test installation. Ports are configurable from the environment. MYSQL_TEST_MANAGER_PORT = 9305