From eaff81e91cacc321065ae7ebf44ea2f5dad41097 Mon Sep 17 00:00:00 2001 From: Francisco Miguel Biete Banon Date: Sat, 24 Aug 2024 10:34:46 +0100 Subject: [PATCH 1/2] Change: execute DDL only when required to avoid requesting metadata locks. There is a race condition when executing xtrabackup concurrently in multiple PXC nodes with Page Tracking enabled: a node will issue CREATE DATABASE IF NOT EXISTS... and a second node will hang while trying to apply this in TOI. --- .../innobase/xtrabackup/src/backup_mysql.cc | 91 +++++++++++++------ 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/storage/innobase/xtrabackup/src/backup_mysql.cc b/storage/innobase/xtrabackup/src/backup_mysql.cc index a2246b34400d..a16f04a572d1 100644 --- a/storage/innobase/xtrabackup/src/backup_mysql.cc +++ b/storage/innobase/xtrabackup/src/backup_mysql.cc @@ -1808,6 +1808,9 @@ bool write_xtrabackup_info(MYSQL *connection) { const char *uuid = NULL; char *server_version = NULL; char *xtrabackup_info_data = NULL; + char *schema_exists = NULL; + char *table_exists = NULL; + char *column_is_changed = NULL; int idx; bool null = true; @@ -1837,37 +1840,62 @@ bool write_xtrabackup_info(MYSQL *connection) { uuid = get_backup_uuid(connection); server_version = read_mysql_one_value(connection, "SELECT VERSION()"); - xb_mysql_query(connection, "CREATE DATABASE IF NOT EXISTS PERCONA_SCHEMA", - false); - xb_mysql_query(connection, - "CREATE TABLE IF NOT EXISTS PERCONA_SCHEMA.xtrabackup_history(" - "uuid VARCHAR(40) NOT NULL PRIMARY KEY," - "name VARCHAR(255) DEFAULT NULL," - "tool_name VARCHAR(255) DEFAULT NULL," - "tool_command TEXT DEFAULT NULL," - "tool_version VARCHAR(255) DEFAULT NULL," - "ibbackup_version VARCHAR(255) DEFAULT NULL," - "server_version VARCHAR(255) DEFAULT NULL," - "start_time TIMESTAMP NULL DEFAULT NULL," - "end_time TIMESTAMP NULL DEFAULT NULL," - "lock_time BIGINT UNSIGNED DEFAULT NULL," - "binlog_pos TEXT DEFAULT NULL," - "innodb_from_lsn BIGINT UNSIGNED DEFAULT NULL," - "innodb_to_lsn BIGINT UNSIGNED DEFAULT NULL," - "partial ENUM('Y', 'N') DEFAULT NULL," - "incremental ENUM('Y', 'N') DEFAULT NULL," - "format ENUM('file', 'tar', 'xbstream') DEFAULT NULL," - "compact ENUM('Y', 'N') DEFAULT NULL," - "compressed ENUM('Y', 'N') DEFAULT NULL," - "encrypted ENUM('Y', 'N') DEFAULT NULL" - ") CHARACTER SET utf8 ENGINE=innodb", - false); + schema_exists = read_mysql_one_value(connection, "SELECT COUNT(*) " + "FROM INFORMATION_SCHEMA.SCHEMATA " + "WHERE SCHEMA_NAME = 'PERCONA_SCHEMA'"); + if (strcmp(schema_exists, "0") == 0) { + // Only create the schema if it doesn't exist to avoid requesting a metadata lock + xb_mysql_query(connection, "CREATE DATABASE IF NOT EXISTS PERCONA_SCHEMA", + false); + + table_exists = read_mysql_one_value(connection, "SELECT COUNT(*) " + "FROM INFORMATION_SCHEMA.TABLES " + "WHERE TABLE_SCHEMA = 'PERCONA_SCHEMA' " + "AND TABLE_NAME = 'xtrabackup_history'"); + if (strcmp(table_exists, "0") == 0) + { + // Only create the table if it doesn't exist to avoid requesting a metadata lock + xb_mysql_query(connection, + "CREATE TABLE IF NOT EXISTS PERCONA_SCHEMA.xtrabackup_history(" + "uuid VARCHAR(40) NOT NULL PRIMARY KEY," + "name VARCHAR(255) DEFAULT NULL," + "tool_name VARCHAR(255) DEFAULT NULL," + "tool_command TEXT DEFAULT NULL," + "tool_version VARCHAR(255) DEFAULT NULL," + "ibbackup_version VARCHAR(255) DEFAULT NULL," + "server_version VARCHAR(255) DEFAULT NULL," + "start_time TIMESTAMP NULL DEFAULT NULL," + "end_time TIMESTAMP NULL DEFAULT NULL," + "lock_time BIGINT UNSIGNED DEFAULT NULL," + "binlog_pos TEXT DEFAULT NULL," + "innodb_from_lsn BIGINT UNSIGNED DEFAULT NULL," + "innodb_to_lsn BIGINT UNSIGNED DEFAULT NULL," + "partial ENUM('Y', 'N') DEFAULT NULL," + "incremental ENUM('Y', 'N') DEFAULT NULL," + "format ENUM('file', 'tar', 'xbstream') DEFAULT NULL," + "compact ENUM('Y', 'N') DEFAULT NULL," + "compressed ENUM('Y', 'N') DEFAULT NULL," + "encrypted ENUM('Y', 'N') DEFAULT NULL" + ") CHARACTER SET utf8 ENGINE=innodb", + false); + } + } - /* Upgrade from previous versions */ - xb_mysql_query(connection, - "ALTER TABLE PERCONA_SCHEMA.xtrabackup_history MODIFY COLUMN " - "binlog_pos TEXT DEFAULT NULL", - false); + column_is_changed = read_mysql_one_value(connection, "SELECT COUNT(*) " + "FROM INFORMATION_SCHEMA.COLUMNS " + "WHERE TABLE_SCHEMA = 'PERCONA_SCHEMA' " + "AND TABLE_NAME = 'xtrabackup_history' " + "AND COLUMN_NAME = 'binlog_pos' " + "AND DATA_TYPE = 'TEXT'"); + + if (strcmp(column_is_changed, "0") == 0) { + // Only alter table if it's required to avoid requesting metadata lock + /* Upgrade from previous versions */ + xb_mysql_query(connection, + "ALTER TABLE PERCONA_SCHEMA.xtrabackup_history MODIFY COLUMN " + "binlog_pos TEXT DEFAULT NULL", + false); + } stmt = mysql_stmt_init(connection); @@ -2012,6 +2040,9 @@ bool write_xtrabackup_info(MYSQL *connection) { free(xtrabackup_info_data); free(server_version); + free(schema_exists); + free(table_exists); + free(column_is_changed); return (true); } From bbdc404de1d74e97cba49ef8a3486bab862486cf Mon Sep 17 00:00:00 2001 From: Francisco Miguel Biete Banon Date: Tue, 3 Sep 2024 10:25:55 +0100 Subject: [PATCH 2/2] Fix: data type is lowercase and bin collation --- storage/innobase/xtrabackup/src/backup_mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/xtrabackup/src/backup_mysql.cc b/storage/innobase/xtrabackup/src/backup_mysql.cc index a16f04a572d1..846756b84c3d 100644 --- a/storage/innobase/xtrabackup/src/backup_mysql.cc +++ b/storage/innobase/xtrabackup/src/backup_mysql.cc @@ -1886,7 +1886,7 @@ bool write_xtrabackup_info(MYSQL *connection) { "WHERE TABLE_SCHEMA = 'PERCONA_SCHEMA' " "AND TABLE_NAME = 'xtrabackup_history' " "AND COLUMN_NAME = 'binlog_pos' " - "AND DATA_TYPE = 'TEXT'"); + "AND DATA_TYPE = 'text'"); if (strcmp(column_is_changed, "0") == 0) { // Only alter table if it's required to avoid requesting metadata lock