diff options
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 120 |
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; |