From ef8c57f988b5b8e1029cd2c36379e995eef9e46a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Dec 2006 17:45:17 +0100 Subject: [PATCH 01/15] minor fixup support-files/mysql.spec.sh: fixup --- support-files/mysql.spec.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 1bf983cb02c..8a633f0d53a 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -588,7 +588,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* -%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.8* +%doc %attr(644, root, man) %{_mandir}/man8/mysqlmanager.8* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* From 36c7c608bf0ea1c016f25bb0ca743528e139b9fa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Dec 2006 17:57:31 +0100 Subject: [PATCH 02/15] also include data files for varbinary test in binary distribution --- scripts/make_binary_distribution.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index a6a2f1e3b49..9469cca875d 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -243,6 +243,7 @@ $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/include/*.test $BASE/mysql-test/include $CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \ + mysql-test/std_data/*.MYD mysql-test/std_data/*.MYI \ mysql-test/std_data/*.pem mysql-test/std_data/Moscow_leap \ mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \ mysql-test/std_data/*.cnf \ From 134b83d0a0094cc3a71dbd0a20f118f5a9f10573 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Dec 2006 11:51:45 +0100 Subject: [PATCH 03/15] support-files/mysql.spec.sh Fix the move of "mysqlmanager" to section 8: Directory name was wrong. support-files/mysql.spec.sh: Fix the move of "mysqlmanager" to section 8: Directory name was wrong. --- support-files/mysql.spec.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 1bf983cb02c..59369f0de35 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -588,7 +588,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* -%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.8* +%doc %attr(644, root, man) %{_mandir}/man8/mysqlmanager.8* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* @@ -755,6 +755,10 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Dec 18 2006 Joerg Bruehe + +- Fix the move of "mysqlmanager" to section 8: Directory name was wrong. + * Thu Dec 14 2006 Joerg Bruehe - Include the new man pages for "my_print_defaults" and "mysql_tzinfo_to_sql" From e55c9a7ab57ef0a8aeac0bb36ad8f585a52e5432 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Dec 2006 13:44:21 +0100 Subject: [PATCH 04/15] Use a temporary directory for sockets if the socket path becomes too long. --- mysql-test/mysql-test-run.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 5002f778da5..397adb9e157 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -58,6 +58,7 @@ $Devel::Trace::TRACE= 0; # Don't trace boring init stuff use File::Path; use File::Basename; use File::Copy; +use File::Temp qw / tempdir /; use Cwd; use Getopt::Long; use Sys::Hostname; @@ -1030,6 +1031,11 @@ sub command_line_setup () { my $sockdir = $opt_tmpdir; $sockdir =~ s|/+$||; + # On some operating systems, there is a limit to the length of a + # UNIX domain socket's path far below PATH_MAX, so try to avoid long + # socket path names. + $sockdir = tempdir(CLEANUP => 1) if ( length($sockdir) > 80 ); + # Put this into a hash, will be a C struct $master->[0]= From 306f42701cdbf0801c710f3c0fe0e74c521455fc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Dec 2006 18:41:38 -0700 Subject: [PATCH 05/15] This ChangeSet must be null-merged to 5.1. Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Bugs fixed: - Bug #21468: InnoDB crash during recovery with corrupted data pages: XA bug? - Bug #24299: Identifiers in foreign keys cannot contain U+0160, U+0360, ..., U+FF60 - Bug #24386: Performance degradation caused by instrumentation in mutex_struct - Bug #24712: SHOW TABLE STATUS for file-per-table showing incorrect time fields innobase/dict/dict0dict.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1030: branches/5.0: Replace isspace() with a wrapper ib_isspace(), because on Win32 isspace(0xa0) appears to hold. (Bug #24299) innobase/include/sync0rw.h: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1040: branches/5.0: Port r1039 from trunk: Port r1034 from branches/zip: Remove some instrumentation and reduce the output of SHOW MUTEX STATUS in non-debug builds. (Bug #24386) innobase/include/sync0sync.h: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1040: branches/5.0: Port r1039 from trunk: Port r1034 from branches/zip: Remove some instrumentation and reduce the output of SHOW MUTEX STATUS in non-debug builds. (Bug #24386) innobase/include/sync0sync.ic: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1040: branches/5.0: Port r1039 from trunk: Port r1034 from branches/zip: Remove some instrumentation and reduce the output of SHOW MUTEX STATUS in non-debug builds. (Bug #24386) innobase/log/log0recv.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1076: branches/5.0: Remove the unintentionally committed change to univ.i in r1075. Fix assertion failure sync0sync.c line 1239 (the latter ut_error in sync_thread_reset_level()) in crash recovery when UNIV_SYNC_DEBUG is enabled. Revision r1079: branches/5.0: recv_recovery_from_checkpoint_finish(): Add 1 sec delay before switching on the sync order checks in crash recovery, so that file I/O threads have time to suspend themselves. innobase/srv/srv0start.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1075: branches/5.0: Fix assertion failure sync0sync.c line 1239 (the latter ut_error in sync_thread_reset_level()) in crash recovery when UNIV_SYNC_DEBUG is enabled. Revision r1077: branches/5.0: innobase_start_or_create_for_mysql(): Remove unnecessary delay now that we moved the setting sync_order_checks_on=TRUE to log0recv.c, to the start of the rollback phase in crash recovery. innobase/sync/sync0rw.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1040: branches/5.0: Port r1039 from trunk: Port r1034 from branches/zip: Remove some instrumentation and reduce the output of SHOW MUTEX STATUS in non-debug builds. (Bug #24386) innobase/sync/sync0sync.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1040: branches/5.0: Port r1039 from trunk: Port r1034 from branches/zip: Remove some instrumentation and reduce the output of SHOW MUTEX STATUS in non-debug builds. (Bug #24386) innobase/trx/trx0roll.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1067: branches/5.0: trx_rollback_for_mysql(), trx_commit_for_mysql(): Protect the creation of trx_dummy_sess with kernel_mutex. This error was introduced in r1046 and r1050. Revision r1050: branches/5.0: trx_rollback_for_mysql(): Fix the comment introduced in r1046. trx_commit_for_mysql(): Use the dummy trx->sess also for committing a prepared transaction in XA recovery, just in case our code would need the session object also in that case (does not seem to need it right now). Revision r1048: branches/5.0: trx_rollback_for_mysql(): Do not set trx->sess back to NULL. This bug was introduced in r1046. Revision r1046: branches/5.0: trx_rollback_for_mysql(): Ensure that trx->sess is non-NULL when calling trx_general_rollback_for_mysql(). This removes a segmentation fault when rolling back a prepared transaction in XA recovery. (Bug #21468) innobase/trx/trx0trx.c: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1067: branches/5.0: trx_rollback_for_mysql(), trx_commit_for_mysql(): Protect the creation of trx_dummy_sess with kernel_mutex. This error was introduced in r1046 and r1050. Revision r1050: branches/5.0: trx_rollback_for_mysql(): Fix the comment introduced in r1046. trx_commit_for_mysql(): Use the dummy trx->sess also for committing a prepared transaction in XA recovery, just in case our code would need the session object also in that case (does not seem to need it right now). sql/ha_innodb.cc: Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Revision r1040: branches/5.0: Port r1039 from trunk: Port r1034 from branches/zip: Remove some instrumentation and reduce the output of SHOW MUTEX STATUS in non-debug builds. (Bug #24386) Revision r1099: branches/5.0: Merge revision 1098 from trunk: Fix bug #24712: SHOW TABLE STATUS for file-per-table showing incorrect time fields --- innobase/dict/dict0dict.c | 29 +++++++++++---------- innobase/include/sync0rw.h | 14 +++++++--- innobase/include/sync0sync.h | 32 ++++++++++++++--------- innobase/include/sync0sync.ic | 4 +-- innobase/log/log0recv.c | 10 ++++++++ innobase/srv/srv0start.c | 11 -------- innobase/sync/sync0rw.c | 14 +++++----- innobase/sync/sync0sync.c | 32 +++++++++++++---------- innobase/trx/trx0roll.c | 22 ++++++++++++++-- innobase/trx/trx0trx.c | 18 +++++++++++++ sql/ha_innodb.cc | 48 +++++++++++++++++++++-------------- 11 files changed, 152 insertions(+), 82 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index fffe851bc52..ba03e1f5e41 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -27,6 +27,9 @@ Created 1/8/1996 Heikki Tuuri #include "que0que.h" #include "rem0cmp.h" +/* Implement isspace() in a locale-independent way. (Bug #24299) */ +#define ib_isspace(c) strchr(" \v\f\t\r\n", c) + dict_sys_t* dict_sys = NULL; /* the dictionary system */ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve @@ -2406,7 +2409,7 @@ dict_accept( *success = FALSE; - while (isspace(*ptr)) { + while (ib_isspace(*ptr)) { ptr++; } @@ -2451,7 +2454,7 @@ dict_scan_id( *id = NULL; - while (isspace(*ptr)) { + while (ib_isspace(*ptr)) { ptr++; } @@ -2482,7 +2485,7 @@ dict_scan_id( len++; } } else { - while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' + while (!ib_isspace(*ptr) && *ptr != '(' && *ptr != ')' && (accept_also_dot || *ptr != '.') && *ptr != ',' && *ptr != '\0') { @@ -2512,12 +2515,12 @@ dict_scan_id( if (heap && !quote) { /* EMS MySQL Manager sometimes adds characters 0xA0 (in latin1, a 'non-breakable space') to the end of a table name. - But isspace(0xA0) is not true, which confuses our foreign key - parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2 - and 0xA0 are at the end of the string. + After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2 + and 0xA0 are at the end of the string, and ib_isspace() + does not work for multi-byte UTF-8 characters. - TODO: we should lex the string using thd->charset_info, and - my_isspace(). Only after that, convert id names to UTF-8. */ + In MySQL 5.1 we lex the string using thd->charset_info, and + my_isspace(). This workaround is not needed there. */ b = (byte*)(*id); id_len = strlen((char*) b); @@ -3006,11 +3009,11 @@ loop: ut_a(success); - if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') { + if (!ib_isspace(*ptr) && *ptr != '"' && *ptr != '`') { goto loop; } - while (isspace(*ptr)) { + while (ib_isspace(*ptr)) { ptr++; } @@ -3052,7 +3055,7 @@ loop: goto loop; } - if (!isspace(*ptr)) { + if (!ib_isspace(*ptr)) { goto loop; } @@ -3140,7 +3143,7 @@ col_loop1: } ptr = dict_accept(ptr, "REFERENCES", &success); - if (!success || !isspace(*ptr)) { + if (!success || !ib_isspace(*ptr)) { dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); @@ -3527,7 +3530,7 @@ loop: ptr = dict_accept(ptr, "DROP", &success); - if (!isspace(*ptr)) { + if (!ib_isspace(*ptr)) { goto loop; } diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h index 741f9500612..4cd26ba1921 100644 --- a/innobase/include/sync0rw.h +++ b/innobase/include/sync0rw.h @@ -61,8 +61,12 @@ Creates, or rather, initializes an rw-lock object in a specified memory location (which must be appropriately aligned). The rw-lock is initialized to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free is necessary only if the memory block containing it is freed. */ -#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L) - +#ifdef UNIV_DEBUG +# define rw_lock_create(L) rw_lock_create_func((L), #L, __FILE__, __LINE__) +#else /* UNIV_DEBUG */ +# define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__) +#endif /* UNIV_DEBUG */ + /*=====================*/ /********************************************************************** Creates, or rather, initializes an rw-lock object in a specified memory @@ -74,9 +78,11 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline); /* in: file line where created */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the rw-lock is freed. Removes an rw-lock object from the global list. The diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h index 9893921c5d2..769c2a98244 100644 --- a/innobase/include/sync0sync.h +++ b/innobase/include/sync0sync.h @@ -39,7 +39,11 @@ location (which must be appropriately aligned). The mutex is initialized in the reset state. Explicit freeing of the mutex with mutex_free is necessary only if the memory block containing it is freed. */ -#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, #M) +#ifdef UNIV_DEBUG +# define mutex_create(M) mutex_create_func((M), #M, __FILE__, __LINE__) +#else +# define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__) +#endif /*===================*/ /********************************************************************** Creates, or rather, initializes a mutex object in a specified memory @@ -51,9 +55,11 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline); /* in: file line where created */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the mutex is freed. Removes a mutex object from the mutex list. The mutex @@ -479,15 +485,17 @@ struct mutex_struct { ulint cline; /* Line where created */ ulint magic_n; #ifndef UNIV_HOTBACKUP - ulong count_using; /* count of times mutex used */ - ulong count_spin_loop; /* count of spin loops */ - ulong count_spin_rounds; /* count of spin rounds */ - ulong count_os_wait; /* count of os_wait */ - ulong count_os_yield; /* count of os_wait */ - ulonglong lspent_time; /* mutex os_wait timer msec */ - ulonglong lmax_spent_time; /* mutex os_wait timer msec */ - const char* cmutex_name;/* mutex name */ - ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ + ulong count_os_wait; /* count of os_wait */ +# ifdef UNIV_DEBUG + ulong count_using; /* count of times mutex used */ + ulong count_spin_loop; /* count of spin loops */ + ulong count_spin_rounds; /* count of spin rounds */ + ulong count_os_yield; /* count of os_wait */ + ulonglong lspent_time; /* mutex os_wait timer msec */ + ulonglong lmax_spent_time; /* mutex os_wait timer msec */ + const char* cmutex_name;/* mutex name */ + ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ }; diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic index b3fde61db5e..a32a82d6e8b 100644 --- a/innobase/include/sync0sync.ic +++ b/innobase/include/sync0sync.ic @@ -250,9 +250,9 @@ mutex_enter_func( /* Note that we do not peek at the value of lock_word before trying the atomic test_and_set; we could peek, and possibly save time. */ -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_using++; -#endif /* UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ if (!mutex_test_and_set(mutex)) { diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 113d237b535..c1ceb9791f2 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -33,6 +33,7 @@ Created 9/20/1997 Heikki Tuuri #include "btr0cur.h" #include "dict0boot.h" #include "fil0fil.h" +#include "sync0sync.h" #ifdef UNIV_HOTBACKUP /* This is set to FALSE if the backup was originally taken with the @@ -2969,6 +2970,15 @@ recv_recovery_from_checkpoint_finish(void) #ifndef UNIV_LOG_DEBUG recv_sys_free(); #endif + +#ifdef UNIV_SYNC_DEBUG + /* Wait for a while so that created threads have time to suspend + themselves before we switch the latching order checks on */ + os_thread_sleep(1000000); + + /* Switch latching order checks on in sync0sync.c */ + sync_order_checks_on = TRUE; +#endif if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { /* Rollback the uncommitted transactions which have no user session */ diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index b41dcbe44cd..5f8707a661c 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1554,17 +1554,6 @@ innobase_start_or_create_for_mysql(void) srv_was_started = TRUE; srv_is_being_started = FALSE; -#ifdef UNIV_DEBUG - /* Wait a while so that the created threads have time to suspend - themselves before we switch sync debugging on; otherwise a thread may - execute mutex_enter() before the checks are on, and mutex_exit() after - the checks are on, which will cause an assertion failure in sync - debug. */ - - os_thread_sleep(3000000); -#endif - sync_order_checks_on = TRUE; - if (trx_doublewrite == NULL) { /* Create the doublewrite buffer to a new tablespace */ diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c index 050de73db9e..629331d6049 100644 --- a/innobase/sync/sync0rw.c +++ b/innobase/sync/sync0rw.c @@ -89,9 +89,11 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline) /* in: file line where created */ { /* If this is the very first time a synchronization object is created, then the following call initializes @@ -102,10 +104,10 @@ rw_lock_create_func( lock->mutex.cfile_name = cfile_name; lock->mutex.cline = cline; -#ifndef UNIV_HOTBACKUP - lock->mutex.cmutex_name = cmutex_name; - lock->mutex.mutex_type = 1; -#endif /* !UNIV_HOTBACKUP */ +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP + lock->mutex.cmutex_name = cmutex_name; + lock->mutex.mutex_type = 1; +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ rw_lock_set_waiters(lock, 0); rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 95bf83dce79..25b7a5588d9 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -202,9 +202,11 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline) /* in: file line where created */ { #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); @@ -223,6 +225,8 @@ mutex_create_func( mutex->cfile_name = cfile_name; mutex->cline = cline; #ifndef UNIV_HOTBACKUP + mutex->count_os_wait = 0; +# ifdef UNIV_DEBUG mutex->cmutex_name= cmutex_name; mutex->count_using= 0; mutex->mutex_type= 0; @@ -230,8 +234,8 @@ mutex_create_func( mutex->lmax_spent_time= 0; mutex->count_spin_loop= 0; mutex->count_spin_rounds= 0; - mutex->count_os_wait= 0; mutex->count_os_yield= 0; +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ /* Check that lock_word is aligned; this is important on Intel */ @@ -378,13 +382,13 @@ mutex_spin_wait( { ulint index; /* index of the reserved wait cell */ ulint i; /* spin round count */ -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ ulint ltime_diff; ulint sec; ulint ms; uint timer_started = 0; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ ut_ad(mutex); mutex_loop: @@ -398,10 +402,10 @@ mutex_loop: memory word. */ spin_loop: -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex_spin_wait_count++; mutex->count_spin_loop++; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { @@ -415,7 +419,7 @@ spin_loop: if (i == SYNC_SPIN_ROUNDS) { -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_os_yield++; if (timed_mutexes == 1 && timer_started==0) { @@ -423,7 +427,7 @@ spin_loop: lstart_time= (ib_longlong)sec * 1000000 + ms; timer_started = 1; } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ os_thread_yield(); } @@ -436,9 +440,9 @@ spin_loop: mutex_spin_round_count += i; -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_spin_rounds += i; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ if (mutex_test_and_set(mutex) == 0) { @@ -522,6 +526,7 @@ Now there is no risk of infinite wait on the event. */ #ifndef UNIV_HOTBACKUP mutex->count_os_wait++; +# ifdef UNIV_DEBUG /* !!!!! Sometimes os_wait can be called without os_thread_yield */ @@ -532,13 +537,14 @@ Now there is no risk of infinite wait on the event. */ lstart_time= (ib_longlong)sec * 1000000 + ms; timer_started = 1; } +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ sync_array_wait_event(sync_primary_wait_array, index); goto mutex_loop; finish_timing: -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP if (timed_mutexes == 1 && timer_started==1) { ut_usectime(&sec, &ms); @@ -551,7 +557,7 @@ finish_timing: mutex->lmax_spent_time= ltime_diff; } } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ return; } diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index fdfb7428129..bf8b9fd1939 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -129,9 +129,27 @@ trx_rollback_for_mysql( } trx->op_info = "rollback"; - - err = trx_general_rollback_for_mysql(trx, FALSE, NULL); + /* If we are doing the XA recovery of prepared transactions, then + the transaction object does not have an InnoDB session object, and we + set a dummy session that we use for all MySQL transactions. */ + + mutex_enter(&kernel_mutex); + + if (trx->sess == NULL) { + /* Open a dummy session */ + + if (!trx_dummy_sess) { + trx_dummy_sess = sess_open(); + } + + trx->sess = trx_dummy_sess; + } + + mutex_exit(&kernel_mutex); + + err = trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx->op_info = ""; return(err); diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 2637b28ef90..4dc826e5947 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1601,7 +1601,25 @@ trx_commit_for_mysql( ut_a(trx); trx->op_info = "committing"; + + /* If we are doing the XA recovery of prepared transactions, then + the transaction object does not have an InnoDB session object, and we + set the dummy session that we use for all MySQL transactions. */ + mutex_enter(&kernel_mutex); + + if (trx->sess == NULL) { + /* Open a dummy session */ + + if (!trx_dummy_sess) { + trx_dummy_sess = sess_open(); + } + + trx->sess = trx_dummy_sess; + } + + mutex_exit(&kernel_mutex); + trx_start_if_not_started(trx); mutex_enter(&kernel_mutex); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e9ccc0ccede..617712d72bb 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5309,19 +5309,11 @@ ha_innobase::info( prebuilt->trx->op_info = (char*) "returning various info to MySQL"; - - if (ib_table->space != 0) { - my_snprintf(path, sizeof(path), "%s/%s%s", - mysql_data_home, ib_table->name, - ".ibd"); - unpack_filename(path,path); - } else { - my_snprintf(path, sizeof(path), "%s/%s%s", + my_snprintf(path, sizeof(path), "%s/%s%s", mysql_data_home, ib_table->name, reg_ext); - unpack_filename(path,path); - } + unpack_filename(path,path); /* Note that we do not know the access time of the table, nor the CHECK TABLE time, nor the UPDATE or INSERT time. */ @@ -6378,14 +6370,17 @@ innodb_mutex_show_status( Protocol *protocol= thd->protocol; List field_list; mutex_t* mutex; +#ifdef UNIV_DEBUG ulint rw_lock_count= 0; ulint rw_lock_count_spin_loop= 0; ulint rw_lock_count_spin_rounds= 0; ulint rw_lock_count_os_wait= 0; ulint rw_lock_count_os_yield= 0; ulonglong rw_lock_wait_time= 0; +#endif /* UNIV_DEBUG */ DBUG_ENTER("innodb_mutex_show_status"); +#ifdef UNIV_DEBUG field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN)); field_list.push_back(new Item_empty_string("Module", FN_REFLEN)); field_list.push_back(new Item_uint("Count", 21)); @@ -6394,19 +6389,23 @@ innodb_mutex_show_status( field_list.push_back(new Item_uint("OS_waits", 21)); field_list.push_back(new Item_uint("OS_yields", 21)); field_list.push_back(new Item_uint("OS_waits_time", 21)); +#else /* UNIV_DEBUG */ + field_list.push_back(new Item_empty_string("File", FN_REFLEN)); + field_list.push_back(new Item_uint("Line", 21)); + field_list.push_back(new Item_uint("OS_waits", 21)); +#endif /* UNIV_DEBUG */ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_enter(&mutex_list_mutex); -#endif + mutex_enter_noninline(&mutex_list_mutex); mutex = UT_LIST_GET_FIRST(mutex_list); while ( mutex != NULL ) { +#ifdef UNIV_DEBUG if (mutex->mutex_type != 1) { if (mutex->count_using > 0) @@ -6423,9 +6422,7 @@ innodb_mutex_show_status( if (protocol->write()) { -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); -#endif + mutex_exit_noninline(&mutex_list_mutex); DBUG_RETURN(1); } } @@ -6439,10 +6436,25 @@ innodb_mutex_show_status( rw_lock_count_os_yield += mutex->count_os_yield; rw_lock_wait_time += mutex->lspent_time; } +#else /* UNIV_DEBUG */ + protocol->prepare_for_resend(); + protocol->store(mutex->cfile_name, system_charset_info); + protocol->store((ulonglong)mutex->cline); + protocol->store((ulonglong)mutex->count_os_wait); + + if (protocol->write()) + { + mutex_exit_noninline(&mutex_list_mutex); + DBUG_RETURN(1); + } +#endif /* UNIV_DEBUG */ mutex = UT_LIST_GET_NEXT(list, mutex); } + mutex_exit_noninline(&mutex_list_mutex); + +#ifdef UNIV_DEBUG protocol->prepare_for_resend(); protocol->store("rw_lock_mutexes", system_charset_info); protocol->store("", system_charset_info); @@ -6457,10 +6469,8 @@ innodb_mutex_show_status( { DBUG_RETURN(1); } +#endif /* UNIV_DEBUG */ -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); -#endif send_eof(thd); DBUG_RETURN(FALSE); } From f8920dd59f87f488435f7f60939ed63e0a4b6b52 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2006 15:54:12 -0700 Subject: [PATCH 06/15] Bug #24947: REPEAT function returns NULL when passed a field as the count parameter Handling of large signed/unsigned values was not consistent, so some string functions could return bogus results. The current fix is to simply patch up the val_str() methods for those string items. It would be good clean this code up in general, to make similar problems much harder to make. This is left as an exercise for the reader. mysql-test/r/func_str.result: Update test results for bug #24947 mysql-test/t/func_str.test: Add test case for bug #24947 sql/item_strfunc.cc: Adjust some string function Items' val_str() methods to handle large signed/unsigned arguments properly --- mysql-test/r/func_str.result | 12 +++++++++++ mysql-test/t/func_str.test | 8 +++++++ sql/item_strfunc.cc | 41 ++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 14c61a2dd93..b5a9d4de105 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1916,4 +1916,16 @@ CHAR(0xff,0x8f USING utf8) IS NULL Warnings: Error 1300 Invalid utf8 character string: 'FF8F' SET SQL_MODE=@orig_sql_mode; +select substring('abc', cast(2 as unsigned int)); +substring('abc', cast(2 as unsigned int)) +bc +select repeat('a', cast(2 as unsigned int)); +repeat('a', cast(2 as unsigned int)) +aa +select rpad('abc', cast(5 as unsigned integer), 'x'); +rpad('abc', cast(5 as unsigned integer), 'x') +abcxx +select lpad('abc', cast(5 as unsigned integer), 'x'); +lpad('abc', cast(5 as unsigned integer), 'x') +xxabc End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index af4f8b9a9d2..a55b633b91e 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -991,5 +991,13 @@ SELECT CHAR(0xff,0x8f USING utf8) IS NULL; SET SQL_MODE=@orig_sql_mode; +# +# Bug #24947: problem with some string function with unsigned int parameters +# + +select substring('abc', cast(2 as unsigned int)); +select repeat('a', cast(2 as unsigned int)); +select rpad('abc', cast(5 as unsigned integer), 'x'); +select lpad('abc', cast(5 as unsigned integer), 'x'); --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0b48a00012a..afc2edb06dd 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1166,7 +1166,8 @@ String *Item_func_substr::val_str(String *str) /* if "unsigned_flag" is set, we have a *huge* positive number. */ /* Assumes that the maximum length of a String is < INT_MAX32. */ - if ((args[1]->unsigned_flag) || (start < INT_MIN32) || (start > INT_MAX32)) + if ((!args[1]->unsigned_flag && (start < INT_MIN32 || start > INT_MAX32)) || + (args[1]->unsigned_flag && ((ulonglong) start > INT_MAX32))) return &my_empty_string; start= ((start < 0) ? res->numchars() + start : start - 1); @@ -2227,25 +2228,23 @@ String *Item_func_repeat::val_str(String *str) uint length,tot_length; char *to; /* must be longlong to avoid truncation */ - longlong tmp_count= args[1]->val_int(); - long count= (long) tmp_count; + longlong count= args[1]->val_int(); String *res= args[0]->val_str(str); - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Bounds check on count: If this is triggered, we will error. */ - if ((tmp_count > INT_MAX32) || args[1]->unsigned_flag) - count= INT_MAX32; - if (args[0]->null_value || args[1]->null_value) goto err; // string and/or delim are null null_value= 0; - if ((tmp_count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code + if ((count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code return &my_empty_string; + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Bounds check on count: If this is triggered, we will error. */ + if ((ulonglong) count > INT_MAX32) + count= INT_MAX32; if (count == 1) // To avoid reallocs return res; length=res->length(); // Safe length check - if (length > current_thd->variables.max_allowed_packet/count) + if (length > current_thd->variables.max_allowed_packet / (uint) count) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_ALLOWED_PACKET_OVERFLOWED, @@ -2319,15 +2318,14 @@ String *Item_func_rpad::val_str(String *str) String *res= args[0]->val_str(str); String *rpad= args[2]->val_str(&rpad_str); - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Set here so that rest of code sees out-of-bound value as such. */ - if ((count > INT_MAX32) || args[1]->unsigned_flag) - count= INT_MAX32; - - if (!res || args[1]->null_value || !rpad || count < 0) + if (!res || args[1]->null_value || !rpad || + ((count < 0) && !args[1]->unsigned_flag)) goto err; null_value=0; - + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((ulonglong) count > INT_MAX32) + count= INT_MAX32; if (count <= (res_char_length= res->numchars())) { // String to pad is big enough res->length(res->charpos((int) count)); // Shorten result if longer @@ -2421,14 +2419,15 @@ String *Item_func_lpad::val_str(String *str) String *res= args[0]->val_str(&tmp_value); String *pad= args[2]->val_str(&lpad_str); + if (!res || args[1]->null_value || !pad || + ((count < 0) && !args[1]->unsigned_flag)) + goto err; + null_value=0; /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Set here so that rest of code sees out-of-bound value as such. */ - if ((count > INT_MAX32) || args[1]->unsigned_flag) + if ((ulonglong) count > INT_MAX32) count= INT_MAX32; - if (!res || args[1]->null_value || !pad || count < 0) - goto err; - null_value=0; res_char_length= res->numchars(); if (count <= res_char_length) From 47b0a0b08904e900e6b034e32ad124139c9dcb93 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2006 16:57:51 -0700 Subject: [PATCH 07/15] Added innodb_rollback_on_timeout option to restore the 4.1 InnoDB timeout behavior (Bug #24200) mysql-test/t/innodb_mysql-master.opt: Set --innodb-lock-wait-timeout=2, since test for bug #24200 times out. This *could* cause random test failures if some long-running transaction concurrency is being tested. However, such a test really should go in innodb-big or some other test file. --- innobase/include/row0mysql.h | 2 + innobase/row/row0mysql.c | 11 +++++- .../include/innodb_rollback_on_timeout.inc | 37 +++++++++++++++++++ mysql-test/r/innodb_mysql.result | 36 ++++++++++++++++++ mysql-test/r/innodb_timeout_rollback.result | 35 ++++++++++++++++++ mysql-test/t/innodb_mysql-master.opt | 1 + mysql-test/t/innodb_mysql.test | 2 + .../t/innodb_timeout_rollback-master.opt | 1 + mysql-test/t/innodb_timeout_rollback.test | 5 +++ sql/ha_innodb.cc | 7 ++++ sql/ha_innodb.h | 1 + sql/mysqld.cc | 7 +++- sql/set_var.cc | 1 + 13 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 mysql-test/include/innodb_rollback_on_timeout.inc create mode 100644 mysql-test/r/innodb_timeout_rollback.result create mode 100644 mysql-test/t/innodb_mysql-master.opt create mode 100644 mysql-test/t/innodb_timeout_rollback-master.opt create mode 100644 mysql-test/t/innodb_timeout_rollback.test diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 7d8740db044..9e28fabe491 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -19,6 +19,8 @@ Created 9/17/2000 Heikki Tuuri #include "btr0pcur.h" #include "trx0types.h" +extern ibool row_rollback_on_timeout; + typedef struct row_prebuilt_struct row_prebuilt_t; /*********************************************************************** diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index efbb93ba9f5..4bc5f39359c 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -35,6 +35,9 @@ Created 9/17/2000 Heikki Tuuri /* A dummy variable used to fool the compiler */ ibool row_mysql_identically_false = FALSE; +/* Provide optional 4.x backwards compatibility for 5.0 and above */ +ibool row_rollback_on_timeout = FALSE; + /* List of tables we should drop in background. ALTER TABLE in MySQL requires that the table handler can drop the table in background when there are no queries to it any more. Protected by the kernel mutex. */ @@ -514,7 +517,9 @@ handle_new_error: return(TRUE); } else if (err == DB_DEADLOCK - || err == DB_LOCK_TABLE_FULL) { + || err == DB_LOCK_TABLE_FULL + || (err == DB_LOCK_WAIT_TIMEOUT + && row_rollback_on_timeout)) { /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ @@ -522,6 +527,10 @@ handle_new_error: } else if (err == DB_OUT_OF_FILE_SPACE || err == DB_LOCK_WAIT_TIMEOUT) { + + ut_ad(!(err == DB_LOCK_WAIT_TIMEOUT + && row_rollback_on_timeout)); + if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ diff --git a/mysql-test/include/innodb_rollback_on_timeout.inc b/mysql-test/include/innodb_rollback_on_timeout.inc new file mode 100644 index 00000000000..73c7374c79e --- /dev/null +++ b/mysql-test/include/innodb_rollback_on_timeout.inc @@ -0,0 +1,37 @@ +# +# Bug #24200: Provide backwards compatibility mode for 4.x "rollback on +# transaction timeout" +# +show variables like 'innodb_rollback_on_timeout'; +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +connection con2; +begin work; +insert into t1 values (2); +select * from t1; + +connection con1; +begin work; +insert into t1 values (5); +select * from t1; +# Lock wait timeout set to 2 seconds in -master.opt; this +# statement will time out; in 5.0.13+, it will not roll back transaction. +--error ER_LOCK_WAIT_TIMEOUT +insert into t1 values (2); +# On 5.0.13+, this should give ==> 1, 5 +select * from t1; +commit; + +connection con2; +select * from t1; +commit; + +connection default; +select * from t1; +drop table t1; +disconnect con1; +disconnect con2; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 012f9492d8d..f150af4b6c2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -383,4 +383,40 @@ EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort DROP TABLE t1; +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout OFF +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +5 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +5 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/innodb_timeout_rollback.result b/mysql-test/r/innodb_timeout_rollback.result new file mode 100644 index 00000000000..b25a2bbd815 --- /dev/null +++ b/mysql-test/r/innodb_timeout_rollback.result @@ -0,0 +1,35 @@ +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout ON +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql-master.opt b/mysql-test/t/innodb_mysql-master.opt new file mode 100644 index 00000000000..205c733455d --- /dev/null +++ b/mysql-test/t/innodb_mysql-master.opt @@ -0,0 +1 @@ +--innodb-lock-wait-timeout=2 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 06cfe71ef11..45a2ede091b 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -384,4 +384,6 @@ EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; DROP TABLE t1; +--source include/innodb_rollback_on_timeout.inc + --echo End of 5.0 tests diff --git a/mysql-test/t/innodb_timeout_rollback-master.opt b/mysql-test/t/innodb_timeout_rollback-master.opt new file mode 100644 index 00000000000..50921bb4df0 --- /dev/null +++ b/mysql-test/t/innodb_timeout_rollback-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=2 --innodb_rollback_on_timeout diff --git a/mysql-test/t/innodb_timeout_rollback.test b/mysql-test/t/innodb_timeout_rollback.test new file mode 100644 index 00000000000..99890971064 --- /dev/null +++ b/mysql-test/t/innodb_timeout_rollback.test @@ -0,0 +1,5 @@ +-- source include/have_innodb.inc + +--source include/innodb_rollback_on_timeout.inc + +--echo End of 5.0 tests diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 9f367313fb0..456fd27d9d9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -173,6 +173,7 @@ my_bool innobase_use_large_pages = FALSE; my_bool innobase_use_native_aio = FALSE; my_bool innobase_file_per_table = FALSE; my_bool innobase_locks_unsafe_for_binlog = FALSE; +my_bool innobase_rollback_on_timeout = FALSE; my_bool innobase_create_status_file = FALSE; static char *internal_innobase_data_file_path = NULL; @@ -467,6 +468,10 @@ convert_error_code_to_mysql( latest SQL statement in a lock wait timeout. Previously, we rolled back the whole transaction. */ + if (thd && row_rollback_on_timeout) { + ha_rollback(thd); + } + return(HA_ERR_LOCK_WAIT_TIMEOUT); } else if (error == (int) DB_NO_REFERENCED_ROW) { @@ -1380,6 +1385,8 @@ innobase_init(void) os_use_large_pages = (ibool) innobase_use_large_pages; os_large_page_size = (ulint) innobase_large_page_size; + row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout; + srv_file_per_table = (ibool) innobase_file_per_table; srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog; diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 95d7a9437ad..60bc0e9c7cf 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -216,6 +216,7 @@ extern my_bool innobase_log_archive, innobase_use_large_pages, innobase_use_native_aio, innobase_file_per_table, innobase_locks_unsafe_for_binlog, + innobase_rollback_on_timeout, innobase_create_status_file; extern my_bool innobase_very_fast_shutdown; /* set this to 1 just before calling innobase_end() if you want diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9411ba2ef12..5890a2af21d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4692,7 +4692,8 @@ enum options_mysqld OPT_LOG_SLOW_ADMIN_STATEMENTS, OPT_TABLE_LOCK_WAIT_TIMEOUT, OPT_PORT_OPEN_TIMEOUT, - OPT_MERGE + OPT_MERGE, + OPT_INNODB_ROLLBACK_ON_TIMEOUT }; @@ -4968,6 +4969,10 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, (gptr*) &srv_max_purge_lag, (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1L, 0}, + {"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT, + "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)", + (gptr*) &innobase_rollback_on_timeout, (gptr*) &innobase_rollback_on_timeout, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_status_file", OPT_INNODB_STATUS_FILE, "Enable SHOW INNODB STATUS output in the innodb_status. file", (gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file, diff --git a/sql/set_var.cc b/sql/set_var.cc index 23afef742a6..5bbab6224ef 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -904,6 +904,7 @@ struct show_var_st init_vars[]= { {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG }, + {"innodb_rollback_on_timeout", (char*) &innobase_rollback_on_timeout, SHOW_MY_BOOL}, {sys_innodb_support_xa.name, (char*) &sys_innodb_support_xa, SHOW_SYS}, {sys_innodb_sync_spin_loops.name, (char*) &sys_innodb_sync_spin_loops, SHOW_SYS}, {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, From fe3672d28570eb552786cb3c5c179f205ed73324 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2006 17:42:26 -0700 Subject: [PATCH 08/15] Alternative decimal2double implementation using an algorithm more similar to my_strtod() (and maybe even a bit faster due to less floating point divisions). This should at least partially fix Bug #23260 for DECIMALs with a moderate number of total digits. --- strings/decimal.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/strings/decimal.c b/strings/decimal.c index 6b7a2266194..bdc3b1eef42 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -138,6 +138,12 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ 900000000, 990000000, 999000000, 999900000, 999990000, 999999000, 999999900, 999999990 }; +static double scaler10[]= { + 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 +}; +static double scaler1[]= { + 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 +}; #ifdef HAVE_purify #define sanity(d) DBUG_ASSERT((d)->len > 0) @@ -946,15 +952,27 @@ fatal_error: int decimal2double(decimal_t *from, double *to) { - double x=0, t=DIG_BASE; - int intg, frac; - dec1 *buf=from->buf; + double result= 0.0; + int i, exp= 0; + dec1 *buf= from->buf; + + for (i= from->intg; i > 0; i-= DIG_PER_DEC1) + result= result * DIG_BASE + *buf++; + + for (i= from->frac; i > 0; i-= DIG_PER_DEC1) { + result= result * DIG_BASE + *buf++; + exp+= DIG_PER_DEC1; + } + + DBUG_PRINT("info", ("interm.: %f %d %f", result, exp, + scaler10[exp / 10] * scaler1[exp % 10])); + + result/= scaler10[exp / 10] * scaler1[exp % 10]; + + *to= from->sign ? -result : result; + + DBUG_PRINT("info", ("result: %f (%lx)", *to, *to)); - for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1) - x=x*DIG_BASE + *buf++; - for (frac=from->frac; frac > 0; frac-=DIG_PER_DEC1, t*=DIG_BASE) - x+=*buf++/t; - *to=from->sign ? -x : x; return E_DEC_OK; } From 29aae170443d7bbc6dff1b6dd868ed7ea719eec3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Dec 2006 20:17:33 -0700 Subject: [PATCH 09/15] Remove warnings by casting cmd-line-utils/readline/histfile.c: Remove warning (compare signed & unsigned) sql/udf_example.c: Remove warning (cast integer to pointer of different size) strings/decimal.c: Remove warning (%lx format, double arg) --- cmd-line-utils/readline/histfile.c | 3 ++- sql/udf_example.c | 2 +- strings/decimal.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c index a7d6a68098e..f1822b105a4 100644 --- a/cmd-line-utils/readline/histfile.c +++ b/cmd-line-utils/readline/histfile.c @@ -334,7 +334,8 @@ history_truncate_file (fname, lines) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if (file_size != finfo.st_size || file_size + 1 < file_size) + if ((long long) file_size != (long long) finfo.st_size || + file_size + 1 < file_size) { close (file); #if defined (EFBIG) diff --git a/sql/udf_example.c b/sql/udf_example.c index bbab47e253d..f938cc9c1d3 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1087,7 +1087,7 @@ my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message) strmov(message, "IS_CONST accepts only one argument"); return 1; } - initid->ptr= (char*)((args->args[0] != NULL) ? 1 : 0); + initid->ptr= (char*)((args->args[0] != NULL) ? 1UL : 0); return 0; } diff --git a/strings/decimal.c b/strings/decimal.c index bdc3b1eef42..f6ac4717a32 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -971,7 +971,7 @@ int decimal2double(decimal_t *from, double *to) *to= from->sign ? -result : result; - DBUG_PRINT("info", ("result: %f (%lx)", *to, *to)); + DBUG_PRINT("info", ("result: %f (%lx)", *to, *(ulong *)to)); return E_DEC_OK; } From 14d05efc913143e998b1e032e16ee66b2f03611c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Dec 2006 10:54:41 +0100 Subject: [PATCH 10/15] Disable test "im_deamon_life_cycle", Bug#24425, see note: [19 Dec 23:17] Trudy Pelzer --- mysql-test/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 53b73363c22..3ee1130760e 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,6 +10,7 @@ # ############################################################################## +im_deamon_life_cycle : Bug#24425 see note: [19 Dec 23:17] Trudy Pelzer ndb_load : Bug#17233 user_limits : Bug#23921 random failure of user_limits.test flush2 : Bug#24805 Pushbuild can't handle test with --disable-log-bin From b8550ca15a961b522c3197afb465b8998a966722 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Dec 2006 11:13:16 +0100 Subject: [PATCH 11/15] Fix silly typos in the disabling of "im_daemon_life_cycle" (bug#24415). --- mysql-test/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 3ee1130760e..3213bd4eb5b 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,7 +10,7 @@ # ############################################################################## -im_deamon_life_cycle : Bug#24425 see note: [19 Dec 23:17] Trudy Pelzer +im_daemon_life_cycle : Bug#24415 see note: [19 Dec 23:17] Trudy Pelzer ndb_load : Bug#17233 user_limits : Bug#23921 random failure of user_limits.test flush2 : Bug#24805 Pushbuild can't handle test with --disable-log-bin From 40b23b3bbc075ceef019cf94ecf2e798edd728aa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Dec 2006 15:18:09 +0100 Subject: [PATCH 12/15] Bug#25208 - Warnings in mi_packrec.c Compiler warnings due to non-matching conversion specifications in format strings in DBUG_PRINT calls. Fixed DBUG_PRINT format specifiactions. myisam/mi_packrec.c: Bug#25208 - Warnings in mi_packrec.c Fixed DBUG_PRINT format specifiactions. --- myisam/mi_packrec.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index c88b8ab6607..5363a3ecf23 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -177,12 +177,12 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) if (share->min_pack_length > 254) share->base.min_block_length+=2; DBUG_PRINT("info", ("fixed header length: %u", HEAD_LENGTH)); - DBUG_PRINT("info", ("total header length: %u", share->pack.header_length)); + DBUG_PRINT("info", ("total header length: %lu", share->pack.header_length)); DBUG_PRINT("info", ("pack file version: %u", share->pack.version)); - DBUG_PRINT("info", ("min pack length: %u", share->min_pack_length)); - DBUG_PRINT("info", ("max pack length: %u", share->max_pack_length)); - DBUG_PRINT("info", ("elements of all trees: %u", elements)); - DBUG_PRINT("info", ("distinct values bytes: %u", intervall_length)); + DBUG_PRINT("info", ("min pack length: %lu", share->min_pack_length)); + DBUG_PRINT("info", ("max pack length: %lu", share->max_pack_length)); + DBUG_PRINT("info", ("elements of all trees: %lu", elements)); + DBUG_PRINT("info", ("distinct values bytes: %lu", intervall_length)); DBUG_PRINT("info", ("number of code trees: %u", trees)); DBUG_PRINT("info", ("bytes for record lgt: %u", share->pack.ref_length)); DBUG_PRINT("info", ("record pointer length: %u", rec_reflength)); @@ -364,7 +364,8 @@ static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree, } size=elements*2-2; DBUG_PRINT("info", ("tree size in uint16: %u", size)); - DBUG_PRINT("info", ("tree size in bytes: %u", size * sizeof(uint16))); + DBUG_PRINT("info", ("tree size in bytes: %u", + size * (uint) sizeof(uint16))); for (end=ptr+size ; ptr < end ; ptr++) { From fc9642b46dcd928a2116f04adf1bb24fb179f6cb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Dec 2006 15:32:02 +0100 Subject: [PATCH 13/15] Bug#25213 - Compiler warnings in MyISAM code Compiler warnings due to non-matching conversion specifications in format strings in DBUG_PRINT calls, due to non-used parameters (in non-debug mode), and due to seemingly uninitialized variables. Initialized variables, declared parameters unused, and casted DBUG_PRINT arguments to get rid of warnings. myisam/mi_range.c: Bug#25213 - Compiler warnings in MyISAM code Initialized a variable to get rid of a compiler warning. myisam/mi_test1.c: Bug#25213 - Compiler warnings in MyISAM code Declared an parameter unused to get rid of warnings. myisam/mi_write.c: Bug#25213 - Compiler warnings in MyISAM code Initialized a variable to get rid of a compiler warning. Casted arguments to DBUG_PRINT to match them with their format string conversion specification. myisam/rt_split.c: Bug#25213 - Compiler warnings in MyISAM code Initialized variables to get rid of compiler warnings. --- myisam/mi_range.c | 1 + myisam/mi_test1.c | 2 +- myisam/mi_write.c | 18 +++++++++++------- myisam/rt_split.c | 4 ++++ 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/myisam/mi_range.c b/myisam/mi_range.c index de042845d1e..4248fa7f04b 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -171,6 +171,7 @@ static double _mi_search_pos(register MI_INFO *info, uchar *keypos,*buff; double offset; DBUG_ENTER("_mi_search_pos"); + LINT_INIT(max_keynr); if (pos == HA_OFFSET_ERROR) DBUG_RETURN(0.5); diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c index 77c4d3dfbad..f6e1f7617d0 100644 --- a/myisam/mi_test1.c +++ b/myisam/mi_test1.c @@ -562,7 +562,7 @@ static struct my_option my_long_options[] = static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), - char *argument) + char *argument __attribute__((unused))) { switch(optid) { case 'a': diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 720c96b2d38..f8a5c6fa652 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -331,7 +331,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_bool was_last_key; my_off_t next_page, dupp_key_pos; DBUG_ENTER("w_search"); - DBUG_PRINT("enter",("page: %ld",page)); + DBUG_PRINT("enter",("page: %ld", (long) page)); search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ @@ -453,7 +453,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *endpos, *prev_key; MI_KEY_PARAM s_temp; DBUG_ENTER("_mi_insert"); - DBUG_PRINT("enter",("key_pos: %lx",key_pos)); + DBUG_PRINT("enter",("key_pos: %lx", (ulong) key_pos)); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,USE_WHOLE_KEY);); nod_flag=mi_test_if_nod(anc_buff); @@ -475,7 +475,8 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, DBUG_PRINT("test",("t_length: %d ref_len: %d", t_length,s_temp.ref_length)); DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: %lx", - s_temp.n_ref_length,s_temp.n_length,s_temp.key)); + s_temp.n_ref_length, s_temp.n_length, + (ulong) s_temp.key)); } #endif if (t_length > 0) @@ -572,6 +573,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_off_t new_pos; MI_KEY_PARAM s_temp; DBUG_ENTER("mi_split_page"); + LINT_INIT(after_key); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); if (info->s->keyinfo+info->lastinx == keyinfo) @@ -664,7 +666,8 @@ uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, uchar *page, } while (page < end); *return_key_length=length; *after_key=page; - DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end)); + DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx", + (ulong) lastpos, (ulong) page, (ulong) end)); DBUG_RETURN(lastpos); } /* _mi_find_half_pos */ @@ -718,7 +721,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, } *return_key_length=last_length; *after_key=lastpos; - DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx",prevpos,page,end)); + DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx", + (ulong) prevpos, (ulong) page, (ulong) end)); DBUG_RETURN(prevpos); } /* _mi_find_last_pos */ @@ -754,7 +758,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, next_page= _mi_kpos(info->s->base.key_reflength, father_key_pos+father_keylength); buff=info->buff; - DBUG_PRINT("test",("use right page: %lu",next_page)); + DBUG_PRINT("test",("use right page: %lu", (ulong) next_page)); } else { @@ -763,7 +767,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, next_page= _mi_kpos(info->s->base.key_reflength,father_key_pos); /* Fix that curr_buff is to left */ buff=curr_buff; curr_buff=info->buff; - DBUG_PRINT("test",("use left page: %lu",next_page)); + DBUG_PRINT("test",("use left page: %lu", (ulong) next_page)); } /* father_key_pos ptr to parting key */ if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0)) diff --git a/myisam/rt_split.c b/myisam/rt_split.c index 664dd2c75e3..87da22a93c7 100644 --- a/myisam/rt_split.c +++ b/myisam/rt_split.c @@ -188,6 +188,10 @@ static int split_rtree_node(SplitStruct *node, int n_entries, int next_node; int i; SplitStruct *end = node + n_entries; + LINT_INIT(a); + LINT_INIT(b); + LINT_INIT(next); + LINT_INIT(next_node); if (all_size < min_size * 2) { From 377cfb8b1b6bef25c1f63baf015837750479dab2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Dec 2006 13:35:41 +0100 Subject: [PATCH 14/15] configure.in : Update of the NDB version number was missing, do it. configure.in: Fix an omission: Version number for NDB is still kept separate (up to 5.0) and must be changed in sync with the general version number in AM_INIT_AUTOMAKE. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 5657cb1be93..49e295eeebb 100644 --- a/configure.in +++ b/configure.in @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=32 +NDB_VERSION_BUILD=34 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From f63d8c8d0c4a57b9f77a1c190cde4de7ad91bf81 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Dec 2006 17:47:30 +0400 Subject: [PATCH 15/15] BUG#25048 - ERROR 126 : Incorrect key file for table '.XXXX.MYI'; try to repair it Multi-table delete that is optimized with QUICK_RANGE reports table corruption. DELETE statement must not use KEYREAD optimization, and sets table->no_keyread to 1. This was ignored in QUICK_RANGE optimization. With this fix QUICK_RANGE optimization honors table->no_keyread value and does not enable KEYREAD when it is requested. mysql-test/r/index_merge.result: Fixed a test case according to fix for bug#25048. mysql-test/r/index_merge_ror.result: A test case for bug#25048. mysql-test/t/index_merge_ror.test: A test case for bug#25048. sql/opt_range.cc: Do not use key read when head->no_keyread is set. --- mysql-test/r/index_merge.result | 2 +- mysql-test/r/index_merge_ror.result | 11 +++++++++++ mysql-test/t/index_merge_ror.test | 15 +++++++++++++++ sql/opt_range.cc | 23 +++++++++++++++++------ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 3f3360e2da0..9456b4ec978 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -284,7 +284,7 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 -2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where +2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where; Using index create table t3 like t0; insert into t3 select * from t0; alter table t3 add key9 int not null, add index i9(key9); diff --git a/mysql-test/r/index_merge_ror.result b/mysql-test/r/index_merge_ror.result index 69cd11d1dbf..5d08125be53 100644 --- a/mysql-test/r/index_merge_ror.result +++ b/mysql-test/r/index_merge_ror.result @@ -194,3 +194,14 @@ explain select a from t2 where a='ab'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 6 const 1 Using where drop table t2; +CREATE TABLE t1(c1 INT, c2 INT DEFAULT 0, c3 CHAR(255) DEFAULT '', +KEY(c1), KEY(c2), KEY(c3)); +INSERT INTO t1(c1) VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), +(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0); +INSERT INTO t1 VALUES(0,0,0); +CREATE TABLE t2(c1 int); +INSERT INTO t2 VALUES(1); +DELETE t1 FROM t1,t2 WHERE t1.c1=0 AND t1.c2=0; +SELECT * FROM t1; +c1 c2 c3 +DROP TABLE t1,t2; diff --git a/mysql-test/t/index_merge_ror.test b/mysql-test/t/index_merge_ror.test index 48fe5526f11..a9de2f955ee 100644 --- a/mysql-test/t/index_merge_ror.test +++ b/mysql-test/t/index_merge_ror.test @@ -250,3 +250,18 @@ select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA'; insert into t2 values ('ab', 'ab', 'uh', 'oh'); explain select a from t2 where a='ab'; drop table t2; + +# +# BUG#25048 - ERROR 126 : Incorrect key file for table '.XXXX.MYI'; try to +# repair it +# +CREATE TABLE t1(c1 INT, c2 INT DEFAULT 0, c3 CHAR(255) DEFAULT '', +KEY(c1), KEY(c2), KEY(c3)); +INSERT INTO t1(c1) VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), +(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0); +INSERT INTO t1 VALUES(0,0,0); +CREATE TABLE t2(c1 int); +INSERT INTO t2 VALUES(1); +DELETE t1 FROM t1,t2 WHERE t1.c1=0 AND t1.c2=0; +SELECT * FROM t1; +DROP TABLE t1,t2; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 23a82c6eda7..4659c21f20f 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -875,7 +875,11 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() if (file) { range_end(); - file->extra(HA_EXTRA_NO_KEYREAD); + if (head->key_read) + { + head->key_read= 0; + file->extra(HA_EXTRA_NO_KEYREAD); + } if (free_file) { DBUG_PRINT("info", ("Freeing separate handler 0x%lx (free: %d)", (long) file, @@ -1017,8 +1021,12 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) if (reuse_handler) { DBUG_PRINT("info", ("Reusing handler %p", file)); - if (file->extra(HA_EXTRA_KEYREAD) || - file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) || + if (!head->no_keyread) + { + head->key_read= 1; + file->extra(HA_EXTRA_KEYREAD); + } + if (file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) || init() || reset()) { DBUG_RETURN(1); @@ -1041,9 +1049,12 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) } if (file->external_lock(thd, F_RDLCK)) goto failure; - - if (file->extra(HA_EXTRA_KEYREAD) || - file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) || + if (!head->no_keyread) + { + head->key_read= 1; + file->extra(HA_EXTRA_KEYREAD); + } + if (file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) || init() || reset()) { file->external_lock(thd, F_UNLCK);