@@ -8417,8 +8417,24 @@ MYSQL_BIN_LOG::sync_binlog_file(bool force)
8417
8417
if (force || (sync_period && ++sync_counter >= sync_period))
8418
8418
{
8419
8419
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
+ */
8420
8435
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))))
8422
8438
{
8423
8439
THD *thd= current_thd;
8424
8440
thd->commit_error = THD::CE_SYNC_ERROR;
@@ -8756,7 +8772,6 @@ int MYSQL_BIN_LOG::ordered_commit(THD *thd, bool all, bool skip_commit)
8756
8772
mysql_mutex_t *leave_mutex_before_commit_stage= NULL ;
8757
8773
my_off_t flush_end_pos= 0 ;
8758
8774
bool update_binlog_end_pos_after_sync;
8759
- bool need_LOCK_log;
8760
8775
if (unlikely (!is_open ()))
8761
8776
{
8762
8777
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)
8814
8829
/*
8815
8830
Stage #2: Syncing binary log file to disk
8816
8831
*/
8817
- need_LOCK_log= sync_counter + 1 >= get_sync_period () && get_prep_xids () == 0 ;
8818
8832
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))
8827
8834
{
8828
8835
DBUG_PRINT (" return" , (" Thread ID: %u, commit_error: %d" ,
8829
8836
thd->thread_id (), thd->commit_error ));
@@ -8854,9 +8861,6 @@ int MYSQL_BIN_LOG::ordered_commit(THD *thd, bool all, bool skip_commit)
8854
8861
update_binlog_end_pos (tmp_thd->get_trans_pos ());
8855
8862
}
8856
8863
8857
- if (need_LOCK_log)
8858
- mysql_mutex_unlock (&LOCK_log);
8859
-
8860
8864
DEBUG_SYNC (thd, " bgc_after_sync_stage_before_commit_stage" );
8861
8865
8862
8866
leave_mutex_before_commit_stage= &LOCK_sync;
0 commit comments