diff options
-rw-r--r-- | sql/ha_innobase.cc | 21 | ||||
-rw-r--r-- | sql/ha_innobase.h | 5 | ||||
-rw-r--r-- | sql/handler.cc | 40 | ||||
-rw-r--r-- | sql/handler.h | 4 | ||||
-rw-r--r-- | sql/log.cc | 21 | ||||
-rw-r--r-- | sql/sql_class.h | 2 |
6 files changed, 90 insertions, 3 deletions
diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 62c721de13f..ccb41880fc5 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -731,6 +731,27 @@ innobase_commit( } /********************************************************************* +This is called when MySQL writes the binlog entry for the current +transaction. Writes to the InnoDB tablespace info which tells where the +MySQL binlog entry for the current transaction ended. Also commits the +transaction inside InnoDB. */ + +int +innobase_report_binlog_offset_and_commit( +/*=====================================*/ + /* out: 0 or error code */ + THD* thd, /* in: user thread */ + void* trx_handle, /* in: InnoDB trx handle */ + char* log_file_name, /* in: latest binlog file name */ + my_off_t end_offset) /* in: the offset in the binlog file + up to which we wrote */ +{ + /* Currently does nothing ! */ + + return(0); +} + +/********************************************************************* Rolls back a transaction in an InnoDB database. */ int diff --git a/sql/ha_innobase.h b/sql/ha_innobase.h index 3f4bd5144eb..54449a1ef2b 100644 --- a/sql/ha_innobase.h +++ b/sql/ha_innobase.h @@ -185,6 +185,11 @@ bool innobase_flush_logs(void); uint innobase_get_free_space(void); int innobase_commit(THD *thd, void* trx_handle); +int innobase_report_binlog_offset_and_commit( + THD* thd, + void* trx_handle, + char* log_file_name, + my_off_t end_offset); int innobase_rollback(THD *thd, void* trx_handle); int innobase_close_connection(THD *thd); int innobase_drop_database(char *path); diff --git a/sql/handler.cc b/sql/handler.cc index 0b493219674..c1e28b0058e 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -257,6 +257,44 @@ int ha_autocommit_or_rollback(THD *thd, int error) DBUG_RETURN(error); } +/* This function is called when MySQL writes the log segment of a transaction +to the binlog. It is called when the LOCK_log mutex is reserved. Here we +communicate to transactional table handlers whta binlog position corresponds +to the current transaction. The handler can store it and in recovery print +to the user, so that the user knows from what position in the binlog to +start possible roll-forward, for example, if the crashed server was a slave +in replication. This function also calls the commit of the table handler, +because the order of trasnactions in the log of the table handler must be +the same as in the binlog. */ + +int ha_report_binlog_offset_and_commit( + THD *thd, /* in: user thread */ + char *log_file_name, /* in: latest binlog file name */ + my_off_t end_offset) /* in: the offset in the binlog file + up to which we wrote */ +{ + THD_TRANS *trans; + int error = 0; + + trans = &thd->transaction.all; + +#ifdef HAVE_INNOBASE_DB + if (trans->innobase_tid) + { + if ((error=innobase_report_binlog_offset_and_commit(thd, + trans->innobase_tid, + log_file_name, + end_offset))) + { + my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); + error=1; + } + trans->innodb_active_trans=0; + } +#endif + + return error; +} int ha_commit_trans(THD *thd, THD_TRANS* trans) { @@ -269,7 +307,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) if (trans == &thd->transaction.all && mysql_bin_log.is_open() && my_b_tell(&thd->transaction.trans_log)) { - mysql_bin_log.write(&thd->transaction.trans_log); + mysql_bin_log.write(thd, &thd->transaction.trans_log); reinit_io_cache(&thd->transaction.trans_log, WRITE_CACHE, (my_off_t) 0, 0, 1); thd->transaction.trans_log.end_of_file= max_binlog_cache_size; diff --git a/sql/handler.h b/sql/handler.h index 560420a480d..e4cac60ed67 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -353,6 +353,10 @@ int ha_delete_table(enum db_type db_type, const char *path); void ha_drop_database(char* path); void ha_key_cache(void); int ha_start_stmt(THD *thd); +int ha_report_binlog_offset_and_commit( + THD *thd, + char *log_file_name, + my_off_t end_offset); int ha_commit_trans(THD *thd, THD_TRANS *trans); int ha_rollback_trans(THD *thd, THD_TRANS *trans); int ha_autocommit_or_rollback(THD *thd, int error); diff --git a/sql/log.cc b/sql/log.cc index 1b236d342f5..bc2b19d921f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -658,6 +658,7 @@ bool MYSQL_LOG::write(Query_log_event* event_info) VOID(pthread_mutex_unlock(&LOCK_log)); return 0; } + error=1; if (thd->last_insert_id_used) @@ -694,6 +695,20 @@ bool MYSQL_LOG::write(Query_log_event* event_info) goto err; error=0; should_rotate = (file == &log_file && my_b_tell(file) >= max_binlog_size); + + /* Tell for transactional table handlers up to which position in the + binlog file we wrote. The table handler can store this info, and + after crash recovery print for the user the offset of the last + transactions which were recovered. Actually, we must also call + the table handler commit here, protected by the LOCK_log mutex, + because otherwise the transactions may end up in a different order + in the table handler log! */ + + if (file == &log_file) { + error = ha_report_binlog_offset_and_commit(thd, log_file_name, + file->pos_in_file); + } + err: if (error) { @@ -718,7 +733,7 @@ err: 'cache' needs to be reinitialized after this functions returns. */ -bool MYSQL_LOG::write(IO_CACHE *cache) +bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache) { VOID(pthread_mutex_lock(&LOCK_log)); bool error=1; @@ -754,6 +769,10 @@ bool MYSQL_LOG::write(IO_CACHE *cache) sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno); goto err; } + error = ha_report_binlog_offset_and_commit(thd, log_file_name, + log_file.pos_in_file); + if (error) + goto err; } error=0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 3d218a06d0c..d9497907926 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -82,7 +82,7 @@ public: time_t query_start=0); bool write(Query_log_event* event_info); // binary log write bool write(Load_log_event* event_info); - bool write(IO_CACHE *cache); + bool write(THD *thd, IO_CACHE *cache); int generate_new_name(char *new_name,const char *old_name); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); |