Skip to content

Commit 5be7bc2

Browse files
author
Jaideep Karande
committed
Bug#31586243: SERVER CRASH WITH BAD_ALLOC WHEN MEMORY IS TIGHT IN GR
Rpl_transaction_write_set_ctx::add_write_set may throw bad_alloc during vector update. Resolution: Code has been modified to handle bad_alloc from add_write_set. ReviewBoard: 24813
1 parent 533e45f commit 5be7bc2

File tree

4 files changed

+81
-7
lines changed

4 files changed

+81
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
include/group_replication.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 server1]
6+
CREATE TABLE t1 (c1 INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
7+
INSERT INTO t1 VALUES (1);
8+
9+
# 1. Set DBUG_SYNC to throw bad_alloc.
10+
SET @debug_saved= @@GLOBAL.DEBUG;
11+
SET @@GLOBAL.DEBUG= '+d,add_write_set_crash_no_memory';
12+
13+
# 2. Confirm there is no crash.
14+
INSERT INTO t1 VALUES (2);
15+
ERROR HY000: Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space
16+
SET @@GLOBAL.DEBUG= @debug_saved;
17+
18+
# 3. Data is consistem on M1 and M2.
19+
INSERT INTO t1 VALUES (3);
20+
include/rpl_sync.inc
21+
include/diff_tables.inc [server_1:t1, server2:t1]
22+
23+
# 4. Cleanup.
24+
DROP TABLE t1;
25+
include/group_replication_end.inc
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
################################################################################
2+
# This test verify that when memory allocation fails during write set
3+
# push back, it is handled properly.
4+
#
5+
# Test:
6+
# 0. The test requires two servers: M1 and M2.
7+
# 1. Set DBUG_SYNC to throw bad_alloc.
8+
# 2. Confirm there is no crash.
9+
# 3. Data is consistem on M1 and M2.
10+
# 4. Cleanup.
11+
################################################################################
12+
--source include/have_debug.inc
13+
--source include/have_group_replication_plugin.inc
14+
--source include/group_replication.inc
15+
16+
CREATE TABLE t1 (c1 INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
17+
INSERT INTO t1 VALUES (1);
18+
19+
--echo
20+
--echo # 1. Set DBUG_SYNC to throw bad_alloc.
21+
SET @debug_saved= @@GLOBAL.DEBUG;
22+
SET @@GLOBAL.DEBUG= '+d,add_write_set_crash_no_memory';
23+
24+
--echo
25+
--echo # 2. Confirm there is no crash.
26+
27+
--error 1041
28+
INSERT INTO t1 VALUES (2);
29+
SET @@GLOBAL.DEBUG= @debug_saved;
30+
31+
--echo
32+
--echo # 3. Data is consistem on M1 and M2.
33+
34+
INSERT INTO t1 VALUES (3);
35+
--source include/rpl_sync.inc
36+
37+
--let $diff_tables=server_1:t1, server2:t1
38+
--source include/diff_tables.inc
39+
40+
--echo
41+
--echo # 4. Cleanup.
42+
DROP TABLE t1;
43+
--source include/group_replication_end.inc

sql/handler.cc

+11-6
Original file line numberDiff line numberDiff line change
@@ -7686,12 +7686,17 @@ int binlog_log_row(TABLE *table, const uchar *before_record,
76867686

76877687
if (check_table_binlog_row_based(thd, table)) {
76887688
if (thd->variables.transaction_write_set_extraction != HASH_ALGORITHM_OFF) {
7689-
if (before_record && after_record) {
7690-
/* capture both images pke */
7691-
add_pke(table, thd, table->record[0]);
7692-
add_pke(table, thd, table->record[1]);
7693-
} else {
7694-
add_pke(table, thd, table->record[0]);
7689+
try {
7690+
if (before_record && after_record) {
7691+
/* capture both images pke */
7692+
add_pke(table, thd, table->record[0]);
7693+
add_pke(table, thd, table->record[1]);
7694+
} else {
7695+
add_pke(table, thd, table->record[0]);
7696+
}
7697+
} catch (const std::bad_alloc &) {
7698+
my_error(ER_OUT_OF_RESOURCES, MYF(0));
7699+
return HA_ERR_RBR_LOGGING_FAILED;
76957700
}
76967701
}
76977702
if (table->in_use->is_error()) return error ? HA_ERR_RBR_LOGGING_FAILED : 0;

sql/rpl_transaction_write_set_ctx.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2014, 2020, 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, version 2.0,
@@ -51,6 +51,7 @@ Rpl_transaction_write_set_ctx::Rpl_transaction_write_set_ctx()
5151

5252
void Rpl_transaction_write_set_ctx::add_write_set(uint64 hash) {
5353
DBUG_TRACE;
54+
DBUG_EXECUTE_IF("add_write_set_crash_no_memory", throw std::bad_alloc(););
5455
write_set.push_back(hash);
5556
}
5657

0 commit comments

Comments
 (0)