summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/ha_innobase.cc21
-rw-r--r--sql/ha_innobase.h5
-rw-r--r--sql/handler.cc40
-rw-r--r--sql/handler.h4
-rw-r--r--sql/log.cc21
-rw-r--r--sql/sql_class.h2
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);