Split the code in binlog_flush_trx_cache() so that we can do some in binlog_prepare() and some in log_xid(). This in preparation for implementing group commit for binlog. --- sql/log.cc | 111 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 60 insertions(+), 51 deletions(-) Index: work-5.1-groupcommit/sql/log.cc =================================================================== --- work-5.1-groupcommit.orig/sql/log.cc 2010-06-09 11:54:18.000000000 +0200 +++ work-5.1-groupcommit/sql/log.cc 2010-06-09 11:54:20.000000000 +0200 @@ -1391,6 +1391,43 @@ static int binlog_close_connection(handl return 0; } +/* Helper functions for binlog_flush_trx_cache(). */ +static int +binlog_flush_trx_cache_prepare(THD *thd) +{ + if (thd->binlog_flush_pending_rows_event(TRUE)) + return 1; + return 0; +} + +static int +binlog_flush_trx_cache_log(THD *thd, binlog_trx_data *trx_data, + Log_event *end_ev) +{ + IO_CACHE *trans_log= &trx_data->trans_log; + /* + Doing a commit or a rollback including non-transactional tables, + i.e., ending a transaction where we might write the transaction + cache to the binary log. + + We can always end the statement when ending a transaction since + transactions are not allowed inside stored functions. If they + were, we would have to ensure that we're not ending a statement + inside a stored function. + */ + int error= mysql_bin_log.write_transaction_to_binlog(thd, trx_data, end_ev); + + trx_data->reset(); + + statistic_increment(binlog_cache_use, &LOCK_status); + if (trans_log->disk_writes != 0) + { + statistic_increment(binlog_cache_disk_use, &LOCK_status); + trans_log->disk_writes= 0; + } + return error; +} + /* End a transaction, writing events to the binary log. @@ -1416,34 +1453,15 @@ binlog_flush_trx_cache(THD *thd, binlog_ Log_event *end_ev) { DBUG_ENTER("binlog_flush_trx_cache"); - int error; - IO_CACHE *trans_log= &trx_data->trans_log; DBUG_PRINT("enter", ("end_ev: 0x%lx", (long) end_ev)); DBUG_PRINT("info", ("thd->options={ %s%s}", FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT), FLAGSTR(thd->options, OPTION_BEGIN))); - if (thd->binlog_flush_pending_rows_event(TRUE)) + if (binlog_flush_trx_cache_prepare(thd)) DBUG_RETURN(1); - /* - Doing a commit or a rollback including non-transactional tables, - i.e., ending a transaction where we might write the transaction - cache to the binary log. - We can always end the statement when ending a transaction since - transactions are not allowed inside stored functions. If they - were, we would have to ensure that we're not ending a statement - inside a stored function. - */ - error= mysql_bin_log.write_transaction_to_binlog(thd, trx_data, end_ev); - trx_data->reset(); - - statistic_increment(binlog_cache_use, &LOCK_status); - if (trans_log->disk_writes != 0) - { - statistic_increment(binlog_cache_disk_use, &LOCK_status); - trans_log->disk_writes= 0; - } + int error= binlog_flush_trx_cache_log(thd, trx_data, end_ev); DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL); DBUG_RETURN(error); @@ -1508,13 +1526,7 @@ binlog_truncate_trx_cache(THD *thd, binl static int binlog_prepare(handlerton *hton, THD *thd, bool all) { - /* - do nothing. - just pretend we can do 2pc, so that MySQL won't - switch to 1pc. - real work will be done in MYSQL_BIN_LOG::log_xid() - */ - return 0; + return binlog_flush_trx_cache_prepare(thd); } /** @@ -4205,44 +4217,41 @@ MYSQL_BIN_LOG::flush_and_set_pending_row if (Rows_log_event* pending= trx_data->pending()) { - IO_CACHE *file= &log_file; - /* Decide if we should write to the log file directly or to the transaction log. */ if (pending->get_cache_stmt() || my_b_tell(&trx_data->trans_log)) - file= &trx_data->trans_log; - - /* - If we are writing to the log file directly, we could avoid - locking the log. - */ - pthread_mutex_lock(&LOCK_log); - - /* - Write pending event to log file or transaction cache - */ - if (pending->write(file)) { - pthread_mutex_unlock(&LOCK_log); - set_write_error(thd); - DBUG_RETURN(1); + /* Write to transaction log/cache. */ + if (pending->write(&trx_data->trans_log)) + { + set_write_error(thd); + DBUG_RETURN(1); + } } - - delete pending; - - if (file == &log_file) + else { + /* Write directly to log file. */ + pthread_mutex_lock(&LOCK_log); + if (pending->write(&log_file)) + { + pthread_mutex_unlock(&LOCK_log); + set_write_error(thd); + DBUG_RETURN(1); + } + error= flush_and_sync(); if (!error) { signal_update(); rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); } + + pthread_mutex_unlock(&LOCK_log); } - pthread_mutex_unlock(&LOCK_log); + delete pending; } thd->binlog_set_pending_rows_event(event); @@ -5885,7 +5894,7 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_ We always commit the entire transaction when writing an XID. Also note that the return value is inverted. */ - DBUG_RETURN(!binlog_flush_trx_cache(thd, trx_data, &xle)); + DBUG_RETURN(!binlog_flush_trx_cache_log(thd, trx_data, &xle)); } void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)