Skip to content

Commit 7954a17

Browse files
author
He Zhenxing
committed
Auto merge fix for Bug#49020
2 parents 75b9db9 + 16ec25c commit 7954a17

File tree

7 files changed

+213
-85
lines changed

7 files changed

+213
-85
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
stop slave;
2+
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
3+
reset master;
4+
reset slave;
5+
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
6+
start slave;
7+
include/stop_slave.inc
8+
include/start_slave.inc
9+
SET GLOBAL event_scheduler = ON;
10+
CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=ENGINE_TYPE;
11+
INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a');
12+
INSERT INTO t1 SELECT i+5, f FROM t1;
13+
INSERT INTO t1 SELECT i+10, f FROM t1;
14+
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND
15+
DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID()));
16+
CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND
17+
DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev2_',CONNECTION_ID()));
18+
STOP SLAVE IO_THREAD;
19+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 20;
20+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 19;
21+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 18;
22+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 17;
23+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 16;
24+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 15;
25+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 14;
26+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 13;
27+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 12;
28+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 11;
29+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 10;
30+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 9;
31+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 8;
32+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 7;
33+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 6;
34+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 5;
35+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 4;
36+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 3;
37+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 2;
38+
UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = 1;
39+
SET GLOBAL event_scheduler = OFF;
40+
include/stop_slave.inc
41+
UNINSTALL PLUGIN rpl_semi_sync_slave;
42+
UNINSTALL PLUGIN rpl_semi_sync_master;
43+
include/start_slave.inc
44+
DROP EVENT ev1;
45+
DROP EVENT ev2;
46+
DROP TABLE t1;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$SEMISYNC_PLUGIN_OPT --max-connections=23
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$SEMISYNC_PLUGIN_OPT
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
source include/have_semisync_plugin.inc;
2+
source include/not_embedded.inc;
3+
source include/master-slave.inc;
4+
source include/have_innodb.inc;
5+
6+
let $engine_type= InnoDB;
7+
8+
# Suppress warnings that might be generated during the test
9+
disable_query_log;
10+
connection master;
11+
call mtr.add_suppression("Timeout waiting for reply of binlog");
12+
call mtr.add_suppression("Semi-sync master .* waiting for slave reply");
13+
call mtr.add_suppression("Read semi-sync reply");
14+
connection slave;
15+
call mtr.add_suppression("Master server does not support semi-sync");
16+
call mtr.add_suppression("Semi-sync slave .* reply");
17+
enable_query_log;
18+
19+
connection master;
20+
disable_query_log;
21+
let $value = query_get_value(show variables like 'rpl_semi_sync_master_enabled', Value, 1);
22+
if (`select '$value' = 'No such row'`)
23+
{
24+
set sql_log_bin=0;
25+
eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN';
26+
SET GLOBAL rpl_semi_sync_master_enabled = 1;
27+
set sql_log_bin=1;
28+
}
29+
enable_query_log;
30+
31+
connection slave;
32+
source include/stop_slave.inc;
33+
34+
disable_query_log;
35+
let $value= query_get_value(show variables like 'rpl_semi_sync_slave_enabled', Value, 1);
36+
if (`select '$value' = 'No such row'`)
37+
{
38+
set sql_log_bin=0;
39+
eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN';
40+
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
41+
set sql_log_bin=1;
42+
}
43+
enable_query_log;
44+
45+
source include/start_slave.inc;
46+
47+
connection master;
48+
SET GLOBAL event_scheduler = ON;
49+
50+
replace_result $engine_type ENGINE_TYPE;
51+
eval CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=$engine_type;
52+
INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a');
53+
INSERT INTO t1 SELECT i+5, f FROM t1;
54+
INSERT INTO t1 SELECT i+10, f FROM t1;
55+
56+
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND
57+
DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID()));
58+
CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND
59+
DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev2_',CONNECTION_ID()));
60+
61+
connection slave;
62+
STOP SLAVE IO_THREAD;
63+
64+
connection master;
65+
let $run = 20;
66+
while ($run)
67+
{
68+
connect (m$run,localhost,root,,);
69+
connection m$run;
70+
send;
71+
eval UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = $run;
72+
connection master;
73+
dec $run;
74+
}
75+
76+
connection master;
77+
SET GLOBAL event_scheduler = OFF;
78+
79+
let $run = 20;
80+
while ($run)
81+
{
82+
connection m$run;
83+
reap;
84+
disconnect m$run;
85+
dec $run;
86+
}
87+
88+
#
89+
# Clean up
90+
#
91+
connection slave;
92+
source include/stop_slave.inc;
93+
94+
disable_warnings;
95+
UNINSTALL PLUGIN rpl_semi_sync_slave;
96+
97+
connection master;
98+
UNINSTALL PLUGIN rpl_semi_sync_master;
99+
enable_warnings;
100+
101+
connection slave;
102+
source include/start_slave.inc;
103+
104+
connection master;
105+
DROP EVENT ev1;
106+
DROP EVENT ev2;
107+
DROP TABLE t1;
108+
sync_slave_with_master;

