[MDEV-18778] mysql_tzinfo_to_sql does not work correctly in MariaDB Galera Created: 2019-03-01  Updated: 2023-04-18  Resolved: 2019-08-16

Status: Closed
Project: MariaDB Server
Component/s: Configuration, Data Manipulation - Insert, Galera, Replication, Scripts & Clients
Affects Version/s: 10.4.3, 10.1.38, 10.2.22, 10.3.13, 10.0.38-galera
Fix Version/s: 10.2.27, 10.1.42, 10.3.18, 10.4.8

Type: Bug Priority: Critical
Reporter: Juan Assignee: Jan Lindström (Inactive)
Resolution: Fixed Votes: 1
Labels: None
Environment:

CentOS 7.5


Issue Links:
Duplicate
is duplicated by MDEV-10439 mysql_tzinfo_to_sql DDL clears other ... Closed
Problem/Incident
causes MDEV-21208 mysql_tzinfo_to_sql does not work in ... Closed
causes MDEV-21209 mysql_tzinfo_to_sql's Galera checks d... Closed
causes MDEV-28263 mariadb-tzinfo-to-sql binlog, embedde... Closed
Relates
relates to MDEV-20046 mysql_tzinfo_to_sql still sets wsrep_... Closed
relates to MDEV-20051 Add new mode to wsrep_OSU_method in w... Closed
relates to MDEV-23440 mysql_tzinfo_to_sql under innodb is slow Closed
relates to MDEV-24946 Implement wsrep_replicate_aria Closed
relates to MDEV-23326 aria TRANSACTIONAL=1 significantly sl... Closed
relates to MDEV-30854 mariadb-tzinfo-to-sql creates sql_mod... Closed

 Description   

mysql_tz_info_to_sql fails to replicate data correctly to other nodes in MariaDB Galera cluster environments, causing time_zone data inconsistencies.

For example

10.1.38 Node 1:

~# for i in $( mysql -ABNe "show tables like 'time_%'" mysql); do echo -n "$i: "; mysql -ABNe "select count(*) from mysql.$i;";  done
time_zone: 0
time_zone_leap_second: 0
time_zone_name: 0
time_zone_transition: 0
time_zone_transition_type: 0
 
~# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
 
~# for i in $( mysql -ABNe "show tables like 'time_%'" mysql); do echo -n "$i: "; mysql -ABNe "select count(*) from mysql.$i;";  done
time_zone: 1777
time_zone_leap_second: 0
time_zone_name: 1777
time_zone_transition: 118417
time_zone_transition_type: 8527

Result in 10.1.38 Node 2 after running mysql_tzinfo_to_sql on Node 1:

~# for i in $( mysql -ABNe "show tables like 'time_%'" mysql); do echo -n "$i: "; mysql -ABNe "select count(*) from  count(*) from mysql.$i;";  done
time_zone: 1777
time_zone_leap_second: 0
time_zone_name: 0
time_zone_transition: 3663
time_zone_transition_type: 2

10.4.3 Node 1:

~# for i in $( mysql -ABNe "show tables like 'time_%'" mysql); do echo -n "$i: "; mysql -ABNe "select count(*) from mysql.$i;";  done
time_zone: 0
time_zone_leap_second: 0
time_zone_name: 0
time_zone_transition: 0
time_zone_transition_type: 0
 
~# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
 
~# for i in $( mysql -ABNe "show tables like 'time_%'" mysql); do echo -n "$i: "; mysql -ABNe "select count(*) from mysql.$i;";  done
time_zone: 1777
time_zone_leap_second: 0
time_zone_name: 1777
time_zone_transition: 118417
time_zone_transition_type: 8527

Result in 10.4.3 Node 2 after running mysql_tzinfo_to_sql on Node 1:

~# for i in $( mysql -ABNe "show tables like 'time_%'" mysql); do echo -n "$i: "; mysql -ABNe "select count(*) from mysql.$i;";  done
time_zone: 0
time_zone_leap_second: 0
time_zone_name: 0
time_zone_transition: 0
time_zone_transition_type: 0

  • the script works correctly on Percona XtraDB Cluster 5.7.24 with Galera version 31.33. Percona, like MySQL, uses InnoDB storage engine for these tables as of 5.7

