[Commits] 32cfec4: MDEV-9162 : MariaDB Galera Cluster memory leak on async slave node

Nirbhay Choubey nirbhay at mariadb.com
Mon Dec 14 08:46:06 EET 2015


revision-id: 32cfec453d3367c89f410b7db2027da249f0803e
parent(s): b88c67d5f23c6beca5604b31919ab45906dd9b39
committer: Nirbhay Choubey
branch nick: 10.0-galera
timestamp: 2015-12-14 01:46:06 -0500
message:

MDEV-9162 : MariaDB Galera Cluster memory leak on async slave node

As galera node (slave) received query log events from an async
replication master, it partially wrote the updates made to replication
state table (mysql.gtid_slave_pos) to galera transaction writeset post
TOI. As a result, the transaction handle, thus created within galera,
was never freed/purged as the corresponding trx did not commit.
Thus, it kept piling up for every query log event and was only reclaimed
upon server shutdown when the transaction map object got destructed.
Fixed by making sure that updates in replication slave state table
are not written to galera transaction writeset and thus, not replicated
to other nodes.

---
 sql/rpl_gtid.cc                       | 12 ++++++++++++
 sql/sql_class.cc                      |  7 ++++++-
 sql/sql_class.h                       |  1 +
 sql/wsrep_mysqld.h                    |  3 +--
 storage/innobase/handler/ha_innodb.cc | 19 +++++++++++--------
 storage/xtradb/handler/ha_innodb.cc   | 18 +++++++++++-------
 6 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 709cb28..81f2dd5 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -574,6 +574,14 @@ class Gtid_db_intact : public Table_check_intact
   if ((err= gtid_check_rpl_slave_state_table(table)))
     goto end;
 
