diff --git a/mysql-test/suite/galera/t/galera_as_slave_ctas.test b/mysql-test/suite/galera/t/galera_as_slave_ctas.test
index eced636c600..8943ae1faec 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_ctas.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_ctas.test
@@ -27,18 +27,25 @@ SHOW VARIABLES LIKE 'binlog_format';
 #
 # test phase one, issue CTAS with empty source table
 #
-
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
 CREATE TABLE source (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
-
 CREATE TABLE target AS SELECT * FROM source;
 
 --connection node_1
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'source';
+--source include/wait_condition.inc
 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
 --source include/wait_condition.inc
+SELECT * FROM source;
+SELECT * FROM target;
 
 --connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'source';
+--source include/wait_condition.inc
 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
 --source include/wait_condition.inc
+SELECT * FROM source;
+SELECT * FROM target;
 
 #
 # test phase two, issue CTAS with populated source table
@@ -50,18 +57,30 @@ INSERT INTO source VALUES(1);
 CREATE TABLE target AS SELECT * FROM source;
 
 --connection node_1
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
+--source include/wait_condition.inc
 --let $wait_condition = SELECT COUNT(*) = 1 FROM target;
 --source include/wait_condition.inc
 
+SELECT * FROM source;
+SELECT * FROM target;
+
 --connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
+--source include/wait_condition.inc
 --let $wait_condition = SELECT COUNT(*) = 1 FROM target;
 --source include/wait_condition.inc
 
+SELECT * FROM source;
+SELECT * FROM target;
+
 --connection node_3
 DROP TABLE source;
 DROP TABLE target;
 
---connection node_2
+--connection node_1
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'source';
+--source include/wait_condition.inc
 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
 --source include/wait_condition.inc
 
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 6a59a021efc..d29ab143cd3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5433,6 +5433,10 @@ bool Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
 
 int Query_log_event::do_apply_event(rpl_group_info *rgi)
 {
+#ifdef WITH_WSREP
+  if (WSREP(thd))
+    WSREP_DEBUG("Query_log_event::do_apply_event for %s", query);
+#endif
   return do_apply_event(rgi, query, q_len);
 }
 
diff --git a/sql/slave.cc b/sql/slave.cc
index 2cc11b9ed42..62cb1b0765f 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -8040,7 +8040,7 @@ event(errno: %d  cur_log->error: %d)",
 #ifdef WITH_WSREP
 enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size)
 {
-  enum Log_event_type ev_type;
+  enum Log_event_type ev_type= QUERY_EVENT;
 
   mysql_mutex_lock(&rgi->rli->data_lock);
 
@@ -8048,18 +8048,54 @@ enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size)
   unsigned long long orig_future_pos= rgi->future_event_relay_log_pos;
   unsigned long long future_pos= rgi->future_event_relay_log_pos;
 
-  /* scan the log to read next event and we skip
-     annotate events. */
+  /*
+    Here we scan log to find out has CTAS row events i.e.
+    is Select from empty table or not. Remember that
+    mysql.gtid_slave_pos updates are bundled.
+
+    (1) CTAS from empty table
+      Query           Query
+      Xid       OR    Table_map: `mysql`.`gtid_slave_pos`
+                      Write_rows
+		      Xid
+
+    (2) CTAS from not empty table
+      Query
+      Annotate_rows
+      Table_map not to `mysql`.`gtid_slave_pos`
+    
+  */
   do {
+    // Make sure that future position is not larger than EOF
+    // because e.g. in CTAS where selected table is empty
+    // there will be no row events.
+    if (future_pos >= rgi->rli->cur_log->end_of_file)
+      break;
+
     my_b_seek(rgi->rli->cur_log, future_pos);
     rgi->rli->event_relay_log_pos= future_pos;
     rgi->event_relay_log_pos= future_pos;
     Log_event* ev= next_event(rgi, event_size);
     ev_type= (ev) ? ev->get_type_code() : UNKNOWN_EVENT;
+
+    if (ev && ev_type == TABLE_MAP_EVENT)
+    {
+      Table_map_log_event *tev= static_cast<Table_map_log_event *>(ev);
+      // Update to mysql.gtid_pos_table is always at the end of "transaction"
+      if (!my_strcasecmp(system_charset_info, tev->get_db_name(), "mysql") &&
+          !my_strcasecmp(system_charset_info, tev->get_table_name(), "gtid_slave_pos"))
+      {
+        ev_type= QUERY_EVENT; // CTAS selected table is empty
+        delete ev;
+        goto wsrep_peak_end;
+      }
+    }
     delete ev;
     future_pos+= *event_size;
+    WSREP_DEBUG("CTAS reading events=%d", ev_type);
   } while (ev_type == ANNOTATE_ROWS_EVENT || ev_type == XID_EVENT);
 
