mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
merge of mysql-5.5 into mysql-5.5-wl1054
This commit is contained in:
210
sql/sql_class.cc
210
sql/sql_class.cc
@ -57,6 +57,7 @@
|
||||
#include "transaction.h"
|
||||
#include "debug_sync.h"
|
||||
#include "sql_parse.h" // is_update_query
|
||||
#include "sql_callback.h"
|
||||
|
||||
/*
|
||||
The following is used to initialise Table_ident with a internal
|
||||
@ -306,6 +307,11 @@ void **thd_ha_data(const THD *thd, const struct handlerton *hton)
|
||||
return (void **) &thd->ha_data[hton->slot].ha_ptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void thd_storage_lock_wait(THD *thd, long long value)
|
||||
{
|
||||
thd->utime_after_lock+= value;
|
||||
}
|
||||
|
||||
/**
|
||||
Provide a handler data getter to simplify coding
|
||||
@ -1071,6 +1077,7 @@ THD::~THD()
|
||||
DBUG_ENTER("~THD()");
|
||||
/* Ensure that no one is using THD */
|
||||
mysql_mutex_lock(&LOCK_thd_data);
|
||||
mysys_var=0; // Safety (shouldn't be needed)
|
||||
mysql_mutex_unlock(&LOCK_thd_data);
|
||||
add_to_status(&global_status_var, &status_var);
|
||||
|
||||
@ -1096,7 +1103,6 @@ THD::~THD()
|
||||
my_free(db);
|
||||
db= NULL;
|
||||
free_root(&transaction.mem_root,MYF(0));
|
||||
mysys_var=0; // Safety (shouldn't be needed)
|
||||
mysql_mutex_destroy(&LOCK_thd_data);
|
||||
#ifndef DBUG_OFF
|
||||
dbug_sentry= THD_SENTRY_GONE;
|
||||
@ -1185,7 +1191,7 @@ void THD::awake(THD::killed_state state_to_set)
|
||||
{
|
||||
thr_alarm_kill(thread_id);
|
||||
if (!slave_thread)
|
||||
thread_scheduler.post_kill_notification(this);
|
||||
MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (this));
|
||||
#ifdef SIGNAL_WITH_VIO_CLOSE
|
||||
if (this != current_thd)
|
||||
{
|
||||
@ -1254,6 +1260,15 @@ bool THD::store_globals()
|
||||
if (my_pthread_setspecific_ptr(THR_THD, this) ||
|
||||
my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
|
||||
return 1;
|
||||
/*
|
||||
mysys_var is concurrently readable by a killer thread.
|
||||
It is protected by LOCK_thd_data, it is not needed to lock while the
|
||||
pointer is changing from NULL not non-NULL. If the kill thread reads
|
||||
NULL it doesn't refer to anything, but if it is non-NULL we need to
|
||||
ensure that the thread doesn't proceed to assign another thread to
|
||||
have the mysys_var reference (which in fact refers to the worker
|
||||
threads local storage with key THR_KEY_mysys.
|
||||
*/
|
||||
mysys_var=my_thread_var;
|
||||
/*
|
||||
Let mysqld define the thread id (not mysys)
|
||||
@ -3190,6 +3205,60 @@ extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)
|
||||
{
|
||||
return sqlcom_can_generate_row_events(thd);
|
||||
}
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
extern "C" void thd_pool_wait_begin(MYSQL_THD thd, int wait_type);
|
||||
extern "C" void thd_pool_wait_end(MYSQL_THD thd);
|
||||
|
||||
/*
|
||||
Interface for MySQL Server, plugins and storage engines to report
|
||||
when they are going to sleep/stall.
|
||||
|
||||
SYNOPSIS
|
||||
thd_wait_begin()
|
||||
thd Thread object
|
||||
wait_type Type of wait
|
||||
1 -- short wait (e.g. for mutex)
|
||||
2 -- medium wait (e.g. for disk io)
|
||||
3 -- large wait (e.g. for locked row/table)
|
||||
NOTES
|
||||
This is used by the threadpool to have better knowledge of which
|
||||
threads that currently are actively running on CPUs. When a thread
|
||||
reports that it's going to sleep/stall, the threadpool scheduler is
|
||||
free to start another thread in the pool most likely. The expected wait
|
||||
time is simply an indication of how long the wait is expected to
|
||||
become, the real wait time could be very different.
|
||||
|
||||
thd_wait_end MUST be called immediately after waking up again.
|
||||
*/
|
||||
extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
|
||||
{
|
||||
MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type));
|
||||
}
|
||||
|
||||
/**
|
||||
Interface for MySQL Server, plugins and storage engines to report
|
||||
when they waking up from a sleep/stall.
|
||||
|
||||
@param thd Thread handle
|
||||
*/
|
||||
extern "C" void thd_wait_end(MYSQL_THD thd)
|
||||
{
|
||||
MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd));
|
||||
}
|
||||
#else
|
||||
extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
|
||||
{
|
||||
/* do NOTHING for the embedded library */
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" void thd_wait_end(MYSQL_THD thd)
|
||||
{
|
||||
/* do NOTHING for the embedded library */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif // INNODB_COMPATIBILITY_HOOKS */
|
||||
|
||||
/****************************************************************************
|
||||
@ -3373,6 +3442,13 @@ void THD::set_query_id(query_id_t new_query_id)
|
||||
mysql_mutex_unlock(&LOCK_thd_data);
|
||||
}
|
||||
|
||||
/** Assign a new value to thd->mysys_var. */
|
||||
void THD::set_mysys_var(struct st_my_thread_var *new_mysys_var)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_thd_data);
|
||||
mysys_var= new_mysys_var;
|
||||
mysql_mutex_unlock(&LOCK_thd_data);
|
||||
}
|
||||
|
||||
/**
|
||||
Leave explicit LOCK TABLES or prelocked mode and restore value of
|
||||
@ -3651,7 +3727,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
{
|
||||
DBUG_ENTER("THD::decide_logging_format");
|
||||
DBUG_PRINT("info", ("query: %s", query()));
|
||||
DBUG_PRINT("info", ("variables.binlog_format: %u",
|
||||
DBUG_PRINT("info", ("variables.binlog_format: %lu",
|
||||
variables.binlog_format));
|
||||
DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x",
|
||||
lex->get_stmt_unsafe_flags()));
|
||||
@ -3782,124 +3858,16 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
int error= 0;
|
||||
int unsafe_flags;
|
||||
|
||||
/*
|
||||
Classify a statement as unsafe when there is a mixed statement and an
|
||||
on-going transaction at any point of the execution if:
|
||||
bool multi_stmt_trans= in_multi_stmt_transaction_mode();
|
||||
bool trans_table= trans_has_updated_trans_table(this);
|
||||
bool binlog_direct= variables.binlog_direct_non_trans_update;
|
||||
|
||||
1. The mixed statement is about to update a transactional table and
|
||||
a non-transactional table.
|
||||
|
||||
2. The mixed statement is about to update a temporary transactional
|
||||
table and a non-transactional table.
|
||||
|
||||
3. The mixed statement is about to update a transactional table and
|
||||
read from a non-transactional table.
|
||||
|
||||
4. The mixed statement is about to update a temporary transactional
|
||||
table and read from a non-transactional table.
|
||||
|
||||
5. The mixed statement is about to update a non-transactional table
|
||||
and read from a transactional table when the isolation level is
|
||||
lower than repeatable read.
|
||||
|
||||
After updating a transactional table if:
|
||||
|
||||
6. The mixed statement is about to update a non-transactional table
|
||||
and read from a temporary transactional table.
|
||||
|
||||
7. The mixed statement is about to update a non-transactional table
|
||||
and read from a temporary transactional table.
|
||||
|
||||
8. The mixed statement is about to update a non-transactionala table
|
||||
and read from a temporary non-transactional table.
|
||||
|
||||
9. The mixed statement is about to update a temporary non-transactional
|
||||
table and update a non-transactional table.
|
||||
|
||||
10. The mixed statement is about to update a temporary non-transactional
|
||||
table and read from a non-transactional table.
|
||||
|
||||
11. A statement is about to update a non-transactional table and the
|
||||
option variables.binlog_direct_non_trans_update is OFF.
|
||||
|
||||
The reason for this is that locks acquired may not protected a concurrent
|
||||
transaction of interfering in the current execution and by consequence in
|
||||
the result. In particular, if there is an on-going transaction and a
|
||||
transactional table was already updated, a temporary table must be written
|
||||
to the binary log in the boundaries of the on-going transaction and as
|
||||
such we artificially classify them as transactional.
|
||||
*/
|
||||
if (in_multi_stmt_transaction_mode())
|
||||
{
|
||||
my_bool mixed_unsafe= FALSE;
|
||||
my_bool non_trans_unsafe= FALSE;
|
||||
|
||||
/* Case 1. */
|
||||
if (lex->stmt_accessed_table(LEX::STMT_WRITES_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 2. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 3. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 4. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 5. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_TRANS_TABLE) &&
|
||||
tx_isolation < ISO_REPEATABLE_READ)
|
||||
/*
|
||||
By default, InnoDB operates in REPEATABLE READ and with the option
|
||||
--innodb-locks-unsafe-for-binlog disabled. In this case, InnoDB uses
|
||||
next-key locks for searches and index scans, which prevents phantom
|
||||
rows.
|
||||
|
||||
This is scenario is safe for Innodb. However, there are no means to
|
||||
transparently get this information. Therefore, we need to improve this
|
||||
and change the storage engines to report somehow when an execution is
|
||||
safe under an isolation level & binary logging format.
|
||||
*/
|
||||
mixed_unsafe= TRUE;
|
||||
|
||||
if (trans_has_updated_trans_table(this))
|
||||
{
|
||||
/* Case 6. */
|
||||
if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 7. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_TEMP_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 8. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_TEMP_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 9. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 10. */
|
||||
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
|
||||
lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
|
||||
mixed_unsafe= TRUE;
|
||||
/* Case 11. */
|
||||
else if (!variables.binlog_direct_non_trans_update &&
|
||||
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
|
||||
non_trans_unsafe= TRUE;
|
||||
}
|
||||
|
||||
if (mixed_unsafe)
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MIXED_STATEMENT);
|
||||
else if (non_trans_unsafe)
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS);
|
||||
}
|
||||
if (lex->is_mixed_stmt_unsafe(multi_stmt_trans, binlog_direct,
|
||||
trans_table, tx_isolation))
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MIXED_STATEMENT);
|
||||
else if (multi_stmt_trans && trans_table && !binlog_direct &&
|
||||
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS);
|
||||
|
||||
/*
|
||||
If more than one engine is involved in the statement and at
|
||||
@ -4024,7 +3992,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
DBUG_PRINT("info", ("decision: no logging since "
|
||||
"mysql_bin_log.is_open() = %d "
|
||||
"and (options & OPTION_BIN_LOG) = 0x%llx "
|
||||
"and binlog_format = %u "
|
||||
"and binlog_format = %lu "
|
||||
"and binlog_filter->db_ok(db) = %d",
|
||||
mysql_bin_log.is_open(),
|
||||
(variables.option_bits & OPTION_BIN_LOG),
|
||||
|
Reference in New Issue
Block a user