Skip to content

Commit aa5e331

Browse files
AliSQLAliSQL
authored andcommitted
[Feature] Issue#16 OMIT MAINTAINING OWNED_GTID SET IF GTID IS AUTO-GENERATED
Description: ------------ Before this patch, the life cycle for a GTID like the following: Generate a GTID => Add the GTID into owned_gtid => Flush the GTID into binlog => Remove the GTID from owned_gtid. Owned_gtid can be treated as an intermediate set to hold all of the GTIDs of current thread. After this patch, the life cycle for such a GTID can be like this: Generate a GTID => Add the GTID into binlog. Of course, if anything wrong happens, we have to remove the GTID from the binlog. Before this patch, we can remove the GTID from owned_gtid. Obviously, we shortened the life cycle of GTID. In order to support this feature, we introduced a new system variable "rds_gtid_precommit". If it's on, we will change the life cycle of GTID.
1 parent a7716a9 commit aa5e331

12 files changed

Lines changed: 198 additions & 13 deletions

mysql-test/r/mysqld--help-notwin.result

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,9 @@ The following options may be given as the first argument:
740740
--rds-threads-running-high-watermark=#
741741
When threads_running exceeds this limit, query that isn't
742742
in active transaction should quit.
743+
--rds-gtid-precommit
744+
Add gtid into gtid_executed before flushing binlog from
745+
cache to file.
743746
--read-buffer-size=#
744747
Each thread that does a sequential scan allocates a
745748
buffer of this size for each table it scans. If you do
@@ -1284,6 +1287,7 @@ rds-sql-update-filter (No default value)
12841287
rds-tablestat FALSE
12851288
rds-threads-running-ctl-mode SELECTS
12861289
rds-threads-running-high-watermark 151
1290+
rds-gtid-precommit FALSE
12871291
read-buffer-size 131072
12881292
read-only FALSE
12891293
read-rnd-buffer-size 262144
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
include/master-slave.inc
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5+
[connection master]
6+
include/rpl_set_gtid_mode.inc
7+
CALL mtr.add_suppression('Error writing file*');
8+
SET @old_gtid_precommit = @@global.rds_gtid_precommit;
9+
SET GLOBAL rds_gtid_precommit = 0;
10+
CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
11+
INSERT INTO t1 VALUES (1,2);
12+
INSERT INTO t1 VALUES (2,3);
13+
INSERT INTO t1 VALUES (3,4);
14+
SET GLOBAL rds_gtid_precommit = 1;
15+
INSERT INTO t1 VALUES (4,5);
16+
INSERT INTO t1 VALUES (5,6);
17+
INSERT INTO t1 VALUES (6,7);
18+
SET GLOBAL rds_gtid_precommit = 0;
19+
INSERT INTO t1 VALUES (8,9);
20+
SELECT * from t1 ORDER BY a;
21+
a b
22+
1 2
23+
2 3
24+
3 4
25+
4 5
26+
5 6
27+
6 7
28+
8 9
29+
SELECT * FROM t1 ORDER BY a;
30+
a b
31+
1 2
32+
2 3
33+
3 4
34+
4 5
35+
5 6
36+
6 7
37+
8 9
38+
SET GLOBAL rds_gtid_precommit = @old_gtid_precommit;
39+
DROP TABLE t1;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--source include/master-slave.inc
2+
--source include/rpl_set_gtid_mode.inc
3+
--source include/have_debug.inc
4+
--source include/have_binlog_format_row.inc
5+
6+
CALL mtr.add_suppression('Error writing file*');
7+
8+
connection master;
9+
SET @old_gtid_precommit = @@global.rds_gtid_precommit;
10+
11+
SET GLOBAL rds_gtid_precommit = 0;
12+
CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
13+
INSERT INTO t1 VALUES (1,2);
14+
INSERT INTO t1 VALUES (2,3);
15+
INSERT INTO t1 VALUES (3,4);
16+
17+
SET GLOBAL rds_gtid_precommit = 1;
18+
INSERT INTO t1 VALUES (4,5);
19+
INSERT INTO t1 VALUES (5,6);
20+
INSERT INTO t1 VALUES (6,7);
21+
22+
SET GLOBAL rds_gtid_precommit = 0;
23+
24+
INSERT INTO t1 VALUES (8,9);
25+
26+
sync_slave_with_master;
27+
SELECT * from t1 ORDER BY a;
28+
29+
connection master;
30+
SELECT * FROM t1 ORDER BY a;
31+
32+
#cleanup
33+
SET GLOBAL rds_gtid_precommit = @old_gtid_precommit;
34+
DROP TABLE t1;

