Bug #80651 larget rpl_semi_sync_master_timeout will affect performance
Submitted: 8 Mar 2016 3:45 Modified: 7 Apr 2016 5:46
Reporter: huajun chen Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: Replication Severity:S3 (Non-critical)
Version:5.5 5.6 OS:Any
Assigned to: CPU Architecture:Any
Tags: performance, rpl_semi_sync_master_timeout

[8 Mar 2016 3:45] huajun chen
Description:
Hi,all

When i enlarged the rpl_semi_sync_master_timeout in mysql semi sync replication deployment,
i found the write performance become pool.

rpl_semi_sync_master_timeout    qps
10000                           3637.16
21600000                        3583.02
43200000                        3211.17
86400000                        2146.96
214748364                       1251.67
2147483648                      196.3
21474836480                     13.99

Note:test by sysbench's insert.lua

This is because of a inappropriate while loop in the semisync_master.cc, show as below:

plugin\semisync\semisync_master.cc:
-------------------------------------------------
#define TIME_THOUSAND 1000
#define TIME_MILLION  1000000
#define TIME_BILLION  1000000000
...
int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
				  my_off_t trx_wait_binlog_pos)
{
...
      /* Calcuate the waiting period. */
...
      unsigned long long diff_nsecs =
        start_ts.tv_nsec + (unsigned long long)wait_timeout_ * TIME_MILLION;
      abstime.tv_sec = start_ts.tv_sec;
      while (diff_nsecs >= TIME_BILLION)//here is a large loop!!!
      {
        abstime.tv_sec++;
        diff_nsecs -= TIME_BILLION;
      }
      abstime.tv_nsec = diff_nsecs;
...
}

How to repeat:
1. setup semi sync replication
2. rpl_semi_sync_master_timeout to a large value
3. run benchmark for write

Suggested fix:
By the following modify, the problem can be fixed.

diff plugin/semisync/semisync_master.cc plugin/semisync/semisync_master.cc_bak 
687,688c687,688
<         start_ts.tv_nsec + ((unsigned long long)wait_timeout_ % TIME_THOUSAND) * TIME_MILLION;
<       abstime.tv_sec = start_ts.tv_sec + (unsigned long long)wait_timeout_ / TIME_THOUSAND;      
---
>         start_ts.tv_nsec + (unsigned long long)wait_timeout_ * TIME_MILLION;
>       abstime.tv_sec = start_ts.tv_sec;
[23 Mar 2016 12:02] huajun chen
Found it had been fixed in MySQL 5.7
[7 Apr 2016 5:46] Umesh Shastry
Hello Huajun Chen,

Thank you for the report.
Discussed with Dev's and confirmed that reported issue has been handled/fixed as part of Bug #69341.  Marking this as duplicate of Bug #69341.

Thanks,
Umesh