#At file:///home/acorreia/workspace.sun/repository.mysql.new/bzrwork/bug-53452/mysql-trunk-bugfixing/ based on revid:alfranio.correia@stripped
3087 Alfranio Correia 2010-07-11
(no message)
modified:
sql/log.cc
sql/log_event.cc
sql/sql_class.cc
sql/sql_lex.h
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-07-09 09:05:17 +0000
+++ b/sql/log.cc 2010-07-11 19:35:51 +0000
@@ -209,7 +209,7 @@ class binlog_cache_data
{
public:
binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
- incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE)
+ incident(FALSE)
{
cache_log.end_of_file= max_binlog_cache_size;
}
@@ -245,20 +245,9 @@ public:
return(incident);
}
- void set_changes_to_non_trans_temp_table()
- {
- changes_to_non_trans_temp_table_flag= TRUE;
- }
-
- bool changes_to_non_trans_temp_table()
- {
- return (changes_to_non_trans_temp_table_flag);
- }
-
void reset()
{
truncate(0);
- changes_to_non_trans_temp_table_flag= FALSE;
incident= FALSE;
before_stmt_pos= MY_OFF_T_UNDEF;
cache_log.end_of_file= max_binlog_cache_size;
@@ -316,12 +305,6 @@ private:
bool incident;
/*
- This flag indicates if the cache has changes to temporary tables.
- @TODO This a temporary fix and should be removed after BUG#54562.
- */
- bool changes_to_non_trans_temp_table_flag;
-
- /*
It truncates the cache to a certain position. This includes deleting the
pending event.
*/
@@ -1801,8 +1784,6 @@ static int binlog_rollback(handlerton *h
((thd->variables.option_bits & OPTION_KEEP_LOG) ||
(trans_has_updated_non_trans_table(thd) &&
thd->variables.binlog_format == BINLOG_FORMAT_STMT) ||
- (cache_mngr->trx_cache.changes_to_non_trans_temp_table() &&
- thd->variables.binlog_format == BINLOG_FORMAT_MIXED) ||
(trans_has_updated_non_trans_table(thd) &&
ending_single_stmt_trans(thd,all) &&
thd->variables.binlog_format == BINLOG_FORMAT_MIXED)))
@@ -1822,9 +1803,7 @@ static int binlog_rollback(handlerton *h
else if (ending_trans(thd, all) ||
(!(thd->variables.option_bits & OPTION_KEEP_LOG) &&
(!stmt_has_updated_non_trans_table(thd) ||
- thd->variables.binlog_format != BINLOG_FORMAT_STMT) &&
- (!cache_mngr->trx_cache.changes_to_non_trans_temp_table() ||
- thd->variables.binlog_format != BINLOG_FORMAT_MIXED)))
+ thd->variables.binlog_format != BINLOG_FORMAT_STMT)))
error= binlog_truncate_trx_cache(thd, cache_mngr, all);
}
@@ -4701,9 +4680,6 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
file= cache_mngr->get_binlog_cache_log(is_trans_cache);
cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
- if (thd->lex->stmt_accessed_non_trans_temp_table())
- cache_data->set_changes_to_non_trans_temp_table();
-
thd->binlog_start_trans_and_stmt();
}
DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2010-07-09 09:05:17 +0000
+++ b/sql/log_event.cc 2010-07-11 19:35:51 +0000
@@ -678,11 +678,11 @@ Log_event::Log_event(THD* thd_arg, uint1
{
server_id= thd->server_id;
when= thd->start_time;
- cache_type= ((using_trans || stmt_has_updated_trans_table(thd) ||
- (thd->lex->stmt_accessed_temp_table() &&
- trans_has_updated_trans_table(thd)))
- ? Log_event::EVENT_TRANSACTIONAL_CACHE :
- Log_event::EVENT_STMT_CACHE);
+
+ if (using_trans)
+ cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
+ else
+ cache_type= Log_event::EVENT_STMT_CACHE;
}
/**
@@ -2468,21 +2468,18 @@ Query_log_event::Query_log_event(THD* th
LEX *lex= thd->lex;
/*
- TRUE defines that either a trx-cache or stmt-cache must be used
- and wrapped by a BEGIN...COMMIT. Otherwise, the statement will
- be written directly to the binary log without being wrapped by
- a BEGIN...COMMIT.
+ Defines that the statement will be written directly to the binary log
+ without being wrapped by a BEGIN...COMMIT. Otherwise, the statement
+ will be written to either the trx-cache or stmt-cache.
- Note that a cache will not be used if the parameter direct is
- TRUE.
+ Note that a cache will not be used if the parameter direct is TRUE.
*/
bool use_cache= FALSE;
/*
- TRUE defines that the trx-cache must be used and by consequence
- the use_cache is TRUE.
+ TRUE defines that the trx-cache must be used and by consequence the
+ use_cache is TRUE.
- Note that a cache will not be used if the parameter direct is
- TRUE.
+ Note that a cache will not be used if the parameter direct is TRUE.
*/
bool trx_cache= FALSE;
cache_type= Log_event::EVENT_INVALID_CACHE;
@@ -2490,16 +2487,14 @@ Query_log_event::Query_log_event(THD* th
switch (lex->sql_command)
{
case SQLCOM_DROP_TABLE:
- use_cache= trx_cache= (lex->drop_temporary &&
- thd->in_multi_stmt_transaction_mode());
+ use_cache= (lex->drop_temporary && thd->in_multi_stmt_transaction_mode());
break;
case SQLCOM_CREATE_TABLE:
- use_cache= trx_cache=
- ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- thd->in_multi_stmt_transaction_mode()) ||
- (lex->select_lex.item_list.elements &&
+ trx_cache= (lex->select_lex.item_list.elements &&
thd->is_current_stmt_binlog_format_row());
+ use_cache= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
+ thd->in_multi_stmt_transaction_mode()) || trx_cache;
break;
case SQLCOM_SET_OPTION:
use_cache= trx_cache= (lex->autocommit ? FALSE : TRUE);
@@ -2518,14 +2513,13 @@ Query_log_event::Query_log_event(THD* th
{
cache_type= Log_event::EVENT_NO_CACHE;
}
- else
- {
- cache_type= ((using_trans || stmt_has_updated_trans_table(thd) || trx_cache ||
- (thd->lex->stmt_accessed_temp_table() &&
- trans_has_updated_trans_table(thd)))
- ? Log_event::EVENT_TRANSACTIONAL_CACHE :
- Log_event::EVENT_STMT_CACHE);
- }
+ else if (using_trans || trx_cache || stmt_has_updated_trans_table(thd) ||
+ thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
+ thd->tx_isolation,
+ trans_has_updated_trans_table(thd)))
+ cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
+ else
+ cache_type= Log_event::EVENT_STMT_CACHE;
DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu",
(ulong) flags2, sql_mode));
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-07-09 09:05:17 +0000
+++ b/sql/sql_class.cc 2010-07-11 19:35:51 +0000
@@ -3768,124 +3768,14 @@ int THD::decide_logging_format(TABLE_LIS
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:
-
- 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);
- }
+ bool multi_stmt_trans= in_multi_stmt_transaction_mode();
+ bool trans_table= trans_has_updated_trans_table(this);
+ if (lex->is_mixed_stmt_unsafe(multi_stmt_trans, tx_isolation, trans_table))
+ lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_MIXED_STATEMENT);
+ else if (multi_stmt_trans && trans_table &&
+ !variables.binlog_direct_non_trans_update &&
+ 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
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-07-09 09:05:17 +0000
+++ b/sql/sql_lex.h 2010-07-11 19:35:51 +0000
@@ -1332,7 +1332,7 @@ public:
*/
inline void set_stmt_accessed_table(enum_stmt_accessed_table accessed_table)
{
- DBUG_ENTER("THD::set_stmt_accessed_table");
+ DBUG_ENTER("LEX::set_stmt_accessed_table");
DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT);
stmt_accessed_table_flag |= (1U << accessed_table);
@@ -1353,49 +1353,156 @@ public:
*/
inline bool stmt_accessed_table(enum_stmt_accessed_table accessed_table)
{
- DBUG_ENTER("THD::stmt_accessed_table");
+ DBUG_ENTER("LEX::stmt_accessed_table");
DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT);
DBUG_RETURN((stmt_accessed_table_flag & (1U << accessed_table)) != 0);
}
- /**
- Checks if a temporary table is about to be accessed while executing a
- statement.
-
- @return
- @retval TRUE if a temporary table is about to be accessed
- @retval FALSE otherwise
- */
- inline bool stmt_accessed_temp_table()
+ inline bool is_mixed_stmt_unsafe(bool in_multi_stmt_transaction_mode,
+ uint tx_isolation,
+ bool trx_cache_is_not_empty)
{
- DBUG_ENTER("THD::stmt_accessed_temp_table");
-
- DBUG_RETURN((stmt_accessed_table_flag &
- ((1U << STMT_READS_TEMP_TRANS_TABLE) |
- (1U << STMT_WRITES_TEMP_TRANS_TABLE) |
- (1U << STMT_READS_TEMP_NON_TRANS_TABLE) |
- (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0);
- }
+ my_bool mixed_unsafe= FALSE;
- /**
- Checks if a temporary non-transactional table is about to be accessed
- while executing a statement.
+ DBUG_ENTER("LEX::is_mixed_stmt_unsafe");
+ /*
+ Classify a statement as unsafe when there is a mixed statement and an
+ on-going transaction at any point of the execution if:
- @return
- @retval TRUE if a temporary non-transactional table is about to be
- accessed
- @retval FALSE otherwise
- */
- inline bool stmt_accessed_non_trans_temp_table()
- {
- DBUG_ENTER("THD::stmt_accessed_non_trans_temp_table");
+ 1. The mixed statement is about to update a transactional table and
+ a non-transactional table.
- DBUG_RETURN((stmt_accessed_table_flag &
- ((1U << STMT_READS_TEMP_NON_TRANS_TABLE) |
- (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0);
- }
+ 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)
+ {
+ /* Case 1. */
+ if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 2. */
+ else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 3. */
+ else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 4. */
+ else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_TEMP_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 5. */
+ else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 6. */
+ else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+ stmt_accessed_table(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;
+ /* Case 7. */
+ else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 8. */
+ else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 9. */
+ else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_TEMP_NON_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 10. */
+ else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
+ stmt_accessed_table(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 (trx_cache_is_not_empty)
+ {
+ /* Case 11. */
+ if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 12 */
+ else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_TEMP_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 13. */
+ else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ /* Case 14. */
+ else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
+ stmt_accessed_table(STMT_READS_TEMP_TRANS_TABLE))
+ mixed_unsafe= TRUE;
+ }
+ }
+ DBUG_RETURN(mixed_unsafe);
+ }
/**
true if the parsed tree contains references to stored procedures
Attachment: [text/bzr-bundle]
| Thread |
|---|
| • bzr commit into mysql-trunk-bugfixing branch (alfranio.correia:3087) | Alfranio Correia | 11 Jul |