mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Review and crash-safety fix
This commit is contained in:
committed by
Sergei Golubchik
parent
428024524c
commit
7da721be31
@ -195,3 +195,41 @@
|
||||
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 CONVERT PARTITION p1 TO TABLE tp1
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
@@ -270,15 +234,12 @@
|
||||
x
|
||||
12
|
||||
# CRASH: crash_convert_partition_10
|
||||
-t1#P#p0.MYD
|
||||
-t1#P#p0.MYI
|
||||
-t1#P#pn.MYD
|
||||
-t1#P#pn.MYI
|
||||
+t1#P#p0.ibd
|
||||
+t1#P#pn.ibd
|
||||
t1.frm
|
||||
t1.par
|
||||
-tp1.MYD
|
||||
-tp1.MYI
|
||||
tp1.frm
|
||||
+tp1.ibd
|
||||
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 CONVERT PARTITION p1 TO TABLE tp1
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
@@ -297,15 +258,12 @@
|
||||
x
|
||||
12
|
||||
# CRASH: crash_convert_partition_11
|
||||
-t1#P#p0.MYD
|
||||
-t1#P#p0.MYI
|
||||
-t1#P#pn.MYD
|
||||
-t1#P#pn.MYI
|
||||
+t1#P#p0.ibd
|
||||
+t1#P#pn.ibd
|
||||
t1.frm
|
||||
t1.par
|
||||
-tp1.MYD
|
||||
-tp1.MYI
|
||||
tp1.frm
|
||||
+tp1.ibd
|
||||
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 CONVERT PARTITION p1 TO TABLE tp1
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
|
@ -269,5 +269,59 @@ tp1 CREATE TABLE `tp1` (
|
||||
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
x
|
||||
12
|
||||
# CRASH: crash_convert_partition_10
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#pn.MYD
|
||||
t1#P#pn.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
tp1.MYD
|
||||
tp1.MYI
|
||||
tp1.frm
|
||||
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 CONVERT PARTITION p1 TO TABLE tp1
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`x` int(11) DEFAULT NULL
|
||||
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
PARTITION BY RANGE (`x`)
|
||||
(PARTITION `p0` VALUES LESS THAN (10) ENGINE = DEFAULT_ENGINE,
|
||||
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = DEFAULT_ENGINE)
|
||||
x
|
||||
2
|
||||
22
|
||||
Table Create Table
|
||||
tp1 CREATE TABLE `tp1` (
|
||||
`x` int(11) DEFAULT NULL
|
||||
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
x
|
||||
12
|
||||
# CRASH: crash_convert_partition_11
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#pn.MYD
|
||||
t1#P#pn.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
tp1.MYD
|
||||
tp1.MYI
|
||||
tp1.frm
|
||||
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 CONVERT PARTITION p1 TO TABLE tp1
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`x` int(11) DEFAULT NULL
|
||||
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
PARTITION BY RANGE (`x`)
|
||||
(PARTITION `p0` VALUES LESS THAN (10) ENGINE = DEFAULT_ENGINE,
|
||||
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = DEFAULT_ENGINE)
|
||||
x
|
||||
2
|
||||
22
|
||||
Table Create Table
|
||||
tp1 CREATE TABLE `tp1` (
|
||||
`x` int(11) DEFAULT NULL
|
||||
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
x
|
||||
12
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'test.t1'
|
||||
|
@ -36,7 +36,7 @@ if ($MTR_COMBINATION_ROW)
|
||||
|
||||
let $MYSQLD_DATADIR= `SELECT @@datadir`;
|
||||
|
||||
let $crash_count= 12;
|
||||
let $crash_count= 14;
|
||||
let $crash_points='crash_create_before_create_frm',
|
||||
'crash_alter_partition_after_create_frm',
|
||||
'crash_alter_partition_after_write_frm',
|
||||
@ -48,10 +48,12 @@ let $crash_points='crash_create_before_create_frm',
|
||||
'crash_convert_partition_6',
|
||||
'crash_convert_partition_7',
|
||||
'crash_convert_partition_8',
|
||||
'crash_convert_partition_9';
|
||||
'crash_convert_partition_9',
|
||||
'crash_convert_partition_10',
|
||||
'crash_convert_partition_11';
|
||||
|
||||
#let $crash_count= 1;
|
||||
#let $crash_points= 'crash_convert_partition_8';
|
||||
#let $crash_points= 'crash_convert_partition_10';
|
||||
|
||||
let $statement_count= 1;
|
||||
let $statements= 'ALTER TABLE t1 CONVERT PARTITION p1 TO TABLE tp1';
|
||||
|
@ -3899,7 +3899,6 @@ UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
set session debug_dbug=@save_dbug;
|
||||
set session debug_dbug="+d,fail_convert_partition_9";
|
||||
# Already finished DDL logging, so tp2 now exists:
|
||||
create or replace table t1 (x int primary key)
|
||||
partition by range(x) (
|
||||
partition p1 values less than (10),
|
||||
@ -3952,6 +3951,183 @@ ERROR HY000: Unknown error
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1#P#p3.MYD
|
||||
t1#P#p3.MYI
|
||||
t1#P#p4.MYD
|
||||
t1#P#p4.MYI
|
||||
t1#P#p5.MYD
|
||||
t1#P#p5.MYI
|
||||
t1#P#pn.MYD
|
||||
t1#P#pn.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`x` int(11) NOT NULL,
|
||||
PRIMARY KEY (`x`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
PARTITION BY RANGE (`x`)
|
||||
(PARTITION `p1` VALUES LESS THAN (10) ENGINE = MyISAM,
|
||||
PARTITION `p2` VALUES LESS THAN (20) ENGINE = MyISAM,
|
||||
PARTITION `p3` VALUES LESS THAN (30) ENGINE = MyISAM,
|
||||
PARTITION `p4` VALUES LESS THAN (40) ENGINE = MyISAM,
|
||||
PARTITION `p5` VALUES LESS THAN (50) ENGINE = MyISAM,
|
||||
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = MyISAM)
|
||||
SELECT * FROM t1;
|
||||
x
|
||||
12
|
||||
2
|
||||
22
|
||||
32
|
||||
42
|
||||
52
|
||||
DROP TABLE t1;
|
||||
create or replace table t1 (x int primary key)
|
||||
partition by range(x) (
|
||||
partition p1 values less than (10),
|
||||
partition p2 values less than (20),
|
||||
partition p3 values less than (30),
|
||||
partition p4 values less than (40),
|
||||
partition p5 values less than (50),
|
||||
partition pn values less than maxvalue);
|
||||
insert into t1 values (2), (12), (22), (32), (42), (52);
|
||||
# d,fail_convert_partition_9: BEFORE failure (under LOCK TABLE)
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1#P#p3.MYD
|
||||
t1#P#p3.MYI
|
||||
t1#P#p4.MYD
|
||||
t1#P#p4.MYI
|
||||
t1#P#p5.MYD
|
||||
t1#P#p5.MYI
|
||||
t1#P#pn.MYD
|
||||
t1#P#pn.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`x` int(11) NOT NULL,
|
||||
PRIMARY KEY (`x`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
PARTITION BY RANGE (`x`)
|
||||
(PARTITION `p1` VALUES LESS THAN (10) ENGINE = MyISAM,
|
||||
PARTITION `p2` VALUES LESS THAN (20) ENGINE = MyISAM,
|
||||
PARTITION `p3` VALUES LESS THAN (30) ENGINE = MyISAM,
|
||||
PARTITION `p4` VALUES LESS THAN (40) ENGINE = MyISAM,
|
||||
PARTITION `p5` VALUES LESS THAN (50) ENGINE = MyISAM,
|
||||
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = MyISAM)
|
||||
SELECT * FROM t1;
|
||||
x
|
||||
12
|
||||
2
|
||||
22
|
||||
32
|
||||
42
|
||||
52
|
||||
LOCK TABLE t1 WRITE;
|
||||
alter table t1 convert partition p2 to table tp2;
|
||||
ERROR HY000: Unknown error
|
||||
# d,fail_convert_partition_9: AFTER failure (under LOCK TABLE)
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1#P#p3.MYD
|
||||
t1#P#p3.MYI
|
||||
t1#P#p4.MYD
|
||||
t1#P#p4.MYI
|
||||
t1#P#p5.MYD
|
||||
t1#P#p5.MYI
|
||||
t1#P#pn.MYD
|
||||
t1#P#pn.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`x` int(11) NOT NULL,
|
||||
PRIMARY KEY (`x`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
PARTITION BY RANGE (`x`)
|
||||
(PARTITION `p1` VALUES LESS THAN (10) ENGINE = MyISAM,
|
||||
PARTITION `p2` VALUES LESS THAN (20) ENGINE = MyISAM,
|
||||
PARTITION `p3` VALUES LESS THAN (30) ENGINE = MyISAM,
|
||||
PARTITION `p4` VALUES LESS THAN (40) ENGINE = MyISAM,
|
||||
PARTITION `p5` VALUES LESS THAN (50) ENGINE = MyISAM,
|
||||
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = MyISAM)
|
||||
SELECT * FROM t1;
|
||||
x
|
||||
12
|
||||
2
|
||||
22
|
||||
32
|
||||
42
|
||||
52
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
set session debug_dbug=@save_dbug;
|
||||
set session debug_dbug="+d,fail_convert_partition_11";
|
||||
# Already finished DDL logging, so tp2 now exists:
|
||||
create or replace table t1 (x int primary key)
|
||||
partition by range(x) (
|
||||
partition p1 values less than (10),
|
||||
partition p2 values less than (20),
|
||||
partition p3 values less than (30),
|
||||
partition p4 values less than (40),
|
||||
partition p5 values less than (50),
|
||||
partition pn values less than maxvalue);
|
||||
insert into t1 values (2), (12), (22), (32), (42), (52);
|
||||
# d,fail_convert_partition_11: BEFORE failure
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1#P#p3.MYD
|
||||
t1#P#p3.MYI
|
||||
t1#P#p4.MYD
|
||||
t1#P#p4.MYI
|
||||
t1#P#p5.MYD
|
||||
t1#P#p5.MYI
|
||||
t1#P#pn.MYD
|
||||
t1#P#pn.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`x` int(11) NOT NULL,
|
||||
PRIMARY KEY (`x`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
PARTITION BY RANGE (`x`)
|
||||
(PARTITION `p1` VALUES LESS THAN (10) ENGINE = MyISAM,
|
||||
PARTITION `p2` VALUES LESS THAN (20) ENGINE = MyISAM,
|
||||
PARTITION `p3` VALUES LESS THAN (30) ENGINE = MyISAM,
|
||||
PARTITION `p4` VALUES LESS THAN (40) ENGINE = MyISAM,
|
||||
PARTITION `p5` VALUES LESS THAN (50) ENGINE = MyISAM,
|
||||
PARTITION `pn` VALUES LESS THAN MAXVALUE ENGINE = MyISAM)
|
||||
SELECT * FROM t1;
|
||||
x
|
||||
12
|
||||
2
|
||||
22
|
||||
32
|
||||
42
|
||||
52
|
||||
alter table t1 convert partition p2 to table tp2;
|
||||
ERROR HY000: Unknown error
|
||||
# d,fail_convert_partition_11: AFTER failure
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
t1#P#p3.MYD
|
||||
t1#P#p3.MYI
|
||||
t1#P#p4.MYD
|
||||
@ -3994,7 +4170,7 @@ partition p4 values less than (40),
|
||||
partition p5 values less than (50),
|
||||
partition pn values less than maxvalue);
|
||||
insert into t1 values (2), (12), (22), (32), (42), (52);
|
||||
# d,fail_convert_partition_9: BEFORE failure (under LOCK TABLE)
|
||||
# d,fail_convert_partition_11: BEFORE failure (under LOCK TABLE)
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
@ -4037,7 +4213,7 @@ x
|
||||
LOCK TABLE t1 WRITE;
|
||||
alter table t1 convert partition p2 to table tp2;
|
||||
ERROR 42S01: Table 'tp2' already exists
|
||||
# d,fail_convert_partition_9: AFTER failure (under LOCK TABLE)
|
||||
# d,fail_convert_partition_11: AFTER failure (under LOCK TABLE)
|
||||
db.opt
|
||||
t1#P#p1.MYD
|
||||
t1#P#p1.MYI
|
||||
|
@ -104,6 +104,9 @@ set session debug_dbug="+d,fail_convert_partition_8";
|
||||
--source suite/parts/inc/partition_fail.inc
|
||||
set session debug_dbug=@save_dbug;
|
||||
set session debug_dbug="+d,fail_convert_partition_9";
|
||||
--source suite/parts/inc/partition_fail.inc
|
||||
set session debug_dbug=@save_dbug;
|
||||
set session debug_dbug="+d,fail_convert_partition_11";
|
||||
--echo # Already finished DDL logging, so tp2 now exists:
|
||||
--source suite/parts/inc/partition_fail.inc
|
||||
set session debug_dbug=@save_dbug;
|
||||
|
@ -77,6 +77,8 @@
|
||||
#define DDL_LOG_MAGIC_LENGTH 4
|
||||
/* How many times to try to execute a ddl log entry that causes crashes */
|
||||
#define DDL_LOG_MAX_RETRY 3
|
||||
#define DDL_LOG_RETRY_MASK 0xFF
|
||||
#define DDL_LOG_RETRY_BITS 8
|
||||
|
||||
uchar ddl_log_file_magic[]=
|
||||
{ (uchar) 254, (uchar) 254, (uchar) 11, (uchar) 2 };
|
||||
@ -155,7 +157,7 @@ mysql_mutex_t LOCK_gdl;
|
||||
#define DDL_LOG_XID_POS 10
|
||||
/* Used to store unique uuid from the .frm file */
|
||||
#define DDL_LOG_UUID_POS 18
|
||||
/* ID_POS can be used to store something unique, like file size (4 bytes) */
|
||||
/* ID_POS can be used to store something unique, like file size (8 bytes) */
|
||||
#define DDL_LOG_ID_POS DDL_LOG_UUID_POS + MY_UUID_SIZE
|
||||
#define DDL_LOG_END_POS DDL_LOG_ID_POS + 8
|
||||
|
||||
@ -2515,6 +2517,7 @@ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry,
|
||||
|
||||
@param first_entry First entry in linked list of entries
|
||||
to execute.
|
||||
@param cond_entry Check and don't execute if cond_entry is active
|
||||
@param[in,out] active_entry Entry to execute, 0 = NULL if the entry
|
||||
is written first time and needs to be
|
||||
returned. In this case the entry written
|
||||
@ -2525,6 +2528,7 @@ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry,
|
||||
*/
|
||||
|
||||
bool ddl_log_write_execute_entry(uint first_entry,
|
||||
uint cond_entry,
|
||||
DDL_LOG_MEMORY_ENTRY **active_entry)
|
||||
{
|
||||
uchar *file_entry_buf= global_ddl_log.file_entry_buf;
|
||||
@ -2541,6 +2545,7 @@ bool ddl_log_write_execute_entry(uint first_entry,
|
||||
|
||||
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (uchar)DDL_LOG_EXECUTE_CODE;
|
||||
int4store(file_entry_buf + DDL_LOG_NEXT_ENTRY_POS, first_entry);
|
||||
int8store(file_entry_buf + DDL_LOG_ID_POS, (cond_entry << DDL_LOG_RETRY_BITS));
|
||||
|
||||
if (!(*active_entry))
|
||||
{
|
||||
@ -2763,13 +2768,13 @@ int ddl_log_execute_recovery()
|
||||
recovery_state.xid= ddl_log_entry.xid;
|
||||
|
||||
/* purecov: begin tested */
|
||||
if (ddl_log_entry.unique_id > DDL_LOG_MAX_RETRY)
|
||||
if ((ddl_log_entry.unique_id & DDL_LOG_RETRY_MASK) > DDL_LOG_MAX_RETRY)
|
||||
{
|
||||
error= -1;
|
||||
continue;
|
||||
}
|
||||
update_unique_id(i, ++ddl_log_entry.unique_id);
|
||||
if (ddl_log_entry.unique_id > DDL_LOG_MAX_RETRY)
|
||||
if ((ddl_log_entry.unique_id & DDL_LOG_RETRY_MASK) > DDL_LOG_MAX_RETRY)
|
||||
{
|
||||
sql_print_error("DDL_LOG: Aborting executing entry %u after %llu "
|
||||
"retries", i, ddl_log_entry.unique_id);
|
||||
@ -2778,6 +2783,15 @@ int ddl_log_execute_recovery()
|
||||
}
|
||||
/* purecov: end tested */
|
||||
|
||||
uint cond_entry= (uint)(ddl_log_entry.unique_id >> DDL_LOG_RETRY_BITS);
|
||||
|
||||
if (cond_entry && is_execute_entry_active(cond_entry))
|
||||
{
|
||||
if (disable_execute_entry(i))
|
||||
error= -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ddl_log_execute_entry_no_lock(thd, ddl_log_entry.next_entry))
|
||||
{
|
||||
/* Real unpleasant scenario but we have to continue anyway */
|
||||
@ -3534,3 +3548,32 @@ err:
|
||||
mysql_mutex_unlock(&LOCK_gdl);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Log an delete frm file
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO: Partitioning atomic DDL refactoring: this should be replaced with
|
||||
ddl_log_create_table().
|
||||
*/
|
||||
bool ddl_log_delete_frm(DDL_LOG_STATE *ddl_state, const char *to_path)
|
||||
{
|
||||
DDL_LOG_ENTRY ddl_log_entry;
|
||||
DDL_LOG_MEMORY_ENTRY *log_entry;
|
||||
DBUG_ENTER("ddl_log_delete_frm");
|
||||
bzero(&ddl_log_entry, sizeof(ddl_log_entry));
|
||||
ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
|
||||
ddl_log_entry.next_entry= ddl_state->list ? ddl_state->list->entry_pos : 0;
|
||||
|
||||
lex_string_set(&ddl_log_entry.handler_name, reg_ext);
|
||||
lex_string_set(&ddl_log_entry.name, to_path);
|
||||
|
||||
mysql_mutex_assert_owner(&LOCK_gdl);
|
||||
if (ddl_log_write_entry(&ddl_log_entry, &log_entry))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
ddl_log_add_entry(ddl_state, log_entry);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -262,8 +262,14 @@ int ddl_log_execute_recovery();
|
||||
bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry,
|
||||
DDL_LOG_MEMORY_ENTRY **active_entry);
|
||||
|
||||
bool ddl_log_write_execute_entry(uint first_entry, uint cond_entry,
|
||||
DDL_LOG_MEMORY_ENTRY** active_entry);
|
||||
inline
|
||||
bool ddl_log_write_execute_entry(uint first_entry,
|
||||
DDL_LOG_MEMORY_ENTRY **active_entry);
|
||||
DDL_LOG_MEMORY_ENTRY **active_entry)
|
||||
{
|
||||
return ddl_log_write_execute_entry(first_entry, 0, active_entry);
|
||||
}
|
||||
bool ddl_log_disable_execute_entry(DDL_LOG_MEMORY_ENTRY **active_entry);
|
||||
|
||||
void ddl_log_complete(DDL_LOG_STATE *ddl_log_state);
|
||||
@ -349,5 +355,6 @@ bool ddl_log_alter_table(THD *thd, DDL_LOG_STATE *ddl_state,
|
||||
bool is_renamed);
|
||||
bool ddl_log_store_query(THD *thd, DDL_LOG_STATE *ddl_log_state,
|
||||
const char *query, size_t length);
|
||||
bool ddl_log_delete_frm(DDL_LOG_STATE *ddl_state, const char *to_path);
|
||||
extern mysql_mutex_t LOCK_gdl;
|
||||
#endif /* DDL_LOG_INCLUDED */
|
||||
|
@ -6225,48 +6225,6 @@ static void release_part_info_log_entries(DDL_LOG_MEMORY_ENTRY *log_entry)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Log an delete frm file
|
||||
SYNOPSIS
|
||||
write_log_delete_frm()
|
||||
lpt Struct for parameters
|
||||
to_path Name to delete
|
||||
RETURN VALUES
|
||||
TRUE Error
|
||||
FALSE Success
|
||||
DESCRIPTION
|
||||
Support routine that writes a delete of an frm file into the
|
||||
ddl log. It also inserts an entry that keeps track of used space into
|
||||
the partition info object
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
TODO: Partitioning atomic DDL refactoring: this should be replaced with
|
||||
ddl_log_create_table().
|
||||
*/
|
||||
static bool write_log_delete_frm(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
const char *to_path)
|
||||
{
|
||||
DDL_LOG_ENTRY ddl_log_entry;
|
||||
DDL_LOG_MEMORY_ENTRY *log_entry;
|
||||
DBUG_ENTER("write_log_delete_frm");
|
||||
bzero(&ddl_log_entry, sizeof(ddl_log_entry));
|
||||
ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
|
||||
ddl_log_entry.next_entry= lpt->part_info->list ? lpt->part_info->list->entry_pos : 0;
|
||||
|
||||
lex_string_set(&ddl_log_entry.handler_name, reg_ext);
|
||||
lex_string_set(&ddl_log_entry.name, to_path);
|
||||
|
||||
if (ddl_log_write_entry(&ddl_log_entry, &log_entry))
|
||||
{
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
ddl_log_add_entry(lpt->part_info, log_entry);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Log an rename frm file
|
||||
SYNOPSIS
|
||||
@ -6541,11 +6499,10 @@ static bool write_log_convert_out_partition(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
DDL_LOG_MEMORY_ENTRY *main_entry= lpt->part_info->main_entry;
|
||||
bool res= log_drop_or_convert_action(lpt, next_entry, path, from_name, false);
|
||||
/*
|
||||
NOTE: main_entry is "drop shadow frm", we have to keep it like this,
|
||||
because partitioning crash-safety disables it at install shadow FRM phase
|
||||
That is not really needed though, because shadow frm is replaced with
|
||||
backup frm so there is nothing to drop. But we avoid spurious action by
|
||||
disabling it.
|
||||
NOTE: main_entry is "drop shadow frm", we have to keep it like this
|
||||
because partitioning crash-safety disables it at install shadow FRM phase.
|
||||
This is needed to avoid spurious drop action when the shadow frm is replaced
|
||||
by the backup frm and there is nothing to drop.
|
||||
*/
|
||||
lpt->part_info->main_entry= main_entry;
|
||||
return res;
|
||||
@ -6556,10 +6513,9 @@ static bool write_log_convert_out_partition(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
Write the log entry to ensure that the shadow frm file is removed at
|
||||
crash.
|
||||
SYNOPSIS
|
||||
write_log_drop_shadow_frm()
|
||||
write_log_drop_frm()
|
||||
lpt Struct containing parameters
|
||||
install_frm Should we log action to install shadow frm or should
|
||||
the action be to remove the shadow frm file.
|
||||
|
||||
RETURN VALUES
|
||||
TRUE Error
|
||||
FALSE Success
|
||||
@ -6568,38 +6524,43 @@ static bool write_log_convert_out_partition(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
file and its corresponding handler file.
|
||||
*/
|
||||
|
||||
static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
uint flags= 0)
|
||||
static bool write_log_drop_frm(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
DDL_LOG_STATE *drop_chain)
|
||||
{
|
||||
partition_info *part_info= lpt->part_info;
|
||||
DDL_LOG_MEMORY_ENTRY *log_entry;
|
||||
char path[FN_REFLEN + 1];
|
||||
DBUG_ENTER("write_log_drop_shadow_frm");
|
||||
const bool drop_backup= (flags & WFRM_DROP_BACKUP);
|
||||
|
||||
DBUG_ASSERT(!drop_backup || !part_info->is_active());
|
||||
DBUG_ENTER("write_log_drop_frm");
|
||||
const DDL_LOG_STATE *main_chain= lpt->part_info;
|
||||
const bool drop_backup= (drop_chain != main_chain);
|
||||
|
||||
build_table_shadow_filename(path, sizeof(path) - 1, lpt, drop_backup);
|
||||
mysql_mutex_lock(&LOCK_gdl);
|
||||
if (write_log_delete_frm(lpt, (const char*)path))
|
||||
if (ddl_log_delete_frm(drop_chain, (const char*)path))
|
||||
goto error;
|
||||
|
||||
log_entry= part_info->list;
|
||||
if (ddl_log_write_execute_entry(log_entry->entry_pos,
|
||||
&part_info->execute_entry))
|
||||
if (ddl_log_write_execute_entry(drop_chain->list->entry_pos,
|
||||
drop_backup ?
|
||||
main_chain->execute_entry->entry_pos : 0,
|
||||
&drop_chain->execute_entry))
|
||||
goto error;
|
||||
mysql_mutex_unlock(&LOCK_gdl);
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
error:
|
||||
release_part_info_log_entries(part_info->list);
|
||||
release_part_info_log_entries(drop_chain->list);
|
||||
mysql_mutex_unlock(&LOCK_gdl);
|
||||
part_info->list= NULL;
|
||||
drop_chain->list= NULL;
|
||||
my_error(ER_DDL_LOG_ERROR, MYF(0));
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
{
|
||||
return write_log_drop_frm(lpt, lpt->part_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Log renaming of shadow frm to real frm name and dropping of old frm
|
||||
SYNOPSIS
|
||||
@ -6910,6 +6871,10 @@ static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||
NONE
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO: Partitioning atomic DDL refactoring: this should be replaced with
|
||||
ddl_log_release_entries().
|
||||
*/
|
||||
static void release_log_entries(partition_info *part_info)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_gdl);
|
||||
@ -7414,6 +7379,9 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
||||
}
|
||||
else if (alter_info->partition_flags & ALTER_PARTITION_CONVERT_OUT)
|
||||
{
|
||||
DDL_LOG_STATE chain_drop_backup;
|
||||
bzero(&chain_drop_backup, sizeof(chain_drop_backup));
|
||||
|
||||
if (mysql_write_frm(lpt, WFRM_WRITE_CONVERTED_TO) ||
|
||||
ERROR_INJECT("convert_partition_1") ||
|
||||
write_log_drop_shadow_frm(lpt) ||
|
||||
@ -7428,40 +7396,27 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
||||
ERROR_INJECT("convert_partition_6") ||
|
||||
alter_partition_convert_out(lpt) ||
|
||||
ERROR_INJECT("convert_partition_7") ||
|
||||
(frm_install= true, false) ||
|
||||
write_log_drop_frm(lpt, &chain_drop_backup) ||
|
||||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) ||
|
||||
log_partition_alter_to_ddl_log(lpt) ||
|
||||
(frm_install= false, false) ||
|
||||
ERROR_INJECT("convert_partition_8") ||
|
||||
((!thd->lex->no_write_to_binlog) &&
|
||||
((thd->binlog_xid= thd->query_id),
|
||||
ddl_log_update_xid(lpt->part_info, thd->binlog_xid),
|
||||
write_bin_log(thd, false, thd->query(), thd->query_length()),
|
||||
(thd->binlog_xid= 0))) ||
|
||||
(ddl_log_complete(lpt->part_info), false) ||
|
||||
/*
|
||||
TODO:
|
||||
|
||||
1. Add DDL_LOG_EXECUTE_IF_CLOSED to ddl_log_entry_code.
|
||||
Execute entry is executed only if another entry is active.
|
||||
This requires ddl log file extension or store entry_pos into some
|
||||
string field of execute entry: name, tmp_name, etc. These are
|
||||
not used now for execute entry.
|
||||
2. Log WFRM_DROP_BACKUP into separate "cleanup" chain and execute it
|
||||
only if the main chain is closed. That must be logged before
|
||||
WFRM_BACKUP_ORIGINAL is done.
|
||||
|
||||
*/
|
||||
write_log_drop_shadow_frm(lpt, WFRM_DROP_BACKUP) ||
|
||||
ERROR_INJECT("convert_partition_9"))
|
||||
{
|
||||
ddl_log_complete(&chain_drop_backup);
|
||||
(void) ddl_log_revert(thd, lpt->part_info);
|
||||
handle_alter_part_error(lpt, true, true, frm_install);
|
||||
handle_alter_part_error(lpt, true, true, false);
|
||||
goto err;
|
||||
}
|
||||
/* Drop backup frm */
|
||||
(void) ddl_log_revert(thd, lpt->part_info);
|
||||
if (alter_partition_lock_handling(lpt))
|
||||
ddl_log_complete(lpt->part_info);
|
||||
ERROR_INJECT("convert_partition_10");
|
||||
(void) ddl_log_revert(thd, &chain_drop_backup);
|
||||
if (alter_partition_lock_handling(lpt) ||
|
||||
ERROR_INJECT("convert_partition_11"))
|
||||
goto err;
|
||||
}
|
||||
else if ((alter_info->partition_flags & ALTER_PARTITION_ADD) &&
|
||||
|
@ -59,7 +59,6 @@ enum enum_explain_filename_mode
|
||||
#define WFRM_KEEP_SHARE 4
|
||||
#define WFRM_WRITE_CONVERTED_TO 8
|
||||
#define WFRM_BACKUP_ORIGINAL 16
|
||||
#define WFRM_DROP_BACKUP 32
|
||||
|
||||
/* Flags for conversion functions. */
|
||||
static const uint FN_FROM_IS_TMP= 1 << 0;
|
||||
|
Reference in New Issue
Block a user