mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
@ -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
|
1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where
|
||||||
drop table t3;
|
drop table t3;
|
||||||
drop table t0, t1, t2;
|
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;
|
||||||
|
@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1;
|
|||||||
|
|
||||||
drop table t3;
|
drop table t3;
|
||||||
drop table t0, t1, t2;
|
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;
|
||||||
|
@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg)
|
|||||||
can_enable_indexes(1)
|
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[] = {
|
static const char *ha_myisam_exts[] = {
|
||||||
".MYI",
|
".MYI",
|
||||||
|
@ -45,6 +45,7 @@ class ha_myisam: public handler
|
|||||||
public:
|
public:
|
||||||
ha_myisam(TABLE *table_arg);
|
ha_myisam(TABLE *table_arg);
|
||||||
~ha_myisam() {}
|
~ha_myisam() {}
|
||||||
|
handler *clone(MEM_ROOT *mem_root);
|
||||||
const char *table_type() const { return "MyISAM"; }
|
const char *table_type() const { return "MyISAM"; }
|
||||||
const char *index_type(uint key_number);
|
const char *index_type(uint key_number);
|
||||||
const char **bas_ext() const;
|
const char **bas_ext() const;
|
||||||
|
@ -1372,6 +1372,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** General handler functions
|
** 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 */
|
/* 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 */
|
/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
|
||||||
|
@ -563,6 +563,7 @@ public:
|
|||||||
pushed_cond(NULL)
|
pushed_cond(NULL)
|
||||||
{}
|
{}
|
||||||
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
|
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);
|
int ha_open(const char *name, int mode, int test_if_locked);
|
||||||
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
|
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
|
||||||
bool update_auto_increment();
|
bool update_auto_increment();
|
||||||
|
@ -1033,10 +1033,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type)))
|
if (!(file= head->file->clone(thd->mem_root)))
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
/* Caller will free the memory */
|
/* Caller will free the memory */
|
||||||
goto failure;
|
goto failure;
|
||||||
|
Reference in New Issue
Block a user