1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

WL 2826: First step in error handling of ALTER TABLE for partitioning

This commit is contained in:
mikron@c-4d08e253.1238-1-64736c10.cust.bredbandsbolaget.se
2006-02-01 10:06:07 +01:00
parent 86a15e5e86
commit 08e12cada9
15 changed files with 307 additions and 138 deletions

View File

@ -5244,7 +5244,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
1) Write the new frm, pack it and then delete it
2) Perform the change within the handler
*/
if ((mysql_write_frm(lpt, WFRM_INITIAL_WRITE | WFRM_PACK_FRM)) ||
if ((mysql_write_frm(lpt, WFRM_WRITE_SHADOW | WFRM_PACK_FRM)) ||
(mysql_change_partitions(lpt)))
{
fast_alter_partition_error_handler(lpt);
@ -5275,29 +5275,56 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
after a DROP PARTITION) if one ensured that failed accesses to the
dropped partitions was aborted for sure (thus only possible for
transactional engines).
1) Lock the table in TL_WRITE_ONLY to ensure all other accesses to
0) Write an entry that removes the shadow frm file if crash occurs
1) Write the new frm file as a shadow frm
2) Write the table log to ensure that the operation is completed
even in the presence of a MySQL Server crash
3) Lock the table in TL_WRITE_ONLY to ensure all other accesses to
the table have completed
2) Write the new frm file where the partitions have changed but are
still remaining with the state PART_TO_BE_DROPPED
3) Write the bin log
4) Prepare MyISAM handlers for drop of partitions
5) Ensure that any users that has opened the table but not yet
4) Write the bin log
Unfortunately the writing of the binlog is not synchronised with
other logging activities. So no matter in which order the binlog
is written compared to other activities there will always be cases
where crashes make strange things occur. In this placement it can
happen that the ALTER TABLE DROP PARTITION gets performed in the
master but not in the slaves if we have a crash, after writing the
table log but before writing the binlog. A solution to this would
require writing the statement first in the table log and then
when recovering from the crash read the binlog and insert it into
the binlog if not written already.
5) Install the previously written shadow frm file
6) Ensure that any users that has opened the table but not yet
reached the abort lock do that before downgrading the lock.
6) Drop the partitions
7) Write the frm file that the partition has been dropped
8) Wait until all accesses using the old frm file has completed
9) Complete query
7) Prepare MyISAM handlers for drop of partitions
8) Drop the partitions
9) Remove entries from table log
10) Wait until all accesses using the old frm file has completed
11) Complete query
We insert Error injections at all places where it could be interesting
to test if recovery is properly done.
*/
if ((abort_and_upgrade_lock(lpt)) ||
(mysql_write_frm(lpt, WFRM_INITIAL_WRITE)) ||
if (write_log_shadow_frm(lpt) ||
ERROR_INJECTOR_CRASH(1000) ||
mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
ERROR_INJECTOR_CRASH(1001) ||
write_log_drop_partition(lpt) ||
ERROR_INJECTOR_CRASH(1002) ||
abort_and_upgrade_lock(lpt) ||
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
thd->query, thd->query_length), FALSE)) ||
(table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE)) ||
write_bin_log(thd, FALSE,
thd->query, thd->query_length), FALSE) ||
ERROR_INJECTOR_CRASH(1003) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
(close_open_tables_and_downgrade(lpt), FALSE) ||
(mysql_drop_partitions(lpt)) ||
(mysql_write_frm(lpt, WFRM_CREATE_HANDLER_FILES)) ||
ERROR_INJECTOR_CRASH(1004) ||
table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE) ||
ERROR_INJECTOR_CRASH(1005) ||
mysql_drop_partitions(lpt) ||
ERROR_INJECTOR_CRASH(1006) ||
write_log_completed(lpt) ||
ERROR_INJECTOR_CRASH(1007) ||
(mysql_wait_completed_table(lpt, table), FALSE))
{
fast_alter_partition_error_handler(lpt);
@ -5317,26 +5344,38 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
miss updates made by a transaction serialised before it that are
inserted into the new partition.
1) Write the new frm file where state of added partitions is
changed to PART_TO_BE_ADDED
0) Write an entry that removes the shadow frm file if crash occurs
1) Write the new frm file as a shadow frm file
2) Log the changes to happen in table log
2) Add the new partitions
3) Lock all partitions in TL_WRITE_ONLY to ensure that no users
are still using the old partitioning scheme. Wait until all
ongoing users have completed before progressing.
4) Write a new frm file of the table where the partitions are added
to the table.
5) Write binlog
4) Write binlog
5) Install the new frm file of the table where the partitions are
added to the table.
6) Wait until all accesses using the old frm file has completed
7) Complete query
7) Remove entries from table log
8) Complete query
*/
if ((mysql_write_frm(lpt, WFRM_INITIAL_WRITE)) ||
(mysql_change_partitions(lpt)) ||
(abort_and_upgrade_lock(lpt)) ||
(mysql_write_frm(lpt, WFRM_CREATE_HANDLER_FILES)) ||
if (write_log_shadow_frm(lpt) ||
ERROR_INJECTED_CRASH(1010) ||
mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
ERROR_INJECTED_CRASH(1011) ||
write_log_add_partition(lpt) ||
ERROR_INJECTED_CRASH(1012) ||
mysql_change_partitions(lpt) ||
ERROR_INJECTED_CRASH(1013) ||
abort_and_upgrade_lock(lpt) ||
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
thd->query, thd->query_length), FALSE)) ||
(close_open_tables_and_downgrade(lpt), FALSE))
ERROR_INJECTED_CRASH(1014) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
ERROR_INJECTED_CRASH(1015) ||
(close_open_tables_and_downgrade(lpt), FALSE) ||
write_log_completed(lpt) ||
ERROR_INJECTED_CRASH(1016))
{
fast_alter_partition_error_handler(lpt);
DBUG_RETURN(TRUE);
@ -5375,40 +5414,56 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
use a lower lock level. This can be handled inside store_lock in the
respective handler.
1) Write the new frm file where state of added partitions is
changed to PART_TO_BE_ADDED and the reorganised partitions
are set in state PART_TO_BE_REORGED.
2) Add the new partitions
0) Write an entry that removes the shadow frm file if crash occurs
1) Write the shadow frm file of new partitioning
2) Log such that temporary partitions added in change phase are
removed in a crash situation
3) Add the new partitions
Copy from the reorganised partitions to the new partitions
3) Lock all partitions in TL_WRITE_ONLY to ensure that no users
4) Log that operation is completed and log all complete actions
needed to complete operation from here
5) Lock all partitions in TL_WRITE_ONLY to ensure that no users
are still using the old partitioning scheme. Wait until all
ongoing users have completed before progressing.
4) Prepare MyISAM handlers for rename and delete of partitions
5) Write a new frm file of the table where the partitions are
reorganised.
6) Rename the reorged partitions such that they are no longer
6) Prepare MyISAM handlers for rename and delete of partitions
7) Rename the reorged partitions such that they are no longer
used and rename those added to their real new names.
7) Write bin log
8) Wait until all accesses using the old frm file has completed
9) Drop the reorganised partitions
10)Write a new frm file of the table where the partitions are
reorganised.
11)Wait until all accesses using the old frm file has completed
12)Complete query
8) Write bin log
9) Install the shadow frm file
10) Wait until all accesses using the old frm file has completed
11) Drop the reorganised partitions
12) Remove log entry
13)Wait until all accesses using the old frm file has completed
14)Complete query
*/
if ((mysql_write_frm(lpt, WFRM_INITIAL_WRITE)) ||
(mysql_change_partitions(lpt)) ||
(abort_and_upgrade_lock(lpt)) ||
(mysql_write_frm(lpt, WFRM_CREATE_HANDLER_FILES)) ||
(table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE)) ||
(mysql_rename_partitions(lpt)) ||
if (write_log_shadow_frm(lpt) ||
ERROR_INJECT_CRASH(1020) ||
mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
ERROR_INJECT_CRASH(1021) ||
write_log_ph1_change_partition(lpt) ||
ERROR_INJECT_CRASH(1022) ||
mysql_change_partitions(lpt) ||
ERROR_INJECT_CRASH(1023) ||
write_log_ph2_change_partition(lpt) ||
ERROR_INJECT_CRASH(1024) ||
abort_and_upgrade_lock(lpt) ||
table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE) ||
ERROR_INJECT_CRASH(1025) ||
mysql_rename_partitions(lpt) ||
ERROR_INJECT_CRASH(1026) ||
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
thd->query, thd->query_length), FALSE)) ||
ERROR_INJECT_CRASH(1027) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
ERROR_INJECT_CRASH(1028) ||
(close_open_tables_and_downgrade(lpt), FALSE) ||
(mysql_drop_partitions(lpt)) ||
(mysql_write_frm(lpt, 0UL)) ||
ERROR_INJECT_CRASH(1029) ||
mysql_drop_partitions(lpt) ||
ERROR_INJECT_CRASH(1030) ||
write_log_completed(lpt) ||
ERROR_INJECT_CRASH(1031) ||
(mysql_wait_completed_table(lpt, table), FALSE))
{
fast_alter_partition_error_handler(lpt);