summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsvoj@april.(none) <>2006-09-12 18:25:35 +0500
committersvoj@april.(none) <>2006-09-12 18:25:35 +0500
commit44f167ee1d0ca223562066c5d2ccd85be93832d0 (patch)
treef55c1bef77080c8bc784fbe2aac8f150441acea5
parent50192889a485a60c54d6899aaf6649ef50291c41 (diff)
downloadmariadb-git-44f167ee1d0ca223562066c5d2ccd85be93832d0.tar.gz
BUG#20256 - LOCK WRITE - MyISAM
Only MyISAM tables locked with LOCK TABLES ... WRITE were affected. A query that is optimized with index_merge doesn't reflect rows inserted within LOCK TABLES. MyISAM doesn't flush a state within LOCK TABLES. index_merge optimization creates a copy of the handler, which thus gets outdated MyISAM state. New handler->clone() method is introduced to fix this problem. For non-MyISAM storage engines it allocates a handler and opens it with ha_open(). For MyISAM it additionally copies MyISAM state pointer to cloned handler.
-rw-r--r--mysql-test/r/index_merge.result31
-rw-r--r--mysql-test/t/index_merge.test32
-rw-r--r--sql/ha_myisam.cc8
-rw-r--r--sql/ha_myisam.h1
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/handler.h1
-rw-r--r--sql/opt_range.cc5
7 files changed, 83 insertions, 4 deletions
diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result
index 3a69f56cbd3..3f3360e2da0 100644
--- a/mysql-test/r/index_merge.result
+++ b/mysql-test/r/index_merge.result
@@ -424,3 +424,34 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where
drop table t3;
drop table t0, t1, t2;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1);
+CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b));
+INSERT INTO t2(a,b) 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,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),(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,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),(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,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),(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,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),(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,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),(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,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),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(1,2);
+LOCK TABLES t1 WRITE, t2 WRITE;
+INSERT INTO t2(a,b) VALUES(1,2);
+SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1;
+a
+1
+1
+UNLOCK TABLES;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test
index 3da5711bf7a..30eb0b40fca 100644
--- a/mysql-test/t/index_merge.test
+++ b/mysql-test/t/index_merge.test
@@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1;
drop table t3;
drop table t0, t1, t2;
+
+#
+# BUG#20256 - LOCK WRITE - MyISAM
+#
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1);
+CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b));
+INSERT INTO t2(a,b) 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,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),(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,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),(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,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),(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,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),(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,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),(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,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),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
+(1,2);
+LOCK TABLES t1 WRITE, t2 WRITE;
+INSERT INTO t2(a,b) VALUES(1,2);
+SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1;
+UNLOCK TABLES;
+DROP TABLE t1, t2;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 128cc191434..876cd33ec9c 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg)
can_enable_indexes(1)
{}
+handler *ha_myisam::clone(MEM_ROOT *mem_root)
+{
+ ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
+ if (new_handler)
+ new_handler->file->state= file->state;
+ return new_handler;
+}
+
static const char *ha_myisam_exts[] = {
".MYI",
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index ca684463311..950817d42bd 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -45,6 +45,7 @@ class ha_myisam: public handler
public:
ha_myisam(TABLE *table_arg);
~ha_myisam() {}
+ handler *clone(MEM_ROOT *mem_root);
const char *table_type() const { return "MyISAM"; }
const char *index_type(uint key_number);
const char **bas_ext() const;
diff --git a/sql/handler.cc b/sql/handler.cc
index 01aa7491383..81981a5dcc6 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1372,6 +1372,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
/****************************************************************************
** General handler functions
****************************************************************************/
+handler *handler::clone(MEM_ROOT *mem_root)
+{
+ handler *new_handler= get_new_handler(table, mem_root, table->s->db_type);
+ if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED))
+ return new_handler;
+ return NULL;
+}
+
/* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
diff --git a/sql/handler.h b/sql/handler.h
index 44de0cc715a..471bb08b748 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -563,6 +563,7 @@ public:
pushed_cond(NULL)
{}
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
+ virtual handler *clone(MEM_ROOT *mem_root);
int ha_open(const char *name, int mode, int test_if_locked);
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
bool update_auto_increment();
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 3b77d1b419e..5866fe731cf 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1033,10 +1033,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
}
THD *thd= current_thd;
- if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type)))
- goto failure;
- DBUG_PRINT("info", ("Allocated new handler %p", file));
- if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED))
+ if (!(file= head->file->clone(thd->mem_root)))
{
/* Caller will free the memory */
goto failure;