+#ifdef WITH_WSREP
+  /*
+    Updates in slave state table should not be appended to galera transaction
+    writeset.
+  */
+  thd->wsrep_skip_append_keys= true;
+#endif
+
   if (!in_transaction)
   {
     DBUG_PRINT("info", ("resetting OPTION_BEGIN"));
@@ -687,6 +695,10 @@ class Gtid_db_intact : public Table_check_intact
 
 end:
 
+#ifdef WITH_WSREP
+  thd->wsrep_skip_append_keys= false;
+#endif
+
   if (table_opened)
   {
     if (err || (err= ha_commit_trans(thd, FALSE)))
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5f17145..6c7282c 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -962,6 +962,10 @@ extern int wsrep_on(void *thd)
 {
   return(thd->wsrep_retry_counter);
 }
+extern "C" bool wsrep_thd_skip_append_keys(THD *thd)
+{
+  return thd->wsrep_skip_append_keys;
+}
 
 extern int
 wsrep_trx_order_before(void *thd1, void *thd2)
@@ -1083,7 +1087,8 @@ bool Drop_table_error_handler::handle_condition(THD *thd,
    wsrep_po_cnt(0),
    wsrep_po_in_trans(FALSE),
    wsrep_apply_format(0),
-   wsrep_apply_toi(false)
+   wsrep_apply_toi(false),
+   wsrep_skip_append_keys(false)
 #endif
 {
   ulong tmp;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 596a271..83899ec 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3863,6 +3863,7 @@ class THD :public Statement,
 #endif /*  GTID_SUPPORT */
   void*                     wsrep_apply_format;
   bool                      wsrep_apply_toi; /* applier processing in TOI */
+  bool                      wsrep_skip_append_keys;
 #endif /* WITH_WSREP */
 };
 
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 4e0d2f4..1616bab 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -180,7 +180,7 @@ enum enum_wsrep_sync_wait {
 extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
 extern "C" void wsrep_thd_awake(THD *thd, my_bool signal);
 extern "C" int wsrep_thd_retry_counter(THD *thd);
-
+extern "C" bool wsrep_thd_skip_append_keys(THD *thd);
 
 extern void wsrep_close_client_connections(my_bool wait_to_end);
 extern int  wsrep_wait_committing_connections_close(int wait_time);
@@ -195,7 +195,6 @@ enum enum_wsrep_sync_wait {
 extern bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
 extern int  wsrep_check_opts (int argc, char* const* argv);
 extern void wsrep_prepend_PATH (const char* path);
-/* some inline functions are defined in wsrep_mysqld_inl.h */
 
 /* Other global variables */
 extern wsrep_seqno_t wsrep_locked_seqno;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 7afc90d..9dd07bf 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7762,7 +7762,8 @@ translation table rebuild (fter create/drop index) and DMLs that
 	if (!error_result                                &&
 	    wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
 	    wsrep_on(user_thd)                           &&
-	    !wsrep_consistency_check(user_thd))
+	    !wsrep_consistency_check(user_thd)           &&
+	    !wsrep_thd_skip_append_keys(user_thd))
 	{
 		if (wsrep_append_keys(user_thd, false, record, NULL))
 		{
@@ -8280,10 +8281,11 @@ translation table rebuild (fter create/drop index) and DMLs that
 	innobase_active_small();
 
 #ifdef WITH_WSREP
-	if (error == DB_SUCCESS                          && 
+	if (error == DB_SUCCESS                          &&
 	    wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
-            wsrep_on(user_thd)) {
-
+	    wsrep_on(user_thd)                           &&
+	    !wsrep_thd_skip_append_keys(user_thd))
+        {
 		DBUG_PRINT("wsrep", ("update row key"));
 
 		if (wsrep_append_keys(user_thd, false, old_row, new_row)) {
@@ -8345,10 +8347,11 @@ translation table rebuild (fter create/drop index) and DMLs that
 	innobase_active_small();
 
 #ifdef WITH_WSREP
-	if (error == DB_SUCCESS                          && 
-	    wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
-            wsrep_on(user_thd)) {
-
+	if (error == DB_SUCCESS                          &&
+            wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
+            wsrep_on(user_thd)                           &&
+            !wsrep_thd_skip_append_keys(user_thd))
+        {
 		if (wsrep_append_keys(user_thd, false, record, NULL)) {
 			DBUG_PRINT("wsrep", ("delete fail"));
 			error = (dberr_t)HA_ERR_INTERNAL_ERROR;
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 886a3ef..003b852 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -8386,7 +8386,8 @@ translation table rebuild (fter create/drop index) and DMLs that
 	if (!error_result                                &&
 	    wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
 	    wsrep_on(user_thd)                           &&
-	    !wsrep_consistency_check(user_thd))
+	    !wsrep_consistency_check(user_thd)           &&
+	    !wsrep_thd_skip_append_keys(user_thd))
 	{
 		if (wsrep_append_keys(user_thd, false, record, NULL))
 		{
@@ -8916,10 +8917,11 @@ translation table rebuild (fter create/drop index) and DMLs that
 	innobase_active_small();
 
 #ifdef WITH_WSREP
-	if (error == DB_SUCCESS                          && 
+	if (error == DB_SUCCESS                          &&
 	    wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
-            wsrep_on(user_thd)) {
-
+	    wsrep_on(user_thd)                           &&
+	    !wsrep_thd_skip_append_keys(user_thd))
+        {
 		DBUG_PRINT("wsrep", ("update row key"));
 
 		if (wsrep_append_keys(user_thd, false, old_row, new_row)) {
@@ -8995,9 +8997,11 @@ translation table rebuild (fter create/drop index) and DMLs that
 	innobase_active_small();
 
 #ifdef WITH_WSREP
-	if (error == DB_SUCCESS && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
-            wsrep_on(user_thd)) {
-
+	if (error == DB_SUCCESS                          &&
+            wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
+            wsrep_on(user_thd)                           &&
+            !wsrep_thd_skip_append_keys(user_thd))
+        {
 		if (wsrep_append_keys(user_thd, false, record, NULL)) {
 			DBUG_PRINT("wsrep", ("delete fail"));
 			error = DB_ERROR;


More information about the commits mailing list