mysql-test/suite/sys_vars/r/all_vars.result

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,7 @@ TRX_IDLE_TIMEOUT
5252
TRX_IDLE_TIMEOUT
5353
TRX_READONLY_IDLE_TIMEOUT
5454
TRX_READONLY_IDLE_TIMEOUT
55+
RDS_GTID_PRECOMMIT
56+
RDS_GTID_PRECOMMIT
5557
drop table t1;
5658
drop table t2;

sql/binlog.cc

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ static int limit_unsafe_warning_count= 0;
6262

6363
static handlerton *binlog_hton;
6464
bool opt_binlog_order_commits= true;
65+
bool opt_gtid_precommit= false;
6566

6667
const char *log_bin_index= 0;
6768
const char *log_bin_basename= 0;
@@ -6026,7 +6027,7 @@ bool MYSQL_BIN_LOG::write_cache(THD *thd, binlog_cache_data *cache_data)
60266027
DBUG_SUICIDE();
60276028
});
60286029

6029-
if ((write_error= do_write_cache(cache)))
6030+
if (write_error= do_write_cache(cache))
60306031
goto err;
60316032

60326033
if (incident && write_incident(thd, false/*need_lock_log=false*/,
@@ -6043,13 +6044,16 @@ bool MYSQL_BIN_LOG::write_cache(THD *thd, binlog_cache_data *cache_data)
60436044
goto err;
60446045
}
60456046

6046-
global_sid_lock->rdlock();
6047-
if (gtid_state->update_on_flush(thd) != RETURN_STATUS_OK)
6047+
if (!thd->gtid_precommit)
60486048
{
6049+
global_sid_lock->rdlock();
6050+
if (gtid_state->update_on_flush(thd) != RETURN_STATUS_OK)
6051+
{
6052+
global_sid_lock->unlock();
6053+
goto err;
6054+
}
60496055
global_sid_lock->unlock();
6050-
goto err;
60516056
}
6052-
global_sid_lock->unlock();
60536057
}
60546058
update_thd_next_event_pos(thd);
60556059
}
@@ -6066,6 +6070,13 @@ bool MYSQL_BIN_LOG::write_cache(THD *thd, binlog_cache_data *cache_data)
60666070
}
60676071
thd->commit_error= THD::CE_FLUSH_ERROR;
60686072

6073+
/* Remove gtid from logged_gtid set if failed. */
6074+
if (write_error && thd->gtid_precommit)
6075+
{
6076+
global_sid_lock->rdlock();
6077+
gtid_state->remove_gtid_on_failure(thd);
6078+
global_sid_lock->unlock();
6079+
}
60696080
DBUG_RETURN(1);
60706081
}
60716082

@@ -7005,13 +7016,24 @@ MYSQL_BIN_LOG::finish_commit(THD *thd)
70057016
else if (thd->transaction.flags.xid_written)
70067017
dec_prep_xids(thd);
70077018

7008-
/*
7009-
Remove committed GTID from owned_gtids, it was already logged on
7010-
MYSQL_BIN_LOG::write_cache().
7011-
*/
7012-
global_sid_lock->rdlock();
7013-
gtid_state->update_on_commit(thd);
7014-
global_sid_lock->unlock();
7019+
if (!thd->gtid_precommit)
7020+
{
7021+
/*
7022+
Remove committed GTID from owned_gtids, it was already logged on
7023+
MYSQL_BIN_LOG::write_cache().
7024+
*/
7025+
global_sid_lock->rdlock();
7026+
gtid_state->update_on_commit(thd);
7027+
global_sid_lock->unlock();
7028+
}
7029+
else
7030+
{
7031+
/* Reset gtid_precommit. */
7032+
thd->gtid_precommit= false;
7033+
/* Clear gtid owned by current THD. */
7034+
thd->clear_owned_gtids();
7035+
thd->variables.gtid_next.set_undefined();
7036+
}
70157037

