diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-02-25 18:19:55 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-02-25 18:19:55 +0100 |
commit | 00d1db7a38b17d4512a6ba5147926608aca5624d (patch) | |
tree | c2b28145304e9eacf79fcabaeb962a20d79fec93 /sql/sql_class.cc | |
parent | 0485328d030f4b742dac7b667e8ed099beb9e9f2 (diff) | |
parent | 0251232f8c3bca33b4dd15d6668105f3de9d024d (diff) | |
download | mariadb-git-00d1db7a38b17d4512a6ba5147926608aca5624d.tar.gz |
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 125 |
1 files changed, 122 insertions, 3 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c1f64c89e1b..38289b188b2 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB + Copyright (c) 2008, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -896,7 +896,7 @@ THD::THD(bool is_wsrep_applier) wsrep_po_handle(WSREP_PO_INITIALIZER), wsrep_po_cnt(0), wsrep_apply_format(0), - wsrep_skip_append_keys(false) + wsrep_ignore_table(false) #endif { ulong tmp; @@ -1021,6 +1021,7 @@ THD::THD(bool is_wsrep_applier) wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */ + wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1441,7 +1442,8 @@ void THD::init(void) wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; -#endif + wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; +#endif /* WITH_WSREP */ if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; @@ -2204,6 +2206,10 @@ void THD::cleanup_after_query() rgi_slave->cleanup_after_query(); #endif +#ifdef WITH_WSREP + wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; +#endif /* WITH_WSREP */ + DBUG_VOID_RETURN; } @@ -5450,6 +5456,94 @@ int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) &argument); } +/* + Tells if two (or more) tables have auto_increment columns and we want to + lock those tables with a write lock. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment + tables Table list + + NOTES: + Call this function only when you have established the list of all tables + which you'll want to update (including stored functions, triggers, views + inside your statement). +*/ + +static bool +has_write_table_with_auto_increment(TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE)) + return 1; + } + + return 0; +} + +/* + checks if we have select tables in the table list and write tables + with auto-increment column. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment_and_select + tables Table list + + RETURN VALUES + + -true if the table list has atleast one table with auto-increment column + + + and atleast one table to select from. + -false otherwise +*/ + +static bool +has_write_table_with_auto_increment_and_select(TABLE_LIST *tables) +{ + bool has_select= false; + bool has_auto_increment_tables = has_write_table_with_auto_increment(tables); + for(TABLE_LIST *table= tables; table; table= table->next_global) + { + if (!table->placeholder() && + (table->lock_type <= TL_READ_NO_INSERT)) + { + has_select= true; + break; + } + } + return(has_select && has_auto_increment_tables); +} + +/* + Tells if there is a table whose auto_increment column is a part + of a compound primary key while is not the first column in + the table definition. + + @param tables Table list + + @return true if the table exists, fais if does not. +*/ + +static bool +has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE) + && table->table->s->next_number_keypart != 0) + return 1; + } + + return 0; +} /** Decide on logging format to use for the statement and issue errors @@ -5634,6 +5728,31 @@ int THD::decide_logging_format(TABLE_LIST *tables) } #endif + if (wsrep_binlog_format() != BINLOG_FORMAT_ROW && tables) + { + /* + DML statements that modify a table with an auto_increment column based on + rows selected from a table are unsafe as the order in which the rows are + fetched fron the select tables cannot be determined and may differ on + master and slave. + */ + if (has_write_table_with_auto_increment_and_select(tables)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); + + if (has_write_table_auto_increment_not_first_in_pk(tables)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST); + + /* + A query that modifies autoinc column in sub-statement can make the + master and slave inconsistent. + We can solve these problems in mixed mode by switching to binlogging + if at least one updated table is used by sub-statement + */ + if (lex->requires_prelocking() && + has_write_table_with_auto_increment(lex->first_not_own_table())) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); + } + /* Get the capabilities vector for all involved storage engines and mask out the flags for the binary log. |