MDEV-29831 Galera crashes when running CoR for a locked table after
setting the minimum memory for a user session.
Failure happens when finalize_atomic_replace() was already finished
and we removed the table from locked tables list.
finalize_locked_tables() doesn't know about that, it doesn't add back
last deleted lock because operation_failed == true.
reopen_tables() doesn't reopen table and as a result we have NULL in
pos_in_locked_tables->table.
The fix adds the knowledge that the locked_tables_count changed since
the start of the command. And if that happened we
add_back_last_deleted_lock(). That makes MDEV-29544 fix with
locked_tables_decremented deprecated.
Alternative fix would add atomic_replace_finished to Atomic_info and
updated it on successful finalize_atomic_replace(). Then the condition
would look like this:
if (atomic_replace_finished || !operation_failed)
{
/*
Add back the deleted table and re-created table as a locked table
This should always work as we have a meta lock on the table.
*/
thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
}
MDEV-29824 Galera crashes when running CoR for a locked table
locked_tables_list.reopen_tables() does external_lock() which in
InnoDB opens new transaction. The previous commit in send_eof() sets
s_committed state in wsrep. The new transaction didn't change that
state yet and on commit s_committed state is unexpected.
The fix is similar to MDEV-22222 (2b8b7394a12): we update wsrep state
before starting new transaction. The better wsrep fix would track the
state properly when the new transaction is started.
MDEV-29770 Broken table cannot be CREATE OR REPLACE -ed anymore
finalize_atomic_replace():
If rename to backup fails we fall back to the mechanism of dropping
old table. For that we write into cleanup chain these events
(executed in reverse order):
1. rename from temporary to original;
2. drop the original table.
After binlogging is done, in finalize_ddl() we execute that cleanup
chain in case of success. In case of error finalize_ddl() closes
cleanup chain and executes rollback chain which drops backup (at that
point non-existent) and the new table under tmp name.
mysql_rename_table():
ha_rename_table() is non-atomic, it can make partial changes and
fail. In that case we revert back these partitial changes to make it
more atomic-friendly.
ddl_log API changes:
DROP sequence of actions can now be written into non-empty
chain. After the sequence is replayed in straight order the chain
continues from what was before DROP_INIT action. That is done by
remembering last entry in ddl_log_drop_init() and update next_entry to
that in each ddl_log_drop(). Of course, each next ddl_log_drop()
updates previous DROP (or DROP_INIT) to point to itself as it was
before.
ddl_log_start_atomic_block()/ddl_log_commit_atomic_block(): these
functions allow to write multiple chain entries without updating
execute entry. Required when the block of several actions must be
atomic.
MDEV-29767 CREATE OR REPLACE bypasses S3 restriction for table creation
For CREATE .. LIKE create_info->db_type contains default value MyISAM,
so it is wrong to use it for is_atomic_replace(). The fix uses
local_create_info for that when it already contains the correct
db_type of the source table.
MDEV-29783 ER_NO_SUCH_TABLE_IN_ENGINE after failed CREATE OR REPLACE with FK violation
If atomic C-O-R fails it reverts back to original table. When doing so
InnoDB code checked old table for foreign key consistency and
failed. The patch disables foreign key check when reverting to
original table: they was created in previous statement and current
statement has nothing to do with that.
InnoDB part just disables any warnings in that case. The warnings was
done when the foreign keys was created.
MDEV-29793 Assertion failure in translog_write_record upon CREATE OR REPLACE
Aria cannot start bulk insert with transactional logging of temporary
table (fails on assertion). But complex join does external_lock()
which disables logging again but sees log_incomplete and does
translog_write_record() which expects logging on.
Probably some logic of Aria is wrong. Atomic C-O-R does
mysql_trans_prepare_alter_copy_data() hack to overcome the prohibition
of transactional logging in temporary table for bulk insert. There is
no objective reason for that prohibition for atomic C-O-R temporary
table as the same works with non-temporary table. And now we enable
transaction back after ha_start_bulk_insert() so complex join will be
happy with external_lock().
MDEV-29791 ER_NO_SUCH_TABLE_IN_ENGINE or "File not found"
upon concurrent DDL with CREATE OR REPLACE
Race condition happens when atomic C-O-R drops backup table by
replaying ddl_log_state_rm in finalize_ddl(). When it already dropped
table (DDL_DROP_PHASE_TABLE) and before DDL_DROP_PHASE_TRIGGER
triggers still exist. At that point another thread tries to drop the
trigger and finds no such table.
The fix protects triggers with MDL lock when renaming original table
to backup. Thus we can drop triggers in another thread either before
that and rename to backup will be already without triggers or after
the C-O-R is finished and at that point there will be no table nor
triggers.