70167038
DBUG_ASSERT(thd->commit_error || !thd->transaction.flags.run_hooks);
70177039
DBUG_ASSERT(!thd_get_cache_mngr(thd)->dbug_any_finalized());
@@ -7163,6 +7185,9 @@ int MYSQL_BIN_LOG::ordered_commit(THD *thd, bool all, bool skip_commit)
71637185
thd->stage_leader= false;
71647186
thd->stage_cond_id= UNDEF_COND_SLOT;
71657187
thd->prev_to_commit= NULL;
7188+
thd->gtid_precommit= (gtid_mode &&
7189+
opt_gtid_precommit &&
7190+
thd->variables.gtid_next.type == AUTOMATIC_GROUP);
71667191
#ifndef DBUG_OFF
71677192
/*
71687193
The group commit Leader may have to wait for follower whose transaction

sql/binlog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@ int gtid_empty_group_log_and_cleanup(THD *thd);
781781
extern const char *log_bin_index;
782782
extern const char *log_bin_basename;
783783
extern bool opt_binlog_order_commits;
784+
extern bool opt_gtid_precommit;
784785

785786
/**
786787
Turns a relative log binary log path into a full path, based on the

sql/rpl_gtid.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,6 +2163,16 @@ class Gtid_state
21632163
@return RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.
21642164
*/
21652165
enum_return_status acquire_ownership(THD *thd, const Gtid &gtid);
2166+
2167+
/**
2168+
Remove gtid from logged_gtid set if fail to flush binlog
2169+
from cache to file.
2170+
*/
2171+
enum_return_status remove_gtid_on_failure(THD *thd);
2172+
2173+
/* Add gtid into logged_gtid set. */
2174+
enum_return_status mark_gtid_executed(THD *thd, const Gtid &gtid);
2175+
21662176
/**
21672177
Update the state after the given thread has flushed cache to binlog.
21682178

sql/rpl_gtid_cache.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ enum_return_status Group_cache::generate_automatic_gno(THD *thd)
156156
gtid_state->unlock_sidno(automatic_gtid.sidno);
157157
RETURN_REPORTED_ERROR;
158158
}
159-
gtid_state->acquire_ownership(thd, automatic_gtid);
159+
/* Log gtid into logged_gtid directly. */
160+
if (thd->gtid_precommit)
161+
gtid_state->mark_gtid_executed(thd, automatic_gtid);
162+
else
163+
gtid_state->acquire_ownership(thd, automatic_gtid);
160164
gtid_state->unlock_sidno(automatic_gtid.sidno);
161165
}
162166
}

sql/rpl_gtid_state.cc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,55 @@ void Gtid_state::clear()
3232
DBUG_VOID_RETURN;
3333
}
3434

35+
enum_return_status Gtid_state::remove_gtid_on_failure(THD *thd)
36+
{
37+
DBUG_ENTER("Gtid_state::remove_gtid_on_failure");
38+
global_sid_lock->assert_some_lock();
39+
40+
if (thd->owned_gtid.sidno > 0)
41+
{
42+
sid_locks.lock(thd->owned_gtid.sidno);
43+
/* Remove Gtid from logged_gtid set. */
44+
if (logged_gtids._remove_gtid(thd->owned_gtid) != RETURN_STATUS_OK)
45+
{
46+
sid_locks.unlock(thd->owned_gtid.sidno);
47+
/* Print an error message, so people knows a serious error happend.*/
48+
sql_print_error("Failed to remove GTID from logged_gtids after a"
49+
" serious error happened. Sidno:%d, Gno:%lld",
50+
thd->owned_gtid.sidno, thd->owned_gtid.gno);
51+
52+
RETURN_REPORTED_ERROR;
53+
}
54+
55+
sid_locks.unlock(thd->owned_gtid.sidno);
56+
thd->owned_gtid.sidno= 0;
57+
}
58+
59+
RETURN_OK;
60+
}
61+
62+
enum_return_status Gtid_state::mark_gtid_executed(THD *thd, const Gtid &gtid)
63+
{
64+
DBUG_ENTER("Gtid_state::mark_gtid_executed");
65+
// caller must take lock on the SIDNO.
66+
global_sid_lock->assert_some_lock();
67+
gtid_state->assert_sidno_lock_owner(gtid.sidno);
68+
DBUG_ASSERT(!logged_gtids.contains_gtid(gtid));
69+
DBUG_ASSERT(thd->owned_gtid.sidno == 0);
70+
71+
if (logged_gtids._add_gtid(gtid) != RETURN_STATUS_OK)
72+
goto err;
73+
74+
thd->owned_gtid= gtid;
75+
76+
RETURN_OK;
77+
78+
err:
79+
thd->owned_gtid_set.clear();
80+
thd->owned_gtid.sidno= 0;
81+
RETURN_REPORTED_ERROR;
82+
}
83+
3584

3685
enum_return_status Gtid_state::acquire_ownership(THD *thd, const Gtid &gtid)
3786
{
@@ -157,6 +206,12 @@ enum_return_status Gtid_state::update_on_flush(THD *thd)
157206
{
158207
lock_sidno(thd->owned_gtid.sidno);
159208
ret= logged_gtids._add_gtid(thd->owned_gtid);
209+
if (unlikely(ret != RETURN_STATUS_OK))
210+
{
211+
/* Print an error message, so users know a serious error happends. */
212+
sql_print_error("Failed to add thd->owned_gtid into logged_gtids"
213+
" set. Sidno:%d, Gno:%lld", thd->owned_gtid.sidno, thd->owned_gtid.gno);
214+
}
160215
}
161216

162217
/*

sql/sql_class.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,7 @@ void THD::init(void)
14551455

14561456
owned_gtid.sidno= 0;
14571457
owned_gtid.gno= 0;
1458+
gtid_precommit= false;
14581459
}
14591460

14601461

0 commit comments

Comments
 (0)