mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Bug#55458: Partitioned MyISAM table gets crashed by multi-table update
Problem was that the handler call ::extra(HA_EXTRA_CACHE) was cached but the ::extra(HA_EXTRA_PREPARE_FOR_UPDATE) was not. Solution was to also cache the other call and forward it when moving to a new partition to scan. mysql-test/r/partition.result: test result mysql-test/t/partition.test: New test from bug report. sql/ha_partition.cc: cache the HA_EXTRA_PREPARE_FOR_UPDATE just like HA_EXTRA_CACHE. sql/ha_partition.h: Added cache flag for HA_EXTRA_PREPARE_FOR_UPDATE
This commit is contained in:
@@ -1,4 +1,29 @@
|
|||||||
drop table if exists t1, t2;
|
drop table if exists t1, t2;
|
||||||
|
#
|
||||||
|
# Bug#55458: Partitioned MyISAM table gets crashed by multi-table update
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
`id` int NOT NULL,
|
||||||
|
`user_num` int DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM CHARSET=latin1;
|
||||||
|
INSERT INTO t1 VALUES (1,8601);
|
||||||
|
INSERT INTO t1 VALUES (2,8601);
|
||||||
|
INSERT INTO t1 VALUES (3,8601);
|
||||||
|
INSERT INTO t1 VALUES (4,8601);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
`id` int(11) NOT NULL,
|
||||||
|
`user_num` int DEFAULT NULL,
|
||||||
|
`name` varchar(64) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM CHARSET=latin1
|
||||||
|
PARTITION BY HASH (id)
|
||||||
|
PARTITIONS 2;
|
||||||
|
INSERT INTO t2 VALUES (1,8601,'John');
|
||||||
|
INSERT INTO t2 VALUES (2,8601,'JS');
|
||||||
|
INSERT INTO t2 VALUES (3,8601,'John S');
|
||||||
|
UPDATE t1, t2 SET t2.name = 'John Smith' WHERE t1.user_num = t2.user_num;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
CREATE TABLE t1 (a INT, b INT)
|
CREATE TABLE t1 (a INT, b INT)
|
||||||
PARTITION BY LIST (a)
|
PARTITION BY LIST (a)
|
||||||
SUBPARTITION BY HASH (b)
|
SUBPARTITION BY HASH (b)
|
||||||
|
@@ -14,6 +14,33 @@
|
|||||||
drop table if exists t1, t2;
|
drop table if exists t1, t2;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#55458: Partitioned MyISAM table gets crashed by multi-table update
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
`id` int NOT NULL,
|
||||||
|
`user_num` int DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM CHARSET=latin1;
|
||||||
|
INSERT INTO t1 VALUES (1,8601);
|
||||||
|
INSERT INTO t1 VALUES (2,8601);
|
||||||
|
INSERT INTO t1 VALUES (3,8601);
|
||||||
|
INSERT INTO t1 VALUES (4,8601);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
`id` int(11) NOT NULL,
|
||||||
|
`user_num` int DEFAULT NULL,
|
||||||
|
`name` varchar(64) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM CHARSET=latin1
|
||||||
|
PARTITION BY HASH (id)
|
||||||
|
PARTITIONS 2;
|
||||||
|
INSERT INTO t2 VALUES (1,8601,'John');
|
||||||
|
INSERT INTO t2 VALUES (2,8601,'JS');
|
||||||
|
INSERT INTO t2 VALUES (3,8601,'John S');
|
||||||
|
|
||||||
|
UPDATE t1, t2 SET t2.name = 'John Smith' WHERE t1.user_num = t2.user_num;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
#
|
#
|
||||||
# Bug#48276: can't add column if subpartition exists
|
# Bug#48276: can't add column if subpartition exists
|
||||||
CREATE TABLE t1 (a INT, b INT)
|
CREATE TABLE t1 (a INT, b INT)
|
||||||
|
@@ -232,6 +232,7 @@ void ha_partition::init_handler_variables()
|
|||||||
m_innodb= FALSE;
|
m_innodb= FALSE;
|
||||||
m_extra_cache= FALSE;
|
m_extra_cache= FALSE;
|
||||||
m_extra_cache_size= 0;
|
m_extra_cache_size= 0;
|
||||||
|
m_extra_prepare_for_update= FALSE;
|
||||||
m_handler_status= handler_not_initialized;
|
m_handler_status= handler_not_initialized;
|
||||||
m_low_byte_first= 1;
|
m_low_byte_first= 1;
|
||||||
m_part_field_array= NULL;
|
m_part_field_array= NULL;
|
||||||
@@ -5549,9 +5550,20 @@ int ha_partition::extra(enum ha_extra_function operation)
|
|||||||
case HA_EXTRA_PREPARE_FOR_RENAME:
|
case HA_EXTRA_PREPARE_FOR_RENAME:
|
||||||
DBUG_RETURN(prepare_for_rename());
|
DBUG_RETURN(prepare_for_rename());
|
||||||
break;
|
break;
|
||||||
|
case HA_EXTRA_PREPARE_FOR_UPDATE:
|
||||||
|
DBUG_ASSERT(m_extra_cache);
|
||||||
|
/*
|
||||||
|
Needs to be run on the first partition in the range now, and
|
||||||
|
later in late_extra_cache, when switching to a new partition to scan.
|
||||||
|
*/
|
||||||
|
m_extra_prepare_for_update= TRUE;
|
||||||
|
if (m_part_spec.start_part != NO_CURRENT_PART_ID)
|
||||||
|
{
|
||||||
|
VOID(m_file[m_part_spec.start_part]->extra(HA_EXTRA_PREPARE_FOR_UPDATE));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case HA_EXTRA_NORMAL:
|
case HA_EXTRA_NORMAL:
|
||||||
case HA_EXTRA_QUICK:
|
case HA_EXTRA_QUICK:
|
||||||
case HA_EXTRA_PREPARE_FOR_UPDATE:
|
|
||||||
case HA_EXTRA_FORCE_REOPEN:
|
case HA_EXTRA_FORCE_REOPEN:
|
||||||
case HA_EXTRA_PREPARE_FOR_DROP:
|
case HA_EXTRA_PREPARE_FOR_DROP:
|
||||||
case HA_EXTRA_FLUSH_CACHE:
|
case HA_EXTRA_FLUSH_CACHE:
|
||||||
@@ -5578,6 +5590,7 @@ int ha_partition::extra(enum ha_extra_function operation)
|
|||||||
{
|
{
|
||||||
m_extra_cache= FALSE;
|
m_extra_cache= FALSE;
|
||||||
m_extra_cache_size= 0;
|
m_extra_cache_size= 0;
|
||||||
|
m_extra_prepare_for_update= FALSE;
|
||||||
DBUG_RETURN(loop_extra(operation));
|
DBUG_RETURN(loop_extra(operation));
|
||||||
}
|
}
|
||||||
case HA_EXTRA_IGNORE_NO_KEY:
|
case HA_EXTRA_IGNORE_NO_KEY:
|
||||||
@@ -5705,6 +5718,7 @@ int ha_partition::extra_opt(enum ha_extra_function operation, ulong cachesize)
|
|||||||
void ha_partition::prepare_extra_cache(uint cachesize)
|
void ha_partition::prepare_extra_cache(uint cachesize)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("ha_partition::prepare_extra_cache()");
|
DBUG_ENTER("ha_partition::prepare_extra_cache()");
|
||||||
|
DBUG_PRINT("info", ("cachesize %u", cachesize));
|
||||||
|
|
||||||
m_extra_cache= TRUE;
|
m_extra_cache= TRUE;
|
||||||
m_extra_cache_size= cachesize;
|
m_extra_cache_size= cachesize;
|
||||||
@@ -5793,14 +5807,21 @@ void ha_partition::late_extra_cache(uint partition_id)
|
|||||||
{
|
{
|
||||||
handler *file;
|
handler *file;
|
||||||
DBUG_ENTER("ha_partition::late_extra_cache");
|
DBUG_ENTER("ha_partition::late_extra_cache");
|
||||||
|
DBUG_PRINT("info", ("extra_cache %u partid %u size %u", m_extra_cache,
|
||||||
|
partition_id, m_extra_cache_size));
|
||||||
|
|
||||||
if (!m_extra_cache)
|
if (!m_extra_cache && !m_extra_prepare_for_update)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
file= m_file[partition_id];
|
file= m_file[partition_id];
|
||||||
if (m_extra_cache_size == 0)
|
if (m_extra_cache_size == 0)
|
||||||
VOID(file->extra(HA_EXTRA_CACHE));
|
VOID(file->extra(HA_EXTRA_CACHE));
|
||||||
else
|
else
|
||||||
VOID(file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size));
|
VOID(file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size));
|
||||||
|
if (m_extra_prepare_for_update)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(m_extra_cache);
|
||||||
|
VOID(file->extra(HA_EXTRA_PREPARE_FOR_UPDATE));
|
||||||
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5821,7 +5842,7 @@ void ha_partition::late_extra_no_cache(uint partition_id)
|
|||||||
handler *file;
|
handler *file;
|
||||||
DBUG_ENTER("ha_partition::late_extra_no_cache");
|
DBUG_ENTER("ha_partition::late_extra_no_cache");
|
||||||
|
|
||||||
if (!m_extra_cache)
|
if (!m_extra_cache && !m_extra_prepare_for_update)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
file= m_file[partition_id];
|
file= m_file[partition_id];
|
||||||
VOID(file->extra(HA_EXTRA_NO_CACHE));
|
VOID(file->extra(HA_EXTRA_NO_CACHE));
|
||||||
|
@@ -154,6 +154,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool m_extra_cache;
|
bool m_extra_cache;
|
||||||
uint m_extra_cache_size;
|
uint m_extra_cache_size;
|
||||||
|
/* The same goes for HA_EXTRA_PREPARE_FOR_UPDATE */
|
||||||
|
bool m_extra_prepare_for_update;
|
||||||
|
|
||||||
void init_handler_variables();
|
void init_handler_variables();
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user