Notes:

1. mysql_tzinfo_to_sql relies on wsrep_replicate_myisam, which is turned on for the population of these tables and restored at the end of the operation to it's original state. This means any user relying on distinct un-replicated MyISAM tables in different nodes may encounter problems resulting from unintentionally propagating updates while mysql_tzinfo_to_sql runs^(support issue 26586)^. Additionally, our own documentation states that wsrep_replicate_myisam is experimental. QED

2. mysql_tzinfo_to_sql begins by truncating the tables. TRUNCATE TABLE is propagated to other nodes for MyISAM tables regardless of the state of wsrep_replicate_myisam. Because of this oddity, running mysql_tzinfo_to_sql on each node separately is not a workaround, since every time the script is run it successfully truncates all mysql.time_zone_% tables on all other nodes and then populates only one node correctly.

3. tested 10.0 10.1 10.2 and 10.3 versions all managed to populate the time_zone table correctly on all nodes (the only table in the set that has an int primary key). 10.0 also managed to replicate about 2% of the time_zone_transition table and 2 rows of the time_zone_transition_type table to other nodes. 10.4, however, in which Aria rather than MyISAM is used for time_zone tables, propagates none of the information to other nodes.

4. Converting all time_zone tables to InnoDB before running the utility works correctly in all tested versions. Starting with MariaDB 10.2 an additional error message is displayed at the end of the script:

ERROR 1105 (HY000) at line 139025: ORDER BY ignored as there is a user-defined clustered index in the table 'time_zone_transition'

This is caused by two ALTER TABLE ORDER BY statements issued at the end of the script, which have no adverse effect on the InnoDB tables.

All affected functions: NOW(), CURTIME(), and UNIX_TIMESTAMP() work correctly when the time_zone tables are converted to InnoDB, altering their output according to the current value in @@time_zone.



 Comments   
Comment by Geoff Montee (Inactive) [ 2019-03-01 ]

Converting all time_zone tables to InnoDB before running the utility works correctly in all tested versions.

I think we should convert these time zone tables to InnoDB like MySQL did in 5.7:

https://github.com/mysql/mysql-server/blob/fdbdce701ab8145ae234c9d401109dff4e4106cb/scripts/mysql_system_tables.sql#L63

It looks like we have already converted these tables to Aria in 10.4:

https://github.com/MariaDB/server/blob/4abb8216a054e14afbeb81e8529e02bab6fa14ac/scripts/mysql_system_tables.sql#L122

So if the table is Aria in 10.4, then even the "experimental" wsrep_replicate_myisam option wouldn't allow the table to replicate in Galera. Using InnoDB instead seems better, in my opinion.

Comment by Juan [ 2019-03-02 ]

A concrete example of the implications of the problem:

Node 1:

MariaDB [test]> show variables like 'time_zone';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| time_zone     | SYSTEM |
+---------------+--------+
1 row in set (0.001 sec)
 
MariaDB [test]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-03-01 18:49:17 |
+---------------------+
1 row in set (0.000 sec)
 
MariaDB [test]> set time_zone='Japan';
Query OK, 0 rows affected (0.000 sec)
 
MariaDB [test]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-03-02 08:49:17 |
+---------------------+
1 row in set (0.000 sec)

Node 2 (All tested versions):

MariaDB [test]> show global variables like 'time_zone';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| time_zone     | SYSTEM |
+---------------+--------+
1 row in set (0.001 sec)
 
MariaDB [test]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-03-01 18:50:34 |
+---------------------+
1 row in set (0.000 sec)
 
MariaDB [test]> set time_zone='Japan';
ERROR 1298 (HY000): Unknown or incorrect time zone: 'Japan'
MariaDB [test]> show variables like 'time_zone';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| time_zone     | SYSTEM |
+---------------+--------+
1 row in set (0.001 sec)
 
MariaDB [test]> select now();
+---------------------+
| now()               |
+---------------------+
| 2019-03-01 18:50:34 |
+---------------------+
1 row in set (0.000 sec)

