From 7890388d9145ab5000e945b7a518caffd1fc197e Mon Sep 17 00:00:00 2001 From: Anson Chung Date: Mon, 18 Mar 2024 20:45:45 +0000 Subject: [PATCH] MDEV-33044 Loading time zones does not work with alter_algorithm INPLACE $MYSQL_TZINFO_TO_SQL works by truncating tables. Truncation is an operation that cannot be done in-place and therefore is fundamentally incompatible with alter_algorithm='INPLACE'. As a result, we override the default alter_algorithm setting in tztime.cc to alter_algorithm='COPY' so that timezones can be loaded regardless of the previously set alter_algorithm. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc. --- ...ezones_with_alter_algorithm_inplace.result | 18 +++++++++ ...imezones_with_alter_algorithm_inplace.test | 38 +++++++++++++++++++ .../main/mysql_tzinfo_to_sql_symlink.result | 18 +++++++++ sql/tztime.cc | 5 +++ 4 files changed, 79 insertions(+) create mode 100644 mysql-test/main/load_timezones_with_alter_algorithm_inplace.result create mode 100644 mysql-test/main/load_timezones_with_alter_algorithm_inplace.test diff --git a/mysql-test/main/load_timezones_with_alter_algorithm_inplace.result b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.result new file mode 100644 index 00000000000..4992e7ed93b --- /dev/null +++ b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.result @@ -0,0 +1,18 @@ +set global alter_algorithm=INPLACE; +RENAME TABLE mysql.time_zone TO mysql.time_zone_BACKUP; +RENAME TABLE mysql.time_zone_name TO mysql.time_zone_name_BACKUP; +RENAME TABLE mysql.time_zone_transition TO mysql.time_zone_transition_BACKUP; +RENAME TABLE mysql.time_zone_transition_type TO mysql.time_zone_transition_type_BACKUP; +CREATE TABLE mysql.time_zone LIKE mysql.time_zone_BACKUP; +CREATE TABLE mysql.time_zone_name LIKE mysql.time_zone_name_BACKUP; +CREATE TABLE mysql.time_zone_transition LIKE mysql.time_zone_transition_BACKUP; +CREATE TABLE mysql.time_zone_transition_type LIKE mysql.time_zone_transition_type_BACKUP; +DROP TABLE mysql.time_zone; +DROP TABLE mysql.time_zone_name; +DROP TABLE mysql.time_zone_transition; +DROP TABLE mysql.time_zone_transition_type; +RENAME TABLE mysql.time_zone_BACKUP TO mysql.time_zone; +RENAME TABLE mysql.time_zone_name_BACKUP TO mysql.time_zone_name; +RENAME TABLE mysql.time_zone_transition_BACKUP TO mysql.time_zone_transition; +RENAME TABLE mysql.time_zone_transition_type_BACKUP TO mysql.time_zone_transition_type; +set global alter_algorithm=DEFAULT; diff --git a/mysql-test/main/load_timezones_with_alter_algorithm_inplace.test b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.test new file mode 100644 index 00000000000..e840ae94a74 --- /dev/null +++ b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.test @@ -0,0 +1,38 @@ +# MDEV-33044 Loading time zones does not work with alter_algorithm INPLACE + +set global alter_algorithm=INPLACE; + +# Because loading timezones alters the mysql tables, +# this test will leave mysql in a different state than when it started. +# Furthermore, checksums on the various mysql.timezone_x tables will fail. + +# Therefore we: +# 1. Make "backups" of the existing tables by renaming them +# 2. Make dummy clones of the tables we just backed up +# 3. Load timezones with alterations made to the dummy clone tables +# 4. Drop the newly made tables with changes made to them +# 5. Restore the backed up tables so the checksums will pass + +RENAME TABLE mysql.time_zone TO mysql.time_zone_BACKUP; +RENAME TABLE mysql.time_zone_name TO mysql.time_zone_name_BACKUP; +RENAME TABLE mysql.time_zone_transition TO mysql.time_zone_transition_BACKUP; +RENAME TABLE mysql.time_zone_transition_type TO mysql.time_zone_transition_type_BACKUP; + +CREATE TABLE mysql.time_zone LIKE mysql.time_zone_BACKUP; +CREATE TABLE mysql.time_zone_name LIKE mysql.time_zone_name_BACKUP; +CREATE TABLE mysql.time_zone_transition LIKE mysql.time_zone_transition_BACKUP; +CREATE TABLE mysql.time_zone_transition_type LIKE mysql.time_zone_transition_type_BACKUP; + +--exec $MYSQL_TZINFO_TO_SQL std_data/zoneinfo | $MYSQL mysql + +DROP TABLE mysql.time_zone; +DROP TABLE mysql.time_zone_name; +DROP TABLE mysql.time_zone_transition; +DROP TABLE mysql.time_zone_transition_type; + +RENAME TABLE mysql.time_zone_BACKUP TO mysql.time_zone; +RENAME TABLE mysql.time_zone_name_BACKUP TO mysql.time_zone_name; +RENAME TABLE mysql.time_zone_transition_BACKUP TO mysql.time_zone_transition; +RENAME TABLE mysql.time_zone_transition_type_BACKUP TO mysql.time_zone_transition_type; + +set global alter_algorithm=DEFAULT; \ No newline at end of file diff --git a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result index a9ada2d6fdb..ea1a09f66d6 100644 --- a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result @@ -20,12 +20,16 @@ ALTER TABLE time_zone ENGINE=InnoDB; ALTER TABLE time_zone_name ENGINE=InnoDB; ALTER TABLE time_zone_transition ENGINE=InnoDB; ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; START TRANSACTION; ELSE +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -62,6 +66,7 @@ ALTER TABLE time_zone_transition ENGINE=Aria, ORDER BY Time_zone_id, Transition_ ALTER TABLE time_zone_transition_type ENGINE=Aria, ORDER BY Time_zone_id, Transition_type_id; END IF| \d ; +SET session alter_algorithm=@old_alter_alg; SELECT COUNT(*) FROM time_zone; COUNT(*) 0 @@ -85,12 +90,16 @@ ALTER TABLE time_zone ENGINE=InnoDB; ALTER TABLE time_zone_name ENGINE=InnoDB; ALTER TABLE time_zone_transition ENGINE=InnoDB; ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; START TRANSACTION; ELSE +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -124,6 +133,7 @@ ALTER TABLE time_zone_transition ENGINE=Aria, ORDER BY Time_zone_id, Transition_ ALTER TABLE time_zone_transition_type ENGINE=Aria, ORDER BY Time_zone_id, Transition_type_id; END IF| \d ; +SET session alter_algorithm=@old_alter_alg; SELECT COUNT(*) FROM time_zone; COUNT(*) 2 @@ -145,6 +155,8 @@ COUNT(*) set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION WSREP_ON=OFF', 'do 0'); SET SESSION SQL_LOG_BIN=0; execute immediate @prep1; +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -172,6 +184,7 @@ UNLOCK TABLES; COMMIT; ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; +SET session alter_algorithm=@old_alter_alg; SELECT COUNT(*) FROM time_zone; COUNT(*) 2 @@ -432,12 +445,16 @@ ALTER TABLE time_zone ENGINE=InnoDB; ALTER TABLE time_zone_name ENGINE=InnoDB; ALTER TABLE time_zone_transition ENGINE=InnoDB; ALTER TABLE time_zone_transition_type ENGINE=InnoDB; +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; TRUNCATE TABLE time_zone_transition_type; START TRANSACTION; ELSE +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -457,6 +474,7 @@ ALTER TABLE time_zone_transition ENGINE=Aria, ORDER BY Time_zone_id, Transition_ ALTER TABLE time_zone_transition_type ENGINE=Aria, ORDER BY Time_zone_id, Transition_type_id; END IF| \d ; +SET session alter_algorithm=@old_alter_alg; DROP TABLE time_zone; DROP TABLE time_zone_name; DROP TABLE time_zone_transition; diff --git a/sql/tztime.cc b/sql/tztime.cc index 45a11942966..1480de96333 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2718,6 +2718,8 @@ static const char *lock_tables= " time_zone_transition WRITE,\n" " time_zone_transition_type WRITE;\n"; static const char *trunc_tables_const= + "SET @old_alter_alg=@@SESSION.alter_algorithm;\n" + "SET session alter_algorithm='COPY';\n" "TRUNCATE TABLE time_zone;\n" "TRUNCATE TABLE time_zone_name;\n" "TRUNCATE TABLE time_zone_transition;\n" @@ -2833,6 +2835,9 @@ main(int argc, char **argv) "END IF|\n" "\\d ;\n"); + if (argc == 1 && !opt_leap) + printf("SET session alter_algorithm=@old_alter_alg;\n"); + free_allocated_data(); my_end(0); return 0;