Skip to content

Commit f0132cf

Browse files
author
Joao Gramacho
committed
Bug#22102456 ENABLING GTID AT STARTUP RESULTS IN UNNECESSARY GTID SETS
Problem: When a server is initialized with GTID enabled, it creates a large and unnecessary GTID set. Fix: Created an infrastructure to differentiate if a query to be processed during server initialization is a compiled one or if it belongs to a file. Disabled binary logging session option before starting to apply compiled initialize statements and re-enabled it, if needed, when starting to apply file statement or when the initialize has finished.
1 parent 652dc88 commit f0132cf

7 files changed

+154
-13
lines changed

mysql-test/r/initialize_gtid.result

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CALL mtr.add_suppression("InnoDB:");
2+
USE mysql;
3+
# Create bootstrap file
4+
# Shut server down
5+
# Server is down
6+
# Run the server with:
7+
# --initialize-insecure
8+
# --explicit_defaults_for_timestamp --gtid-mode=on --enforce-gtid-consistency=on --log-bin=mysql-bin --server-id=1
9+
# Restart the server against DDIR
10+
# Connect as root
11+
include/assert.inc [GTID_EXECUTED should have only the 5 GTIDs from the init-file]
12+
# Clean up
13+
# Restarting the server after cleaning it up

mysql-test/t/initialize_gtid.test

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# ==== Purpose ====
2+
#
3+
# This test will initialize a new instance of a mysql server enabling binary
4+
# logging and GTID features. After the server initialization, the test case
5+
# will connect to the new server and no GTIDs are expected to be generated
6+
# during the initialization (GTID_EXECUTED should be empty) except from the
7+
# statements in the initialization file.
8+
#
9+
# ==== Related Bugs and Worklogs ====
10+
#
11+
# Bug#22102456 ENABLING GTID AT STARTUP RESULTS IN UNNECESSARY GTID SETS
12+
#
13+
14+
--source include/not_embedded.inc
15+
--source include/have_no_undo_tablespaces.inc
16+
17+
--let BASEDIR= `select @@basedir`
18+
--let DDIR=$MYSQL_TMP_DIR/installdb_test
19+
--let MYSQLD_LOG=$MYSQL_TMP_DIR/server.log
20+
--let extra_args=--no-defaults --console --log-syslog=0 --loose-skip-auto_generate_certs --loose-skip-sha256_password_auto_generate_rsa_keys --skip-ssl --basedir=$BASEDIR --lc-messages-dir=$MYSQL_SHAREDIR
21+
--let init_args=--explicit_defaults_for_timestamp --gtid-mode=on --enforce-gtid-consistency=on --log-bin=mysql-bin --server-id=1
22+
--let BOOTSTRAP_SQL=$MYSQL_TMP_DIR/tiny_bootstrap.sql
23+
24+
# We don't care about innodb warnings at this point
25+
CALL mtr.add_suppression("InnoDB:");
26+
USE mysql;
27+
28+
--echo # Create bootstrap file
29+
write_file $BOOTSTRAP_SQL;
30+
CREATE DATABASE test;
31+
CREATE TABLE test.t1(a INT) ENGINE=innodb;
32+
BEGIN;
33+
INSERT INTO test.t1 VALUES (1);
34+
COMMIT;
35+
DROP TABLE test.t1;
36+
DROP DATABASE test;
37+
EOF
38+
39+
--echo # Shut server down
40+
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
41+
--shutdown_server
42+
--source include/wait_until_disconnected.inc
43+
--echo # Server is down
44+
45+
--echo # Run the server with:
46+
--echo # --initialize-insecure
47+
--echo # $init_args
48+
--exec $MYSQLD $extra_args --initialize-insecure --datadir=$DDIR $init_args --init-file=$BOOTSTRAP_SQL > $MYSQLD_LOG 2>&1
49+
50+
--echo # Restart the server against DDIR
51+
--exec echo "restart:--datadir=$DDIR $init_args" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
52+
--enable_reconnect
53+
--source include/wait_until_connected_again.inc
54+
55+
--echo # Connect as root
56+
connect(root_con,localhost,root,,mysql);
57+
58+
--let $master_uuid= `SELECT @@GLOBAL.SERVER_UUID`
59+
--let $assert_text= GTID_EXECUTED should have only the 5 GTIDs from the init-file
60+
--let $assert_cond= @@GLOBAL.GTID_EXECUTED = "$master_uuid:1-5"
61+
--source include/assert.inc
62+
63+
--echo # Clean up
64+
# Shut server down
65+
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
66+
--shutdown_server
67+
--source include/wait_until_disconnected.inc
68+
69+
# Delete mysqld log and init file
70+
remove_file $MYSQLD_LOG;
71+
# Delete datadir
72+
--perl
73+
use File::Path 'rmtree';
74+
$DDIR=$ENV{"DDIR"};
75+
rmtree([ "$DDIR" ]);
76+
EOF
77+
78+
remove_file $BOOTSTRAP_SQL;
79+
80+
--echo # Restarting the server after cleaning it up
81+
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
82+
--enable_reconnect
83+
--source include/wait_until_connected_again.inc

sql/bootstrap.cc

+39-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ static MYSQL_FILE *bootstrap_file= NULL;
3030
static int bootstrap_error= 0;
3131

3232

