Commit 2d4b76b8 authored by Sujatha Sivakumar's avatar Sujatha Sivakumar

Bug#16513588:"PREPARE_COMMIT_MUTEX" IS NOT FREED DURING

TRANSACTION ROLLBACK

Problem:
=======
"prepare_commit_mutex" is acquired during "innobase_xa_prepare"
and it is freed only in "innobase_commit". After prepare,
if the commit operation fails the transaction is rolled back
but the mutex is not released.

Analysis:
========
During transaction commit process transaction is prepared and
the "prepare_commit_mutex" is acquired to preserve the order
of commit. After prepare write to binlog is initiated.

File: sql/handler.cc
      if (error || (is_real_trans && xid &&
----->             (error= !(cookie= tc_log->log_xid(thd, xid)))))
      {
        ha_rollback_trans(thd, all);

In the above code "tc_log->log_xid" operation fails.

When the write to binlog fails the transaction is rolled back
with out freeing the mutex. A subsequent "INSERT" operation
tries to acquire the same mutex during its commit process
and the server aborts.

Fix:
===
"prepare_commit_mutex" is freed during "innobase_rollback".

storage/innobase/handler/ha_innodb.cc:
  Added code to free "prepare_commit_mutex"
parent 58ba9695
...@@ -2881,6 +2881,9 @@ innobase_rollback( ...@@ -2881,6 +2881,9 @@ innobase_rollback(
|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
error = trx_rollback_for_mysql(trx); error = trx_rollback_for_mysql(trx);
if (trx_has_prepare_commit_mutex(trx)) {
mysql_mutex_unlock(&prepare_commit_mutex);
}
trx_deregister_from_2pc(trx); trx_deregister_from_2pc(trx);
} else { } else {
error = trx_rollback_last_sql_stat_for_mysql(trx); error = trx_rollback_last_sql_stat_for_mysql(trx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment