Skip to content

Commit 2334fda

Browse files
author
Sujatha Sivakumar
committed
Bug#22891628: BINARY GROUP COMMIT HANGS WHEN
BINLOG_GROUP_COMMIT_SYNC_DELAY IS SET TO [1-9] Problem: ======= When binlog_group_commit_sync_delay is set to [1-9]: 1) If binlog_group_commit_sync_no_delay_count > 1, and the number of transaction commits is less than binlog_group_commit_sync_no_delay_count, these commits will hang forever if no more commits come in; 2) If binlog_group_commit_sync_no_delay_count = 0, all transaction commits will hang forever; Analysis: ========= Setting binlog_group_commit_sync_no_delay_count option means that the server exits the wait procedure if the number of sessions reaches the count given before the timeout i.e is set in binlog_group_commit_sync_delay elapses. In order to check if session count has reached the given limit, the waiting time is broken into small intervals called as delta. The delta is calculated as 1/10 of total wait time. After each delta waiting time is elapsed queue size is checked to see if count has reached. If count is not reached then wait_time= wait_time - delta. This process is repeated until wait_time > 0 and count has not been reached. If the wait_time is set to [1-9] then the delta will become 0. If number of transaction commits is less than the count and the delta is '0' then wait_time = wait_time - delta will be a no-op. This will cause the commits to hang as the wait will never end. Fix: === Have '1' as the minimum delta value, i.e max(1, wait_time * 0.1) is set as delta. If 1 > (wait_time * 0.1) then delta=1 other wise delta= (wait_time * 0.1).
1 parent fa8f9e3 commit 2334fda

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CREATE TABLE t(id INT PRIMARY KEY, v INT NOT NULL) ENGINE INNODB;
2+
INSERT INTO t VALUES(1, 100), (2, 100), (3, 100), (4, 100);
3+
SET GLOBAL binlog_group_commit_sync_delay = 8;
4+
SET GLOBAL binlog_group_commit_sync_no_delay_count = 2;
5+
BEGIN;
6+
UPDATE t set v = v + 100 WHERE id = 1;
7+
COMMIT;
8+
SET GLOBAL binlog_group_commit_sync_delay = 8;
9+
SET GLOBAL binlog_group_commit_sync_no_delay_count = 0;
10+
BEGIN;
11+
UPDATE t set v = v + 100 WHERE id = 3;
12+
COMMIT;
13+
SET GLOBAL binlog_group_commit_sync_delay=0;
14+
DROP TABLE t;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# ==== Purpose and Implementation ====
2+
# Set binlog_group_commit_sync_delay to 1~9.
3+
# case1) Have binlog_group_commit_sync_no_delay_count > 1, and the number of
4+
# transaction commits less than binlog_group_commit_sync_no_delay_count, these
5+
# commits should not hang forever if no more commits come in;
6+
# case2) If binlog_group_commit_sync_no_delay_count = 0 transaction commits
7+
# should not hang forever;
8+
#
9+
# ==== References ====
10+
#
11+
# Bug#22891628: BINARY GROUP COMMIT HANGS WHEN BINLOG_GROUP_COMMIT_SYNC_DELAY
12+
# IS SET TO 1~9
13+
#
14+
###############################################################################
15+
--source include/have_log_bin.inc
16+
17+
CREATE TABLE t(id INT PRIMARY KEY, v INT NOT NULL) ENGINE INNODB;
18+
19+
INSERT INTO t VALUES(1, 100), (2, 100), (3, 100), (4, 100);
20+
--let $bgcd_saved=`SELECT @@GLOBAL.binlog_group_commit_sync_delay`
21+
##################### begin of case 1 ######################
22+
SET GLOBAL binlog_group_commit_sync_delay = 8;
23+
SET GLOBAL binlog_group_commit_sync_no_delay_count = 2;
24+
25+
BEGIN;
26+
UPDATE t set v = v + 100 WHERE id = 1;
27+
COMMIT; # hangs here forever if no more commits come in
28+
29+
###################### end of case 1 #######################
30+
31+
##################### begin of case 2 ######################
32+
SET GLOBAL binlog_group_commit_sync_delay = 8;
33+
SET GLOBAL binlog_group_commit_sync_no_delay_count = 0;
34+
35+
BEGIN;
36+
UPDATE t set v = v + 100 WHERE id = 3;
37+
COMMIT; # hangs here forever
38+
39+
###################### end of case 2 #######################
40+
--eval SET GLOBAL binlog_group_commit_sync_delay=$bgcd_saved
41+
DROP TABLE t;

sql/binlog.cc

+4-5
Original file line numberDiff line numberDiff line change
@@ -1919,19 +1919,19 @@ THD *Stage_manager::Mutex_queue::fetch_and_empty()
19191919
DBUG_RETURN(result);
19201920
}
19211921

1922-
time_t Stage_manager::wait_count_or_timeout(ulong count, time_t usec, StageID stage)
1922+
void Stage_manager::wait_count_or_timeout(ulong count, ulong usec, StageID stage)
19231923
{
1924-
time_t to_wait=
1924+
ulong to_wait=
19251925
DBUG_EVALUATE_IF("bgc_set_infinite_delay", LONG_MAX, usec);
19261926
/*
19271927
For testing purposes while waiting for inifinity
19281928
to arrive, we keep checking the queue size at regular,
19291929
small intervals. Otherwise, waiting 0.1 * infinite
19301930
is too long.
19311931
*/
1932-
time_t delta=
1932+
ulong delta=
19331933
DBUG_EVALUATE_IF("bgc_set_infinite_delay", 100000,
1934-
static_cast<time_t>(to_wait * 0.1));
1934+
max<ulong>(1, (to_wait * 0.1)));
19351935

19361936
while (to_wait > 0 && (count == 0 || static_cast<ulong>(m_queue[stage].get_size()) < count))
19371937
{
@@ -1942,7 +1942,6 @@ time_t Stage_manager::wait_count_or_timeout(ulong count, time_t usec, StageID st
19421942
my_sleep(delta);
19431943
to_wait -= delta;
19441944
}
1945-
return to_wait;
19461945
}
19471946

19481947
void Stage_manager::signal_done(THD *queue)

sql/binlog.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ class Stage_manager {
274274
session is waiting on
275275
@param stage which stage queue size to compare count against.
276276
*/
277-
time_t wait_count_or_timeout(ulong count, time_t usec, StageID stage);
277+
void wait_count_or_timeout(ulong count, ulong usec, StageID stage);
278278

279279
void signal_done(THD *queue);
280280

0 commit comments

Comments
 (0)