diff options
author | petr/cps@mysql.com/owlet.local <> | 2006-10-13 17:26:46 +0400 |
---|---|---|
committer | petr/cps@mysql.com/owlet.local <> | 2006-10-13 17:26:46 +0400 |
commit | 6846f8d9c4f5f3d3573ed6fe961125f0172c23ae (patch) | |
tree | d9ddce943269971a31abcd891f5801ef0afea94f /sql/sql_rename.cc | |
parent | faad25233682a040c8d726dbfba6fedc2d4f0b6b (diff) | |
download | mariadb-git-6846f8d9c4f5f3d3573ed6fe961125f0172c23ae.tar.gz |
Fix for Bug #17544 "Cannot do atomic log rotate",
Bug #21785 "Server crashes after rename of the log table" and
Bug #21966 "Strange warnings on create like/repair of the log
tables"
According to the patch, from now on, one should use RENAME to
perform a log table rotation (this should also be reflected in
the manual).
Here is a sample:
use mysql;
CREATE TABLE IF NOT EXISTS general_log2 LIKE general_log;
RENAME TABLE general_log TO general_log_backup, general_log2 TO general_log;
The rules for Rename of the log tables are following:
IF 1. Log tables are enabled
AND 2. Rename operates on the log table and nothing is being
renamed to the log table.
DO 3. Throw an error message.
ELSE 4. Perform rename.
The very RENAME query will go the the old (backup) table. This is
consistent with the behavoiur we have with binlog ROTATE LOGS
statement.
Other problems, which are solved by the patch are:
1) Now REPAIR of the log table is exclusive operation (as it should be), this
also eliminates lock-related warnings. and
2) CREATE LIKE TABLE now usese usual read lock on the source table rather
then name lock, which is too restrictive. This way we get rid of another
log table-related warning, which occured because of the above fact
(as a side-effect, name lock resulted in a warning).
Diffstat (limited to 'sql/sql_rename.cc')
-rw-r--r-- | sql/sql_rename.cc | 102 |
1 files changed, 101 insertions, 1 deletions
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 73473ddd24b..47e85cc0884 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -35,7 +35,10 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) { bool error= 1; - TABLE_LIST *ren_table= 0; + TABLE_LIST *ren_table= 0, *new_table; + int to_table; + char *rename_log_table[2]= {NULL, NULL}; + int disable_logs= 0; DBUG_ENTER("mysql_rename_tables"); /* @@ -52,6 +55,96 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) if (wait_if_global_read_lock(thd,0,1)) DBUG_RETURN(1); + + if (logger.is_log_table_enabled(QUERY_LOG_GENERAL) || + logger.is_log_table_enabled(QUERY_LOG_SLOW)) + { + + /* + Rules for rename of a log table: + + IF 1. Log tables are enabled + AND 2. Rename operates on the log table and nothing is being + renamed to the log table. + DO 3. Throw an error message. + ELSE 4. Perform rename. + */ + + for (to_table= 0, ren_table= table_list; ren_table; + to_table= 1 - to_table, ren_table= ren_table->next_local) + { + int log_table_rename= 0; + + if ((log_table_rename= + check_if_log_table(ren_table->db_length, ren_table->db, + ren_table->table_name_length, + ren_table->table_name, 1))) + { + /* + Log table encoutered we will need to disable and lock logs + for duration of rename. + */ + disable_logs= TRUE; + + /* + as we use log_table_rename as an array index, we need it to start + with 0, while QUERY_LOG_SLOW == 1 and QUERY_LOG_GENERAL == 2. + So, we shift the value to start with 0; + */ + log_table_rename--; + if (rename_log_table[log_table_rename]) + { + if (to_table) + rename_log_table[log_table_rename]= NULL; + else + { + /* + Two renames of "log_table TO" w/o rename "TO log_table" in + between. + */ + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name, + ren_table->table_name); + DBUG_RETURN(1); + } + } + else + { + if (to_table) + { + /* + Attempt to rename a table TO log_table w/o renaming + log_table TO some table. + */ + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name, + ren_table->table_name); + DBUG_RETURN(1); + } + else + { + /* save the name of the log table to report an error */ + rename_log_table[log_table_rename]= ren_table->table_name; + } + } + } + } + if (rename_log_table[0] || rename_log_table[1]) + { + if (rename_log_table[0]) + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[0], + rename_log_table[0]); + else + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[1], + rename_log_table[1]); + DBUG_RETURN(1); + } + + if (disable_logs) + { + logger.lock(); + logger.tmp_close_log_tables(thd); + } + } + VOID(pthread_mutex_lock(&LOCK_open)); if (lock_table_names(thd, table_list)) goto err; @@ -95,6 +188,13 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) err: pthread_mutex_unlock(&LOCK_open); + /* enable logging back if needed */ + if (disable_logs) + { + if (logger.reopen_log_tables()) + error= TRUE; + logger.unlock(); + } start_waiting_global_read_lock(thd); DBUG_RETURN(error); } |