1
0
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:
Georgi Kodinov
2010-09-20 17:17:32 +03:00
503 changed files with 25265 additions and 6911 deletions

View File

@ -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),