plugin/semisync/semisync_master.cc

Lines changed: 21 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,14 @@ static int gettimeofday(struct timeval *tv, void *tz)
6363
*
6464
******************************************************************************/
6565

66-
ActiveTranx::ActiveTranx(int max_connections,
67-
pthread_mutex_t *lock,
66+
ActiveTranx::ActiveTranx(pthread_mutex_t *lock,
6867
unsigned long trace_level)
69-
: Trace(trace_level), num_transactions_(max_connections),
70-
num_entries_(max_connections << 1),
68+
: Trace(trace_level),
69+
num_entries_(max_connections << 1), /* Transaction hash table size
70+
* is set to double the size
71+
* of max_connections */
7172
lock_(lock)
7273
{
73-
/* Allocate the memory for the array */
74-
node_array_ = new TranxNode[num_transactions_];
75-
for (int idx = 0; idx < num_transactions_; ++idx)
76-
{
77-
node_array_[idx].log_pos_ = 0;
78-
node_array_[idx].hash_next_ = NULL;
79-
node_array_[idx].next_ = node_array_ + idx + 1;
80-
81-
node_array_[idx].log_name_ = new char[FN_REFLEN];
82-
node_array_[idx].log_name_[0] = '\x0';
83-
}
84-
node_array_[num_transactions_-1].next_ = NULL;
85-
86-
/* All nodes in the array go to the pool initially. */
87-
free_pool_ = node_array_;
88-
8974
/* No transactions are in the list initially. */
9075
trx_front_ = NULL;
9176
trx_rear_ = NULL;
@@ -95,24 +80,13 @@ ActiveTranx::ActiveTranx(int max_connections,
9580
for (int idx = 0; idx < num_entries_; ++idx)
9681
trx_htb_[idx] = NULL;
9782

98-
sql_print_information("Semi-sync replication initialized for %d "
99-
"transactions.", num_transactions_);
83+
sql_print_information("Semi-sync replication initialized for transactions.");
10084
}
10185

10286
ActiveTranx::~ActiveTranx()
10387
{
104-
for (int idx = 0; idx < num_transactions_; ++idx)
105-
{
106-
delete [] node_array_[idx].log_name_;
107-
node_array_[idx].log_name_ = NULL;
108-
}
109-
110-
delete [] node_array_;
11188
delete [] trx_htb_;
112-
113-
node_array_ = NULL;
11489
trx_htb_ = NULL;
115-
num_transactions_ = 0;
11690
num_entries_ = 0;
11791
}
11892

@@ -143,26 +117,21 @@ unsigned int ActiveTranx::get_hash_value(const char *log_file_name,
143117

144118
ActiveTranx::TranxNode* ActiveTranx::alloc_tranx_node()
145119
{
146-
TranxNode *ptr = free_pool_;
147-
148-
if (free_pool_)
149-
{
150-
free_pool_ = free_pool_->next_;
151-
ptr->next_ = NULL;
152-
ptr->hash_next_ = NULL;
153-
}
154-
else
120+
MYSQL_THD thd= (MYSQL_THD)current_thd;
121+
/* The memory allocated for TranxNode will be automatically freed at
122+
the end of the command of current THD. And because
123+
ha_autocommit_or_rollback() will always be called before that, so
124+
we are sure that the node will be removed from the active list
125+
before it get freed. */
126+
TranxNode *trx_node = (TranxNode *)thd_alloc(thd, sizeof(TranxNode));
127+
if (trx_node)
155128
{
156-
/*
157-
free_pool should never be NULL here, because we have
158-
max_connections number of pre-allocated nodes.
159-
*/
160-
sql_print_error("You have encountered a semi-sync bug (free_pool == NULL), "
161-
"please report to http://bugs.mysql.com");
162-
assert(free_pool_);
129+
trx_node->log_name_[0] = '\0';
130+
trx_node->log_pos_= 0;
131+
trx_node->next_= 0;
132+
trx_node->hash_next_= 0;
163133
}
164-
165-
return ptr;
134+
return trx_node;
166135
}
167136

168137
int ActiveTranx::compare(const char *log_file_name1, my_off_t log_file_pos1,
@@ -306,8 +275,6 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name,
306275
/* Clear the active transaction list. */
307276
if (trx_front_ != NULL)
308277
{
309-
trx_rear_->next_ = free_pool_;
310-
free_pool_ = trx_front_;
311278
trx_front_ = NULL;
312279
trx_rear_ = NULL;
313280
}
@@ -326,11 +293,6 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name,
326293
{
327294
next_node = curr_node->next_;
328295

329-
/* Put the node in the memory pool. */
330-
curr_node->next_ = free_pool_;
331-
free_pool_ = curr_node;
332-
n_frees++;
333-
334296
/* Remove the node from the hash table. */
335297
unsigned int hash_val = get_hash_value(curr_node->log_name_, curr_node->log_pos_);
336298
TranxNode **hash_ptr = &(trx_htb_[hash_val]);
@@ -391,8 +353,7 @@ ReplSemiSyncMaster::ReplSemiSyncMaster()
391353
wait_file_pos_(0),
392354
master_enabled_(false),
393355
wait_timeout_(0L),
394-
state_(0),
395-
max_transactions_(0L)
356+
state_(0)
396357
{
397358
strcpy(reply_file_name_, "");
398359
strcpy(wait_file_name_, "");
@@ -413,7 +374,6 @@ int ReplSemiSyncMaster::initObject()
413374
/* References to the parameter works after set_options(). */
414375
setWaitTimeout(rpl_semi_sync_master_timeout);
415376
setTraceLevel(rpl_semi_sync_master_trace_level);
416-
max_transactions_ = (int)max_connections;
417377

418378
/* Mutex initialization can only be done after MY_INIT(). */
419379
pthread_mutex_init(&LOCK_binlog_, MY_MUTEX_INIT_FAST);
@@ -436,9 +396,7 @@ int ReplSemiSyncMaster::enableMaster()
436396

437397
if (!getMasterEnabled())
438398
{
439-
active_tranxs_ = new ActiveTranx(max_connections,
440-
&LOCK_binlog_,
441-
trace_level_);
399+
active_tranxs_ = new ActiveTranx(&LOCK_binlog_, trace_level_);
442400
if (active_tranxs_ != NULL)
443401
{
444402
commit_file_name_inited_ = false;

plugin/semisync/semisync_master.h

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,26 @@
2323
/**
2424
This class manages memory for active transaction list.
2525
26-
We record each active transaction with a TranxNode. Because each
27-
session can only have only one open transaction, the total active
28-
transaction nodes can not exceed the maximum sessions. Currently
29-
in MySQL, sessions are the same as connections.
26+
We record each active transaction with a TranxNode, each session
27+
can have only one open transaction. Because of EVENT, the total
28+
active transaction nodes can exceed the maximum allowed
29+
connections.
3030
*/
3131
class ActiveTranx
3232
:public Trace {
3333
private:
3434
struct TranxNode {
35-
char *log_name_;
35+
char log_name_[FN_REFLEN];
3636
my_off_t log_pos_;
3737
struct TranxNode *next_; /* the next node in the sorted list */
3838
struct TranxNode *hash_next_; /* the next node during hash collision */
3939
};
4040

41-
/* The following data structure maintains an active transaction list. */
42-
TranxNode *node_array_;
43-
TranxNode *free_pool_;
44-
4541
/* These two record the active transaction list in sort order. */
4642
TranxNode *trx_front_, *trx_rear_;
4743

4844
TranxNode **trx_htb_; /* A hash table on active transactions. */
4945

50-
int num_transactions_; /* maximum transactions */
5146
int num_entries_; /* maximum hash table entries */
5247
pthread_mutex_t *lock_; /* mutex lock */
5348

@@ -74,8 +69,7 @@ class ActiveTranx
7469
}
7570

7671
public:
77-
ActiveTranx(int max_connections, pthread_mutex_t *lock,
78-
unsigned long trace_level);
72+
ActiveTranx(pthread_mutex_t *lock, unsigned long trace_level);
7973
~ActiveTranx();
8074

8175
/* Insert an active transaction node with the specified position.
@@ -177,11 +171,6 @@ class ReplSemiSyncMaster
177171

178172
bool state_; /* whether semi-sync is switched */
179173

180-
/* The number of maximum active transactions. This should be the same as
181-
* maximum connections because MySQL does not do connection sharing now.
182-
*/
183-
int max_transactions_;
184-
185174
void lock();
186175
void unlock();
187176
void cond_broadcast();

0 commit comments

Comments
 (0)