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

Nirbhay Choubey nirbhay at mariadb.com
Mon Dec 14 08:19:56 EET 2015


revision-id: d48d61811edffd9dce3c0d96db7972b4247bd1eb
parent(s): b88c67d5f23c6beca5604b31919ab45906dd9b39
committer: Nirbhay Choubey
branch nick: 10.0-galera
timestamp: 2015-12-14 01:19:52 -0500
message:

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

Updates in replication state table were partially getting written
to galera transaction write set. Since it never formally committed,
the transaction handle, thus created within galera, never got purged.
As a result, it kept piling up for every transaction 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.

---
 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