+wsrep_peak_end:
   /* scan the log back and re-set the positions to original values */
   rgi->rli->event_relay_log_pos= event_pos;
   rgi->event_relay_log_pos= event_pos;
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 7c8bb683aab..11b8db9c06a 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1509,7 +1509,7 @@ static bool wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
 
 static bool wsrep_prepare_keys_for_isolation(THD*              thd,
                                              const char*       db,
-                                             const char*       table,
+                                             const char*       table_name,
                                              const TABLE_LIST* table_list,
                                              Alter_info*       alter_info,
                                              wsrep_key_arr_t*  ka)
@@ -1517,16 +1517,21 @@ static bool wsrep_prepare_keys_for_isolation(THD*              thd,
   ka->keys= 0;
   ka->keys_len= 0;
 
-  if (db || table)
+  if (db || table_name)
   {
-    if (!wsrep_prepare_key_for_isolation(db, table, ka))
+    if (!wsrep_prepare_key_for_isolation(db, table_name, ka))
       goto err;
   }
 
   for (const TABLE_LIST* table= table_list; table; table= table->next_global)
   {
-    if (!wsrep_prepare_key_for_isolation(table->db.str, table->table_name.str, ka))
-      goto err;
+    // Do not add same table again as above
+    if (!db || (db && table->db.str != db) ||
+        !table_name || (table_name && table->table_name.str != table_name))
+    {
+      if (!wsrep_prepare_key_for_isolation(table->db.str, table->table_name.str, ka))
+        goto err;
+    }
   }
 
   if (alter_info)
@@ -1659,20 +1664,25 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
 }
 
 wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
-                                            const char* table,
+                                            const char* table_name,
                                             const TABLE_LIST* table_list,
                                             Alter_info* alter_info,
                                             wsrep::key_array* fk_tables)
 {
   wsrep::key_array ret;
-  if (db || table)
+  if (db || table_name)
   {
-    ret.push_back(wsrep_prepare_key_for_toi(db, table, wsrep::key::exclusive));
+    ret.push_back(wsrep_prepare_key_for_toi(db, table_name, wsrep::key::exclusive));
   }
   for (const TABLE_LIST* table= table_list; table; table= table->next_global)
   {
-    ret.push_back(wsrep_prepare_key_for_toi(table->db.str, table->table_name.str,
-                                            wsrep::key::exclusive));
+    // Do not add same table again as above
+    if (!db || (db && table->db.str != db) ||
+        !table_name || (table_name && table->table_name.str != table_name))
+    {
+      ret.push_back(wsrep_prepare_key_for_toi(table->db.str, table->table_name.str,
+                                              wsrep::key::exclusive));
+    }
   }
   if (alter_info)
   {
@@ -1959,19 +1969,19 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
       switch (ev_type)
       {
       case QUERY_EVENT:
+      case XID_EVENT:
         /* CTAS with empty table, we replicate create table as TOI */
+        WSREP_DEBUG("replicating CTAS of empty table as TOI event=%d",(int)ev_type);
         break;
 
       case TABLE_MAP_EVENT:
-        WSREP_DEBUG("replicating CTAS of empty table as TOI");
-        // fall through
       case WRITE_ROWS_EVENT:
         /* CTAS with populated table, we replicate later at commit time */
-        WSREP_DEBUG("skipping create table of CTAS replication");
+        WSREP_DEBUG("CTAS with populated table replicate later event=%d",(int)ev_type);
         return false;
 
       default:
-        WSREP_WARN("unexpected async replication event: %d", ev_type);
+        WSREP_WARN("unexpected async replication event: %d", (int)ev_type);
       }
       return true;
     }
