3920 Marko Mäkelä 2012-05-31
Fix race condition in InnoDB transaction commit flushing.
trx_flush_log_if_needed_low(), trx_flush_log_if_needed():
Refactored common code. Read srv_flush_log_at_trx_commit only once.
Previously, a race condition could occur if srv_flush_log_at_trx_commit
changed during the checks.
trx_commit(), trx_prepare(), trx_commit_complete_for_mysql():
Invoke trx_flush_log_if_needed() instead of duplicating the code.
modified:
storage/innobase/include/trx0trx.h
storage/innobase/trx/trx0trx.cc
3919 Marko Mäkelä 2012-05-31
WL#6255: Fix a bug that affected ROW_FORMAT conversions
of tables that contain fulltext indexes.
innobase_create_key_defs(): Test for "rebuild" instead of "new_primary".
modified:
storage/innobase/handler/handler0alter.cc
=== modified file 'storage/innobase/include/trx0trx.h'
--- a/storage/innobase/include/trx0trx.h revid:marko.makela@strippedlwqw7qhym51maf
+++ b/storage/innobase/include/trx0trx.h revid:marko.makela@strippedl6a
@@ -224,13 +224,13 @@ trx_get_trx_by_xid(
const XID* xid); /*!< in: X/Open XA transaction identifier */
/**********************************************************************//**
If required, flushes the log to disk if we called trx_commit_for_mysql()
-with trx->flush_log_later == TRUE.
-@return 0 or error number */
+with trx->flush_log_later == TRUE. */
UNIV_INTERN
-ulint
+void
trx_commit_complete_for_mysql(
/*==========================*/
- trx_t* trx); /*!< in: trx handle */
+ trx_t* trx) /*!< in/out: transaction */
+ __attribute__((nonnull));
/**********************************************************************//**
Marks the latest SQL statement ended. */
UNIV_INTERN
=== modified file 'storage/innobase/trx/trx0trx.cc'
--- a/storage/innobase/trx/trx0trx.cc revid:marko.makela@stripped
+++ b/storage/innobase/trx/trx0trx.cc revid:marko.makela@oracle.com-20120531182212-u1l372oy77ggvl6a
@@ -987,6 +987,51 @@ trx_finalize_for_fts(
trx->fts_trx = NULL;
}
+/**********************************************************************//**
+If required, flushes the log to disk based on the value of
+innodb_flush_log_at_trx_commit. */
+static __attribute__((nonnull))
+void
+trx_flush_log_if_needed_low(
+/*========================*/
+ lsn_t lsn) /*!< in: lsn up to which logs are to be
+ flushed. */
+{
+ switch (srv_flush_log_at_trx_commit) {
+ case 0:
+ /* Do nothing */
+ break;
+ case 1:
+ /* Write the log and optionally flush it to disk */
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP,
+ srv_unix_file_flush_method != SRV_UNIX_NOSYNC);
+ break;
+ case 2:
+ /* Write the log but do not flush it to disk */
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
+
+ break;
+ default:
+ ut_error;
+ }
+}
+
+/**********************************************************************//**
+If required, flushes the log to disk based on the value of
+innodb_flush_log_at_trx_commit. */
+static __attribute__((nonnull))
+void
+trx_flush_log_if_needed(
+/*====================*/
+ lsn_t lsn, /*!< in: lsn up to which logs are to be
+ flushed. */
+ trx_t* trx) /*!< in/out: transaction */
+{
+ trx->op_info = "flushing log";
+ trx_flush_log_if_needed_low(lsn);
+ trx->op_info = "";
+}
+
/****************************************************************//**
Commits a transaction. */
UNIV_INTERN
@@ -1151,25 +1196,8 @@ trx_commit(
|| thd_requested_durability(trx->mysql_thd)
== HA_IGNORE_DURABILITY) {
/* Do nothing */
- } else if (srv_flush_log_at_trx_commit == 1) {
- if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP,
- FALSE);
- } else {
- /* Write the log to the log files AND flush
- them to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
- }
- } else if (srv_flush_log_at_trx_commit == 2) {
-
- /* Write the log but do not flush it to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
} else {
- ut_error;
+ trx_flush_log_if_needed(lsn, trx);
}
trx->commit_lsn = lsn;
@@ -1430,63 +1458,24 @@ trx_commit_for_mysql(
/**********************************************************************//**
If required, flushes the log to disk if we called trx_commit_for_mysql()
-with trx->flush_log_later == TRUE.
-@return 0 or error number */
+with trx->flush_log_later == TRUE. */
UNIV_INTERN
-ulint
+void
trx_commit_complete_for_mysql(
/*==========================*/
- trx_t* trx) /*!< in: trx handle */
+ trx_t* trx) /*!< in/out: transaction */
{
- lsn_t lsn = trx->commit_lsn;
-
ut_a(trx);
- if (!trx->must_flush_log_later) {
- return(0);
+ if (!trx->must_flush_log_later
+ || thd_requested_durability(trx->mysql_thd)
+ == HA_IGNORE_DURABILITY) {
+ return;
}
- trx->op_info = "flushing log";
-
- switch (srv_flush_log_at_trx_commit) {
- case 0:
- /* Do nothing */
- break;
- case 1:
- if (thd_requested_durability(trx->mysql_thd)
- == HA_IGNORE_DURABILITY) {
- break;
- }
-
- if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
- } else {
- /* Write the log to the log files AND flush them to
- disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
- }
-
- break;
- case 2:
- if (thd_requested_durability(trx->mysql_thd)
- == HA_IGNORE_DURABILITY) {
- break;
- }
-
- /* Write the log but do not flush it to disk */
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
- default:
- ut_error;
- }
+ trx_flush_log_if_needed(trx->commit_lsn, trx);
trx->must_flush_log_later = FALSE;
-
- trx->op_info = "";
-
- return(0);
}
/**********************************************************************//**
@@ -1859,28 +1848,7 @@ trx_prepare(
TODO: find out if MySQL holds some mutex when calling this.
That would spoil our group prepare algorithm. */
- if (srv_flush_log_at_trx_commit == 0) {
- /* Do nothing */
- } else if (srv_flush_log_at_trx_commit == 1) {
- if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP,
- FALSE);
- } else {
- /* Write the log to the log files AND flush
- them to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
- }
- } else if (srv_flush_log_at_trx_commit == 2) {
-
- /* Write the log but do not flush it to disk */
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
- } else {
- ut_error;
- }
+ trx_flush_log_if_needed(lsn, trx);
}
}
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk-wl6255 branch (marko.makela:3919 to 3920) | marko.makela | 31 May |