Below is the list of changes that have just been committed into a local
4.1 repository of mydev. When mydev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2488 06/04/05 21:05:37 ingo@stripped +5 -0
Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
After a lock wait timeout the open table(s) were not fully
cleaned up for reuse. But they were put into the open table
cache even before the lock was tried. The next statement
reused the table(s) with a wrong lock type set up. This
tricked MyISAM into believing that it don't need to update
the table statistics. Hence CHECK TABLE reported a record
count and table size mismatch.
Fortunately nothing worse has been detected yet. The effect
of the test case was that the insert worked on a read locked
table. (!)
I added a new function that clears the lock type from all
tables that were prepared for a lock. I call this function
when a lock failes.
In an unrelated change I added the configuration variable
'innodb_lock_wait_timeout' to the list of server variables.
I needed it to to shorten the lock wait timeout from 50
seconds to 1 second in the test case. Without this change
the test case would have added 49 additional seconds to the
test suite.
sql/set_var.cc
1.179 06/04/05 21:04:29 ingo@stripped +4 -1
Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
Added 'innodb_lock_wait_timeout' to the list of system variables.
sql/lock.cc
1.65 06/04/05 21:04:29 ingo@stripped +36 -0
Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
Resetting the lock type in the open table(s) lock data
after a failed lock_external().
sql/ha_innodb.h
1.81 06/04/05 21:04:29 ingo@stripped +1 -0
Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
Added 'innodb_lock_wait_timeout' to the list of system variables.
mysql-test/t/innodb.test
1.80 06/04/05 21:04:29 ingo@stripped +35 -0
Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
The test case.
mysql-test/r/innodb.result
1.109 06/04/05 21:04:29 ingo@stripped +16 -0
Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
The test result.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: ingo
# Host: chilla.local
# Root: /home/mydev/mysql-4.1-bug18544
--- 1.64/sql/lock.cc 2006-01-04 15:35:17 +01:00
+++ 1.65/sql/lock.cc 2006-04-05 21:04:29 +02:00
@@ -77,6 +77,7 @@
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
bool unlock, TABLE **write_locked);
+static void reset_lock_data(MYSQL_LOCK *sql_lock);
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error);
@@ -133,6 +134,15 @@
thd->proc_info="System lock";
if (lock_external(thd, tables, count))
{
+ /*
+ At this point we want to quit the locking of the table(s).
+ But we have already set the lock type into the lock data of the
+ open table(s). If the table(s) are in the open table cache, they
+ could be reused with the non-zero lock type set. This could lead
+ to ignoring a different lock type with the next lock. (Bug #18544)
+ Clear the lock type of all lock data.
+ */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
thd->proc_info=0;
@@ -559,6 +569,32 @@
(*org_locks)->debug_print_param= (void *) table;
}
DBUG_RETURN(sql_lock);
+}
+
+
+/*
+ Reset lock type in lock data.
+
+ SYNOPSIS
+ reset_lock_data()
+ sql_lock The MySQL lock.
+
+ RETURN
+ void
+*/
+
+static void reset_lock_data(MYSQL_LOCK *sql_lock)
+{
+ THR_LOCK_DATA **ldata;
+ THR_LOCK_DATA **ldata_end;
+
+ for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
+ ldata < ldata_end;
+ ldata++)
+ {
+ /* Reset lock type. */
+ (*ldata)->type= TL_UNLOCK;
+ }
}
--- 1.108/mysql-test/r/innodb.result 2006-01-30 13:17:30 +01:00
+++ 1.109/mysql-test/r/innodb.result 2006-04-05 21:04:29 +02:00
@@ -1807,3 +1807,19 @@
KEY `t2_ibfk_0` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2,t1;
+create table t1 (c1 varchar(255), primary key(c1)) engine=innodb;
+create table t2 (c1 varchar(255), primary key(c1)) engine=myisam;
+set autocommit=0;
+insert into t1 values ('anything');
+insert into t2 values ('anything');
+set autocommit=0;
+set @old_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout;
+set @@global.innodb_lock_wait_timeout= 1;
+lock tables t1 read, t2 read;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+set @@global.innodb_lock_wait_timeout= @old_innodb_lock_wait_timeout;
+insert into t2 values ('anything else');
+check table t2;
+Table Op Msg_type Msg_text
+test.t2 check status OK
+drop table t1, t2;
--- 1.79/mysql-test/t/innodb.test 2006-01-30 13:17:30 +01:00
+++ 1.80/mysql-test/t/innodb.test 2006-04-05 21:04:29 +02:00
@@ -1378,4 +1378,39 @@
SHOW CREATE TABLE t2;
DROP TABLE t2,t1;
+#
+# Bug#18544 - LOCK TABLES timeout causes MyISAM table corruption
+# This is not really an InnoDB test, but it needs InnoDB to trigger the bug.
+#
+create table t1 (c1 varchar(255), primary key(c1)) engine=innodb;
+create table t2 (c1 varchar(255), primary key(c1)) engine=myisam;
+#
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+#
+connection con1;
+set autocommit=0;
+insert into t1 values ('anything');
+insert into t2 values ('anything');
+#
+connection con2;
+set autocommit=0;
+set @old_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout;
+set @@global.innodb_lock_wait_timeout= 1;
+# The next statement waits because of the innodb lock taken by connection 1.
+# It waits until the lock times out.
+--error 1205
+lock tables t1 read, t2 read;
+set @@global.innodb_lock_wait_timeout= @old_innodb_lock_wait_timeout;
+#
+connection con1;
+insert into t2 values ('anything else');
+# The following shows table corruption if the bug is present.
+check table t2;
+#
+connection default;
+disconnect con1;
+disconnect con2;
+drop table t1, t2;
+
# End of 4.1 tests
--- 1.80/sql/ha_innodb.h 2005-05-04 15:05:53 +02:00
+++ 1.81/sql/ha_innodb.h 2006-04-05 21:04:29 +02:00
@@ -203,6 +203,7 @@
extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag;
extern ulong srv_auto_extend_increment;
+extern ulong srv_lock_wait_timeout;
}
extern TYPELIB innobase_lock_typelib;
--- 1.178/sql/set_var.cc 2005-09-21 00:18:26 +02:00
+++ 1.179/sql/set_var.cc 2006-04-05 21:04:29 +02:00
@@ -374,6 +374,8 @@
&SV::innodb_table_locks);
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
&srv_auto_extend_increment);
+sys_var_long_ptr sys_innodb_lock_wait_timeout("innodb_lock_wait_timeout",
+ &srv_lock_wait_timeout);
#endif
#ifdef HAVE_NDBCLUSTER_DB
@@ -653,6 +655,7 @@
&sys_innodb_table_locks,
&sys_innodb_max_purge_lag,
&sys_innodb_autoextend_increment,
+ &sys_innodb_lock_wait_timeout,
#endif
#ifdef HAVE_NDBCLUSTER_DB
&sys_ndb_autoincrement_prefetch_sz,
@@ -744,7 +747,7 @@
{"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
{"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
{"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
- {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
+ {"innodb_lock_wait_timeout", (char*) &srv_lock_wait_timeout, SHOW_LONG },
{"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL},
{"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR},
{"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL},
| Thread |
|---|
| • bk commit into 4.1 tree (ingo:1.2488) BUG#18544 | ingo | 5 Apr |