@@ -8417,8 +8417,24 @@ MYSQL_BIN_LOG::sync_binlog_file(bool force)
84178417 if (force || (sync_period && ++sync_counter >= sync_period))
84188418 {
84198419 sync_counter= 0 ;
8420+
8421+ /* *
8422+ On *pure non-transactional* workloads there is a small window
8423+ in time where a concurrent rotate might be able to close
8424+ the file before the sync is actually done. In that case,
8425+ ignore the bad file descriptor errors.
8426+
8427+ Transactional workloads (InnoDB) are not affected since the
8428+ the rotation will not happen until all transactions have
8429+ committed to the storage engine, thence decreased the XID
8430+ counters.
8431+
8432+ TODO: fix this properly even for non-transactional storage
8433+ engines.
8434+ */
84208435 if (DBUG_EVALUATE_IF (" simulate_error_during_sync_binlog_file" , 1 ,
8421- mysql_file_sync (log_file.file , MYF (MY_WME))))
8436+ mysql_file_sync (log_file.file ,
8437+ MYF (MY_WME | MY_IGNORE_BADFD))))
84228438 {
84238439 THD *thd= current_thd;
84248440 thd->commit_error = THD::CE_SYNC_ERROR;
@@ -8756,7 +8772,6 @@ int MYSQL_BIN_LOG::ordered_commit(THD *thd, bool all, bool skip_commit)
87568772 mysql_mutex_t *leave_mutex_before_commit_stage= NULL ;
87578773 my_off_t flush_end_pos= 0 ;
87588774 bool update_binlog_end_pos_after_sync;
8759- bool need_LOCK_log;
87608775 if (unlikely (!is_open ()))
87618776 {
87628777 final_queue= stage_manager.fetch_queue_for (Stage_manager::FLUSH_STAGE);
@@ -8814,16 +8829,8 @@ int MYSQL_BIN_LOG::ordered_commit(THD *thd, bool all, bool skip_commit)
88148829 /*
88158830 Stage #2: Syncing binary log file to disk
88168831 */
8817- need_LOCK_log= sync_counter + 1 >= get_sync_period () && get_prep_xids () == 0 ;
88188832
8819- /*
8820- LOCK_log is not released also when we are about to sync the binary log and
8821- there is no transactional storage engine prepared transactions. This will
8822- guarantee that the binary log rotation will not take place before syncing
8823- the binary log file.
8824- */
8825- if (change_stage (thd, Stage_manager::SYNC_STAGE, wait_queue,
8826- need_LOCK_log ? NULL : &LOCK_log, &LOCK_sync))
8833+ if (change_stage (thd, Stage_manager::SYNC_STAGE, wait_queue, &LOCK_log, &LOCK_sync))
88278834 {
88288835 DBUG_PRINT (" return" , (" Thread ID: %u, commit_error: %d" ,
88298836 thd->thread_id (), thd->commit_error ));
@@ -8854,9 +8861,6 @@ int MYSQL_BIN_LOG::ordered_commit(THD *thd, bool all, bool skip_commit)
88548861 update_binlog_end_pos (tmp_thd->get_trans_pos ());
88558862 }
88568863
8857- if (need_LOCK_log)
8858- mysql_mutex_unlock (&LOCK_log);
8859-
88608864 DEBUG_SYNC (thd, " bgc_after_sync_stage_before_commit_stage" );
88618865
88628866 leave_mutex_before_commit_stage= &LOCK_sync;
0 commit comments