diff --git a/sql/handler.cc b/sql/handler.cc index 1de69b0b07d..4bcfd92dfd3 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1416,7 +1416,7 @@ int ha_commit_trans(THD *thd, bool all) if (rw_trans || thd->lex->sql_command == SQLCOM_ALTER_TABLE) { - if (opt_transaction_registry && thd->vers_update_trt) + if (use_transaction_registry && thd->vers_update_trt) { TR_table trt(thd, true); if (trt.update()) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7451fd035b5..a6b4ee3aaee 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -535,6 +535,7 @@ ulong feature_files_opened_with_delayed_keys= 0, feature_check_constraint= 0; ulonglong denied_connections; my_decimal decimal_zero; my_bool opt_transaction_registry= 1; +my_bool use_transaction_registry= 1; /* Maximum length of parameter value which can be set through @@ -6027,25 +6028,35 @@ int mysqld_main(int argc, char **argv) if (Events::init((THD*) 0, opt_noacl || opt_bootstrap)) unireg_abort(1); - if (!opt_bootstrap && opt_transaction_registry) + if (opt_transaction_registry) { - THD *thd = new THD(0); - thd->thread_stack= (char*) &thd; - thd->store_globals(); - + use_transaction_registry= true; + if (opt_bootstrap) { - TR_table trt(thd); - if (trt.check()) - { - sql_print_error("%s schema is incorrect", trt.table_name); - delete thd; - unireg_abort(1); - } + use_transaction_registry= false; } + else + { + THD *thd = new THD(0); + thd->thread_stack= (char*) &thd; + thd->store_globals(); + { + TR_table trt(thd); + if (trt.check()) + { + use_transaction_registry= false; + } + } - trans_commit_stmt(thd); - delete thd; + trans_commit_stmt(thd); + delete thd; + } } + else + use_transaction_registry= false; + + if (opt_transaction_registry && !use_transaction_registry) + sql_print_information("Disabled transaction registry."); if (WSREP_ON) { diff --git a/sql/mysqld.h b/sql/mysqld.h index 9bd1dae2d36..f4c00cc4b4f 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -313,6 +313,7 @@ extern ulong encryption_algorithm; extern const char *encryption_algorithm_names[]; extern const char *quoted_string; extern my_bool opt_transaction_registry; +extern my_bool use_transaction_registry; #ifdef HAVE_PSI_INTERFACE #ifdef HAVE_MMAP diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dbd73dd701f..74eda09f34b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7432,7 +7432,7 @@ static bool mysql_inplace_alter_table(THD *thd, TR_table trt(thd, true); if (thd->vers_update_trt && trt != *table_list) { - if (opt_transaction_registry && trt.update()) + if (use_transaction_registry && trt.update()) return true; } diff --git a/sql/table.cc b/sql/table.cc index bf8194f190e..df5504bde29 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8699,57 +8699,108 @@ bool TR_table::query_sees(bool &result, ulonglong trx_id1, ulonglong trx_id0, return false; } +void TR_table::warn_schema_incorrect(const char *reason) +{ + if (MYSQL_VERSION_ID == table->s->mysql_version) + { + sql_print_error("`%s.%s` schema is incorrect: %s.", db, table_name, reason); + } + else + { + sql_print_error("`%s.%s` schema is incorrect: %s. Created with MariaDB %d, " + "now running %d.", db, table_name, reason, MYSQL_VERSION_ID, + static_cast(table->s->mysql_version)); + } +} + bool TR_table::check() { - // InnoDB may not be loaded if (!ha_resolve_by_legacy_type(thd, DB_TYPE_INNODB)) - return false; + { + sql_print_information("`%s.%s` requires InnoDB storage engine.", db, table_name); + return true; + } if (open()) + { + sql_print_warning("`%s.%s` does not exist (open failed).", db, table_name); return true; + } if (table->file->ht->db_type != DB_TYPE_INNODB) + { + warn_schema_incorrect("Wrong table engine (expected InnoDB)"); return true; + } - if (table->s->fields != 5) +#define WARN_SCHEMA(...) \ + char reason[128]; \ + snprintf(reason, 128, __VA_ARGS__); \ + warn_schema_incorrect(reason); + + if (table->s->fields != FIELD_COUNT) + { + WARN_SCHEMA("Wrong field count (expected %d)", FIELD_COUNT); return true; + } if (table->field[FLD_TRX_ID]->type() != MYSQL_TYPE_LONGLONG) + { + WARN_SCHEMA("Wrong field %d type (expected BIGINT UNSIGNED)", FLD_TRX_ID); return true; + } if (table->field[FLD_COMMIT_ID]->type() != MYSQL_TYPE_LONGLONG) + { + WARN_SCHEMA("Wrong field %d type (expected BIGINT UNSIGNED)", FLD_COMMIT_ID); return true; + } if (table->field[FLD_BEGIN_TS]->type() != MYSQL_TYPE_TIMESTAMP) + { + WARN_SCHEMA("Wrong field %d type (expected TIMESTAMP(6))", FLD_BEGIN_TS); return true; + } if (table->field[FLD_COMMIT_TS]->type() != MYSQL_TYPE_TIMESTAMP) + { + WARN_SCHEMA("Wrong field %d type (expected TIMESTAMP(6))", FLD_COMMIT_TS); return true; + } if (table->field[FLD_ISO_LEVEL]->type() != MYSQL_TYPE_STRING || !(table->field[FLD_ISO_LEVEL]->flags & ENUM_FLAG)) + { + wrong_enum: + WARN_SCHEMA("Wrong field %d type (expected ENUM('READ-UNCOMMITTED', " + "'READ-COMMITTED', 'REPEATABLE-READ', 'SERIALIZABLE'))", + FLD_ISO_LEVEL); return true; + } Field_enum *iso_level= static_cast(table->field[FLD_ISO_LEVEL]); st_typelib *typelib= iso_level->typelib; if (typelib->count != 4) - return true; + goto wrong_enum; if (strcmp(typelib->type_names[0], "READ-UNCOMMITTED") || strcmp(typelib->type_names[1], "READ-COMMITTED") || strcmp(typelib->type_names[2], "REPEATABLE-READ") || strcmp(typelib->type_names[3], "SERIALIZABLE")) { - return true; + goto wrong_enum; } if (!table->key_info || !table->key_info->key_part) - return true; + goto wrong_pk; - if (strcmp(table->key_info->key_part->field->field_name.str, - "transaction_id")) + if (strcmp(table->key_info->key_part->field->field_name.str, "transaction_id")) + { + wrong_pk: + WARN_SCHEMA("Wrong PRIMARY KEY (expected `transaction_id`)"); return true; + } return false; } diff --git a/sql/table.h b/sql/table.h index 9b8f345c03f..5da230f3606 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2967,6 +2967,8 @@ public: DBUG_ASSERT(iso_level <= ISO_SERIALIZABLE); store(FLD_ISO_LEVEL, iso_level + 1); } + + void warn_schema_incorrect(const char *reason); bool check(); public: diff --git a/sql/vtmd.cc b/sql/vtmd.cc index 417e4ada909..b752f828972 100644 --- a/sql/vtmd.cc +++ b/sql/vtmd.cc @@ -255,7 +255,7 @@ err: } quit: - if (!result && opt_transaction_registry) + if (!result && use_transaction_registry) { DBUG_ASSERT(thd->vers_update_trt); TR_table trt(thd, true);