mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge branch '10.5' into 10.6
This commit is contained in:
111
sql/sql_class.cc
111
sql/sql_class.cc
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2008, 2022, MariaDB Corporation.
|
||||
|
||||
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
|
||||
@ -679,7 +679,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
|
||||
#ifdef HAVE_REPLICATION
|
||||
,
|
||||
current_linfo(0),
|
||||
slave_info(0)
|
||||
slave_info(0),
|
||||
is_awaiting_semisync_ack(0)
|
||||
#endif
|
||||
#ifdef WITH_WSREP
|
||||
,
|
||||
@ -862,11 +863,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
|
||||
get_sequence_last_key, (my_hash_free_key) free_sequence_last,
|
||||
HASH_THREAD_SPECIFIC);
|
||||
|
||||
sp_proc_cache= NULL;
|
||||
sp_func_cache= NULL;
|
||||
sp_package_spec_cache= NULL;
|
||||
sp_package_body_cache= NULL;
|
||||
|
||||
/* For user vars replication*/
|
||||
if (opt_bin_log)
|
||||
my_init_dynamic_array(key_memory_user_var_entry, &user_var_events,
|
||||
@ -1452,10 +1448,7 @@ void THD::change_user(void)
|
||||
SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key)
|
||||
get_sequence_last_key, (my_hash_free_key) free_sequence_last,
|
||||
HASH_THREAD_SPECIFIC);
|
||||
sp_cache_clear(&sp_proc_cache);
|
||||
sp_cache_clear(&sp_func_cache);
|
||||
sp_cache_clear(&sp_package_spec_cache);
|
||||
sp_cache_clear(&sp_package_body_cache);
|
||||
sp_caches_clear();
|
||||
opt_trace.delete_traces();
|
||||
}
|
||||
|
||||
@ -1582,10 +1575,7 @@ void THD::cleanup(void)
|
||||
|
||||
my_hash_free(&user_vars);
|
||||
my_hash_free(&sequences);
|
||||
sp_cache_clear(&sp_proc_cache);
|
||||
sp_cache_clear(&sp_func_cache);
|
||||
sp_cache_clear(&sp_package_spec_cache);
|
||||
sp_cache_clear(&sp_package_body_cache);
|
||||
sp_caches_clear();
|
||||
auto_inc_intervals_forced.empty();
|
||||
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
|
||||
|
||||
@ -6744,49 +6734,86 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int THD::decide_logging_format_low(TABLE *table)
|
||||
|
||||
/*
|
||||
Reconsider logging format in case of INSERT...ON DUPLICATE KEY UPDATE
|
||||
for tables with more than one unique keys in case of MIXED binlog format.
|
||||
|
||||
Unsafe means that a master could execute the statement differently than
|
||||
the slave.
|
||||
This could can happen in the following cases:
|
||||
- The unique check are done in different order on master or slave
|
||||
(different engine or different key order).
|
||||
- There is a conflict on another key than the first and before the
|
||||
statement is committed, another connection commits a row that conflicts
|
||||
on an earlier unique key. Example follows:
|
||||
|
||||
Below a and b are unique keys, the table has a row (1,1,0)
|
||||
connection 1:
|
||||
INSERT INTO t1 set a=2,b=1,c=0 ON DUPLICATE KEY UPDATE c=1;
|
||||
connection 2:
|
||||
INSERT INTO t1 set a=2,b=2,c=0;
|
||||
|
||||
If 2 commits after 1 has been executed but before 1 has committed
|
||||
(and are thus put before the other in the binary log), one will
|
||||
get different data on the slave:
|
||||
(1,1,1),(2,2,1) instead of (1,1,1),(2,2,0)
|
||||
*/
|
||||
|
||||
void THD::reconsider_logging_format_for_iodup(TABLE *table)
|
||||
{
|
||||
DBUG_ENTER("decide_logging_format_low");
|
||||
/*
|
||||
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
|
||||
can be unsafe.
|
||||
*/
|
||||
if (wsrep_binlog_format() <= BINLOG_FORMAT_STMT &&
|
||||
!is_current_stmt_binlog_format_row() &&
|
||||
!lex->is_stmt_unsafe() &&
|
||||
lex->duplicates == DUP_UPDATE)
|
||||
DBUG_ENTER("reconsider_logging_format_for_iodup");
|
||||
enum_binlog_format bf= (enum_binlog_format) wsrep_binlog_format();
|
||||
|
||||
DBUG_ASSERT(lex->duplicates == DUP_UPDATE);
|
||||
|
||||
if (bf <= BINLOG_FORMAT_STMT &&
|
||||
!is_current_stmt_binlog_format_row())
|
||||
{
|
||||
KEY *end= table->s->key_info + table->s->keys;
|
||||
uint unique_keys= 0;
|
||||
uint keys= table->s->keys, i= 0;
|
||||
Field *field;
|
||||
for (KEY* keyinfo= table->s->key_info;
|
||||
i < keys && unique_keys <= 1; i++, keyinfo++)
|
||||
if (keyinfo->flags & HA_NOSAME &&
|
||||
!(keyinfo->key_part->field->flags & AUTO_INCREMENT_FLAG &&
|
||||
//User given auto inc can be unsafe
|
||||
!keyinfo->key_part->field->val_int()))
|
||||
|
||||
for (KEY *keyinfo= table->s->key_info; keyinfo < end ; keyinfo++)
|
||||
{
|
||||
if (keyinfo->flags & HA_NOSAME)
|
||||
{
|
||||
/*
|
||||
We assume that the following cases will guarantee that the
|
||||
key is unique if a key part is not set:
|
||||
- The key part is an autoincrement (autogenerated)
|
||||
- The key part has a default value that is null and it not
|
||||
a virtual field that will be calculated later.
|
||||
*/
|
||||
for (uint j= 0; j < keyinfo->user_defined_key_parts; j++)
|
||||
{
|
||||
field= keyinfo->key_part[j].field;
|
||||
if(!bitmap_is_set(table->write_set,field->field_index))
|
||||
goto exit;
|
||||
Field *field= keyinfo->key_part[j].field;
|
||||
if (!bitmap_is_set(table->write_set, field->field_index))
|
||||
{
|
||||
/* Check auto_increment */
|
||||
if (field == table->next_number_field)
|
||||
goto exit;
|
||||
if (field->is_real_null() && !field->default_value)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
unique_keys++;
|
||||
if (unique_keys++)
|
||||
break;
|
||||
exit:;
|
||||
}
|
||||
|
||||
}
|
||||
if (unique_keys > 1)
|
||||
{
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
|
||||
binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
|
||||
if (bf == BINLOG_FORMAT_STMT && !lex->is_stmt_unsafe())
|
||||
{
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
|
||||
binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
|
||||
}
|
||||
set_current_stmt_binlog_format_row_if_mixed();
|
||||
if (is_current_stmt_binlog_format_row())
|
||||
binlog_prepare_for_row_logging();
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
|
Reference in New Issue
Block a user