From 8375e6684db2a33c14c1cfaaf7e00a160443cc7a Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Fri, 8 Dec 2006 10:23:03 +0100 Subject: [PATCH 01/17] BUG#24896 mysql_upgrade -p fix --- client/mysql_upgrade.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 520d87b5ed7..309b532051c 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -142,6 +142,7 @@ void set_extra_default(int id, const struct my_option *opt) case 'f': /* --force is ours */ case 'u': /* --user passed on cmdline */ case 'T': /* --debug-info is not accepted by mysqlcheck */ + case 'p': /* --password may change yet */ /* so, do nothing */ break; default: @@ -173,7 +174,7 @@ void set_extra_default(int id, const struct my_option *opt) d->id= id; d->name= opt->name; d->n_len= strlen(opt->name); - if (opt->arg_type != NO_ARG) + if (opt->arg_type != NO_ARG && opt->value) switch (opt->var_type & GET_TYPE_MASK) { case GET_BOOL: if (*((int *)opt->value)) @@ -319,6 +320,15 @@ static int create_defaults_file(const char *path, const char *forced_path) } dynstr_set(&buf, "\n[client]"); + if (opt_password) + { + if (dynstr_append_mem(&buf, "\npassword=", 10) + || dynstr_append_mem(&buf, opt_password, strlen(opt_password))) + { + ret = 1; + goto error; + } + } while (extra_defaults) { int len; From bd44245eb66c4cfc9268585ddc896909e7089cb1 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Tue, 12 Dec 2006 13:55:40 +0100 Subject: [PATCH 02/17] BUG#24902 in 5.0 --- mysql-test/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 72998d786b9..eff2ae740f5 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -98,7 +98,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data - $(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib From b9cce096a2bc21bc5237c1f98dba8105662c0d06 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Tue, 12 Dec 2006 15:47:02 +0100 Subject: [PATCH 03/17] BUG#24896 magnus' suggestion --- client/mysql_upgrade.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 309b532051c..0f3f307a26d 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -322,8 +322,8 @@ static int create_defaults_file(const char *path, const char *forced_path) dynstr_set(&buf, "\n[client]"); if (opt_password) { - if (dynstr_append_mem(&buf, "\npassword=", 10) - || dynstr_append_mem(&buf, opt_password, strlen(opt_password))) + if (dynstr_append(&buf, "\npassword=") + || dynstr_append(&buf, opt_password)) { ret = 1; goto error; From 1d6ff3a2036aa95b4cc5649f4be01d5c5b374fa7 Mon Sep 17 00:00:00 2001 From: "bteam/mysqldev@mysql.com/production.mysql.com" <> Date: Fri, 15 Dec 2006 13:18:16 +0100 Subject: [PATCH 04/17] Raise version number after cloning 5.0.32 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index f6a6eedac70..5657cb1be93 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.32) +AM_INIT_AUTOMAKE(mysql, 5.0.34) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 0cce240581291e0bf26f8e508b5e1ff58271f60e Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Fri, 15 Dec 2006 17:45:17 +0100 Subject: [PATCH 05/17] minor 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 905d9e848c39b28eb91864e41f0d56ac3213bcf8 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Fri, 15 Dec 2006 17:57:31 +0100 Subject: [PATCH 06/17] 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 534b2ca0a8e9546caad2301f46490703cc59b1a5 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Mon, 18 Dec 2006 11:51:45 +0100 Subject: [PATCH 07/17] 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 4a98f36e591a3f6f57974d96a3063ae4d8b3076b Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Mon, 18 Dec 2006 13:44:21 +0100 Subject: [PATCH 08/17] 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 d60550a4d6310a52aab55fa4c7c1d0f96bd5ba4f Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Mon, 18 Dec 2006 18:41:38 -0700 Subject: [PATCH 09/17] 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 | 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 6b27694ac8b3283904a8ece44ce826415f938f0c Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Tue, 19 Dec 2006 15:10:15 +0100 Subject: [PATCH 10/17] remove hard-coded socket paths from some tests --- mysql-test/t/grant_cache.test | 14 +++++++------- mysql-test/t/myisam.test | 2 +- mysql-test/t/query_cache_notembedded.test | 4 ++-- mysql-test/t/rpl000015.test | 4 ++-- mysql-test/t/rpl000017.test | 4 ++-- mysql-test/t/rpl_rotate_logs.test | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test index 703ad5d8004..7e17a03ec21 100644 --- a/mysql-test/t/grant_cache.test +++ b/mysql-test/t/grant_cache.test @@ -14,7 +14,7 @@ set GLOBAL query_cache_size=1355776; reset query cache; flush status; -connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; show grants for current_user; show grants; @@ -29,7 +29,7 @@ insert into mysqltest.t2 values (3,3,3); create table test.t1 (a char (10)); insert into test.t1 values ("test.t1"); select * from t1; -connect (root2,localhost,root,,mysqltest,$MASTER_MYPORT,master.sock); +connect (root2,localhost,root,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); connection root2; # put queries in cache select * from t1; @@ -47,7 +47,7 @@ grant SELECT on test.t1 to mysqltest_2@localhost; grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost; # The following queries should be fetched from cache -connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,master.sock); +connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); connection user1; show grants for current_user(); show status like "Qcache_queries_in_cache"; @@ -72,12 +72,12 @@ show status like "Qcache_hits"; show status like "Qcache_not_cached"; # Don't use '' as user because it will pick Unix login -connect (unkuser,localhost,unkuser,,,$MASTER_MYPORT,master.sock); +connect (unkuser,localhost,unkuser,,,$MASTER_MYPORT,$MASTER_MYSOCK); connection unkuser; show grants for current_user(); # The following queries should be fetched from cache -connect (user2,localhost,mysqltest_2,,mysqltest,$MASTER_MYPORT,master.sock); +connect (user2,localhost,mysqltest_2,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); connection user2; select "user2"; select * from t1; @@ -92,7 +92,7 @@ show status like "Qcache_hits"; show status like "Qcache_not_cached"; # The following queries should not be fetched from cache -connect (user3,localhost,mysqltest_3,,mysqltest,$MASTER_MYPORT,master.sock); +connect (user3,localhost,mysqltest_3,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); connection user3; select "user3"; --replace_result 127.0.0.1 localhost @@ -113,7 +113,7 @@ show status like "Qcache_hits"; show status like "Qcache_not_cached"; # Connect without a database -connect (user4,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,master.sock); +connect (user4,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK); connection user4; select "user4"; show grants; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 745e3a2e377..c3269084c6f 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -495,7 +495,7 @@ insert into t1 values (1),(2),(3),(4),(5),(6); insert into t2 values (1,1),(2,1); lock tables t1 read local, t2 read local; select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; -connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); insert into t2 values(2,0); disconnect root; connection default; diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index fd4785ffe95..20baf3450e2 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -81,12 +81,12 @@ drop table t1, t2, t3, t11, t21; # # do not use QC if tables locked (BUG#12385) # -connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE = MyISAM; LOCK TABLE t1 READ LOCAL; -connect (root2,localhost,root,,test,$MASTER_MYPORT,master.sock); +connect (root2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root2; INSERT INTO t1 VALUES (), (), (); connection root; diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test index 4e329fc87ea..a23a4b0ba5f 100644 --- a/mysql-test/t/rpl000015.test +++ b/mysql-test/t/rpl000015.test @@ -1,5 +1,5 @@ -connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock); -connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock); +connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK); connection master; reset master; show master status; diff --git a/mysql-test/t/rpl000017.test b/mysql-test/t/rpl000017.test index 7b4e6bf4d3a..ea3aba8fb75 100644 --- a/mysql-test/t/rpl000017.test +++ b/mysql-test/t/rpl000017.test @@ -1,5 +1,5 @@ -connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock); -connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock); +connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK); connection master; reset master; grant replication slave on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab'; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 891582a167c..8d751e43958 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -9,11 +9,11 @@ # changes # - Test creating a duplicate key error and recover from it -connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock); +connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); --disable_warnings drop table if exists t1, t2, t3, t4; --enable_warnings -connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock); +connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK); system cat /dev/null > var/slave-data/master.info; system chmod 000 var/slave-data/master.info; connection slave; From 2bc45899c02d31937d77d47f3e09ae01d5639e04 Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 15:54:12 -0700 Subject: [PATCH 11/17] 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 | 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 0d5dc51438463226da454808a4ef370d194ae65d Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 16:57:51 -0700 Subject: [PATCH 12/17] Added innodb_rollback_on_timeout option to restore the 4.1 InnoDB timeout behavior (Bug #24200) --- 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 6cbfc343a82915a49d747e45548671722f8a7d1c Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 17:42:26 -0700 Subject: [PATCH 13/17] 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 7c82a06dcf0dbf4cff2e2001ae03cdb574e6105e Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 20:17:33 -0700 Subject: [PATCH 14/17] Remove warnings by casting --- 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 f9802fd47dabb8f5f10fd5dd6bbb64379ae1f639 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Wed, 20 Dec 2006 10:54:41 +0100 Subject: [PATCH 15/17] 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 90fc044fc2b604a6679da0730c8955e1ea81ae9a Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Wed, 20 Dec 2006 11:13:16 +0100 Subject: [PATCH 16/17] 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 c2de802e9cd5ac6e8d5d22736641f9deb9c1cc90 Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Wed, 20 Dec 2006 17:11:47 -0700 Subject: [PATCH 17/17] Post-merge fix (related to bug 24200 changes) --- sql/mysqld.cc | 4 +++- sql/set_var.cc | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1764c1975de..d6031504799 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -391,6 +391,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 "C" { extern ulong srv_max_buf_pool_modified_pct; @@ -8154,7 +8155,8 @@ my_bool innobase_log_archive, innobase_use_doublewrite, innobase_use_checksums, innobase_file_per_table, - innobase_locks_unsafe_for_binlog; + innobase_locks_unsafe_for_binlog, + innobase_rollback_on_timeout; extern "C" { ulong srv_max_buf_pool_modified_pct; diff --git a/sql/set_var.cc b/sql/set_var.cc index 728aefd6428..64d46b1fc30 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -78,7 +78,8 @@ extern my_bool innobase_log_archive, innobase_use_doublewrite, innobase_use_checksums, innobase_file_per_table, - innobase_locks_unsafe_for_binlog; + innobase_locks_unsafe_for_binlog, + innobase_rollback_on_timeout; extern "C" { extern ulong srv_max_buf_pool_modified_pct;