Comment by Jan Lindström (Inactive) [ 2019-07-11 ]

First observation is that on 10.1-10.3 wsrep_replicate_myisam is set true on tztime.cc i.e. mysql_tz_info_to_sql will use it causing TRUNCATE TABLE to replicate all nodes.

Comment by Geoff Montee (Inactive) [ 2019-07-11 ]

If we don't want to convert the tables to InnoDB for all users, then some other ideas that I had were:

1.) Tell Galera users to manually convert these tables to InnoDB, and then make the script throw an error if it detects that "SELECT @@global.wsrep_on" returns ON, and if the time zone tables use a storage engine that is not InnoDB.

2.) Add an option to the script with a name like --galera. If this option is enabled, then the script could set wsrep_osu_method=TOI, and then convert all time zone tables to InnoDB before it loads them.

3.) Add an option to the script with a name like --skip-write-binlog, similar to the one mysql_upgrade has. If this option is enabled, then it would execute "SET SQL_LOG_BIN=0, WSREP_ON=OFF;" before it loads the tables. If we take this approach, then the script would have to be
run separately on each Galera node. Here's the relevant mysql_upgrade check:

https://github.com/MariaDB/server/blob/mariadb-10.4.6/client/mysql_upgrade.c#L535

Comment by Geoff Montee (Inactive) [ 2019-07-11 ]

2. mysql_tzinfo_to_sql begins by truncating the tables. TRUNCATE TABLE is propagated to other nodes for MyISAM tables regardless of the state of wsrep_replicate_myisam. Because of this oddity, running mysql_tzinfo_to_sql on each node separately is not a workaround, since every time the script is run it successfully truncates all mysql.time_zone_% tables on all other nodes and then populates only one node correctly.

I have confirmed that Galera replicates TRUNCATE TABLE statements in TOI mode for non-InnoDB tables by performing a test with Aria. These tables use the Aria storage engine in MariaDB 10.4, so MariaDB 10.4 will also be effected by this.

I performed the following test with a 3-node cluster running MariaDB 10.3.16:

Node 1:
 
SET SESSION wsrep_OSU_method='TOI';
USE db1;
CREATE TABLE aria_tab (id int primary key) ENGINE=Aria;
INSERT INTO aria_tab VALUES (1);
SELECT * FROM aria_tab;
 
Node 2:
 
USE db1;
SELECT * FROM aria_tab;
INSERT INTO aria_tab VALUES (2);
SELECT * FROM aria_tab;
 
Node 3:
 
USE db1;
SELECT * FROM aria_tab;
INSERT INTO aria_tab VALUES (3);
SELECT * FROM aria_tab;
 
Node 1:
 
SELECT * FROM aria_tab;
TRUNCATE TABLE aria_tab;
SELECT * FROM aria_tab;
 
 
Node 2:
 
 
SELECT * FROM aria_tab;
 
 
Node 3:
 
 
SELECT * FROM aria_tab;

First, the output of the CREATE and INSERT portion:

Node 1:
 
 
MariaDB [(none)]> SET SESSION wsrep_OSU_method='TOI';
Query OK, 0 rows affected (0.000 sec)
 
MariaDB [(none)]> USE db1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
MariaDB [db1]> CREATE TABLE aria_tab (id int primary key) ENGINE=Aria;
Query OK, 0 rows affected (0.010 sec)
 
MariaDB [db1]> INSERT INTO aria_tab VALUES (1);
Query OK, 1 row affected (0.001 sec)
 
MariaDB [db1]> SELECT * FROM aria_tab;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.000 sec)
 
 
Node 2:
 
 
MariaDB [(none)]> USE db1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
MariaDB [db1]> SELECT * FROM aria_tab;
Empty set (0.000 sec)
 
MariaDB [db1]> INSERT INTO aria_tab VALUES (2);
Query OK, 1 row affected (0.001 sec)
 
