fails in PB sporadically)
The IO thread can concurrently access the relay log IO_CACHE
while another thread is performing an FLUSH LOGS procedure.
FLUSH LOGS closes and reopens the relay log and while doing so it
(re)initializes its IO_CACHE. During this procedure the IO_CACHE
mutex is also reinitialized, which can cause problems if some
other thread (namely the IO THREAD) is concurrently accessing it
at the time .
This patch fixes the problem by extending the interface of the
flush_master_info function to also include a second paramater,
"need_relay_log_lock", stating whether the thread should grab the
relay log lock or not before actually flushing the relay log.
Also, IO thread now calls flush_master_info with this flag set
when it flushes master info with in the event read_event loop.
Finally, we also increase loop time in rpl_heartbeat_basic test
case, so that the number of calls to flush logs doubles, stressing
this part of the code a little more.
The root cause of the crash is that a TranxNode is freed before it is used.
A TranxNode is allocated and inserted into the active list each time
a log event is written and flushed into the binlog file.
The memory for TranxNode is allocated with thd_alloc and will be freed
at the end of the statement. The after_commit/after_rollback callback
was supposed to be called before the end of each statement and remove the node from
the active list. However this assumption is not correct in all cases(e.g. call
'CREATE TEMPORARY TABLE myisam_t SELECT * FROM innodb_t' in a transaction
and delete all temporary tables automatically when a session closed),
and can cause the memory allocated for TranxNode be freed
before it was removed from the active list. So The TranxNode pointer in the active
list would become a wild pointer and cause the crash.
After this patch, We have a class called a TranxNodeAllocate which manages the memory
for allocating and freeing TranxNode. It uses my_malloc to allocate memory.
The auto-inc unsafe warning makes sense even though it's just
one auto-inc table could be involved via a trigger or a stored
function.
However its content was not updated by bug@45677 fixes continuing to mention
two tables whereas the fixes refined semantics of replication of auto_increment
in stored routine.
Fixed with updating the error message, renaming the error and an internal unsafe-condition
constants.
A documentation notice
======================
Inserting into an autoincrement column in a stored function or a trigger
is unsafe for replication.
Even with just one autoincrement column, if the routine is invoked more than
once slave is not guaranteed to execute the statement graph same way as
the master.
And since it's impossible to estimate how many times a routine can be invoked at
the query pre-execution phase (see lock_tables), the statement is marked
pessimistically unsafe.
It is well-known that due to concurrency issues, a slave can become
inconsistent when a transaction contains updates to both transaction and
non-transactional tables.
In a nutshell, the current code-base tries to preserve causality among the
statements by writing non-transactional statements to the txn-cache which
is flushed upon commit. However, modifications done to non-transactional
tables on behalf of a transaction become immediately visible to other
connections but may not immediately get into the binary log and therefore
consistency may be broken.
In general, it is impossible to automatically detect causality/dependency
among statements by just analyzing the statements sent to the server. This
happen because dependency may be hidden in the application code and it is
necessary to know a priori all the statements processed in the context of
a transaction such as in a procedure. Moreover, even for the few cases that
we could automatically address in the server, the computation effort
required could make the approach infeasible.
So, in this patch we introduce the option
- "--binlog-direct-non-transactional-updates" that can be used to bypass
the current behavior in order to write directly to binary log statements
that change non-transactional tables.
Besides, it is used to enable the WL#2687 which is disabled by default.
Problem: The test case failed because: (i) warning text in
result file differed from the warning output by the
server, and (ii) binlog contents in result file did
not show the statements logged wrapped in BEGIN/COMMIT
as it is the case after WL 2687.
Solution: We update the result file, but first we change the
unsafe warning text to also refer to performance_schema
table(s). This required changing the result files for
existing test cases that provide output for warnings
related to ER_BINLOG_UNSAFE_SYSTEM_TABLE. "Grepping" in
result files, shows that only binlog_unsafe contained
reference to such a warning.
We also update the result file with the missing
BEGIN/COMMIT statements.
- mysqld--help-win
Updated result so that it contains missing
value for slave-type-conversions
- rpl_idempotency
This seems a bad merge. In BUG#39934, the contents of
this file had been split into rpl_row_idempontency and
rpl_idempotency. The patch was pushed to 5.1-rep+3 which
was later merged in rep+2-delivery1 which in turn was
merged in 5.1-rpl-merge. Now while merging next-mr in
5.1-rpl-merge, the file got back it's old content (which
is in rpl_row_idempotency now because of BUG#39934). This
cset reverts the bad merge:
bzr merge -r revid:dao-gang.qu@sun.com-20100112120709-ioxp11yl9bvquaqd..\
before:revid:dao-gang.qu@sun.com-20100112120709-ioxp11yl9bvquaqd\
suite/rpl/t/rpl_idempotency.test
- sys_vars.all_vars:
Added test case for slave_type_conversions variable
- rpl_row_idempotency
Removed ER_SLAVE_AMBIGOUS_EXEC_MODE (which was removed by WL 4738)
from the test case. Using ER_WRONG_VALUE_FOR_VAR instead.
- mysqld--help-win
Added missing help for --slave-type-conversions from the
result file.
The test case did not start with fresh binlogs, so in some
cases, dependending on the order MTR runs the tests, it would
try to show binlog contents from invalid positions (binary log
would contain unexpected events from previous test).
We fix this by deploying a RESET MASTER at the beginning of the
test case.
Conflicts:
Text conflict in .bzr-mysql/default.conf
Text conflict in mysql-test/extra/rpl_tests/rpl_loaddata.test
Text conflict in mysql-test/r/mysqlbinlog2.result
Text conflict in mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
Text conflict in mysql-test/suite/binlog/r/binlog_unsafe.result
Text conflict in mysql-test/suite/rpl/r/rpl_insert_id.result
Text conflict in mysql-test/suite/rpl/r/rpl_loaddata.result
Text conflict in mysql-test/suite/rpl/r/rpl_stm_auto_increment_bug33029.result
Text conflict in mysql-test/suite/rpl/r/rpl_udf.result
Text conflict in mysql-test/suite/rpl/t/rpl_slow_query_log.test
Text conflict in sql/field.h
Text conflict in sql/log.cc
Text conflict in sql/log_event.cc
Text conflict in sql/log_event_old.cc
Text conflict in sql/mysql_priv.h
Text conflict in sql/share/errmsg.txt
Text conflict in sql/sp.cc
Text conflict in sql/sql_acl.cc
Text conflict in sql/sql_base.cc
Text conflict in sql/sql_class.h
Text conflict in sql/sql_db.cc
Text conflict in sql/sql_delete.cc
Text conflict in sql/sql_insert.cc
Text conflict in sql/sql_lex.cc
Text conflict in sql/sql_lex.h
Text conflict in sql/sql_load.cc
Text conflict in sql/sql_table.cc
Text conflict in sql/sql_update.cc
Text conflict in sql/sql_view.cc
Conflict adding files to storage/innobase. Created directory.
Conflict because storage/innobase is not versioned, but has versioned children. Versioned directory.
Conflict adding file storage/innobase. Moved existing file to storage/innobase.moved.
Conflict adding files to storage/innobase/handler. Created directory.
Conflict because storage/innobase/handler is not versioned, but has versioned children. Versioned directory.
Contents conflict in storage/innobase/handler/ha_innodb.cc
"set engine_condition_pushdown" is deprecated, engine condition pushdown is controlled
by a new "set optimizer_switch=engine_condition_pushdown=on|off".
In auto-commit mode, updating both trx and non-trx tables (i.e. issuing a mixed
statement) causes the following sequence of events:
1 - "Flush trx changes" (MYSQL_BIN_LOG::write) - T1:
1.1 - mutex_lock (&LOCK_log)
1.2 - mutex_lock (&LOCK_prep_xids)
1.3 - increase prepared_xids
1.4 - mutex_unlock (&LOCK_prep_xids)
1.5 - mutex_unlock (&LOCK_log)
2 - "Flush non-trx changes" (MYSQL_BIN_LOG::write) - T1:
2.1 - mutex_lock (&LOCK_log)
2.2 - mutex_unlock (&LOCK_log)
3. "unlog" - T1
3.1 - mutex_lock (&LOCK_prep_xids)
3.2 - decrease prepared xids
3.3 - pthread_cond_signal(&COND_prep_xids);
3.4 - mutex_unlock (&LOCK_prep_xids)
The "FLUSH logs" command produces the following sequence of events:
1 - "FLUSH logs" command (MYSQL_BIN_LOG::new_file_impl) - user thread:
1.1 - mutex_lock (&LOCK_log)
1.2 - mutex_lock (&LOCK_prep_xids)
1.3 - while (prepared_xids) pthread_cond_wait(..., &LOCK_prep_xids);
1.4 - mutex_unlock (&LOCK_prep_xids)
1.5 - mutex_unlock (&LOCK_log)
A deadlock will arise if T1 flushes the trx changes and thus increases
prepared_xids but before it is able to continue the execution and flush the
non-trx changes, an user thread calls the "FLUSH logs" command and wait that
the prepared_xids is decreased and gets to zero. However, T1 cannot proceed
with the call to "Flush non-trx changes" because it will block in the mutex
"LOCK_log" and by consequence cannot complete the execution and call the
unlog to decrease the prepared_xids.
To fix the problem, we ensure that the non-trx changes are always flushed
before the trx changes.
Note that if you call "Flush non-trx changes" and a concurrent "FLUSH logs" is
issued, the "Flush non-trx changes" may block, but a deadlock will never happen
because the prepared_xids will eventually get to zero. Bottom line, there will
not be any transaction able to increase the prepared_xids because they will
block in the mutex "LOCK_log" (MYSQL_BIN_LOG::write) and those that increased
the prepared_xids will eventually commit and decrease the prepared_xids.
- backported code that handles %f/%g arguments in
my_vsnprintf.c from 6.0
- backported %f/%g tests in unittest/mysys/my_vsnprintf-t.c
from 6.0
- replaced snprintf("%g") in sql/set_var.cc with my_gcvt()
- removed unnecessary "--replace-result"s for Windows in
mysql-test/suite/sys_vars/t/long_query_time_basic.test
- some test results adjustments
The 'rpl_cross_version' fails on mysql-next-mr-bugfixing as following:
mysqltest: In included file "./include/setup_fake_relay_log.inc": At line 80: query
'select './$_fake_filename-fake.000001\n' into dumpfile '$_fake_relay_index'' failed:
1290: The MySQL server is running with the --secure-file-priv option so it cannot execute
this statement.
To fix the problem by removeing the --secure-file-priv option
for adapting the update of the 'setup_fake_relay_log.inc'.
Metadata for geometric fields was not being properly stored by
the slave in its the table definition. This happened because
MYSQL_TYPE_GEOMETRY was not included in the 'switch... case' that
handles field metadata according to the field type. Therefore, it
would default to 0, leading to always have a mismatch between
master's field and slave fields'.
We fix this by deploying the missing 'case MYSQL_TYPE_GEOMETRY:'.