summaryrefslogtreecommitdiff
path: root/sql/log.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc120
1 files changed, 78 insertions, 42 deletions
diff --git a/sql/log.cc b/sql/log.cc
index de501d94100..cb789e7f9f3 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -61,6 +61,8 @@
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_TIME_SIZE 32
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
+/* Truncate cache log files bigger than this */
+#define CACHE_FILE_TRUNC_SIZE 65536
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
@@ -250,7 +252,8 @@ void make_default_log_name(char **out, const char* log_ext, bool once)
class binlog_cache_data
{
public:
- binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
+ binlog_cache_data(): m_pending(0), status(0),
+ before_stmt_pos(MY_OFF_T_UNDEF),
incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE),
saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
ptr_binlog_cache_disk_use(0)
@@ -262,9 +265,22 @@ public:
close_cached_file(&cache_log);
}
+ /*
+ Return 1 if there is no relevant entries in the cache
+
+ This is:
+ - Cache is empty
+ - There are row or critical (DDL?) events in the cache
+
+ The status test is needed to avoid writing entries with only
+ a table map entry, which would crash in do_apply_event() on the slave
+ as it assumes that there is always a row entry after a table map.
+ */
bool empty() const
{
- return pending() == NULL && my_b_tell(&cache_log) == 0;
+ return (pending() == NULL &&
+ (my_b_write_tell(&cache_log) == 0 ||
+ ((status & (LOGGED_ROW_EVENT | LOGGED_CRITICAL)) == 0)));
}
Rows_log_event *pending() const
@@ -299,23 +315,19 @@ public:
void reset()
{
- compute_statistics();
- truncate(0);
- if(cache_log.file != -1)
+ bool cache_was_empty= empty();
+ bool truncate_file= (cache_log.file != -1 &&
+ my_b_write_tell(&cache_log) > CACHE_FILE_TRUNC_SIZE);
+ truncate(0,1); // Forget what's in cache
+ if (!cache_was_empty)
+ compute_statistics();
+ if (truncate_file)
my_chsize(cache_log.file, 0, 0, MYF(MY_WME));
changes_to_non_trans_temp_table_flag= FALSE;
+ status= 0;
incident= FALSE;
before_stmt_pos= MY_OFF_T_UNDEF;
- /*
- The truncate function calls reinit_io_cache that calls
- my_b_flush_io_cache which may increase disk_writes. This breaks
- the disk_writes use by the binary log which aims to compute the
- ratio between in-memory cache usage and disk cache usage. To
- avoid this undesirable behavior, we reset the variable after
- truncating the cache.
- */
- cache_log.disk_writes= 0;
DBUG_ASSERT(empty());
}
@@ -376,6 +388,11 @@ public:
cache_log.end_of_file= saved_max_binlog_cache_size;
}
+ void add_status(enum_logged_status status_arg)
+ {
+ status|= status_arg;
+ }
+
/*
Cache to store data before copying it to the binary log.
*/
@@ -389,6 +406,13 @@ private:
Rows_log_event *m_pending;
/*
+ Bit flags for what has been writting to cache. Used to
+ discard logs without any data changes.
+ see enum_logged_status;
+ */
+ uint32 status;
+
+ /*
Binlog position before the start of the current statement.
*/
my_off_t before_stmt_pos;
@@ -410,11 +434,16 @@ private:
*/
void compute_statistics()
{
- if (!empty())
+ statistic_increment(*ptr_binlog_cache_use, &LOCK_status);
+ if (cache_log.disk_writes != 0)
{
- statistic_increment(*ptr_binlog_cache_use, &LOCK_status);
- if (cache_log.disk_writes != 0)
- statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status);
+#ifdef REAL_STATISTICS
+ statistic_add(*ptr_binlog_cache_disk_use,
+ cache_log.disk_writes, &LOCK_status);
+#else
+ statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status);
+#endif
+ cache_log.disk_writes= 0;
}
}
@@ -443,7 +472,7 @@ private:
It truncates the cache to a certain position. This includes deleting the
pending event.
*/
- void truncate(my_off_t pos)
+ void truncate(my_off_t pos, bool reset_cache=0)
{
DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
if (pending())
@@ -451,7 +480,7 @@ private:
delete pending();
set_pending(0);
}
- reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, 0);
+ reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, reset_cache);
cache_log.end_of_file= saved_max_binlog_cache_size;
}
@@ -459,6 +488,13 @@ private:
binlog_cache_data(const binlog_cache_data& info);
};
+
+void Log_event_writer::add_status(enum_logged_status status)
+{
+ if (likely(cache_data))
+ cache_data->add_status(status);
+}
+
class binlog_cache_mngr {
public:
binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size,
@@ -976,7 +1012,7 @@ int Log_to_csv_event_handler::
{
TABLE_LIST table_list;
TABLE *table;
- LEX_STRING *UNINIT_VAR(log_name);
+ LEX_CSTRING *UNINIT_VAR(log_name);
int result;
Open_tables_backup open_tables_backup;
@@ -5190,12 +5226,14 @@ end:
DBUG_RETURN(error);
}
-bool MYSQL_BIN_LOG::write_event(Log_event *ev, IO_CACHE *file)
+bool MYSQL_BIN_LOG::write_event(Log_event *ev, binlog_cache_data *cache_data,
+ IO_CACHE *file)
{
- Log_event_writer writer(file, &crypto);
+ Log_event_writer writer(file, 0, &crypto);
if (crypto.scheme && file == &log_file)
writer.ctx= alloca(crypto.ctx_size);
-
+ if (cache_data)
+ cache_data->add_status(ev->logged_status());
return writer.write(ev);
}
@@ -5632,12 +5670,10 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
-
- IO_CACHE *file=
- cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional));
- Log_event_writer writer(file);
- binlog_cache_data *cache_data=
- cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
+ binlog_cache_data *cache_data= (cache_mngr->
+ get_binlog_cache_data(is_transactional));
+ IO_CACHE *file= &cache_data->cache_log;
+ Log_event_writer writer(file, cache_data);
if (with_annotate && *with_annotate)
{
@@ -5778,7 +5814,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
if (Rows_log_event* pending= cache_data->pending())
{
- Log_event_writer writer(&cache_data->cache_log);
+ Log_event_writer writer(&cache_data->cache_log, cache_data);
/*
Write pending event to the cache.
@@ -6190,8 +6226,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
goto err;
is_trans_cache= use_trans_cache(thd, using_trans);
- file= cache_mngr->get_binlog_cache_log(is_trans_cache);
cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
+ file= &cache_data->cache_log;
if (thd->lex->stmt_accessed_non_trans_temp_table())
cache_data->set_changes_to_non_trans_temp_table();
@@ -6215,21 +6251,19 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
Annotate_rows_log_event anno(thd, using_trans, direct);
/* Annotate event should be written not more than once */
*with_annotate= 0;
- if (write_event(&anno, file))
+ if (write_event(&anno, cache_data, file))
goto err;
}
- if (thd)
{
if (!thd->is_current_stmt_binlog_format_row())
{
-
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
{
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
thd->first_successful_insert_id_in_prev_stmt_for_binlog,
using_trans, direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
@@ -6240,14 +6274,14 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
thd->auto_inc_intervals_in_cur_stmt_for_binlog.
minimum(), using_trans, direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
if (thd->rand_used)
{
Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2,
using_trans, direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
if (thd->user_var_events.elements)
@@ -6271,7 +6305,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
flags,
using_trans,
direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
}
@@ -6281,7 +6315,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
/*
Write the event.
*/
- if (write_event(event_info, file) ||
+ if (write_event(event_info, cache_data, file) ||
DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0))
goto err;
@@ -6666,7 +6700,8 @@ public:
CacheWriter(THD *thd_arg, IO_CACHE *file_arg, bool do_checksum,
Binlog_crypt_data *cr)
- : Log_event_writer(file_arg, cr), remains(0), thd(thd_arg), first(true)
+ : Log_event_writer(file_arg, 0, cr), remains(0), thd(thd_arg),
+ first(true)
{ checksum_len= do_checksum ? BINLOG_CHECKSUM_LEN : 0; }
~CacheWriter()
@@ -6674,6 +6709,7 @@ public:
int write(uchar* pos, size_t len)
{
+ DBUG_ENTER("CacheWriter::write");
if (first)
write_header(pos, len);
else
@@ -6682,7 +6718,7 @@ public:
remains -= len;
if ((first= !remains))
write_footer();
- return 0;
+ DBUG_RETURN(0);
}
private:
THD *thd;