MariaDB [db1]> SELECT * FROM aria_tab;
+----+
| id |
+----+
|  2 |
+----+
1 row in set (0.000 sec)
 
 
Node 3:
 
 
MariaDB [(none)]> USE db1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
MariaDB [db1]> SELECT * FROM aria_tab;
Empty set (0.000 sec)
 
MariaDB [db1]> INSERT INTO aria_tab VALUES (3);
Query OK, 1 row affected (0.001 sec)
 
MariaDB [db1]> SELECT * FROM aria_tab;
+----+
| id |
+----+
|  3 |
+----+
1 row in set (0.000 sec)

The CREATE was replicated, but the INSERTs were not.

Next, the output of the TRUNCATE portion:

Node 1:
 
 
MariaDB [db1]> SELECT * FROM aria_tab;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.000 sec)
 
MariaDB [db1]> TRUNCATE TABLE aria_tab;
Query OK, 0 rows affected (0.010 sec)
 
MariaDB [db1]> SELECT * FROM aria_tab;
Empty set (0.000 sec)
 
 
Node 2:
 
 
MariaDB [db1]> SELECT * FROM aria_tab;
Empty set (0.000 sec)
 
 
Node 3:
 
 
MariaDB [db1]> SELECT * FROM aria_tab;
Empty set (0.000 sec)

We can see that the TRUNCATE was also replicated.

Comment by Jan Lindström (Inactive) [ 2019-07-11 ]

https://github.com/MariaDB/server/commit/4a21c866a84499e6920050027a590cc3f30733d3

Comment by Sergei Golubchik [ 2019-07-21 ]

Is ALTER TABLE replicated? If yes, an option could be to ALTER timezone tables to InnoDB, load then, ALTER back (only when wsrep_on is set)

Comment by Geoff Montee (Inactive) [ 2019-07-21 ]

Yeah, ALTER TABLE is replicated as long as wsrep_OSU_method is set to TOI, which is the default.

Comment by Sergei Golubchik [ 2019-07-24 ]

jplindst, so what do you think about ALTER TABLE approach?

Comment by Jan Lindström (Inactive) [ 2019-08-12 ]

serg There is two problems currently:

  • User wants same time zone info on all nodes in a cluster. Here Alter table approach will help.
  • User wants different time zone info on every node in a cluster. Here alter table would make thing worse and instead we should disable all Galera replication.
Comment by Sergei Golubchik [ 2019-08-12 ]

So, the fix could be something like a new option to mysql_tzinfo_to_sql. Basically, like you did, to disable binlogging — to cover your second use case. And by default (where users expect it to "just work") it should use ALTER trick. Right?

Comment by Jan Lindström (Inactive) [ 2019-08-12 ]

Right

Comment by Jan Lindström (Inactive) [ 2019-08-20 ]

greenman Can you update the documentation based on below (no need to repeat why it was broken)

(1) If user wanted same time zone information on all nodes in the Galera
cluster all updates were not replicated as time zone information was
stored on MyISAM tables. This is fixed on Galera by altering time zone
tables to InnoDB while they are modified.

(2) If user wanted different time zone information to nodes in the Galera
cluster TRUNCATE TABLE for time zone tables was replicated by Galera
destroying time zone information from other nodes. This is fixed
on Galera by introducing new option for mysql_tzinfo_to_sql_symlink
tool --skip-write-binlog to disable Galera replication while
time zone tables are modified.

Comment by Jan Geboers [ 2019-12-03 ]

Hello,

I am not sure if this is the right place to report this, but all of the most recent docker images of mariadb are broken when you are not using SSD storage.
I am referring to this github issue:

https://github.com/docker-library/mariadb/issues/262

On our servers we could not get mariadb 10.1.42 or 10.1.43 running, as stated in my own github issue here:

https://github.com/docker-library/mariadb/issues/274

Downgrading to 10.1.41 solves the problem.
Is there a plan to fix the bug in the future so that 10.1.44 shall be usable again as a docker image on spinning hard drives?

Thanks!

Jan

Comment by Geoff Montee (Inactive) [ 2019-12-03 ]

jgb1984,

Your issues might be caused by MDEV-21209.

Generated at Thu Feb 08 08:46:39 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.