33-
int File_command_iterator::next(std::string &query, int *error)
33+
int File_command_iterator::next(std::string &query, int *error,
34+
int *query_source)
3435
{
3536
static char query_buffer[MAX_BOOTSTRAP_QUERY_SIZE];
3637
size_t length= 0;
3738
int rc;
39+
*query_source= QUERY_SOURCE_FILE;
3840

3941
rc= read_bootstrap_query(query_buffer, &length, m_input, m_fgets_fn, error);
4042
if (rc == READ_BOOTSTRAP_SUCCESS)
@@ -85,6 +87,7 @@ static void handle_bootstrap_impl(THD *thd)
8587
DBUG_ENTER("handle_bootstrap");
8688
File_command_iterator file_iter(bootstrap_file, mysql_file_fgets_fn);
8789
Compiled_in_command_iterator comp_iter;
90+
bool has_binlog_option= thd->variables.option_bits & OPTION_BIN_LOG;
8891

8992
thd->thread_stack= (char*) &thd;
9093
thd->security_context()->assign_user(STRING_WITH_LEN("boot"));
@@ -110,8 +113,34 @@ static void handle_bootstrap_impl(THD *thd)
110113
{
111114
int error= 0;
112115
int rc;
116+
int query_source, last_query_source= -1;
113117

114-
rc= Command_iterator::current_iterator->next(query, &error);
118+
rc= Command_iterator::current_iterator->next(query, &error, &query_source);
119+
120+
/*
121+
The server must avoid logging compiled statements into the binary log
122+
(and generating GTIDs for them when GTID_MODE is ON) during bootstrap/
123+
initialize procedures.
124+
We will disable SQL_LOG_BIN session variable before processing compiled
125+
statements, and will re-enable it before processing statements of the
126+
initialization file.
127+
*/
128+
if (has_binlog_option && query_source != last_query_source)
129+
{
130+
switch (query_source)
131+
{
132+
case QUERY_SOURCE_COMPILED:
133+
thd->variables.option_bits&= ~OPTION_BIN_LOG;
134+
break;
135+
case QUERY_SOURCE_FILE:
136+
thd->variables.option_bits|= OPTION_BIN_LOG;
137+
break;
138+
default:
139+
DBUG_ASSERT(false);
140+
break;
141+
}
142+
}
143+
last_query_source= query_source;
115144

116145
if (rc == READ_BOOTSTRAP_EOF)
117146
break;
@@ -196,6 +225,14 @@ static void handle_bootstrap_impl(THD *thd)
196225
}
197226

198227
Command_iterator::current_iterator->end();
228+
229+
/*
230+
We should re-enable SQL_LOG_BIN session if it was enabled during
231+
bootstrap/initialization.
232+
*/
233+
if (has_binlog_option)
234+
thd->variables.option_bits|= OPTION_BIN_LOG;
235+
199236
DBUG_VOID_RETURN;
200237
}
201238

sql/bootstrap_impl.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -29,10 +29,13 @@ class Command_iterator
2929
/**
3030
Get the next query string.
3131
32-
@arg query output parameter to return the query
32+
@param[out] query return the query
33+
@param[out] read_error return the read error code
34+
@param[out] query_source return the source of the query
35+
(if it is from a file or a compiled one).
3336
@return one of the READ_BOOTSTRAP
3437
*/
35-
virtual int next(std::string &query, int *read_error)= 0;
38+
virtual int next(std::string &query, int *read_error, int *query_source)= 0;
3639

3740
/** end processing the iterator */
3841
virtual void end(void) {}
@@ -55,7 +58,7 @@ class File_command_iterator : public Command_iterator
5558
File_command_iterator(const char *file_name);
5659
virtual ~File_command_iterator();
5760

58-
int next(std::string &query, int *read_error);
61+
int next(std::string &query, int *read_error, int *query_source);
5962
void end(void);
6063
bool has_file()
6164
{

sql/sql_bootstrap.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -36,6 +36,9 @@
3636
#define READ_BOOTSTRAP_ERROR 2
3737
#define READ_BOOTSTRAP_QUERY_SIZE 3
3838

39+
#define QUERY_SOURCE_FILE 0
40+
#define QUERY_SOURCE_COMPILED 1
41+
3942
typedef struct st_mysql_file *fgets_input_t;
4043
typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t, int *error);
4144

sql/sql_initialize.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -188,11 +188,13 @@ void Compiled_in_command_iterator::begin(void)
188188
}
189189

190190

191-
int Compiled_in_command_iterator::next(std::string &query, int *read_error)
191+
int Compiled_in_command_iterator::next(std::string &query, int *read_error,
192+
int *query_source)
192193
{
193194
if (init_file_iter)
194-
return init_file_iter->next(query, read_error);
195+
return init_file_iter->next(query, read_error, query_source);
195196

197+
*query_source= QUERY_SOURCE_COMPILED;
196198
while (cmds[cmds_ofs] != NULL && cmds[cmds_ofs][cmd_ofs] == NULL)
197199
{
198200
cmds_ofs++;
@@ -218,7 +220,7 @@ int Compiled_in_command_iterator::next(std::string &query, int *read_error)
218220
return READ_BOOTSTRAP_ERROR;
219221
}
220222
init_file_iter->begin();
221-
return init_file_iter->next(query, read_error);
223+
return init_file_iter->next(query, read_error, query_source);
222224
}
223225

224226
return READ_BOOTSTRAP_EOF;

sql/sql_initialize.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ class Compiled_in_command_iterator : public Command_iterator
2828
end();
2929
}
3030
void begin(void);
31-
int next(std::string &query, int *read_error);
31+
int next(std::string &query, int *read_error, int *iterator_type);
3232
void end(void);
3333
private:
3434
bool is_active;

0 commit comments

Comments
 (0)