summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2018-08-23 17:14:13 +0300
committerJan Lindström <jan.lindstrom@mariadb.com>2018-08-23 17:14:13 +0300
commite4ec889c21ef24fbdfef3d0a36828807241877da (patch)
tree41eb54838e6b6277cb02d0ec3cf7ec0866d78103
parentd6d63f4844bf87adb6250d1b1d43e86feab9a5d0 (diff)
parent420cfe4efe72674d4291c0d5a46205ab70b6b91c (diff)
downloadmariadb-git-bb-10.4-galera-jantmp.tar.gz
Merge remote-tracking branch 'wsrep/10.3_wsrep_api-26' into 10.4bb-10.4-galera-jantmp
Conflicts: mysql-test/include/check-testcase.test mysql-test/include/wait_until_connected_again.inc mysql-test/suite/galera/disabled.def mysql-test/suite/galera/r/MW-416.result mysql-test/suite/galera/r/galera#500.result mysql-test/suite/galera/r/galera_var_dirty_reads.result mysql-test/suite/galera/t/MW-416.test mysql-test/suite/galera/t/galera#500.test sql/handler.cc sql/item_strfunc.cc sql/item_strfunc.h sql/slave.cc sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_insert.cc sql/sql_parse.cc sql/sql_plugin.cc sql/sql_prepare.cc sql/wsrep_applier.cc sql/wsrep_mysqld.cc sql/wsrep_mysqld.h sql/wsrep_sst.cc sql/wsrep_thd.cc storage/innobase/handler/ha_innodb.cc
-rw-r--r--CMakeLists.txt9
-rw-r--r--cmake/wsrep.cmake2
-rw-r--r--include/mysql/service_wsrep.h59
-rw-r--r--include/wsrep.h5
-rw-r--r--mysql-test/include/galera_cluster.inc6
-rw-r--r--mysql-test/include/galera_have_debug_sync.inc (renamed from mysql-test/suite/galera/include/galera_have_debug_sync.inc)0
-rw-r--r--mysql-test/include/galera_wait_sync_point.inc11
-rw-r--r--mysql-test/include/have_ipv6.inc20
-rw-r--r--mysql-test/include/kill_galera.inc20
-rw-r--r--mysql-test/include/mtr_warnings.sql46
-rw-r--r--mysql-test/include/restart_mysqld.inc1
-rw-r--r--mysql-test/include/wait_wsrep_ready.inc13
-rw-r--r--mysql-test/include/wsrep_wait_disconnect.inc20
-rw-r--r--mysql-test/lib/My/ConfigFactory.pm6
-rw-r--r--mysql-test/main/mysqld--help-notwin.result1472
-rw-r--r--mysql-test/main/query_cache_size_functionality.result226
-rw-r--r--mysql-test/main/query_cache_type_functionality.result250
-rwxr-xr-xmysql-test/mysql-test-run.pl124
-rw-r--r--mysql-test/suite/galera/disabled.def2
-rw-r--r--mysql-test/suite/galera/galera_2nodes.cnf25
-rw-r--r--mysql-test/suite/galera/galera_2nodes_as_master.cnf12
-rw-r--r--mysql-test/suite/galera/galera_2nodes_as_slave.cnf47
-rw-r--r--mysql-test/suite/galera/galera_3nodes_as_slave.cnf59
-rw-r--r--mysql-test/suite/galera/galera_4nodes.cnf15
-rw-r--r--mysql-test/suite/galera/include/galera_load_provider.inc68
-rw-r--r--mysql-test/suite/galera/include/galera_resume.inc2
-rw-r--r--mysql-test/suite/galera/include/galera_sst_restore.inc2
-rw-r--r--mysql-test/suite/galera/include/galera_st_clean_slave.inc1
-rw-r--r--mysql-test/suite/galera/include/galera_st_disconnect_slave.inc8
-rw-r--r--mysql-test/suite/galera/include/galera_unload_provider.inc8
-rw-r--r--mysql-test/suite/galera/r/GAL-382.result2
-rw-r--r--mysql-test/suite/galera/r/GAL-401.result2
-rw-r--r--mysql-test/suite/galera/r/GCF-1081.result47
-rw-r--r--mysql-test/suite/galera/r/GCF-939.result12
-rw-r--r--mysql-test/suite/galera/r/MDEV-15443.result2
-rw-r--r--mysql-test/suite/galera/r/MW-252.result2
-rw-r--r--mysql-test/suite/galera/r/MW-258.result2
-rw-r--r--mysql-test/suite/galera/r/MW-259.result2
-rw-r--r--mysql-test/suite/galera/r/MW-284.result4
-rw-r--r--mysql-test/suite/galera/r/MW-285.result2
-rw-r--r--mysql-test/suite/galera/r/MW-292.result27
-rw-r--r--mysql-test/suite/galera/r/MW-309.result2
-rw-r--r--mysql-test/suite/galera/r/MW-313.result2
-rw-r--r--mysql-test/suite/galera/r/MW-328A.result18
-rw-r--r--mysql-test/suite/galera/r/MW-328B.result2
-rw-r--r--mysql-test/suite/galera/r/MW-328C.result2
-rw-r--r--mysql-test/suite/galera/r/MW-328D.result2
-rw-r--r--mysql-test/suite/galera/r/MW-328E.result2
-rw-r--r--mysql-test/suite/galera/r/MW-329.result9
-rw-r--r--mysql-test/suite/galera/r/MW-336.result2
-rw-r--r--mysql-test/suite/galera/r/MW-357.result2
-rw-r--r--mysql-test/suite/galera/r/MW-360.result41
-rw-r--r--mysql-test/suite/galera/r/MW-369.result65
-rw-r--r--mysql-test/suite/galera/r/MW-388.result4
-rw-r--r--mysql-test/suite/galera/r/MW-402.result76
-rw-r--r--mysql-test/suite/galera/r/MW-416.result20
-rw-r--r--mysql-test/suite/galera/r/MW-86-wait1.result17
-rw-r--r--mysql-test/suite/galera/r/MW-86-wait8.result16
-rw-r--r--mysql-test/suite/galera/r/MW-86.result78
-rw-r--r--mysql-test/suite/galera/r/basic.result2
-rw-r--r--mysql-test/suite/galera/r/binlog_checksum.result2
-rw-r--r--mysql-test/suite/galera/r/create.result2
-rw-r--r--mysql-test/suite/galera/r/enforce_storage_engine.result2
-rw-r--r--mysql-test/suite/galera/r/enforce_storage_engine2.result2
-rw-r--r--mysql-test/suite/galera/r/ev51914.result2
-rw-r--r--mysql-test/suite/galera/r/fk.result2
-rw-r--r--mysql-test/suite/galera/r/galera#414.result2
-rw-r--r--mysql-test/suite/galera/r/galera#500.result6
-rw-r--r--mysql-test/suite/galera/r/galera_admin.result2
-rw-r--r--mysql-test/suite/galera/r/galera_alter_engine_innodb.result2
-rw-r--r--mysql-test/suite/galera/r/galera_alter_engine_myisam.result2
-rw-r--r--mysql-test/suite/galera/r/galera_alter_table_force.result2
-rw-r--r--mysql-test/suite/galera/r/galera_applier_ftwrl_table.result2
-rw-r--r--mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result2
-rw-r--r--mysql-test/suite/galera/r/galera_as_master.result4
-rw-r--r--mysql-test/suite/galera/r/galera_as_master_gtid.result44
-rw-r--r--mysql-test/suite/galera/r/galera_as_master_large.result2
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_autoinc.result4
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_gtid.result2
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result160
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result315
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_nonprim.result18
-rw-r--r--mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result2
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort.result4
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result2
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_for_update.result6
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result2
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_get_lock.result4
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_group_commit.result685
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_lock_table.result2
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_shutdown.result9
-rw-r--r--mysql-test/suite/galera/r/galera_bf_abort_sleep.result4
-rw-r--r--mysql-test/suite/galera/r/galera_bf_lock_wait.result2
-rw-r--r--mysql-test/suite/galera/r/galera_binlog_cache_size.result2
-rw-r--r--mysql-test/suite/galera/r/galera_binlog_checksum.result2
-rw-r--r--mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result2
-rw-r--r--mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result2
-rw-r--r--mysql-test/suite/galera/r/galera_binlog_row_image.result2
-rw-r--r--mysql-test/suite/galera/r/galera_create_function.result2
-rw-r--r--mysql-test/suite/galera/r/galera_create_procedure.result2
-rw-r--r--mysql-test/suite/galera/r/galera_create_table_as_select.result103
-rw-r--r--mysql-test/suite/galera/r/galera_create_table_like.result2
-rw-r--r--mysql-test/suite/galera/r/galera_create_trigger.result2
-rw-r--r--mysql-test/suite/galera/r/galera_ddl_multiline.result2
-rw-r--r--mysql-test/suite/galera/r/galera_defaults.result25
-rw-r--r--mysql-test/suite/galera/r/galera_delete_limit.result2
-rw-r--r--mysql-test/suite/galera/r/galera_desync_overlapped.result2
-rw-r--r--mysql-test/suite/galera/r/galera_drop_multi.result2
-rw-r--r--mysql-test/suite/galera/r/galera_enum.result4
-rw-r--r--mysql-test/suite/galera/r/galera_events.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_cascade_delete.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_cascade_update.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_conflict.result4
-rw-r--r--mysql-test/suite/galera/r/galera_fk_mismatch.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_multicolumn.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_multitable.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_no_pk.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_selfreferential.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fk_setnull.result2
-rw-r--r--mysql-test/suite/galera/r/galera_flush_local.result2
-rw-r--r--mysql-test/suite/galera/r/galera_forced_binlog_format.result20
-rw-r--r--mysql-test/suite/galera/r/galera_ftwrl.result2
-rw-r--r--mysql-test/suite/galera/r/galera_ftwrl_drain.result2
-rw-r--r--mysql-test/suite/galera/r/galera_fulltext.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gcs_fc_limit.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gcs_max_packet_size.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gra_log.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gtid.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gtid_slave.result11
-rw-r--r--mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result106
-rw-r--r--mysql-test/suite/galera/r/galera_insert_ignore.result2
-rw-r--r--mysql-test/suite/galera/r/galera_insert_multi.result4
-rw-r--r--mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result24
-rw-r--r--mysql-test/suite/galera/r/galera_ist_progress.result5
-rw-r--r--mysql-test/suite/galera/r/galera_ist_recv_bind.result2
-rw-r--r--mysql-test/suite/galera/r/galera_ist_restart_joiner.result3
-rw-r--r--mysql-test/suite/galera/r/galera_ist_rsync.result2
-rw-r--r--mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result40
-rw-r--r--mysql-test/suite/galera/r/galera_kill_ddl.result2
-rw-r--r--mysql-test/suite/galera/r/galera_kill_largechanges.result2
-rw-r--r--mysql-test/suite/galera/r/galera_kill_smallchanges.result2
-rw-r--r--mysql-test/suite/galera/r/galera_lock_table.result2
-rw-r--r--mysql-test/suite/galera/r/galera_log_bin.result4
-rw-r--r--mysql-test/suite/galera/r/galera_log_output_csv.result2
-rw-r--r--mysql-test/suite/galera/r/galera_many_columns.result4
-rw-r--r--mysql-test/suite/galera/r/galera_many_indexes.result4
-rw-r--r--mysql-test/suite/galera/r/galera_many_rows.result4
-rw-r--r--mysql-test/suite/galera/r/galera_many_tables_nopk.result4
-rw-r--r--mysql-test/suite/galera/r/galera_many_tables_pk.result4
-rw-r--r--mysql-test/suite/galera/r/galera_mdev_10812.result2
-rw-r--r--mysql-test/suite/galera/r/galera_mdev_13787.result2
-rw-r--r--mysql-test/suite/galera/r/galera_mdl_race.result4
-rw-r--r--mysql-test/suite/galera/r/galera_multi_database.result2
-rw-r--r--mysql-test/suite/galera/r/galera_myisam_autocommit.result2
-rw-r--r--mysql-test/suite/galera/r/galera_myisam_transactions.result2
-rw-r--r--mysql-test/suite/galera/r/galera_nopk_bit.result4
-rw-r--r--mysql-test/suite/galera/r/galera_nopk_blob.result4
-rw-r--r--mysql-test/suite/galera/r/galera_nopk_large_varchar.result4
-rw-r--r--mysql-test/suite/galera/r/galera_nopk_unicode.result4
-rw-r--r--mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result6
-rw-r--r--mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result4
-rw-r--r--mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result2
-rw-r--r--mysql-test/suite/galera/r/galera_parallel_simple.result2
-rw-r--r--mysql-test/suite/galera/r/galera_pk_bigint_signed.result4
-rw-r--r--mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result4
-rw-r--r--mysql-test/suite/galera/r/galera_prepared_statement.result2
-rw-r--r--mysql-test/suite/galera/r/galera_query_cache.result2
-rw-r--r--mysql-test/suite/galera/r/galera_query_cache_sync_wait.result2
-rw-r--r--mysql-test/suite/galera/r/galera_read_only.result2
-rw-r--r--mysql-test/suite/galera/r/galera_repl_key_format_flat16.result2
-rw-r--r--mysql-test/suite/galera/r/galera_repl_max_ws_size.result4
-rw-r--r--mysql-test/suite/galera/r/galera_restart_nochanges.result2
-rw-r--r--mysql-test/suite/galera/r/galera_restart_on_unknown_option.result2
-rw-r--r--mysql-test/suite/galera/r/galera_rsu_add_pk.result2
-rw-r--r--mysql-test/suite/galera/r/galera_rsu_drop_pk.result2
-rw-r--r--mysql-test/suite/galera/r/galera_rsu_error.result2
-rw-r--r--mysql-test/suite/galera/r/galera_rsu_simple.result2
-rw-r--r--mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sbr.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sbr_binlog.result2
-rw-r--r--mysql-test/suite/galera/r/galera_schema_dirty_reads.result2
-rw-r--r--mysql-test/suite/galera/r/galera_serializable.result8
-rw-r--r--mysql-test/suite/galera/r/galera_server.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sql_log_bin_zero.result2
-rw-r--r--mysql-test/suite/galera/r/galera_ssl.result2
-rw-r--r--mysql-test/suite/galera/r/galera_ssl_compression.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sst_mysqldump.result114
-rw-r--r--mysql-test/suite/galera/r/galera_sst_rsync.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result110
-rw-r--r--mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result2
-rw-r--r--mysql-test/suite/galera/r/galera_status_cluster.result2
-rw-r--r--mysql-test/suite/galera/r/galera_status_local_index.result2
-rw-r--r--mysql-test/suite/galera/r/galera_status_local_state.result2
-rw-r--r--mysql-test/suite/galera/r/galera_suspend_slave.result2
-rw-r--r--mysql-test/suite/galera/r/galera_sync_wait_show.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_ddl_error.result5
-rw-r--r--mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_ddl_locking.result32
-rw-r--r--mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_ddl_sequential.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_drop_database.result6
-rw-r--r--mysql-test/suite/galera/r/galera_toi_ftwrl.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_lock_exclusive.result4
-rw-r--r--mysql-test/suite/galera/r/galera_toi_lock_shared.result2
-rw-r--r--mysql-test/suite/galera/r/galera_toi_truncate.result4
-rw-r--r--mysql-test/suite/galera/r/galera_transaction_read_only.result2
-rw-r--r--mysql-test/suite/galera/r/galera_transaction_replay.result96
-rw-r--r--mysql-test/suite/galera/r/galera_truncate.result2
-rw-r--r--mysql-test/suite/galera/r/galera_truncate_temporary.result2
-rw-r--r--mysql-test/suite/galera/r/galera_unicode_identifiers.result2
-rw-r--r--mysql-test/suite/galera/r/galera_unicode_pk.result6
-rw-r--r--mysql-test/suite/galera/r/galera_update_limit.result2
-rw-r--r--mysql-test/suite/galera/r/galera_v1_row_events.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_OSU_method.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_OSU_method2.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result4
-rw-r--r--mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_cluster_address.result6
-rw-r--r--mysql-test/suite/galera/r/galera_var_desync_on.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_dirty_reads.result1
-rw-r--r--mysql-test/suite/galera/r/galera_var_fkchecks.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_gtid_domain_id.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result154
-rw-r--r--mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_load_data_splitting.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_log_bin.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_max_ws_rows.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_max_ws_size.result4
-rw-r--r--mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_node_address.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_reject_queries.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_slave_threads.result210
-rw-r--r--mysql-test/suite/galera/r/galera_var_sst_auth.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_sync_wait.result2
-rw-r--r--mysql-test/suite/galera/r/galera_var_wsrep_on_off.result2
-rw-r--r--mysql-test/suite/galera/r/galera_wan.result2
-rw-r--r--mysql-test/suite/galera/r/galera_wan_restart_ist.result2
-rw-r--r--mysql-test/suite/galera/r/galera_wan_restart_sst.result2
-rw-r--r--mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result2
-rw-r--r--mysql-test/suite/galera/r/galera_wsrep_log_conficts.result4
-rw-r--r--mysql-test/suite/galera/r/galera_wsrep_new_cluster.result2
-rw-r--r--mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result2
-rw-r--r--mysql-test/suite/galera/r/galera_zero_length_column.result2
-rw-r--r--mysql-test/suite/galera/r/grant.result2
-rw-r--r--mysql-test/suite/galera/r/lp1276424.result2
-rw-r--r--mysql-test/suite/galera/r/lp1347768.result2
-rw-r--r--mysql-test/suite/galera/r/lp1376747-2.result2
-rw-r--r--mysql-test/suite/galera/r/lp1376747-3.result2
-rw-r--r--mysql-test/suite/galera/r/lp1376747-4.result2
-rw-r--r--mysql-test/suite/galera/r/lp1376747.result2
-rw-r--r--mysql-test/suite/galera/r/lp1438990.result2
-rw-r--r--mysql-test/suite/galera/r/lp959512.result2
-rw-r--r--mysql-test/suite/galera/r/mdev_10518.result2
-rw-r--r--mysql-test/suite/galera/r/mdev_9290.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#110.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#198.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#201.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#237.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#247.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#31.result2
-rw-r--r--mysql-test/suite/galera/r/mysql-wsrep#90.result2
-rw-r--r--mysql-test/suite/galera/r/partition.result6
-rw-r--r--mysql-test/suite/galera/r/pxc-421.result2
-rw-r--r--mysql-test/suite/galera/r/query_cache.result2
-rw-r--r--mysql-test/suite/galera/r/rename.result2
-rw-r--r--mysql-test/suite/galera/r/rpl_row_annotate.result8
-rw-r--r--mysql-test/suite/galera/r/sql_log_bin.result2
-rw-r--r--mysql-test/suite/galera/r/unique_key.result2
-rw-r--r--mysql-test/suite/galera/r/view.result2
-rw-r--r--mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result25
-rw-r--r--mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result13
-rw-r--r--mysql-test/suite/galera/t/GAL-419.test4
-rw-r--r--mysql-test/suite/galera/t/GCF-1081.test72
-rw-r--r--mysql-test/suite/galera/t/GCF-939.test25
-rw-r--r--mysql-test/suite/galera/t/MW-284.test2
-rw-r--r--mysql-test/suite/galera/t/MW-292.test50
-rw-r--r--mysql-test/suite/galera/t/MW-328A.test40
-rw-r--r--mysql-test/suite/galera/t/MW-329.test28
-rw-r--r--mysql-test/suite/galera/t/MW-336.test10
-rw-r--r--mysql-test/suite/galera/t/MW-360-master.opt2
-rw-r--r--mysql-test/suite/galera/t/MW-360.test100
-rw-r--r--mysql-test/suite/galera/t/MW-369.inc7
-rw-r--r--mysql-test/suite/galera/t/MW-369.test1
-rw-r--r--mysql-test/suite/galera/t/MW-388.test1
-rw-r--r--mysql-test/suite/galera/t/MW-402.test56
-rw-r--r--mysql-test/suite/galera/t/MW-416.test24
-rw-r--r--mysql-test/suite/galera/t/MW-86-master.opt1
-rw-r--r--mysql-test/suite/galera/t/MW-86-wait1.test13
-rw-r--r--mysql-test/suite/galera/t/MW-86-wait8.test11
-rw-r--r--mysql-test/suite/galera/t/MW-86.test193
-rw-r--r--mysql-test/suite/galera/t/disabled.def13
-rw-r--r--mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt2
-rw-r--r--mysql-test/suite/galera/t/galera_as_master.test2
-rw-r--r--mysql-test/suite/galera/t/galera_as_master_gtid.test24
-rw-r--r--mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test2
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave.test19
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_autoinc.test20
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid.test21
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf17
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test150
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test176
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_nonprim.test28
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_preordered.test19
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test13
-rw-r--r--mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf15
-rw-r--r--mysql-test/suite/galera/t/galera_bf_abort_group_commit.test76
-rw-r--r--mysql-test/suite/galera/t/galera_bf_abort_shutdown.test22
-rw-r--r--mysql-test/suite/galera/t/galera_create_table_as_select.test145
-rw-r--r--mysql-test/suite/galera/t/galera_defaults.test4
-rw-r--r--mysql-test/suite/galera/t/galera_forced_binlog_format.test5
-rw-r--r--mysql-test/suite/galera/t/galera_ftwrl_drain.test2
-rw-r--r--mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test4
-rw-r--r--mysql-test/suite/galera/t/galera_gtid-master.opt2
-rw-r--r--mysql-test/suite/galera/t/galera_gtid_slave.test14
-rw-r--r--mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test109
-rw-r--r--mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_ist_progress.test4
-rw-r--r--mysql-test/suite/galera/t/galera_ist_restart_joiner.test2
-rw-r--r--mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_log_bin.test2
-rw-r--r--mysql-test/suite/galera/t/galera_migrate.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test4
-rw-r--r--mysql-test/suite/galera/t/galera_parallel_simple.test2
-rw-r--r--mysql-test/suite/galera/t/galera_pc_recovery.test93
-rw-r--r--mysql-test/suite/galera/t/galera_split_brain.test6
-rw-r--r--mysql-test/suite/galera/t/galera_ssl_upgrade.test4
-rw-r--r--mysql-test/suite/galera/t/galera_sst_mysqldump.test3
-rw-r--r--mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf2
-rw-r--r--mysql-test/suite/galera/t/galera_toi_ddl_error.test5
-rw-r--r--mysql-test/suite/galera/t/galera_toi_ddl_locking.test53
-rw-r--r--mysql-test/suite/galera/t/galera_transaction_replay.test201
-rw-r--r--mysql-test/suite/galera/t/galera_var_cluster_address.test9
-rw-r--r--mysql-test/suite/galera/t/galera_var_dirty_reads.test9
-rw-r--r--mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test235
-rw-r--r--mysql-test/suite/galera/t/galera_var_log_bin.cnf5
-rw-r--r--mysql-test/suite/galera/t/galera_var_slave_threads.test123
-rw-r--r--mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt1
-rw-r--r--mysql-test/suite/galera/t/galera_wsrep_new_cluster.test1
-rw-r--r--mysql-test/suite/galera/t/mysql-wsrep#198-master.opt1
-rw-r--r--mysql-test/suite/galera/t/partition.test16
-rw-r--r--mysql-test/suite/galera/t/rpl_row_annotate.test6
-rw-r--r--mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test26
-rw-r--r--mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test22
-rw-r--r--mysql-test/suite/galera_3nodes/galera_3nodes.cnf1
-rw-r--r--mysql-test/suite/galera_3nodes/include/galera_suspend.inc2
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result2
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result3
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result3
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result2
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result13
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_pc_weight.result8
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result77
-rw-r--r--mysql-test/suite/galera_3nodes/t/GAL-501.test6
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test2
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test6
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_garbd.test5
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test30
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test2
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf8
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_pc_weight.test34
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test1
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test74
-rw-r--r--mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf1
-rw-r--r--mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc58
-rw-r--r--mysql-test/suite/galera_3nodes_ee/my.cnf1
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/GCF-354.result23
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/GCF-361.result16
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/GCF-363.result31
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/GCF-376.result48
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result21
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result19
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result32
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result27
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result35
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result33
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result46
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result50
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result52
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result52
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result42
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result32
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result28
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result35
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result19
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result60
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result52
-rw-r--r--mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result12
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-354.test59
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-361.test47
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf8
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-363.test68
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/GCF-376.test84
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test67
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test61
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test75
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test73
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test73
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf11
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test70
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test38
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test38
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test35
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test41
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test92
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test80
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test66
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test69
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test63
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf4
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test80
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt2
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test87
-rw-r--r--mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test39
-rw-r--r--mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf1
-rw-r--r--mysql-test/suite/galera_3nodes_sr/my.cnf1
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-336.result26
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-582.result23
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-606.result23
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-609.result20
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result256
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result100
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result177
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-817.result33
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/GCF-832.result15
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result62
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result25
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result22
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result38
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result44
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result31
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result27
-rw-r--r--mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result84
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-336.test47
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-582.test39
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-606.test80
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-609.test30
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test137
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test49
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test70
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-817.test101
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/GCF-832.test36
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/disabled.def0
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test127
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test56
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test56
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test75
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test76
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test56
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test71
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf5
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test169
-rw-r--r--mysql-test/suite/galera_ee/galera_2nodes.cnf1
-rw-r--r--mysql-test/suite/galera_ee/galera_4nodes.cnf1
-rw-r--r--mysql-test/suite/galera_ee/my.cnf1
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-329A.result30
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-329B.result16
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-360.result416
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-421.result14
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-546.result28
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-563.result52
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-849.result11
-rw-r--r--mysql-test/suite/galera_ee/r/GCF-854.result16
-rw-r--r--mysql-test/suite/galera_ee/r/galera-features#117.result29
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result14
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result44
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result22
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result30
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result37
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result39
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result11
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result29
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result45
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result26
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result19
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result38
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_create_index.result36
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result22
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result13
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result12
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_processlist.result35
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result23
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result14
-rw-r--r--mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result26
-rw-r--r--mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result44
-rw-r--r--mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result47
-rw-r--r--mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result5
-rw-r--r--mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result7
-rw-r--r--mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result12
-rw-r--r--mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result18
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-329A.test42
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-329B.test53
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-360.cnf17
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-360.test64
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-421.test46
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-546.test47
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-563.test63
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-849.test39
-rw-r--r--mysql-test/suite/galera_ee/t/GCF-854.test42
-rw-r--r--mysql-test/suite/galera_ee/t/galera-features#117.cnf4
-rw-r--r--mysql-test/suite/galera_ee/t/galera-features#117.test37
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test57
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test67
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test31
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test34
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test64
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test67
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test15
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test57
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test65
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test29
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test31
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test53
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_create_index.test34
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test38
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test21
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test55
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_processlist.test81
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test89
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt2
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test37
-rw-r--r--mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test42
-rw-r--r--mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf5
-rw-r--r--mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test87
-rw-r--r--mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf4
-rw-r--r--mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test91
-rw-r--r--mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test16
-rw-r--r--mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt1
-rw-r--r--mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test11
-rw-r--r--mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test38
-rw-r--r--mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test39
-rw-r--r--mysql-test/suite/galera_sr/galera_2nodes.cnf1
-rw-r--r--mysql-test/suite/galera_sr/my.cnf1
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1008.result50
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1018.result15
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1018B.result8
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1043A.result15
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1043B.result15
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1051.result37
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-1060.result15
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-437.result12
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-561.result42
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-571.result56
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-572.result29
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-574.result11
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-580.result11
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-585.result25
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-597.result15
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-620.result14
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-623.result22
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-627.result18
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-845.result14
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-851.result24
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-867.result2
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-889.result18
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-900.result13
-rw-r--r--mysql-test/suite/galera_sr/r/galera-features#56.result21
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result448
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_blob.result15
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_cc_master.result45
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result46
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_concurrent.result28
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_conflict.result14
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result22
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result19
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result22
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result41
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result18
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result42
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result34
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result36
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result34
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_gtid.result65
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_insert_select.result11
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result21
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result22
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result22
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result25
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_kill_query.result17
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result39
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result28
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_load_data.result8
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result9
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_log_bin.result87
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result28
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_myisam.result11
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result40
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result26
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_rollback.result29
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result26
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result33
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result22
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_sbr.result16
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result20
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result29
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result10
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_table_contents.result198
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result101
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result18
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result15
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_ws_size.result29
-rw-r--r--mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result28
-rw-r--r--mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result22
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep#215.result88
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result41
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result17
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result8
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result27
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result8
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result752
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result26
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result46
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result26
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result17
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result14
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result22
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result26
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result27
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result12
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result15
-rw-r--r--mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result26
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1008.inc36
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1008.test18
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1018.test38
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1018B.test40
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1043A.test13
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1043B.test13
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1051.test52
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-1060.test9
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-437.test21
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-561.test65
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-571.test54
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-572.test54
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-574.test27
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-580.test27
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-585.test40
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-597.test29
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-620.test22
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-623.test31
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-627.test30
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-845.test30
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-851.test24
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-867.test42
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-889.test28
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-900.test28
-rw-r--r--mysql-test/suite/galera_sr/t/disabled.def4
-rw-r--r--mysql-test/suite/galera_sr/t/galera-features#56.test55
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc145
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test48
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_blob.test38
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_cc_master.test87
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test86
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_concurrent.test45
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_conflict.test45
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test45
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test46
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test44
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test63
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test43
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test65
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test53
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test57
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test62
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt1
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_gtid.test46
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_insert_select.test33
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test52
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf4
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test53
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test54
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test59
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_query.test53
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf4
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test80
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt1
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test58
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_load_data.test39
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test50
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt1
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_log_bin.test66
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test53
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_myisam.test29
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf11
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test79
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test59
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_rollback.test76
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test55
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test51
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test61
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_sbr.test31
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test45
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test63
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf6
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test21
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_table_contents.test49
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test260
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test47
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt1
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test27
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_ws_size.test70
-rw-r--r--mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test62
-rw-r--r--mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test37
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep#215.test161
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt1
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test37
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test25
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test21
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test60
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test17
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc104
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test41
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test63
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test86
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test47
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test29
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test23
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt1
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test44
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test46
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test63
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test44
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test29
-rw-r--r--mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test45
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-online-fk.result10
-rw-r--r--mysql-test/suite/innodb/t/galera.skip53
-rw-r--r--mysql-test/suite/innodb/t/innodb-index-online-fk.test10
-rw-r--r--packaging/deb-in/CMakeLists.txt357
-rw-r--r--plugin/wsrep_info/plugin.cc2
-rw-r--r--scripts/mysqld_safe.sh11
-rw-r--r--scripts/wsrep_sst_mysqldump.sh1
-rw-r--r--scripts/wsrep_sst_xtrabackup-v2.sh2
-rw-r--r--sql/CMakeLists.txt15
-rw-r--r--sql/events.cc1
-rw-r--r--sql/ha_partition.cc7
-rw-r--r--sql/ha_partition.h3
-rw-r--r--sql/handler.cc216
-rw-r--r--sql/item_create.cc102
-rw-r--r--sql/item_strfunc.cc102
-rw-r--r--sql/item_strfunc.h52
-rw-r--r--sql/lock.cc25
-rw-r--r--sql/log.cc379
-rw-r--r--sql/log.h19
-rw-r--r--sql/log_event.cc19
-rw-r--r--sql/mdl.cc74
-rw-r--r--sql/mysqld.cc51
-rw-r--r--sql/protocol.cc21
-rw-r--r--sql/slave.cc111
-rw-r--r--sql/sp_head.cc29
-rw-r--r--sql/sql_alter.cc2
-rw-r--r--sql/sql_base.cc23
-rw-r--r--sql/sql_class.cc145
-rw-r--r--sql/sql_class.h373
-rw-r--r--sql/sql_connect.cc5
-rw-r--r--sql/sql_insert.cc53
-rw-r--r--sql/sql_load.cc9
-rw-r--r--sql/sql_parse.cc604
-rw-r--r--sql/sql_parse.h2
-rw-r--r--sql/sql_plugin.cc5
-rw-r--r--sql/sql_plugin_services.ic9
-rw-r--r--sql/sql_prepare.cc8
-rw-r--r--sql/sql_repl.cc11
-rw-r--r--sql/sql_table.cc32
-rw-r--r--sql/sql_truncate.cc18
-rw-r--r--sql/sys_vars.cc38
-rw-r--r--sql/table.cc7
-rw-r--r--sql/transaction.cc36
-rw-r--r--sql/wsrep_applier.cc898
-rw-r--r--sql/wsrep_applier.h67
-rw-r--r--sql/wsrep_binlog.cc201
-rw-r--r--sql/wsrep_binlog.h55
-rw-r--r--sql/wsrep_dummy.cc19
-rw-r--r--sql/wsrep_hton.cc1
-rw-r--r--sql/wsrep_mysqld.cc2034
-rw-r--r--sql/wsrep_mysqld.h333
-rw-r--r--sql/wsrep_plugin.cc53
-rw-r--r--sql/wsrep_priv.h9
-rw-r--r--sql/wsrep_schema.cc1481
-rw-r--r--sql/wsrep_schema.h141
-rw-r--r--sql/wsrep_sr.cc428
-rw-r--r--sql/wsrep_sr.h275
-rw-r--r--sql/wsrep_sr_file.cc563
-rw-r--r--sql/wsrep_sr_file.h111
-rw-r--r--sql/wsrep_sr_table.cc223
-rw-r--r--sql/wsrep_sr_table.h67
-rw-r--r--sql/wsrep_sst.cc169
-rw-r--r--sql/wsrep_sst.h10
-rw-r--r--sql/wsrep_tc.h0
-rw-r--r--sql/wsrep_thd.cc751
-rw-r--r--sql/wsrep_thd.h176
-rw-r--r--sql/wsrep_thd_pool.cc122
-rw-r--r--sql/wsrep_thd_pool.h37
-rw-r--r--sql/wsrep_trans_observer.cc1663
-rw-r--r--sql/wsrep_trans_observer.h117
-rw-r--r--sql/wsrep_utils.cc1
-rw-r--r--sql/wsrep_utils.h34
-rw-r--r--sql/wsrep_var.cc184
-rw-r--r--sql/wsrep_var.h5
-rw-r--r--sql/wsrep_xid.cc42
-rw-r--r--sql/wsrep_xid.h12
-rw-r--r--storage/innobase/buf/buf0dump.cc6
-rw-r--r--storage/innobase/handler/ha_innodb.cc228
-rw-r--r--storage/innobase/handler/ha_innodb.h9
-rw-r--r--storage/innobase/include/ha_prototypes.h5
-rw-r--r--storage/innobase/include/trx0trx.h17
-rw-r--r--storage/innobase/lock/lock0lock.cc14
-rw-r--r--storage/innobase/lock/lock0wait.cc8
-rw-r--r--storage/innobase/row/row0ins.cc22
-rw-r--r--storage/innobase/row/row0sel.cc16
-rw-r--r--storage/innobase/row/row0upd.cc14
-rw-r--r--storage/innobase/trx/trx0roll.cc5
-rw-r--r--storage/innobase/trx/trx0rseg.cc3
-rw-r--r--wsrep/wsrep_api.h533
-rw-r--r--wsrep/wsrep_dummy.c116
-rw-r--r--wsrep/wsrep_gtid.c2
-rw-r--r--wsrep/wsrep_listener.c261
-rw-r--r--wsrep/wsrep_loader.c28
-rw-r--r--wsrep/wsrep_uuid.c11
833 files changed, 36459 insertions, 2490 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 58b6cc62e9f..5477e68a113 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -380,6 +380,11 @@ INCLUDE(mariadb_connector_c) # this does ADD_SUBDIRECTORY(libmariadb)
# Add storage engines and plugins.
CONFIGURE_PLUGINS()
+IF(WITH_WSREP)
+ADD_SUBDIRECTORY(wsrep)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep)
+ENDIF()
+
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(dbug)
ADD_SUBDIRECTORY(strings)
@@ -401,10 +406,6 @@ IF(NOT WITHOUT_SERVER)
ADD_SUBDIRECTORY(unittest/embedded)
ENDIF(WITH_EMBEDDED_SERVER)
- IF(WITH_WSREP)
- ADD_SUBDIRECTORY(wsrep)
- ENDIF()
-
ADD_SUBDIRECTORY(mysql-test)
ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess)
ADD_SUBDIRECTORY(sql-bench)
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake
index 9fa127380a4..3d77ef754ae 100644
--- a/cmake/wsrep.cmake
+++ b/cmake/wsrep.cmake
@@ -26,7 +26,7 @@ ENDIF()
OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default})
# Set the patch version
-SET(WSREP_PATCH_VERSION "23")
+SET(WSREP_PATCH_VERSION "22")
# Obtain wsrep API version
FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION
diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h
index 1540a5e56fe..d0d00cf2013 100644
--- a/include/mysql/service_wsrep.h
+++ b/include/mysql/service_wsrep.h
@@ -1,4 +1,5 @@
#ifndef MYSQL_SERVICE_WSREP_INCLUDED
+
/* Copyright (c) 2015 MariaDB Corporation Ab
This program is free software; you can redistribute it and/or modify
@@ -48,15 +49,16 @@ enum wsrep_exec_mode {
Transaction procession after it has been replicated in prepare stage and
has passed certification.
*/
- LOCAL_COMMIT
+ LOCAL_COMMIT,
+ LOCAL_ROLLBACK,
};
enum wsrep_query_state {
QUERY_IDLE,
QUERY_EXEC,
QUERY_COMMITTING,
+ QUERY_ORDERED_COMMIT,
QUERY_EXITING,
- QUERY_ROLLINGBACK,
};
enum wsrep_trx_status {
@@ -67,12 +69,12 @@ enum wsrep_trx_status {
};
struct xid_t;
-struct wsrep;
+struct wsrep_st;
struct wsrep_ws_handle;
struct wsrep_buf;
extern struct wsrep_service_st {
- struct wsrep * (*get_wsrep_func)();
+ struct wsrep_st * (*get_wsrep_func)();
my_bool (*get_wsrep_certify_nonPK_func)();
my_bool (*get_wsrep_debug_func)();
my_bool (*get_wsrep_drupal_282555_workaround_func)();
@@ -80,26 +82,22 @@ extern struct wsrep_service_st {
my_bool (*get_wsrep_load_data_splitting_func)();
my_bool (*get_wsrep_log_conflicts_func)();
long (*get_wsrep_protocol_version_func)();
- my_bool (*wsrep_aborting_thd_contains_func)(THD *thd);
- void (*wsrep_aborting_thd_enqueue_func)(THD *thd);
bool (*wsrep_consistency_check_func)(THD *thd);
- int (*wsrep_is_wsrep_xid_func)(const struct xid_t *xid);
+ int (*wsrep_is_wsrep_xid_func)(const void *xid);
long long (*wsrep_xid_seqno_func)(const struct xid_t *xid);
const unsigned char* (*wsrep_xid_uuid_func)(const struct xid_t *xid);
- void (*wsrep_lock_rollback_func)();
- int (*wsrep_on_func)(MYSQL_THD);
- void (*wsrep_post_commit_func)(THD* thd, bool all);
- bool (*wsrep_prepare_key_func)(const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*);
- enum wsrep_trx_status (*wsrep_run_wsrep_commit_func)(THD *thd, bool all);
+ int (*wsrep_on_func)(void *);
+ bool (*wsrep_prepare_key_for_innodb_func)(THD* thd, const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*);
void (*wsrep_thd_LOCK_func)(THD *thd);
void (*wsrep_thd_UNLOCK_func)(THD *thd);
void (*wsrep_thd_awake_func)(THD *thd, my_bool signal);
enum wsrep_conflict_state (*wsrep_thd_conflict_state_func)(MYSQL_THD, my_bool);
+ my_thread_id (*wsrep_thd_thread_id_func)(THD *thd);
const char * (*wsrep_thd_conflict_state_str_func)(THD *thd);
enum wsrep_exec_mode (*wsrep_thd_exec_mode_func)(THD *thd);
const char * (*wsrep_thd_exec_mode_str_func)(THD *thd);
enum wsrep_conflict_state (*wsrep_thd_get_conflict_state_func)(MYSQL_THD);
- my_bool (*wsrep_thd_is_BF_func)(MYSQL_THD , my_bool);
+ my_bool (*wsrep_thd_is_BF_func)(void* , my_bool);
my_bool (*wsrep_thd_is_wsrep_func)(MYSQL_THD thd);
char * (*wsrep_thd_query_func)(THD *thd);
enum wsrep_query_state (*wsrep_thd_query_state_func)(THD *thd);
@@ -107,14 +105,15 @@ extern struct wsrep_service_st {
int (*wsrep_thd_retry_counter_func)(THD *thd);
void (*wsrep_thd_set_conflict_state_func)(THD *thd, enum wsrep_conflict_state state);
bool (*wsrep_thd_ignore_table_func)(THD *thd);
- long long (*wsrep_thd_trx_seqno_func)(THD *thd);
+ int64_t (*wsrep_thd_trx_seqno_func)(const THD *thd);
struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd);
int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd);
int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD);
- void (*wsrep_unlock_rollback_func)();
} *wsrep_service;
+
#ifdef MYSQL_DYNAMIC_PLUGIN
+
#define get_wsrep() wsrep_service->get_wsrep_func()
#define get_wsrep_certify_nonPK() wsrep_service->get_wsrep_certify_nonPK_func()
#define get_wsrep_debug() wsrep_service->get_wsrep_debug_func()
@@ -123,17 +122,12 @@ extern struct wsrep_service_st {
#define get_wsrep_load_data_splitting() wsrep_service->get_wsrep_load_data_splitting_func()
#define get_wsrep_log_conflicts() wsrep_service->get_wsrep_log_conflicts_func()
#define get_wsrep_protocol_version() wsrep_service->get_wsrep_protocol_version_func()
-#define wsrep_aborting_thd_contains(T) wsrep_service->wsrep_aborting_thd_contains_func(T)
-#define wsrep_aborting_thd_enqueue(T) wsrep_service->wsrep_aborting_thd_enqueue_func(T)
#define wsrep_consistency_check(T) wsrep_service->wsrep_consistency_check_func(T)
#define wsrep_is_wsrep_xid(X) wsrep_service->wsrep_is_wsrep_xid_func(X)
#define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X)
#define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X)
-#define wsrep_lock_rollback() wsrep_service->wsrep_lock_rollback_func()
#define wsrep_on(X) wsrep_service->wsrep_on_func(X)
-#define wsrep_post_commit(T,A) wsrep_service->wsrep_post_commit_func(T,A)
-#define wsrep_prepare_key(A,B,C,D,E,F) wsrep_service->wsrep_prepare_key_func(A,B,C,D,E,F)
-#define wsrep_run_wsrep_commit(T,A) wsrep_service->wsrep_run_wsrep_commit_func(T,A)
+#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F.G)
#define wsrep_thd_LOCK(T) wsrep_service->wsrep_thd_LOCK_func(T)
#define wsrep_thd_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T)
#define wsrep_thd_awake(T,S) wsrep_service->wsrep_thd_awake_func(T,S)
@@ -148,13 +142,13 @@ extern struct wsrep_service_st {
#define wsrep_thd_query_state(T) wsrep_service->wsrep_thd_query_state_func(T)
#define wsrep_thd_query_state_str(T) wsrep_service->wsrep_thd_query_state_str_func(T)
#define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T)
-#define wsrep_thd_set_conflict_state(T,S) wsrep_service->wsrep_thd_set_conflict_state_func(T,S)
#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T)
#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T)
#define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T)
#define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T)
#define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2)
-#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func()
+#define wsrep_thd_thread_id(T) wsrep_service->wsrep_thd_thread_id_func(T)
+#define wsrep_thd_xid(T,X,S) wsrep_service->wsrep_thd_xid_func(T,X,S)
#define wsrep_debug get_wsrep_debug()
#define wsrep_log_conflicts get_wsrep_log_conflicts()
@@ -173,10 +167,11 @@ extern my_bool wsrep_load_data_splitting;
extern my_bool wsrep_drupal_282555_workaround;
extern my_bool wsrep_recovery;
extern long wsrep_protocol_version;
+extern my_thread_id wsrep_thd_thread_id(THD *thd);
bool wsrep_consistency_check(THD *thd);
-bool wsrep_prepare_key(const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len);
-char *wsrep_thd_query(THD *thd);
+bool wsrep_prepare_key_for_innodb(THD* thd, const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len);
+extern "C" char *wsrep_thd_query(THD *thd);
const char *wsrep_thd_conflict_state_str(THD *thd);
const char *wsrep_thd_exec_mode_str(THD *thd);
const char *wsrep_thd_query_state_str(THD *thd);
@@ -185,15 +180,15 @@ enum wsrep_conflict_state wsrep_thd_get_conflict_state(MYSQL_THD thd);
enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
enum wsrep_query_state wsrep_thd_query_state(THD *thd);
enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, bool all);
-int wsrep_is_wsrep_xid(const struct xid_t* xid);
+int wsrep_is_wsrep_xid(const void* xid);
long long wsrep_xid_seqno(const struct xid_t* xid);
const unsigned char* wsrep_xid_uuid(const struct xid_t* xid);
-int wsrep_on(MYSQL_THD thd);
+int wsrep_on(void *);
int wsrep_thd_retry_counter(THD *thd);
int wsrep_trx_is_aborting(MYSQL_THD thd);
int wsrep_trx_order_before(MYSQL_THD thd1, MYSQL_THD thd2);
long get_wsrep_protocol_version();
-long long wsrep_thd_trx_seqno(THD *thd);
+int64_t wsrep_thd_trx_seqno(const THD *thd);
my_bool get_wsrep_certify_nonPK();
my_bool get_wsrep_debug();
my_bool get_wsrep_drupal_282555_workaround();
@@ -201,20 +196,18 @@ my_bool get_wsrep_recovery();
my_bool get_wsrep_load_data_splitting();
my_bool get_wsrep_log_conflicts();
my_bool wsrep_aborting_thd_contains(THD *thd);
-my_bool wsrep_thd_is_BF(MYSQL_THD thd, my_bool sync);
+my_bool wsrep_thd_is_BF(void* thd, my_bool sync);
my_bool wsrep_thd_is_wsrep(MYSQL_THD thd);
-struct wsrep *get_wsrep();
+struct wsrep_st *get_wsrep();
struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd);
void wsrep_aborting_thd_enqueue(THD *thd);
-void wsrep_lock_rollback();
void wsrep_post_commit(THD* thd, bool all);
void wsrep_thd_LOCK(THD *thd);
void wsrep_thd_UNLOCK(THD *thd);
void wsrep_thd_awake(THD *thd, my_bool signal);
void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state);
bool wsrep_thd_ignore_table(THD *thd);
-void wsrep_unlock_rollback();
-
+void wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size);
#endif
#ifdef __cplusplus
diff --git a/include/wsrep.h b/include/wsrep.h
index 0c06bb32b31..def7ad1b377 100644
--- a/include/wsrep.h
+++ b/include/wsrep.h
@@ -39,6 +39,11 @@
if (WSREP(thd) && !thd->lex->no_write_to_binlog \
&& wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error;
+#define WSREP_SYNC_WAIT(thd_, before_) \
+ { if (WSREP_CLIENT(thd_) && \
+ wsrep_sync_wait(thd_, before_)) goto error; }
+
+
#define WSREP_DEBUG(...) \
if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
diff --git a/mysql-test/include/galera_cluster.inc b/mysql-test/include/galera_cluster.inc
index c1834c3c26f..7f76ea59c7f 100644
--- a/mysql-test/include/galera_cluster.inc
+++ b/mysql-test/include/galera_cluster.inc
@@ -8,5 +8,11 @@
--let $galera_cluster_size = 2
--source include/galera_init.inc
+--source include/have_innodb.inc
+--source include/galera_wait_ready.inc
+--connection node_2
+--source include/galera_wait_ready.inc
--source include/have_innodb.inc
+
+--connection node_1
diff --git a/mysql-test/suite/galera/include/galera_have_debug_sync.inc b/mysql-test/include/galera_have_debug_sync.inc
index 7c0156052d8..7c0156052d8 100644
--- a/mysql-test/suite/galera/include/galera_have_debug_sync.inc
+++ b/mysql-test/include/galera_have_debug_sync.inc
diff --git a/mysql-test/include/galera_wait_sync_point.inc b/mysql-test/include/galera_wait_sync_point.inc
index cf3a4980186..c0951b220b4 100644
--- a/mysql-test/include/galera_wait_sync_point.inc
+++ b/mysql-test/include/galera_wait_sync_point.inc
@@ -1,6 +1,17 @@
--let $wait_timeout = 10
--let $wsrep_on_orig = `SELECT @@wsrep_on`
SET SESSION wsrep_on = 0;
+
+#
+# following is only for debugging purposes
+# should be commented out when test wporks as planned
+#
+#--sleep 1
+# SHOW PROCESSLIST;
+#SHOW STATUS LIKE 'wsrep_%';
+#--echo $galera_sync_point
+
--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = '$galera_sync_point'
--source include/wait_condition.inc
--eval SET SESSION wsrep_on = $wsrep_on_orig
+
diff --git a/mysql-test/include/have_ipv6.inc b/mysql-test/include/have_ipv6.inc
new file mode 100644
index 00000000000..752dd0db53e
--- /dev/null
+++ b/mysql-test/include/have_ipv6.inc
@@ -0,0 +1,20 @@
+# Check if ipv6 is available.
+#
+--disable_query_log
+--disable_result_log
+--disable_abort_on_error
+connect (checkcon123456789,::1,root,,test);
+if($mysql_errno)
+{
+ skip No IPv6 support;
+}
+connection default;
+if(!$mysql_errno)
+{
+ disconnect checkcon123456789;
+}
+--enable_abort_on_error
+--enable_result_log
+--enable_query_log
+# end check
+
diff --git a/mysql-test/include/kill_galera.inc b/mysql-test/include/kill_galera.inc
new file mode 100644
index 00000000000..d7f665df6c7
--- /dev/null
+++ b/mysql-test/include/kill_galera.inc
@@ -0,0 +1,20 @@
+--echo Killing server ...
+
+# Write file to make mysql-test-run.pl expect the crash, but don't start it
+--let $_server_id= `SELECT @@server_id`
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
+--exec echo "wait" > $_expect_file_name
+
+# Kill the connected server
+--disable_reconnect
+--let KILL_NODE_PIDFILE = `SELECT @@pid_file`
+
+--perl
+ my $pid_filename = $ENV{'KILL_NODE_PIDFILE'};
+ my $mysqld_pid = `cat $pid_filename`;
+ chomp($mysqld_pid);
+ system("kill -9 $mysqld_pid");
+ exit(0);
+EOF
+
+--source include/wait_until_disconnected.inc
diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql
index b7b2a316dfb..28974cff315 100644
--- a/mysql-test/include/mtr_warnings.sql
+++ b/mysql-test/include/mtr_warnings.sql
@@ -229,6 +229,52 @@ INSERT INTO global_suppressions VALUES
MDEV-12501 -- set --maturity-level by default
*/
("Plugin .* is of maturity level .* while the server is .*"),
+ ("WSREP:*down context*"),
+ ("WSREP: Failed to send state UUID:*"),
+ ("WSREP: wsrep_sst_receive_address is set to '127.0.0.1"),
+ ("WSREP: option --wsrep-causal-reads is deprecated"),
+ ("WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0"),
+ ("WSREP: Could not open saved state file for reading: "),
+ ("WSREP: Could not open state file for reading: "),
+ ("WSREP: access file\\(.*gvwstate\\.dat\\) failed\\(No such file or directory\\)"),
+ ("WSREP: Gap in state sequence\\. Need state transfer\\."),
+ ("WSREP: Failed to prepare for incremental state transfer: Local state UUID \\(00000000-0000-0000-0000-000000000000\\) does not match group state UUID"),
+ ("WSREP: No existing UUID has been found, so we assume that this is the first time that this server has been started\\. Generating a new UUID: "),
+ ("WSREP: last inactive check more than"),
+ ("WSREP: binlog cache not empty \\(0 bytes\\) at connection close"),
+ ("WSREP: SQL statement was ineffective"),
+ ("WSREP: Refusing exit for the last slave thread"),
+ ("WSREP: Quorum: No node with complete state"),
+ ("WSREP: Failed to report last committed"),
+ ("Slave SQL: Error 'Duplicate entry"),
+ ("Query apply warning:"),
+ ("WSREP: Ignoring error"),
+ ("WSREP: Initial position was provided by configuration or SST, avoiding override"),
+ ("Warning: Using a password on the command line interface can be insecure"),
+ ("InnoDB: Error: Table \"mysql\"\\.\"innodb_table_stats\" not found"),
+ ("but it is impossible to select State Transfer donor: Resource temporarily unavailable"),
+ ("WSREP: Could not find peer"),
+ ("WSREP: discarding established \\(time wait\\)"),
+ ("sending install message failed: Resource temporarily unavailable"),
+ ("WSREP: Ignoring possible split-brain \\(allowed by configuration\\) from view"),
+ ("WSREP: no nodes coming from prim view, prim not possible"),
+ ("WSREP: Failed to prepare for incremental state transfer: Local state seqno is undefined:"),
+ ("WSREP: gcs_caused\\(\\) returned -107 \\(Transport endpoint is not connected\\)"),
+ ("WSREP: gcs_caused\\(\\) returned -57 \\(Socket is not connected\\)"),
+ ("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"),
+ ("Action message in non-primary configuration from member"),
+ ("SYNC message from member"),
+ ("InnoDB: Resizing redo log from"),
+ ("InnoDB: Starting to delete and rewrite log files"),
+ ("InnoDB: New log files created, LSN="),
+-- WSREP: Send action {0x7f86280147f0, 73, STATE_REQUEST} returned -107 (Transport endpoint is not connected)
+ ("Transport endpoint is not connected"),
+ ("Socket is not connected"),
+-- "WSREP: Protocol violation. JOIN message sender 1.0 (host-91-221-67-96) is not in state transfer (SYNCED). Message ignored.
+ ("is not in state transfer"),
+ ("JOIN message from member .* in non-primary configuration"),
+ ("install timer expired"),
+ ("Last Applied Action message in non-primary configuration from member"),
("THE_LAST_SUPPRESSION")||
diff --git a/mysql-test/include/restart_mysqld.inc b/mysql-test/include/restart_mysqld.inc
index 3d3e55db4ac..8cf2798b592 100644
--- a/mysql-test/include/restart_mysqld.inc
+++ b/mysql-test/include/restart_mysqld.inc
@@ -5,6 +5,5 @@
# --source include/restart_mysqld.inc
--source include/not_embedded.inc
-
--source include/shutdown_mysqld.inc
--source include/start_mysqld.inc
diff --git a/mysql-test/include/wait_wsrep_ready.inc b/mysql-test/include/wait_wsrep_ready.inc
index 2dd1ef7f1ab..7ff65136c92 100644
--- a/mysql-test/include/wait_wsrep_ready.inc
+++ b/mysql-test/include/wait_wsrep_ready.inc
@@ -6,13 +6,26 @@
--disable_query_log
--disable_result_log
+#
+# if node is not ready, SELECT @@GLOBAL.WSREP_ON below does not
+# succeed. However, we can force it to succeed by running the SELECT
+# with dirty reads configuration. So we prepare for that
+#
+--let $my_dirty_reads= `select @@wsrep_dirty_reads`
+SET wsrep_dirty_reads = ON;
+
if (`SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`)
{
if (`SELECT @@GLOBAL.WSREP_ON`)
{
--source include/galera_wait_ready.inc
+ --disable_query_log
+ --disable_result_log
}
}
+# ..and returning original dirty read selection here
+--eval SET wsrep_dirty_reads = $my_dirty_reads;
+
--enable_query_log
--enable_result_log
diff --git a/mysql-test/include/wsrep_wait_disconnect.inc b/mysql-test/include/wsrep_wait_disconnect.inc
new file mode 100644
index 00000000000..740fc0d9426
--- /dev/null
+++ b/mysql-test/include/wsrep_wait_disconnect.inc
@@ -0,0 +1,20 @@
+let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' AND VARIABLE_VALUE = 'OFF';
+# since this is called until AFTER provider disconnects,we need to allow
+# queries in non-prim
+#
+# We are also forced to use a hard-coded value for wsrep_sync_wait here because
+# we can not issue a SELECT query to obtain the original value and then restore
+# it
+disable_query_log;
+SET SESSION wsrep_sync_wait = 7;
+--let $restore_wsrep_on = `SHOW VARIABLES WHERE Variable_name = 'wsrep_on' AND Value = 'ON'`
+SET SESSION wsrep_on = OFF;
+
+--source include/wait_condition.inc
+
+if ($restore_wsrep_on != "")
+{
+ --eval SET SESSION wsrep_on = ON
+}
+SET SESSION wsrep_sync_wait = 15;
+enable_query_log;
diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm
index 830b49d431f..f469cc9b062 100644
--- a/mysql-test/lib/My/ConfigFactory.pm
+++ b/mysql-test/lib/My/ConfigFactory.pm
@@ -206,7 +206,11 @@ my @mysqld_rules=
{ '#user' => sub { return shift->{ARGS}->{user} || ""; } },
{ '#password' => sub { return shift->{ARGS}->{password} || ""; } },
{ 'server-id' => \&fix_server_id, },
- { 'bind-address' => \&fix_bind_address },
+ #
+ # bind-address is commented out here, because this would bind bind
+ # only 127.0.0.1 for mysqld, and in galera mtr testing we will need
+ # also 127.0.0.2 for sst address
+# { 'bind-address' => \&fix_bind_address },
);
if (IS_WINDOWS)
diff --git a/mysql-test/main/mysqld--help-notwin.result b/mysql-test/main/mysqld--help-notwin.result
new file mode 100644
index 00000000000..b7db372a704
--- /dev/null
+++ b/mysql-test/main/mysqld--help-notwin.result
@@ -0,0 +1,1472 @@
+The following options may be given as the first argument:
+--print-defaults Print the program argument list and exit.
+--no-defaults Don't read default options from any option file,
+ except for login file.
+--defaults-file=# Only read default options from the given file #.
+--defaults-extra-file=# Read this file after the global files are read.
+--defaults-group-suffix=#
+ Also read groups with concat(group, suffix)
+--login-path=# Read this path from the login file.
+
+ --abort-slave-event-count=#
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --allow-suspicious-udfs
+ Allows use of UDFs consisting of only one symbol xxx()
+ without corresponding xxx_init() or xxx_deinit(). That
+ also means that one can load any function from any
+ library, for example exit() from libc.so
+ -a, --ansi Use ANSI SQL syntax instead of MySQL syntax. This mode
+ will also set transaction isolation level 'serializable'.
+ --auto-increment-increment[=#]
+ Auto-increment columns are incremented by this
+ --auto-increment-offset[=#]
+ Offset added to Auto-increment columns. Used when
+ auto-increment-increment != 1
+ --autocommit Set default value for autocommit (0 or 1)
+ (Defaults to on; use --skip-autocommit to disable.)
+ --automatic-sp-privileges
+ Creating and dropping stored procedures alters ACLs
+ (Defaults to on; use --skip-automatic-sp-privileges to disable.)
+ --avoid-temporal-upgrade
+ When this option is enabled, the pre-5.6.4 temporal types
+ are not upgraded to the new format for ALTER TABLE
+ requests ADD/CHANGE/MODIFY COLUMN, ADD INDEX or FORCE
+ operation. This variable is deprecated and will be
+ removed in a future release.
+ --back-log=# The number of outstanding connection requests MySQL can
+ have. This comes into play when the main MySQL thread
+ gets very many connection requests in a very short time
+ -b, --basedir=name Path to installation directory. All paths are usually
+ resolved relative to this
+ --big-tables Allow big result sets by saving all temporary sets on
+ file (Solves most 'table full' errors)
+ --bind-address=name IP address to bind to.
+ --binlog-cache-size=#
+ The size of the transactional cache for updates to
+ transactional engines for the binary log. If you often
+ use transactions containing many statements, you can
+ increase this to get more performance
+ --binlog-checksum=name
+ Type of BINLOG_CHECKSUM_ALG. Include checksum for log
+ events in the binary log. Possible values are NONE and
+ CRC32; default is CRC32.
+ --binlog-direct-non-transactional-updates
+ Causes updates to non-transactional engines using
+ statement format to be written directly to binary log.
+ Before using this option make sure that there are no
+ dependencies between transactional and non-transactional
+ tables such as in the statement INSERT INTO t_myisam
+ SELECT * FROM t_innodb; otherwise, slaves may diverge
+ from the master.
+ --binlog-do-db=name Tells the master it should log updates for the specified
+ database, and exclude all others not explicitly
+ mentioned.
+ --binlog-error-action=name
+ When statements cannot be written to the binary log due
+ to a fatal error, the server can either ignore the error
+ and let the master continue, or abort.
+ --binlog-format=name
+ What form of binary logging the master will use: either
+ ROW for row-based binary logging, STATEMENT for
+ statement-based binary logging, or MIXED. MIXED is
+ statement-based binary logging except for those
+ statements where only row-based is correct: those which
+ involve user-defined functions (i.e. UDFs) or the UUID()
+ function; for those, row-based binary logging is
+ automatically used. If NDBCLUSTER is enabled and
+ binlog-format is MIXED, the format switches to row-based
+ and back implicitly per each query accessing an
+ NDBCLUSTER table
+ --binlog-gtid-simple-recovery
+ If this option is enabled, the server does not open more
+ than two binary logs when initializing GTID_PURGED and
+ GTID_EXECUTED, either during server restart or when
+ binary logs are being purged. Enabling this option is
+ useful when the server has already generated many binary
+ logs without GTID events (e.g., having GTID_MODE = OFF).
+ Note: If this option is enabled, GLOBAL.GTID_EXECUTED and
+ GLOBAL.GTID_PURGED may be initialized wrongly in two
+ cases: (1) GTID_MODE was ON for some binary logs but OFF
+ for the newest binary log. (2) SET GTID_PURGED was issued
+ after the oldest existing binary log was generated. If a
+ wrong set is computed in one of case (1) or case (2), it
+ will remain wrong even if the server is later restarted
+ with this option disabled.
+ --binlog-ignore-db=name
+ Tells the master that updates to the given database
+ should not be logged to the binary log.
+ --binlog-max-flush-queue-time=#
+ The maximum time that the binary log group commit will
+ keep reading transactions before it flush the
+ transactions to the binary log (and optionally sync,
+ depending on the value of sync_binlog).
+ --binlog-order-commits
+ Issue internal commit calls in the same order as
+ transactions are written to the binary log. Default is to
+ order commits.
+ (Defaults to on; use --skip-binlog-order-commits to disable.)
+ --binlog-row-event-max-size=#
+ The maximum size of a row-based binary log event in
+ bytes. Rows will be grouped into events smaller than this
+ size if possible. The value has to be a multiple of 256.
+ --binlog-row-image=name
+ Controls whether rows should be logged in 'FULL',
+ 'NOBLOB' or 'MINIMAL' formats. 'FULL', means that all
+ columns in the before and after image are logged.
+ 'NOBLOB', means that mysqld avoids logging blob columns
+ whenever possible (eg, blob column was not changed or is
+ not part of primary key). 'MINIMAL', means that a PK
+ equivalent (PK columns or full row if there is no PK in
+ the table) is logged in the before image, and only
+ changed columns are logged in the after image. (Default:
+ FULL).
+ --binlog-rows-query-log-events
+ Allow writing of Rows_query_log events into binary log.
+ --binlog-stmt-cache-size=#
+ The size of the statement cache for updates to
+ non-transactional engines for the binary log. If you
+ often use statements updating a great number of rows, you
+ can increase this to get more performance
+ --binlogging-impossible-mode=name
+ On a fatal error when statements cannot be binlogged the
+ behaviour can be ignore the error and let the master
+ continue or abort the server. This variable is deprecated
+ and will be removed in a future release. Please use
+ binlog_error_action instead.
+ --block-encryption-mode=name
+ mode for AES_ENCRYPT/AES_DECRYPT
+ --bootstrap Used by mysql installation scripts.
+ --bulk-insert-buffer-size=#
+ Size of tree cache used in bulk insert optimisation. Note
+ that this is a limit per thread!
+ --character-set-client-handshake
+ Don't ignore client side character set value sent during
+ handshake.
+ (Defaults to on; use --skip-character-set-client-handshake to disable.)
+ --character-set-filesystem=name
+ Set the filesystem character set.
+ -C, --character-set-server=name
+ Set the default character set.
+ --character-sets-dir=name
+ Directory where character sets are
+ -r, --chroot=name Chroot mysqld daemon during startup.
+ --collation-server=name
+ Set the default collation.
+ --completion-type=name
+ The transaction completion type, one of NO_CHAIN, CHAIN,
+ RELEASE
+ --concurrent-insert[=name]
+ Use concurrent insert with MyISAM. Possible values are
+ NEVER, AUTO, ALWAYS
+ --connect-timeout=# The number of seconds the mysqld server is waiting for a
+ connect packet before responding with 'Bad handshake'
+ --console Write error output on screen; don't remove the console
+ window on windows.
+ --core-file Write core on errors.
+ -h, --datadir=name Path to the database root directory
+ --date-format=name The DATE format (ignored)
+ --datetime-format=name
+ The DATETIME format (ignored)
+ --default-authentication-plugin=name
+ Defines what password- and authentication algorithm to
+ use per default
+ --default-storage-engine=name
+ The default storage engine for new tables
+ --default-time-zone=name
+ Set the default time zone.
+ --default-tmp-storage-engine=name
+ The default storage engine for new explict temporary
+ tables
+ --default-week-format=#
+ The default week format used by WEEK() functions
+ --delay-key-write[=name]
+ Type of DELAY_KEY_WRITE
+ --delayed-insert-limit=#
+ After inserting delayed_insert_limit rows, the INSERT
+ DELAYED handler will check if there are any SELECT
+ statements pending. If so, it allows these to execute
+ before continuing. This variable is deprecated along with
+ INSERT DELAYED.
+ --delayed-insert-timeout=#
+ How long a INSERT DELAYED thread should wait for INSERT
+ statements before terminating.This variable is deprecated
+ along with INSERT DELAYED.
+ --delayed-queue-size=#
+ What size queue (in rows) should be allocated for
+ handling INSERT DELAYED. If the queue becomes full, any
+ client that does INSERT DELAYED will wait until there is
+ room in the queue again.This variable is deprecated along
+ with INSERT DELAYED.
+ --disconnect-on-expired-password
+ Give clients that don't signal password expiration
+ support execution time error(s) instead of connection
+ error
+ (Defaults to on; use --skip-disconnect-on-expired-password to disable.)
+ --disconnect-slave-event-count=#
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --div-precision-increment=#
+ Precision of the result of '/' operator will be increased
+ on that value
+ --end-markers-in-json
+ In JSON output ("EXPLAIN FORMAT=JSON" and optimizer
+ trace), if variable is set to 1, repeats the structure's
+ key (if it has one) near the closing bracket
+ --enforce-gtid-consistency
+ Prevents execution of statements that would be impossible
+ to log in a transactionally safe manner. Currently, the
+ disallowed statements include CREATE TEMPORARY TABLE
+ inside transactions, all updates to non-transactional
+ tables, and CREATE TABLE ... SELECT.
+ --eq-range-index-dive-limit=#
+ The optimizer will use existing index statistics instead
+ of doing index dives for equality ranges if the number of
+ equality ranges for the index is larger than or equal to
+ this number. If set to 0, index dives are always used.
+ --event-scheduler[=name]
+ Enable the event scheduler. Possible values are ON, OFF,
+ and DISABLED (keep the event scheduler completely
+ deactivated, it cannot be activated run-time)
+ -T, --exit-info[=#] Used for debugging. Use at your own risk.
+ --expire-logs-days=#
+ If non-zero, binary logs will be purged after
+ expire_logs_days days; possible purges happen at startup
+ and at binary log rotation
+ --explicit-defaults-for-timestamp
+ This option causes CREATE TABLE to create all TIMESTAMP
+ columns as NULL with DEFAULT NULL attribute, Without this
+ option, TIMESTAMP columns are NOT NULL and have implicit
+ DEFAULT clauses. The old behavior is deprecated.
+ --external-locking Use system (external) locking (disabled by default).
+ With this option enabled you can run myisamchk to test
+ (not repair) tables while the MySQL server is running.
+ Disable with --skip-external-locking.
+ --flush Flush MyISAM tables to disk between SQL commands
+ --flush-time=# A dedicated thread is created to flush all tables at the
+ given interval
+ --ft-boolean-syntax=name
+ List of operators for MATCH ... AGAINST ( ... IN BOOLEAN
+ MODE)
+ --ft-max-word-len=# The maximum length of the word to be included in a
+ FULLTEXT index. Note: FULLTEXT indexes must be rebuilt
+ after changing this variable
+ --ft-min-word-len=# The minimum length of the word to be included in a
+ FULLTEXT index. Note: FULLTEXT indexes must be rebuilt
+ after changing this variable
+ --ft-query-expansion-limit=#
+ Number of best matches to use for query expansion
+ --ft-stopword-file=name
+ Use stopwords from this file instead of built-in list
+ --gdb Set up signals usable for debugging.
+ --general-log Log connections and queries to a table or log file.
+ Defaults logging to a file hostname.log or a table
+ mysql.general_logif --log-output=TABLE is used
+ --general-log-file=name
+ Log connections and queries to given file
+ --group-concat-max-len=#
+ The maximum length of the result of function
+ GROUP_CONCAT()
+ --gtid-mode=name Whether Global Transaction Identifiers (GTIDs) are
+ enabled. Can be ON or OFF.
+ -?, --help Display this help and exit.
+ --host-cache-size=# How many host names should be cached to avoid resolving.
+ --ignore-builtin-innodb
+ IGNORED. This option will be removed in future releases.
+ Disable initialization of builtin InnoDB plugin
+ --ignore-db-dir=name
+ Specifies a directory to add to the ignore list when
+ collecting database names from the datadir. Put a blank
+ argument to reset the list accumulated so far.
+ --init-connect=name Command(s) that are executed for each new connection
+ --init-file=name Read SQL commands from this file at startup
+ --init-slave=name Command(s) that are executed by a slave server each time
+ the SQL thread starts
+ --interactive-timeout=#
+ The number of seconds the server waits for activity on an
+ interactive connection before closing it
+ --join-buffer-size=#
+ The size of the buffer that is used for full joins
+ --keep-files-on-create
+ Don't overwrite stale .MYD and .MYI even if no directory
+ is specified
+ --key-buffer-size=# The size of the buffer used for index blocks for MyISAM
+ tables. Increase this to get better index handling (for
+ all reads and multiple writes) to as much as you can
+ afford
+ --key-cache-age-threshold=#
+ This characterizes the number of hits a hot block has to
+ be untouched until it is considered aged enough to be
+ downgraded to a warm block. This specifies the percentage
+ ratio of that number of hits to the total number of
+ blocks in key cache
+ --key-cache-block-size=#
+ The default size of key cache blocks
+ --key-cache-division-limit=#
+ The minimum percentage of warm blocks in key cache
+ -L, --language=name Client error messages in given language. May be given as
+ a full path. Deprecated. Use --lc-messages-dir instead.
+ --large-pages Enable support for large pages
+ --lc-messages=name Set the language used for the error messages.
+ --lc-messages-dir=name
+ Directory where error messages are
+ --lc-time-names=name
+ Set the language used for the month names and the days of
+ the week.
+ --local-infile Enable LOAD DATA LOCAL INFILE
+ (Defaults to on; use --skip-local-infile to disable.)
+ --lock-wait-timeout=#
+ Timeout in seconds to wait for a lock before returning an
+ error.
+ --log-bin[=name] Log update queries in binary format. Optional (but
+ strongly recommended to avoid replication problems if
+ server's hostname changes) argument should be the chosen
+ location for the binary log files.
+ --log-bin-index=name
+ File that holds the names for binary log files.
+ --log-bin-trust-function-creators
+ If set to FALSE (the default), then when --log-bin is
+ used, creation of a stored function (or trigger) is
+ allowed only to users having the SUPER privilege and only
+ if this stored function (trigger) may not break binary
+ logging. Note that if ALL connections to this server
+ ALWAYS use row-based binary logging, the security issues
+ do not exist and the binary logging cannot break, so you
+ can safely set this to TRUE
+ --log-bin-use-v1-row-events
+ If equal to 1 then version 1 row events are written to a
+ row based binary log. If equal to 0, then the latest
+ version of events are written. This option is useful
+ during some upgrades.
+ --log-error[=name] Error log file
+ --log-isam[=name] Log all MyISAM changes to file.
+ --log-output=name Syntax: log-output=value[,value...], where "value" could
+ be TABLE, FILE or NONE
+ --log-queries-not-using-indexes
+ Log queries that are executed without benefit of any
+ index to the slow log if it is open
+ --log-raw Log to general log before any rewriting of the query. For
+ use in debugging, not production as sensitive information
+ may be logged.
+ --log-short-format Don't log extra information to update and slow-query
+ logs.
+ --log-slave-updates Tells the slave to log the updates from the slave thread
+ to the binary log. You will need to turn it on if you
+ plan to daisy-chain the slaves
+ --log-slow-admin-statements
+ Log slow OPTIMIZE, ANALYZE, ALTER and other
+ administrative statements to the slow log if it is open.
+ --log-slow-slave-statements
+ Log slow statements executed by slave thread to the slow
+ log if it is open.
+ --log-tc=name Path to transaction coordinator log (used for
+ transactions that affect more than one storage engine,
+ when binary log is disabled).
+ --log-tc-size=# Size of transaction coordinator log.
+ --log-throttle-queries-not-using-indexes[=#]
+ Log at most this many 'not using index' warnings per
+ minute to the slow log. Any further warnings will be
+ condensed into a single summary line. A value of 0
+ disables throttling. Option has no effect unless
+ --log_queries_not_using_indexes is set.
+ -W, --log-warnings[=#]
+ Log some not critical warnings to the log file
+ --long-query-time=# Log all queries that have taken more than long_query_time
+ seconds to execute to file. The argument will be treated
+ as a decimal value with microsecond precision
+ --low-priority-updates
+ INSERT/DELETE/UPDATE has lower priority than selects
+ --lower-case-table-names[=#]
+ If set to 1 table names are stored in lowercase on disk
+ and table names will be case-insensitive. Should be set
+ to 2 if you are using a case insensitive file system
+ --master-info-file=name
+ The location and name of the file that remembers the
+ master and where the I/O replication thread is in the
+ master's binlogs.
+ --master-info-repository=name
+ Defines the type of the repository for the master
+ information.
+ --master-retry-count=#
+ The number of tries the slave will make to connect to the
+ master before giving up. Deprecated option, use 'CHANGE
+ MASTER TO master_retry_count = <num>' instead.
+ --master-verify-checksum
+ Force checksum verification of logged events in binary
+ log before sending them to slaves or printing them in
+ output of SHOW BINLOG EVENTS. Disabled by default.
+ --max-allowed-packet=#
+ Max packet length to send to or receive from the server
+ --max-binlog-cache-size=#
+ Sets the total size of the transactional cache
+ --max-binlog-dump-events=#
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --max-binlog-size=# Binary log will be rotated automatically when the size
+ exceeds this value. Will also apply to relay logs if
+ max_relay_log_size is 0
+ --max-binlog-stmt-cache-size=#
+ Sets the total size of the statement cache
+ --max-connect-errors=#
+ If there is more than this number of interrupted
+ connections from a host this host will be blocked from
+ further connections
+ --max-connections=# The number of simultaneous clients allowed
+ --max-delayed-threads=#
+ Don't start more than this number of threads to handle
+ INSERT DELAYED statements. If set to zero INSERT DELAYED
+ will be not used.This variable is deprecated along with
+ INSERT DELAYED.
+ --max-digest-length=#
+ Maximum length considered for digest text.
+ --max-error-count=# Max number of errors/warnings to store for a statement
+ --max-heap-table-size=#
+ Don't allow creation of heap tables bigger than this
+ --max-join-size=# Joins that are probably going to read more than
+ max_join_size records return an error
+ --max-length-for-sort-data=#
+ Max number of bytes in sorted records
+ --max-prepared-stmt-count=#
+ Maximum number of prepared statements in the server
+ --max-relay-log-size=#
+ If non-zero: relay log will be rotated automatically when
+ the size exceeds this value; if zero: when the size
+ exceeds max_binlog_size
+ --max-seeks-for-key=#
+ Limit assumed max number of seeks when looking up rows
+ based on a key
+ --max-sort-length=# The number of bytes to use when sorting BLOB or TEXT
+ values (only the first max_sort_length bytes of each
+ value are used; the rest are ignored)
+ --max-sp-recursion-depth[=#]
+ Maximum stored procedure recursion depth
+ --max-tmp-tables=# Maximum number of temporary tables a client can keep open
+ at a time
+ --max-user-connections=#
+ The maximum number of active connections for a single
+ user (0 = no limit)
+ --max-write-lock-count=#
+ After this many write locks, allow some read locks to run
+ in between
+ --memlock Lock mysqld in memory.
+ --metadata-locks-cache-size=#
+ Size of unused metadata locks cache
+ --metadata-locks-hash-instances=#
+ Number of metadata locks hash instances
+ --min-examined-row-limit=#
+ Don't write queries to slow log that examine fewer rows
+ than that
+ --multi-range-count=#
+ Number of key ranges to request at once. This variable
+ has no effect, and is deprecated. It will be removed in a
+ future release.
+ --myisam-block-size=#
+ Block size to be used for MyISAM index pages
+ --myisam-data-pointer-size=#
+ Default pointer size to be used for MyISAM tables
+ --myisam-max-sort-file-size=#
+ Don't use the fast sort index method to created index if
+ the temporary file would get bigger than this
+ --myisam-mmap-size=#
+ Restricts the total memory used for memory mapping of
+ MySQL tables
+ --myisam-recover-options[=name]
+ Syntax: myisam-recover-options[=option[,option...]],
+ where option can be DEFAULT, BACKUP, FORCE, QUICK, or OFF
+ --myisam-repair-threads=#
+ If larger than 1, when repairing a MyISAM table all
+ indexes will be created in parallel, with one thread per
+ index. The value of 1 disables parallel repair
+ --myisam-sort-buffer-size=#
+ The buffer that is allocated when sorting the index when
+ doing a REPAIR or when creating indexes with CREATE INDEX
+ or ALTER TABLE
+ --myisam-stats-method=name
+ Specifies how MyISAM index statistics collection code
+ should treat NULLs. Possible values of name are
+ NULLS_UNEQUAL (default behavior for 4.1 and later),
+ NULLS_EQUAL (emulate 4.0 behavior), and NULLS_IGNORED
+ --myisam-use-mmap Use memory mapping for reading and writing MyISAM tables
+ --net-buffer-length=#
+ Buffer length for TCP/IP and socket communication
+ --net-read-timeout=#
+ Number of seconds to wait for more data from a connection
+ before aborting the read
+ --net-retry-count=# If a read on a communication port is interrupted, retry
+ this many times before giving up
+ --net-write-timeout=#
+ Number of seconds to wait for a block to be written to a
+ connection before aborting the write
+ -n, --new Use very new possible "unsafe" functions
+ --old Use compatible behavior
+ --old-alter-table Use old, non-optimized alter table
+ --old-passwords=# Determine which hash algorithm to use when generating
+ passwords using the PASSWORD() function
+ --old-style-user-limits
+ Enable old-style user limits (before 5.0.3, user
+ resources were counted per each user+host vs. per
+ account).
+ --open-files-limit=#
+ If this is not 0, then mysqld will use this value to
+ reserve file descriptors to use with setrlimit(). If this
+ value is 0 then mysqld will reserve max_connections*5 or
+ max_connections + table_open_cache*2 (whichever is
+ larger) number of file descriptors
+ --optimizer-prune-level=#
+ Controls the heuristic(s) applied during query
+ optimization to prune less-promising partial plans from
+ the optimizer search space. Meaning: 0 - do not apply any
+ heuristic, thus perform exhaustive search; 1 - prune
+ plans based on number of retrieved rows
+ --optimizer-search-depth=#
+ Maximum depth of search performed by the query optimizer.
+ Values larger than the number of relations in a query
+ result in better query plans, but take longer to compile
+ a query. Values smaller than the number of tables in a
+ relation result in faster optimization, but may produce
+ very bad query plans. If set to 0, the system will
+ automatically pick a reasonable value
+ --optimizer-switch=name
+ optimizer_switch=option=val[,option=val...], where option
+ is one of {index_merge, index_merge_union,
+ index_merge_sort_union, index_merge_intersection,
+ engine_condition_pushdown, index_condition_pushdown, mrr,
+ mrr_cost_based, materialization, semijoin, loosescan,
+ firstmatch, subquery_materialization_cost_based,
+ block_nested_loop, batched_key_access,
+ use_index_extensions} and val is one of {on, off,
+ default}
+ --optimizer-trace=name
+ Controls tracing of the Optimizer:
+ optimizer_trace=option=val[,option=val...], where option
+ is one of {enabled, one_line} and val is one of {on,
+ default}
+ --optimizer-trace-features=name
+ Enables/disables tracing of selected features of the
+ Optimizer:
+ optimizer_trace_features=option=val[,option=val...],
+ where option is one of {greedy_search, range_optimizer,
+ dynamic_range, repeated_subselect} and val is one of {on,
+ off, default}
+ --optimizer-trace-limit=#
+ Maximum number of shown optimizer traces
+ --optimizer-trace-max-mem-size=#
+ Maximum allowed cumulated size of stored optimizer traces
+ --optimizer-trace-offset=#
+ Offset of first optimizer trace to show; see manual
+ --performance-schema
+ Enable the performance schema.
+ (Defaults to on; use --skip-performance-schema to disable.)
+ --performance-schema-accounts-size=#
+ Maximum number of instrumented user@host accounts. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-consumer-events-stages-current
+ Default startup value for the events_stages_current
+ consumer.
+ --performance-schema-consumer-events-stages-history
+ Default startup value for the events_stages_history
+ consumer.
+ --performance-schema-consumer-events-stages-history-long
+ Default startup value for the events_stages_history_long
+ consumer.
+ --performance-schema-consumer-events-statements-current
+ Default startup value for the events_statements_current
+ consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-events-statements-current to disable.)
+ --performance-schema-consumer-events-statements-history
+ Default startup value for the events_statements_history
+ consumer.
+ --performance-schema-consumer-events-statements-history-long
+ Default startup value for the
+ events_statements_history_long consumer.
+ --performance-schema-consumer-events-waits-current
+ Default startup value for the events_waits_current
+ consumer.
+ --performance-schema-consumer-events-waits-history
+ Default startup value for the events_waits_history
+ consumer.
+ --performance-schema-consumer-events-waits-history-long
+ Default startup value for the events_waits_history_long
+ consumer.
+ --performance-schema-consumer-global-instrumentation
+ Default startup value for the global_instrumentation
+ consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-global-instrumentation to disable.)
+ --performance-schema-consumer-statements-digest
+ Default startup value for the statements_digest consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-statements-digest to disable.)
+ --performance-schema-consumer-thread-instrumentation
+ Default startup value for the thread_instrumentation
+ consumer.
+ (Defaults to on; use --skip-performance-schema-consumer-thread-instrumentation to disable.)
+ --performance-schema-digests-size=#
+ Size of the statement digest. Use 0 to disable, -1 for
+ automated sizing.
+ --performance-schema-events-stages-history-long-size=#
+ Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-events-stages-history-size=#
+ Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-events-statements-history-long-size=#
+ Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-events-statements-history-size=#
+ Number of rows per thread in EVENTS_STATEMENTS_HISTORY.
+ Use 0 to disable, -1 for automated sizing.
+ --performance-schema-events-waits-history-long-size=#
+ Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-events-waits-history-size=#
+ Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-hosts-size=#
+ Maximum number of instrumented hosts. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-instrument[=name]
+ Default startup value for a performance schema
+ instrument.
+ --performance-schema-max-cond-classes=#
+ Maximum number of condition instruments.
+ --performance-schema-max-cond-instances=#
+ Maximum number of instrumented condition objects. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-max-digest-length=#
+ Maximum length considered for digest text, when stored in
+ performance_schema tables.
+ --performance-schema-max-file-classes=#
+ Maximum number of file instruments.
+ --performance-schema-max-file-handles=#
+ Maximum number of opened instrumented files.
+ --performance-schema-max-file-instances=#
+ Maximum number of instrumented files. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-max-mutex-classes=#
+ Maximum number of mutex instruments.
+ --performance-schema-max-mutex-instances=#
+ Maximum number of instrumented MUTEX objects. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-rwlock-classes=#
+ Maximum number of rwlock instruments.
+ --performance-schema-max-rwlock-instances=#
+ Maximum number of instrumented RWLOCK objects. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-socket-classes=#
+ Maximum number of socket instruments.
+ --performance-schema-max-socket-instances=#
+ Maximum number of opened instrumented sockets. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-stage-classes=#
+ Maximum number of stage instruments.
+ --performance-schema-max-statement-classes=#
+ Maximum number of statement instruments.
+ --performance-schema-max-table-handles=#
+ Maximum number of opened instrumented tables. Use 0 to
+ disable, -1 for automated sizing.
+ --performance-schema-max-table-instances=#
+ Maximum number of instrumented tables. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-max-thread-classes=#
+ Maximum number of thread instruments.
+ --performance-schema-max-thread-instances=#
+ Maximum number of instrumented threads. Use 0 to disable,
+ -1 for automated sizing.
+ --performance-schema-session-connect-attrs-size=#
+ Size of session attribute string buffer per thread. Use 0
+ to disable, -1 for automated sizing.
+ --performance-schema-setup-actors-size=#
+ Maximum number of rows in SETUP_ACTORS.
+ --performance-schema-setup-objects-size=#
+ Maximum number of rows in SETUP_OBJECTS.
+ --performance-schema-users-size=#
+ Maximum number of instrumented users. Use 0 to disable,
+ -1 for automated sizing.
+ --pid-file=name Pid file used by safe_mysqld
+ --plugin-dir=name Directory for plugins
+ --plugin-load=name Optional semicolon-separated list of plugins to load,
+ where each plugin is identified as name=library, where
+ name is the plugin name and library is the plugin library
+ in plugin_dir.
+ --plugin-load-add=name
+ Optional semicolon-separated list of plugins to load,
+ where each plugin is identified as name=library, where
+ name is the plugin name and library is the plugin library
+ in plugin_dir. This option adds to the list speficied by
+ --plugin-load in an incremental way. Multiple
+ --plugin-load-add are supported.
+ -P, --port=# Port number to use for connection or 0 to default to,
+ my.cnf, $MYSQL_TCP_PORT, /etc/services, built-in default
+ (3306), whatever comes first
+ --port-open-timeout=#
+ Maximum time in seconds to wait for the port to become
+ free. (Default: No wait).
+ --preload-buffer-size=#
+ The size of the buffer that is allocated when preloading
+ indexes
+ --profiling-history-size=#
+ Limit of query profiling memory
+ --query-alloc-block-size=#
+ Allocation block size for query parsing and execution
+ --query-cache-limit=#
+ Don't cache results that are bigger than this
+ --query-cache-min-res-unit=#
+ The minimum size for blocks allocated by the query cache
+ --query-cache-size=#
+ The memory allocated to store results from old queries
+ --query-cache-type=name
+ OFF = Don't cache or retrieve results. ON = Cache all
+ results except SELECT SQL_NO_CACHE ... queries. DEMAND =
+ Cache only SELECT SQL_CACHE ... queries
+ --query-cache-wlock-invalidate
+ Invalidate queries in query cache on LOCK for write
+ --query-prealloc-size=#
+ Persistent buffer for query parsing and execution
+ --range-alloc-block-size=#
+ Allocation block size for storing ranges during
+ optimization
+ --read-buffer-size=#
+ Each thread that does a sequential scan allocates a
+ buffer of this size for each table it scans. If you do
+ many sequential scans, you may want to increase this
+ value
+ --read-only Make all non-temporary tables read-only, with the
+ exception for replication (slave) threads and users with
+ the SUPER privilege
+ --read-rnd-buffer-size=#
+ When reading rows in sorted order after a sort, the rows
+ are read through this buffer to avoid a disk seeks
+ --relay-log=name The location and name to use for relay logs
+ --relay-log-index=name
+ File that holds the names for relay log files.
+ --relay-log-info-file=name
+ The location and name of the file that remembers where
+ the SQL replication thread is in the relay logs
+ --relay-log-info-repository=name
+ Defines the type of the repository for the relay log
+ information and associated workers.
+ --relay-log-purge if disabled - do not purge relay logs. if enabled - purge
+ them as soon as they are no more needed
+ (Defaults to on; use --skip-relay-log-purge to disable.)
+ --relay-log-recovery
+ Enables automatic relay log recovery right after the
+ database startup, which means that the IO Thread starts
+ re-fetching from the master right after the last
+ transaction processed
+ --relay-log-space-limit=#
+ Maximum space to use for all relay logs
+ --replicate-do-db=name
+ Tells the slave thread to restrict replication to the
+ specified database. To specify more than one database,
+ use the directive multiple times, once for each database.
+ Note that this will only work if you do not use
+ cross-database queries such as UPDATE some_db.some_table
+ SET foo='bar' while having selected a different or no
+ database. If you need cross database updates to work,
+ make sure you have 3.23.28 or later, and use
+ replicate-wild-do-table=db_name.%.
+ --replicate-do-table=name
+ Tells the slave thread to restrict replication to the
+ specified table. To specify more than one table, use the
+ directive multiple times, once for each table. This will
+ work for cross-database updates, in contrast to
+ replicate-do-db.
+ --replicate-ignore-db=name
+ Tells the slave thread to not replicate to the specified
+ database. To specify more than one database to ignore,
+ use the directive multiple times, once for each database.
+ This option will not work if you use cross database
+ updates. If you need cross database updates to work, make
+ sure you have 3.23.28 or later, and use
+ replicate-wild-ignore-table=db_name.%.
+ --replicate-ignore-table=name
+ Tells the slave thread to not replicate to the specified
+ table. To specify more than one table to ignore, use the
+ directive multiple times, once for each table. This will
+ work for cross-database updates, in contrast to
+ replicate-ignore-db.
+ --replicate-rewrite-db=name
+ Updates to a database with a different name than the
+ original. Example:
+ replicate-rewrite-db=master_db_name->slave_db_name.
+ --replicate-same-server-id
+ In replication, if set to 1, do not skip events having
+ our server id. Default value is 0 (to break infinite
+ loops in circular replication). Can't be set to 1 if
+ --log-slave-updates is used.
+ --replicate-wild-do-table=name
+ Tells the slave thread to restrict replication to the
+ tables that match the specified wildcard pattern. To
+ specify more than one table, use the directive multiple
+ times, once for each table. This will work for
+ cross-database updates. Example:
+ replicate-wild-do-table=foo%.bar% will replicate only
+ updates to tables in all databases that start with foo
+ and whose table names start with bar.
+ --replicate-wild-ignore-table=name
+ Tells the slave thread to not replicate to the tables
+ that match the given wildcard pattern. To specify more
+ than one table to ignore, use the directive multiple
+ times, once for each table. This will work for
+ cross-database updates. Example:
+ replicate-wild-ignore-table=foo%.bar% will not do updates
+ to tables in databases that start with foo and whose
+ table names start with bar.
+ --report-host=name Hostname or IP of the slave to be reported to the master
+ during slave registration. Will appear in the output of
+ SHOW SLAVE HOSTS. Leave unset if you do not want the
+ slave to register itself with the master. Note that it is
+ not sufficient for the master to simply read the IP of
+ the slave off the socket once the slave connects. Due to
+ NAT and other routing issues, that IP may not be valid
+ for connecting to the slave from the master or other
+ hosts
+ --report-password=name
+ The account password of the slave to be reported to the
+ master during slave registration
+ --report-port=# Port for connecting to slave reported to the master
+ during slave registration. Set it only if the slave is
+ listening on a non-default port or if you have a special
+ tunnel from the master or other clients to the slave. If
+ not sure, leave this option unset
+ --report-user=name The account user name of the slave to be reported to the
+ master during slave registration
+ --rpl-stop-slave-timeout=#
+ Timeout in seconds to wait for slave to stop before
+ returning a warning.
+ --safe-user-create Don't allow new user creation by the user who has no
+ write privileges to the mysql.user table.
+ --secure-auth Disallow authentication for accounts that have old
+ (pre-4.1) passwords
+ (Defaults to on; use --skip-secure-auth to disable.)
+ --secure-file-priv=name
+ Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to
+ files within specified directory
+ --server-id=# Uniquely identifies the server instance in the community
+ of replication partners
+ --server-id-bits=# Set number of significant bits in server-id
+ --show-old-temporals
+ When this option is enabled, the pre-5.6.4 temporal types
+ will be marked in the 'SHOW CREATE TABLE' and
+ 'INFORMATION_SCHEMA.COLUMNS' table as a comment in
+ COLUMN_TYPE field. This variable is deprecated and will
+ be removed in a future release.
+ --show-slave-auth-info
+ Show user and password in SHOW SLAVE HOSTS on this
+ master.
+ --simplified-binlog-gtid-recovery
+ Alias for @@binlog_gtid_simple_recovery. Deprecated
+ --skip-grant-tables Start without grant tables. This gives all users FULL
+ ACCESS to all tables.
+ --skip-host-cache Don't cache host names.
+ --skip-name-resolve Don't resolve hostnames. All hostnames are IP's or
+ 'localhost'.
+ --skip-networking Don't allow connection with TCP/IP
+ --skip-new Don't use new, possibly wrong routines.
+ --skip-show-database
+ Don't allow 'SHOW DATABASE' commands
+ --skip-slave-start If set, slave is not autostarted.
+ --skip-stack-trace Don't print a stack trace on failure.
+ --slave-allow-batching
+ Allow slave to batch requests
+ --slave-checkpoint-group=#
+ Maximum number of processed transactions by
+ Multi-threaded slave before a checkpoint operation is
+ called to update progress status.
+ --slave-checkpoint-period=#
+ Gather workers' activities to Update progress status of
+ Multi-threaded slave and flush the relay log info to disk
+ after every #th milli-seconds.
+ --slave-compressed-protocol
+ Use compression on master/slave protocol
+ --slave-exec-mode=name
+ Modes for how replication events should be executed.
+ Legal values are STRICT (default) and IDEMPOTENT. In
+ IDEMPOTENT mode, replication will not stop for operations
+ that are idempotent. In STRICT mode, replication will
+ stop on any unexpected difference between the master and
+ the slave
+ --slave-load-tmpdir=name
+ The location where the slave should put its temporary
+ files when replicating a LOAD DATA INFILE command
+ --slave-max-allowed-packet=#
+ The maximum packet length to sent successfully from the
+ master to slave.
+ --slave-net-timeout=#
+ Number of seconds to wait for more data from a
+ master/slave connection before aborting the read
+ --slave-parallel-workers=#
+ Number of worker threads for executing events in parallel
+ --slave-pending-jobs-size-max=#
+ Max size of Slave Worker queues holding yet not applied
+ events.The least possible value must be not less than the
+ master side max_allowed_packet.
+ --slave-rows-search-algorithms=name
+ Set of searching algorithms that the slave will use while
+ searching for records from the storage engine to either
+ updated or deleted them. Possible values are: INDEX_SCAN,
+ TABLE_SCAN and HASH_SCAN. Any combination is allowed, and
+ the slave will always pick the most suitable algorithm
+ for any given scenario. (Default: INDEX_SCAN,
+ TABLE_SCAN).
+ --slave-skip-errors=name
+ Tells the slave thread to continue replication when a
+ query event returns an error from the provided list
+ --slave-sql-verify-checksum
+ Force checksum verification of replication events after
+ reading them from relay log. Note: Events are always
+ checksum-verified by slave on receiving them from the
+ network before writing them to the relay log. Enabled by
+ default.
+ (Defaults to on; use --skip-slave-sql-verify-checksum to disable.)
+ --slave-transaction-retries=#
+ Number of times the slave SQL thread will retry a
+ transaction in case it failed with a deadlock or elapsed
+ lock wait timeout, before giving up and stopping
+ --slave-type-conversions=name
+ Set of slave type conversions that are enabled. Legal
+ values are: ALL_LOSSY to enable lossy conversions,
+ ALL_NON_LOSSY to enable non-lossy conversions,
+ ALL_UNSIGNED to treat all integer column type data to be
+ unsigned values, and ALL_SIGNED to treat all integer
+ column type data to be signed values. Default treatment
+ is ALL_SIGNED. If ALL_SIGNED and ALL_UNSIGNED both are
+ specifed, ALL_SIGNED will take high priority than
+ ALL_UNSIGNED. If the variable is assigned the empty set,
+ no conversions are allowed and it is expected that the
+ types match exactly.
+ --slow-launch-time=#
+ If creating the thread takes longer than this value (in
+ seconds), the Slow_launch_threads counter will be
+ incremented
+ --slow-query-log Log slow queries to a table or log file. Defaults logging
+ to a file hostname-slow.log or a table mysql.slow_log if
+ --log-output=TABLE is used. Must be enabled to activate
+ other slow log options
+ --slow-query-log-file=name
+ Log slow queries to given log file. Defaults logging to
+ hostname-slow.log. Must be enabled to activate other slow
+ log options
+ --socket=name Socket file to use for connection
+ --sort-buffer-size=#
+ Each thread that needs to do a sort allocates a buffer of
+ this size
+ --sporadic-binlog-dump-fail
+ Option used by mysql-test for debugging and testing of
+ replication.
+ --sql-mode=name Syntax: sql-mode=mode[,mode[,mode...]]. See the manual
+ for the complete list of valid sql modes
+ --stored-program-cache=#
+ The soft upper limit for number of cached stored routines
+ for one connection.
+ -s, --symbolic-links
+ Enable symbolic link support.
+ --sync-binlog=# Synchronously flush binary log to disk after every #th
+ write to the file. Use 0 (default) to disable synchronous
+ flushing
+ --sync-frm Sync .frm files to disk on creation
+ (Defaults to on; use --skip-sync-frm to disable.)
+ --sync-master-info=#
+ Synchronously flush master info to disk after every #th
+ event. Use 0 to disable synchronous flushing
+ --sync-relay-log=# Synchronously flush relay log to disk after every #th
+ event. Use 0 to disable synchronous flushing
+ --sync-relay-log-info=#
+ Synchronously flush relay log info to disk after every
+ #th transaction. Use 0 to disable synchronous flushing
+ --sysdate-is-now Non-default option to alias SYSDATE() to NOW() to make it
+ safe-replicable. Since 5.0, SYSDATE() returns a `dynamic'
+ value different for different invocations, even within
+ the same statement.
+ --table-definition-cache=#
+ The number of cached table definitions
+ --table-open-cache=#
+ The number of cached open tables (total for all table
+ cache instances)
+ --table-open-cache-instances=#
+ The number of table cache instances
+ --tc-heuristic-recover=name
+ Decision to use in heuristic recover process. Possible
+ values are COMMIT or ROLLBACK.
+ --thread-cache-size=#
+ How many threads we should keep in a cache for reuse
+ --thread-handling=name
+ Define threads usage for handling queries, one of
+ one-thread-per-connection, no-threads, loaded-dynamically
+ --thread-stack=# The stack size for each thread
+ --time-format=name The TIME format (ignored)
+ --timed-mutexes Specify whether to time mutexes. Deprecated, has no
+ effect.
+ --tmp-table-size=# If an internal in-memory temporary table exceeds this
+ size, MySQL will automatically convert it to an on-disk
+ MyISAM table
+ -t, --tmpdir=name Path for temporary files. Several paths may be specified,
+ separated by a colon (:), in this case they are used in a
+ round-robin fashion
+ --transaction-alloc-block-size=#
+ Allocation block size for transactions to be stored in
+ binary log
+ --transaction-isolation=name
+ Default transaction isolation level.
+ --transaction-prealloc-size=#
+ Persistent buffer for transactions to be stored in binary
+ log
+ --transaction-read-only
+ Default transaction access mode. True if transactions are
+ read-only.
+ --updatable-views-with-limit=name
+ YES = Don't issue an error message (warning only) if a
+ VIEW without presence of a key of the underlying table is
+ used in queries with a LIMIT clause for updating. NO =
+ Prohibit update of a VIEW, which does not contain a key
+ of the underlying table and the query uses a LIMIT clause
+ (usually get from GUI tools)
+ -u, --user=name Run mysqld daemon as user.
+ --validate-user-plugins
+ Turns on additional validation of authentication plugins
+ assigned to user accounts.
+ (Defaults to on; use --skip-validate-user-plugins to disable.)
+ -v, --verbose Used with --help option for detailed help.
+ -V, --version Output version information and exit.
+ --wait-timeout=# The number of seconds the server waits for activity on a
+ connection before closing it
+ --wsrep-OSU-method[=name]
+ Method for Online Schema Upgrade
+ --wsrep-SR-store=name
+ Storage for streaming replication fragments
+ --wsrep-auto-increment-control
+ To automatically control the assignment of autoincrement
+ variables
+ (Defaults to on; use --skip-wsrep-auto-increment-control to disable.)
+ --wsrep-causal-reads
+ (DEPRECATED) setting this variable is equivalent to
+ setting wsrep_sync_wait READ flag
+ --wsrep-certify-nonPK
+ Certify tables with no primary key
+ (Defaults to on; use --skip-wsrep-certify-nonPK to disable.)
+ --wsrep-cluster-address=name
+ Address to initially connect to cluster
+ --wsrep-cluster-name=name
+ Name for the cluster
+ --wsrep-convert-LOCK-to-trx
+ To convert locking sessions into transactions
+ --wsrep-data-home-dir=name
+ home directory for wsrep provider
+ --wsrep-dbug-option=name
+ DBUG options to provider library
+ --wsrep-debug To enable debug level logging
+ --wsrep-desync To desynchronize the node from the cluster
+ --wsrep-dirty-reads Allow reads from a node is not in primary component
+ --wsrep-drupal-282555-workaround
+ To use a workaround forbad autoincrement value
+ --wsrep-forced-binlog-format=name
+ binlog format to take effect over user's choice
+ --wsrep-ignore-apply-errors=#
+ Ignore replication errors
+ --wsrep-load-data-splitting
+ To commit LOAD DATA transaction after every 10K rows
+ inserted (deprecating)
+ (Defaults to on; use --skip-wsrep-load-data-splitting to disable.)
+ --wsrep-log-conflicts
+ To log multi-master conflicts
+ --wsrep-max-ws-rows=#
+ Max number of rows in write set
+ --wsrep-max-ws-size=#
+ Max write set size (bytes)
+ --wsrep-mysql-replication-bundle=#
+ mysql replication group commit
+ --wsrep-node-address=name
+ Node address
+ --wsrep-node-incoming-address=name
+ Client connection address
+ --wsrep-node-name=name
+ Node name
+ --wsrep-notify-cmd=name
+ --wsrep-on To enable wsrep replication
+ (Defaults to on; use --skip-wsrep-on to disable.)
+ --wsrep-preordered To enable preordered write set processing
+ --wsrep-provider=name
+ Path to replication provider library
+ --wsrep-provider-options=name
+ provider specific options
+ --wsrep-recover Recover database state after crash and exit
+ --wsrep-reject-queries[=name]
+ Variable to set to reject queries
+ --wsrep-replicate-myisam
+ To enable myisam replication
+ --wsrep-restart-slave
+ Should MySQL slave be restarted automatically, when node
+ joins back to cluster
+ --wsrep-retry-autocommit=#
+ Max number of times to retry a failed autocommit
+ statement
+ --wsrep-slave-FK-checks
+ Should slave thread do foreign key constraint checks
+ (Defaults to on; use --skip-wsrep-slave-FK-checks to disable.)
+ --wsrep-slave-UK-checks
+ Should slave thread do secondary index uniqueness checks
+ --wsrep-slave-threads=#
+ Number of slave appliers to launch
+ --wsrep-sst-auth=name
+ Authentication for SST connection
+ --wsrep-sst-donor=name
+ preferred donor node for the SST
+ --wsrep-sst-donor-rejects-queries
+ Reject client queries when donating state snapshot
+ transfer
+ --wsrep-sst-method=name
+ State snapshot transfer method
+ --wsrep-sst-receive-address=name
+ Address where node is waiting for SST contact
+ --wsrep-start-position=name
+ global transaction position to start from
+ --wsrep-sync-wait[=#]
+ Ensure "synchronous" read view before executing an
+ operation of the type specified by bitmask: 1 -
+ READ(includes SELECT, SHOW and BEGIN/START TRANSACTION);
+ 2 - UPDATE and DELETE; 4 - INSERT and REPLACE
+ --wsrep-trx-fragment-size=#
+ Size of transaction fragments for streaming replication
+ (measured in units of 'wsrep_trx_fragment_unit')
+ --wsrep-trx-fragment-unit=name
+ Unit for streaming replication transaction fragments'
+ size: bytes, events, rows, statements
+
+Variables (--variable-name=value)
+abort-slave-event-count 0
+allow-suspicious-udfs FALSE
+auto-increment-increment 1
+auto-increment-offset 1
+autocommit TRUE
+automatic-sp-privileges TRUE
+avoid-temporal-upgrade FALSE
+back-log 80
+big-tables FALSE
+bind-address *
+binlog-cache-size 32768
+binlog-checksum CRC32
+binlog-direct-non-transactional-updates FALSE
+binlog-error-action IGNORE_ERROR
+binlog-format STATEMENT
+binlog-gtid-simple-recovery FALSE
+binlog-max-flush-queue-time 0
+binlog-order-commits TRUE
+binlog-row-event-max-size 8192
+binlog-row-image FULL
+binlog-rows-query-log-events FALSE
+binlog-stmt-cache-size 32768
+binlogging-impossible-mode IGNORE_ERROR
+block-encryption-mode aes-128-ecb
+bulk-insert-buffer-size 8388608
+character-set-client-handshake TRUE
+character-set-filesystem binary
+character-set-server latin1
+character-sets-dir MYSQL_CHARSETSDIR/
+chroot (No default value)
+collation-server latin1_swedish_ci
+completion-type NO_CHAIN
+concurrent-insert AUTO
+connect-timeout 10
+console FALSE
+date-format %Y-%m-%d
+datetime-format %Y-%m-%d %H:%i:%s
+default-storage-engine InnoDB
+default-time-zone (No default value)
+default-tmp-storage-engine InnoDB
+default-week-format 0
+delay-key-write ON
+delayed-insert-limit 100
+delayed-insert-timeout 300
+delayed-queue-size 1000
+disconnect-on-expired-password TRUE
+disconnect-slave-event-count 0
+div-precision-increment 4
+end-markers-in-json FALSE
+enforce-gtid-consistency FALSE
+eq-range-index-dive-limit 10
+event-scheduler OFF
+expire-logs-days 0
+explicit-defaults-for-timestamp FALSE
+external-locking FALSE
+flush FALSE
+flush-time 0
+ft-boolean-syntax + -><()~*:""&|
+ft-max-word-len 84
+ft-min-word-len 4
+ft-query-expansion-limit 20
+ft-stopword-file (No default value)
+gdb FALSE
+general-log FALSE
+group-concat-max-len 1024
+gtid-mode OFF
+help TRUE
+host-cache-size 279
+ignore-builtin-innodb FALSE
+init-connect
+init-file (No default value)
+init-slave
+interactive-timeout 28800
+join-buffer-size 262144
+keep-files-on-create FALSE
+key-buffer-size 8388608
+key-cache-age-threshold 300
+key-cache-block-size 1024
+key-cache-division-limit 100
+language MYSQL_SHAREDIR/
+large-pages FALSE
+lc-messages en_US
+lc-messages-dir MYSQL_SHAREDIR/
+lc-time-names en_US
+local-infile TRUE
+lock-wait-timeout 31536000
+log-bin (No default value)
+log-bin-index (No default value)
+log-bin-trust-function-creators FALSE
+log-bin-use-v1-row-events FALSE
+log-error
+log-isam myisam.log
+log-output FILE
+log-queries-not-using-indexes FALSE
+log-raw FALSE
+log-short-format FALSE
+log-slave-updates FALSE
+log-slow-admin-statements FALSE
+log-slow-slave-statements FALSE
+log-tc tc.log
+log-tc-size 24576
+log-throttle-queries-not-using-indexes 0
+log-warnings 1
+long-query-time 10
+low-priority-updates FALSE
+lower-case-table-names 1
+master-info-file master.info
+master-info-repository FILE
+master-retry-count 86400
+master-verify-checksum FALSE
+max-allowed-packet 4194304
+max-binlog-cache-size 18446744073709547520
+max-binlog-dump-events 0
+max-binlog-size 1073741824
+max-binlog-stmt-cache-size 18446744073709547520
+max-connect-errors 100
+max-connections 151
+max-delayed-threads 20
+max-digest-length 1024
+max-error-count 64
+max-heap-table-size 16777216
+max-join-size 18446744073709551615
+max-length-for-sort-data 1024
+max-prepared-stmt-count 16382
+max-relay-log-size 0
+max-seeks-for-key 18446744073709551615
+max-sort-length 1024
+max-sp-recursion-depth 0
+max-tmp-tables 32
+max-user-connections 0
+max-write-lock-count 18446744073709551615
+memlock FALSE
+metadata-locks-cache-size 1024
+metadata-locks-hash-instances 8
+min-examined-row-limit 0
+multi-range-count 256
+myisam-block-size 1024
+myisam-data-pointer-size 6
+myisam-max-sort-file-size 9223372036853727232
+myisam-mmap-size 18446744073709551615
+myisam-recover-options OFF
+myisam-repair-threads 1
+myisam-sort-buffer-size 8388608
+myisam-stats-method nulls_unequal
+myisam-use-mmap FALSE
+net-buffer-length 16384
+net-read-timeout 30
+net-retry-count 10
+net-write-timeout 60
+new FALSE
+old FALSE
+old-alter-table FALSE
+old-passwords 0
+old-style-user-limits FALSE
+optimizer-prune-level 1
+optimizer-search-depth 62
+optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,subquery_materialization_cost_based=on,use_index_extensions=on
+optimizer-trace
+optimizer-trace-features greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on
+optimizer-trace-limit 1
+optimizer-trace-max-mem-size 16384
+optimizer-trace-offset -1
+performance-schema TRUE
+performance-schema-accounts-size -1
+performance-schema-consumer-events-stages-current FALSE
+performance-schema-consumer-events-stages-history FALSE
+performance-schema-consumer-events-stages-history-long FALSE
+performance-schema-consumer-events-statements-current TRUE
+performance-schema-consumer-events-statements-history FALSE
+performance-schema-consumer-events-statements-history-long FALSE
+performance-schema-consumer-events-waits-current FALSE
+performance-schema-consumer-events-waits-history FALSE
+performance-schema-consumer-events-waits-history-long FALSE
+performance-schema-consumer-global-instrumentation TRUE
+performance-schema-consumer-statements-digest TRUE
+performance-schema-consumer-thread-instrumentation TRUE
+performance-schema-digests-size -1
+performance-schema-events-stages-history-long-size -1
+performance-schema-events-stages-history-size -1
+performance-schema-events-statements-history-long-size -1
+performance-schema-events-statements-history-size -1
+performance-schema-events-waits-history-long-size -1
+performance-schema-events-waits-history-size -1
+performance-schema-hosts-size -1
+performance-schema-instrument
+performance-schema-max-cond-classes 80
+performance-schema-max-cond-instances -1
+performance-schema-max-digest-length 1024
+performance-schema-max-file-classes 50
+performance-schema-max-file-handles 32768
+performance-schema-max-file-instances -1
+performance-schema-max-mutex-classes 200
+performance-schema-max-mutex-instances -1
+performance-schema-max-rwlock-classes 40
+performance-schema-max-rwlock-instances -1
+performance-schema-max-socket-classes 10
+performance-schema-max-socket-instances -1
+performance-schema-max-stage-classes 150
+performance-schema-max-statement-classes 168
+performance-schema-max-table-handles -1
+performance-schema-max-table-instances -1
+performance-schema-max-thread-classes 50
+performance-schema-max-thread-instances -1
+performance-schema-session-connect-attrs-size -1
+performance-schema-setup-actors-size 100
+performance-schema-setup-objects-size 100
+performance-schema-users-size -1
+port ####
+port-open-timeout 0
+preload-buffer-size 32768
+profiling-history-size 15
+query-alloc-block-size 8192
+query-cache-limit 1048576
+query-cache-min-res-unit 4096
+query-cache-size 1048576
+query-cache-type OFF
+query-cache-wlock-invalidate FALSE
+query-prealloc-size 8192
+range-alloc-block-size 4096
+read-buffer-size 131072
+read-only FALSE
+read-rnd-buffer-size 262144
+relay-log (No default value)
+relay-log-index (No default value)
+relay-log-info-file relay-log.info
+relay-log-info-repository FILE
+relay-log-purge TRUE
+relay-log-recovery FALSE
+relay-log-space-limit 0
+replicate-same-server-id FALSE
+report-host (No default value)
+report-password (No default value)
+report-port 0
+report-user (No default value)
+rpl-stop-slave-timeout 31536000
+safe-user-create FALSE
+secure-auth TRUE
+server-id 0
+server-id-bits 32
+show-old-temporals FALSE
+show-slave-auth-info FALSE
+simplified-binlog-gtid-recovery FALSE
+skip-grant-tables TRUE
+skip-name-resolve FALSE
+skip-networking FALSE
+skip-show-database FALSE
+skip-slave-start FALSE
+slave-allow-batching FALSE
+slave-checkpoint-group 512
+slave-checkpoint-period 300
+slave-compressed-protocol FALSE
+slave-exec-mode STRICT
+slave-max-allowed-packet 1073741824
+slave-net-timeout 3600
+slave-parallel-workers 0
+slave-pending-jobs-size-max 16777216
+slave-rows-search-algorithms TABLE_SCAN,INDEX_SCAN
+slave-skip-errors (No default value)
+slave-sql-verify-checksum TRUE
+slave-transaction-retries 10
+slave-type-conversions
+slow-launch-time 2
+slow-query-log FALSE
+sort-buffer-size 262144
+sporadic-binlog-dump-fail FALSE
+sql-mode NO_ENGINE_SUBSTITUTION
+stored-program-cache 256
+symbolic-links FALSE
+sync-binlog 0
+sync-frm TRUE
+sync-master-info 10000
+sync-relay-log 10000
+sync-relay-log-info 10000
+sysdate-is-now FALSE
+table-open-cache-instances 1
+tc-heuristic-recover COMMIT
+thread-cache-size 9
+thread-handling one-thread-per-connection
+thread-stack 262144
+time-format %H:%i:%s
+timed-mutexes FALSE
+tmp-table-size 16777216
+transaction-alloc-block-size 8192
+transaction-isolation REPEATABLE-READ
+transaction-prealloc-size 4096
+transaction-read-only FALSE
+updatable-views-with-limit YES
+validate-user-plugins TRUE
+verbose TRUE
+wait-timeout 28800
+wsrep-OSU-method TOI
+wsrep-SR-store table
+wsrep-auto-increment-control TRUE
+wsrep-causal-reads FALSE
+wsrep-certify-nonPK TRUE
+wsrep-cluster-address
+wsrep-cluster-name my_wsrep_cluster
+wsrep-convert-LOCK-to-trx FALSE
+wsrep-data-home-dir
+wsrep-dbug-option
+wsrep-debug FALSE
+wsrep-desync FALSE
+wsrep-dirty-reads FALSE
+wsrep-drupal-282555-workaround FALSE
+wsrep-forced-binlog-format NONE
+wsrep-ignore-apply-errors 7
+wsrep-load-data-splitting TRUE
+wsrep-log-conflicts FALSE
+wsrep-max-ws-rows 0
+wsrep-max-ws-size 2147483647
+wsrep-mysql-replication-bundle 0
+wsrep-node-address
+wsrep-node-incoming-address AUTO
+wsrep-notify-cmd
+wsrep-on FALSE
+wsrep-preordered FALSE
+wsrep-provider none
+wsrep-provider-options
+wsrep-recover FALSE
+wsrep-reject-queries NONE
+wsrep-replicate-myisam FALSE
+wsrep-restart-slave FALSE
+wsrep-retry-autocommit 1
+wsrep-slave-FK-checks TRUE
+wsrep-slave-UK-checks FALSE
+wsrep-slave-threads 1
+wsrep-sst-auth (No default value)
+wsrep-sst-donor
+wsrep-sst-donor-rejects-queries FALSE
+wsrep-sst-method rsync
+wsrep-sst-receive-address AUTO
+wsrep-start-position 00000000-0000-0000-0000-000000000000:-1
+wsrep-sync-wait 0
+wsrep-trx-fragment-size 0
+wsrep-trx-fragment-unit bytes
+
+To see what values a running MySQL server is using, type
+'mysqladmin variables' instead of 'mysqld --verbose --help'.
diff --git a/mysql-test/main/query_cache_size_functionality.result b/mysql-test/main/query_cache_size_functionality.result
new file mode 100644
index 00000000000..7563b3e61eb
--- /dev/null
+++ b/mysql-test/main/query_cache_size_functionality.result
@@ -0,0 +1,226 @@
+'#________________________VAR_02_query_cache_size__________________#'
+echo '##'
+--echo '#---------------------WL6372_VAR_2_01----------------------#'
+####################################################################
+# Checking default value #
+####################################################################
+SELECT COUNT(@@GLOBAL.query_cache_size)
+1 Expected
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+1048576
+1048576 Expected
+'#---------------------WL6372_VAR_2_02----------------------#'
+# Restart server with query_cache_size 51200;
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+51200
+51200 Expected
+SET @@GLOBAL.query_cache_size=DEFAULT;
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+1048576
+1048576 Expected
+'#---------------------WL6372_VAR_2_03----------------------#'
+SET @@local.query_cache_size=1;
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
+Expected error 'Global variable'
+SET @@session.query_cache_size=1;
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
+Expected error 'Global variable'
+SET @@GLOBAL.query_cache_size=1;
+SET @@GLOBAL.query_cache_size=DEFAULT;
+SELECT @@GLOBAL.query_cache_size;
+@@GLOBAL.query_cache_size
+1048576
+1048576 Expected
+'#---------------------WL6372_VAR_2_04----------------------#'
+SELECT @@GLOBAL.query_cache_size = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_size';
+@@GLOBAL.query_cache_size = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.query_cache_size);
+COUNT(@@GLOBAL.query_cache_size)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_size';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------WL6372_VAR_2_05----------------------#'
+SELECT @@query_cache_size = @@GLOBAL.query_cache_size;
+@@query_cache_size = @@GLOBAL.query_cache_size
+1
+1 Expected
+SELECT COUNT(@@local.query_cache_size);
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@SESSION.query_cache_size);
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@GLOBAL.query_cache_size);
+COUNT(@@GLOBAL.query_cache_size)
+1
+1 Expected
+SELECT query_cache_size = @@SESSION.query_cache_size;
+ERROR 42S22: Unknown column 'query_cache_size' in 'field list'
+Expected error 'Unknown column query_cache_size in field list'
+'#---------------------WL6372_VAR_2_06----------------------#'
+Check the size of the vardir
+The output size is in unit blocks
+TRUE
+TRUE Expected
+'#---------------------WL6372_VAR_2_07----------------------#'
+# create 1 table and insert 3 rows each
+DROP TABLE IF EXISTS tab1;
+===============
+create table & Index
+===============
+CREATE TABLE tab1 (col_1 text(10))
+ENGINE=INNODB ;
+===============
+Load the data
+===============
+SET @col_1 = repeat('a', 10);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+commit;
+set @@GLOBAL.query_cache_size=DEFAULT;
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+19
+17 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+24
+22 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+29
+27 Expected
+# Restart server with query_cache_type ON
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+10
+8 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+14
+12 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+18
+16 Expected
+# opening another client session
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+19
+17 Expected
+#cleanup
+DROP TABLE IF EXISTS tab1;
diff --git a/mysql-test/main/query_cache_type_functionality.result b/mysql-test/main/query_cache_type_functionality.result
new file mode 100644
index 00000000000..134d8c3a066
--- /dev/null
+++ b/mysql-test/main/query_cache_type_functionality.result
@@ -0,0 +1,250 @@
+'#________________________VAR_03_query_cache_type__________________#'
+echo '##'
+--echo '#---------------------WL6372_VAR_3_01----------------------#'
+####################################################################
+# Checking default value #
+####################################################################
+SELECT COUNT(@@GLOBAL.query_cache_type)
+1 Expected
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+OFF
+OFF Expected
+'#---------------------WL6372_VAR_3_02----------------------#'
+# Restart server with query_cache_type 1;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+ON
+ON Expected
+SET @@GLOBAL.query_cache_type=DEFAULT;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+OFF
+OFF Expected
+'#---------------------WL6372_VAR_3_03----------------------#'
+SET @@local.query_cache_type=1;
+SELECT @@Local.query_cache_type;
+@@Local.query_cache_type
+ON
+ON Expected
+SET @@session.query_cache_type=1;
+SELECT @@Session.query_cache_type;
+@@Session.query_cache_type
+ON
+ON Expected
+SET @@GLOBAL.query_cache_type=1;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+ON
+ON Expected
+SET @@GLOBAL.query_cache_type=DEFAULT;
+SELECT @@GLOBAL.query_cache_type;
+@@GLOBAL.query_cache_type
+OFF
+OFF Expected
+SET @@Session.query_cache_type=DEFAULT;
+SELECT @@Session.query_cache_type;
+@@Session.query_cache_type
+OFF
+OFF Expected
+SET @@Local.query_cache_type=DEFAULT;
+SELECT @@Local.query_cache_type;
+@@Local.query_cache_type
+OFF
+OFF Expected
+'#---------------------WL6372_VAR_3_04----------------------#'
+SELECT @@GLOBAL.query_cache_type = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_type';
+@@GLOBAL.query_cache_type = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.query_cache_type);
+COUNT(@@GLOBAL.query_cache_type)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='query_cache_type';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------WL6372_VAR_3_05----------------------#'
+SELECT @@query_cache_type = @@GLOBAL.query_cache_type;
+@@query_cache_type = @@GLOBAL.query_cache_type
+1
+1 Expected
+SELECT @@query_cache_type = @@Session.query_cache_type;
+@@query_cache_type = @@Session.query_cache_type
+1
+1 Expected
+SELECT COUNT(@@local.query_cache_type);
+COUNT(@@local.query_cache_type)
+1
+1 Expected
+SELECT COUNT(@@SESSION.query_cache_type);
+COUNT(@@SESSION.query_cache_type)
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.query_cache_type);
+COUNT(@@GLOBAL.query_cache_type)
+1
+1 Expected
+SELECT query_cache_type = @@SESSION.query_cache_type;
+ERROR 42S22: Unknown column 'query_cache_type' in 'field list'
+Expected error 'Unknown column query_cache_type in field list'
+'#---------------------WL6372_VAR_3_06----------------------#'
+Check the size of the vardir
+The output size is in unit blocks
+TRUE
+TRUE Expected
+'#---------------------WL6372_VAR_3_07----------------------#'
+# create 1 table and insert 3 rows each
+DROP TABLE IF EXISTS tab1;
+===============
+create table & Index
+===============
+CREATE TABLE tab1 (col_1 text(10))
+ENGINE=INNODB ;
+===============
+Load the data
+===============
+SET @col_1 = repeat('a', 10);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+INSERT INTO tab1
+VALUES (@col_1);
+commit;
+set @@GLOBAL.query_cache_type=DEFAULT;
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+27
+25 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+32
+30 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+37
+35 Expected
+# Restart server with query_cache_type ON
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+10
+8 Expected
+select 1 from tab1 limit 2;
+1
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+0
+0 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+14
+12 Expected
+select 1 from tab1 limit 1;
+1
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_hits';
+variable_value
+1
+1 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_inserts';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache';
+variable_value
+2
+2 Expected
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+18
+16 Expected
+# opening another client session
+select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached';
+variable_value
+19
+17 Expected
+#cleanup
+DROP TABLE IF EXISTS tab1;
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index af908297d65..fec4f332978 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -2902,6 +2902,55 @@ sub mysql_server_wait {
$warn_seconds);
}
+sub have_wsrep() {
+ my $wsrep_on= $mysqld_variables{'wsrep-on'};
+ return defined $wsrep_on
+}
+
+sub wsrep_is_bootstrap_server($) {
+ my $mysqld= shift;
+ return $mysqld->if_exist('wsrep_cluster_address') &&
+ ($mysqld->value('wsrep_cluster_address') eq "gcomm://" ||
+ $mysqld->value('wsrep_cluster_address') eq "'gcomm://'");
+}
+
+sub check_wsrep_support() {
+ if (have_wsrep())
+ {
+ mtr_report(" - binaries built with wsrep patch");
+
+ # ADD scripts to $PATH to that wsrep_sst_* can be found
+ my ($path) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir;
+ mtr_error("No SST scripts") unless $path;
+ $ENV{PATH}="$path:$ENV{PATH}";
+
+ # Check whether WSREP_PROVIDER environment variable is set.
+ if (defined $ENV{'WSREP_PROVIDER'}) {
+ if ((mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") &&
+ ($ENV{'WSREP_PROVIDER'} ne "none")) {
+ mtr_error("WSREP_PROVIDER env set to an invalid path");
+ }
+ # WSREP_PROVIDER is valid; set to a valid path or "none").
+ mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}");
+ } else {
+ # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider
+ # library.
+ my $file_wsrep_provider=
+ mtr_file_exists("/usr/lib/galera/libgalera_smm.so",
+ "/usr/lib64/galera/libgalera_smm.so");
+
+ if ($file_wsrep_provider ne "") {
+ # wsrep provider library found !
+ mtr_verbose("wsrep provider library found : $file_wsrep_provider");
+ $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider;
+ } else {
+ mtr_verbose("Could not find wsrep provider library, setting it to 'none'");
+ $ENV{'WSREP_PROVIDER'}= "none";
+ }
+ }
+ }
+}
+
sub create_config_file_for_extern {
my %opts=
(
@@ -3365,6 +3414,60 @@ sub run_query {
}
+sub run_query_output {
+ my ($mysqld, $query, $outfile)= @_;
+
+ my $args;
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
+ mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));
+
+ mtr_add_arg($args, "--silent");
+ mtr_add_arg($args, "--execute=%s", $query);
+
+ my $res= My::SafeProcess->run
+ (
+ name => "run_query_output -> ".$mysqld->name(),
+ path => $exe_mysql,
+ args => \$args,
+ output => $outfile,
+ error => $outfile
+ );
+
+ return $res
+}
+
+
+sub wait_wsrep_ready($$) {
+ my ($tinfo, $mysqld)= @_;
+
+ my $sleeptime= 100; # Milliseconds
+ my $loops= ($opt_start_timeout * 1000) / $sleeptime;
+
+ my $name= $mysqld->name();
+ my $outfile= "$opt_vardir/tmp/$name.wsrep_ready";
+ my $query= "SET SESSION wsrep_sync_wait = 0;
+ SELECT VARIABLE_VALUE
+ FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+ WHERE VARIABLE_NAME = 'wsrep_ready'";
+
+ for (my $loop= 1; $loop <= $loops; $loop++)
+ {
+ if (run_query_output($mysqld, $query, $outfile) == 0 &&
+ mtr_grab_file($outfile) =~ /^ON/)
+ {
+ unlink($outfile);
+ return 1;
+ }
+
+ mtr_milli_sleep($sleeptime);
+ }
+
+ $tinfo->{logfile}= "WSREP did not transition to state READY";
+ return 0;
+}
+
+
sub do_before_run_mysqltest($)
{
my $tinfo= shift;
@@ -5410,6 +5513,21 @@ sub start_servers($) {
for (all_servers()) {
$_->{START}->($_, $tinfo) if $_->{START};
+ # If wsrep is on, we need to wait until the first
+ # server starts and bootstraps the cluster before
+ # starting other servers. The bootsrap server in the
+ # configuration should always be the first which has
+ # wsrep_on=ON and should be tagged with "#wsrep-new-cluster".
+ # option
+ if (have_wsrep() && (defined $_->option("#wsrep-new-cluster") ||
+ wsrep_is_bootstrap_server($_)))
+ {
+ mtr_debug("Waiting the first wsrep server to start");
+ if ($_->{WAIT}->($_) && !wait_wsrep_ready($tinfo, $_))
+ {
+ return 1;
+ }
+ }
}
for (all_servers()) {
@@ -5418,7 +5536,13 @@ sub start_servers($) {
$tinfo->{comment}= "Failed to start ".$_->name() . "\n";
return 1;
}
+
+ if (have_wsrep() && !wait_wsrep_ready($tinfo, $_))
+ {
+ return 1;
+ }
}
+
return 0;
}
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index 322eff3506f..0dca1db66a7 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -9,7 +9,7 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-
+MW-360 : needs rewrite to be MariaDB gtid compatible
galera_flush : MariaDB does not have global.thread_statistics
galera_account_management : MariaDB 10.0 does not support ALTER USER
galera_binlog_rows_query_log_events: MariaDB does not support binlog_rows_query_log_events
diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf
index b24f3603894..68e4759ee9b 100644
--- a/mysql-test/suite/galera/galera_2nodes.cnf
+++ b/mysql-test/suite/galera/galera_2nodes.cnf
@@ -2,6 +2,7 @@
!include include/default_mysqld.cnf
[mysqld]
+loose-innodb
wsrep-on=1
binlog-format=row
innodb-autoinc-lock-mode=2
@@ -10,20 +11,34 @@ wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
# enforce read-committed characteristics across the cluster
wsrep-sync-wait=15
-
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
+loose-innodb
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+#wsrep-new-cluster
wsrep-cluster-address=gcomm://
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
+# enforce read-committed characteristics across the cluster
+wsrep_causal_reads=ON
+wsrep_sync_wait = 15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
[mysqld.2]
+loose-innodb
+# debug=d:t:i:o,/tmp/mysqld.2.trace
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S'
@@ -34,8 +49,14 @@ wsrep_sync_wait = 15
wsrep_node_address=127.0.0.1
wsrep_sst_receive_address=127.0.0.2:@mysqld.2.#sst_port
wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+wsrep_sst_receive_address='127.0.0.2:@mysqld.2.#sst_port'
+# enforce read-committed characteristics across the cluster
+wsrep_causal_reads=ON
+wsrep_sync_wait = 15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf
index 33bfc475721..f856b58ab14 100644
--- a/mysql-test/suite/galera/galera_2nodes_as_master.cnf
+++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf
@@ -11,6 +11,9 @@ log-bin=mysqld-bin
binlog-format=row
innodb-autoinc-lock-mode=2
default-storage-engine=innodb
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
#galera_port=@OPT.port
@@ -30,6 +33,9 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.2]
#galera_port=@OPT.port
@@ -49,9 +55,15 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.3]
server-id=3
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf
index 4d9e39d2aae..b432c9db7d3 100644
--- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf
+++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf
@@ -9,17 +9,14 @@
binlog-format=row
[mysqld.1]
-log-bin
-server-id=1
-
-[mysqld.2]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep-on=1
-log-bin
+log-bin=master-bin
+log-bin-index=master-bin
log-slave-updates
innodb-autoinc-lock-mode=2
@@ -27,38 +24,54 @@ default-storage-engine=innodb
wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
wsrep-cluster-address=gcomm://
-wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
-server-id=2
+server-id=1
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
-[mysqld.3]
+[mysqld.2]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep-on=1
-log-bin
+log-bin=master-bin
+log-bin-index=master-bin
log-slave-updates
innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
-wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port'
-wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
+wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
+wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+server-id=2
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
+[mysqld.1]
+log-bin=master-bin
+log-bin-index=master-bin
server-id=3
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
[ENV]
NODE_MYPORT_1= @mysqld.1.port
@@ -70,8 +83,8 @@ NODE_MYSOCK_2= @mysqld.2.socket
NODE_MYPORT_3= @mysqld.3.port
NODE_MYSOCK_3= @mysqld.3.socket
+NODE_GALERAPORT_1= @mysqld.1.#galera_port
NODE_GALERAPORT_2= @mysqld.2.#galera_port
-NODE_GALERAPORT_3= @mysqld.3.#galera_port
+NODE_SSTPORT_1= @mysqld.1.#sst_port
NODE_SSTPORT_2= @mysqld.2.#sst_port
-NODE_SSTPORT_3= @mysqld.3.#sst_port
diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf
index ac1ca34e242..26640374be9 100644
--- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf
+++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf
@@ -8,15 +8,15 @@
[mysqld]
log-bin
binlog-format=row
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
-server-id=1
-
-[mysqld.2]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
-
+wsrep-on=1
log-slave-updates
innodb-autoinc-lock-mode=2
@@ -24,19 +24,23 @@ default-storage-engine=innodb
wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
wsrep-cluster-address=gcomm://
-wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
-server-id=2
+server-id=1
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
-[mysqld.3]
+[mysqld.2]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+wsrep-on=1
log-slave-updates
@@ -44,20 +48,24 @@ innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
-wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port'
-wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
+wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
+wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
-server-id=3
+server-id=2
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
-[mysqld.4]
+[mysqld.3]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+wsrep-on=1
log-slave-updates
@@ -65,15 +73,24 @@ innodb-autoinc-lock-mode=2
default-storage-engine=innodb
wsrep-provider=@ENV.WSREP_PROVIDER
wsrep_node_address=127.0.0.1
-wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port'
-wsrep_provider_options='base_port=@mysqld.4.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
-wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port
-wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port'
+wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
+wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M'
+wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
+wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+server-id=3
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
+
+[mysqld.4]
server-id=4
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
@@ -88,10 +105,10 @@ NODE_MYSOCK_3= @mysqld.3.socket
NODE_MYPORT_4= @mysqld.4.port
NODE_MYSOCK_4= @mysqld.4.socket
+NODE_GALERAPORT_1= @mysqld.1.#galera_port
NODE_GALERAPORT_2= @mysqld.2.#galera_port
NODE_GALERAPORT_3= @mysqld.3.#galera_port
-NODE_GALERAPORT_4= @mysqld.4.#galera_port
+NODE_SSTPORT_1= @mysqld.1.#sst_port
NODE_SSTPORT_2= @mysqld.2.#sst_port
NODE_SSTPORT_3= @mysqld.3.#sst_port
-NODE_SSTPORT_4= @mysqld.4.#sst_port
diff --git a/mysql-test/suite/galera/galera_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf
index 1c195afd54b..2d348c0c2ed 100644
--- a/mysql-test/suite/galera/galera_4nodes.cnf
+++ b/mysql-test/suite/galera/galera_4nodes.cnf
@@ -11,6 +11,9 @@ wsrep_node_address=127.0.0.1
# enforce read-committed characteristics across the cluster
wsrep-causal-reads=ON
wsrep-sync-wait=15
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.1]
#galera_port=@OPT.port
@@ -20,6 +23,9 @@ wsrep-cluster-address=gcomm://
wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.2]
#galera_port=@OPT.port
@@ -29,6 +35,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.3]
@@ -39,6 +48,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[mysqld.4]
@@ -49,6 +61,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.4.#galera_port;gcache.size=10M'
wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port'
+# lock schedule alg appears to be VATS by default, and it is not
+# yet compatible with galera
+innodb_lock_schedule_algorithm=FCFS
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/include/galera_load_provider.inc b/mysql-test/suite/galera/include/galera_load_provider.inc
index aeab7e6ea19..0f843597d9c 100644
--- a/mysql-test/suite/galera/include/galera_load_provider.inc
+++ b/mysql-test/suite/galera/include/galera_load_provider.inc
@@ -2,7 +2,75 @@
--disable_query_log
--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig';
+
+#
+# count occurences of successful node starts in error log
+#
+perl;
+ use strict;
+ my $test_log=$ENV{'LOG_FILE'} or die "LOG_FILE not set";
+ my $test_log_copy=$test_log . '.copy';
+ if (-e $test_log_copy) {
+ unlink $test_log_copy;
+ }
+
+EOF
+--copy_file $LOG_FILE $LOG_FILE.copy
+
+#
+# now join to the cluster
+#
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig';
+
+--enable_query_log
+
+#
+# Cluster address change above, will launch SST/IST
+# if mysqldump ST has been configured, mysqld will close all
+# client connections, and it will be hard for us to poll for
+# cluster status during SST process, therefore wait_until_connected_again.inc
+# and wait_until_ready.inc may fail in this phase
+# To workaround this, we do first lazy polling here just to see when
+# client connections will be possible, and after that check for node readyness
+#
+--disable_result_log
+--disable_query_log
+
+--error 0,1
+perl;
+ use strict;
+ my $logfile = $ENV{'LOG_FILE'} or die ("no error log file set");
+
+ my $counter = 1000;
+ #my $found = false
+
+ while ($counter > 0) {
+
+ open(FILE, "$logfile") or die("Unable to open $logfile : $!\n");
+ my $new_sync_count = () = grep(/Synchronized with group/g,<FILE>);
+ close(FILE);
+
+ open(FILEN, "$logfile.copy") or die("Unable to open $logfile.copy : $!\n");
+ my $old_sync_count = () = grep(/Synchronized with group/g,<FILEN>);
+ close(FILEN);
+
+ if ($new_sync_count > $old_sync_count ) {
+ exit(0);
+ }
+ $counter--;
+ sleep(5);
+ }
+ exit(1);
+EOF
+if ($errno)
+{
+--echo "SST failed $errno"
+}
+
+--remove_file $LOG_FILE.copy
+
--enable_query_log
+--enable_result_log
+#--eval SET GLOBAL log_error = $log_error_;
--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera/include/galera_resume.inc b/mysql-test/suite/galera/include/galera_resume.inc
index 232cb46479e..af8f2b956fd 100644
--- a/mysql-test/suite/galera/include/galera_resume.inc
+++ b/mysql-test/suite/galera/include/galera_resume.inc
@@ -3,7 +3,7 @@
my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
- system("kill -18 $mysqld_pid");
+ system("kill -SIGCONT $mysqld_pid");
exit(0);
EOF
diff --git a/mysql-test/suite/galera/include/galera_sst_restore.inc b/mysql-test/suite/galera/include/galera_sst_restore.inc
index 7c9a08090ad..83d07f086d1 100644
--- a/mysql-test/suite/galera/include/galera_sst_restore.inc
+++ b/mysql-test/suite/galera/include/galera_sst_restore.inc
@@ -20,7 +20,7 @@ CALL mtr.add_suppression("Can't open and lock time zone table");
CALL mtr.add_suppression("Can't open and lock privilege tables");
CALL mtr.add_suppression("Info table is not ready to be used");
CALL mtr.add_suppression("Native table .* has the wrong structure");
-
+CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist");
--disable_query_log
--eval SET GLOBAL wsrep_sst_method = '$wsrep_sst_method_orig';
--eval SET GLOBAL wsrep_sst_receive_address = '$wsrep_sst_receive_address_orig';
diff --git a/mysql-test/suite/galera/include/galera_st_clean_slave.inc b/mysql-test/suite/galera/include/galera_st_clean_slave.inc
index 3a49f4f6ad2..52044775186 100644
--- a/mysql-test/suite/galera/include/galera_st_clean_slave.inc
+++ b/mysql-test/suite/galera/include/galera_st_clean_slave.inc
@@ -34,6 +34,7 @@ COMMIT;
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql
+--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/wsrep_schema
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc
index c8869746bd1..d6d7552f7b6 100644
--- a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc
+++ b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc
@@ -55,6 +55,14 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
--connection node_2
--source suite/galera/include/galera_load_provider.inc
+#
+# client connections were killed by provider load, so have to re-open here
+#
+--disconnect node_2
+--connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2
+--enable_reconnect
+
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
diff --git a/mysql-test/suite/galera/include/galera_unload_provider.inc b/mysql-test/suite/galera/include/galera_unload_provider.inc
index edc7eb31e0e..cd841f51fbc 100644
--- a/mysql-test/suite/galera/include/galera_unload_provider.inc
+++ b/mysql-test/suite/galera/include/galera_unload_provider.inc
@@ -3,5 +3,13 @@
--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
--let $wsrep_provider_orig = `SELECT @@wsrep_provider`
--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+--let $wsrep_error_log_orig = `SELECT @@log_error`
+if(!$wsrep_log_error_orig)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $wsrep_log_error_orig = $MYSQLTEST_VARDIR/log/mysqld.2.err;
+}
+--let LOG_FILE= $wsrep_log_error_orig
SET GLOBAL wsrep_provider = 'none';
diff --git a/mysql-test/suite/galera/r/GAL-382.result b/mysql-test/suite/galera/r/GAL-382.result
index fb7c229bd56..137efe4efba 100644
--- a/mysql-test/suite/galera/r/GAL-382.result
+++ b/mysql-test/suite/galera/r/GAL-382.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
create table t1 (i int, j int, k int, primary key pk(i)) engine=innodb;
insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3);
diff --git a/mysql-test/suite/galera/r/GAL-401.result b/mysql-test/suite/galera/r/GAL-401.result
index 3b55b7589b7..3dfc32ffb8c 100644
--- a/mysql-test/suite/galera/r/GAL-401.result
+++ b/mysql-test/suite/galera/r/GAL-401.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
connection node_2;
SET @@global.wsrep_desync = 1;
diff --git a/mysql-test/suite/galera/r/GCF-1081.result b/mysql-test/suite/galera/r/GCF-1081.result
new file mode 100644
index 00000000000..ede512ec6b1
--- /dev/null
+++ b/mysql-test/suite/galera/r/GCF-1081.result
@@ -0,0 +1,47 @@
+connection node_2;
+connection node_1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 0), (3, 0);
+CREATE PROCEDURE proc_update ()
+BEGIN
+UPDATE t1 SET f2 = 1 where f1 > 0;
+END|
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+CALL proc_update ();;
+connection node_1a;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+connection node_1a;
+SET GLOBAL DEBUG = 'd,sync.wsrep_before_BF_victim_unlock';
+Warnings:
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+connection node_2;
+INSERT INTO t1 VALUES (2, 2);;
+connection node_1a;
+SET SESSION DEBUG_SYNC = 'now WAIT_FOR sync.wsrep_before_BF_victim_unlock_reached';
+SET GLOBAL DEBUG = '';
+Warnings:
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+connection node_2;
+SELECT * FROM t1;
+f1 f2
+1 1
+2 2
+3 1
+connection node_1;
+SELECT * FROM t1;
+f1 f2
+1 1
+2 2
+3 1
+wsrep_local_replays
+1
+DROP PROCEDURE proc_update;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/GCF-939.result b/mysql-test/suite/galera/r/GCF-939.result
new file mode 100644
index 00000000000..57b04efa529
--- /dev/null
+++ b/mysql-test/suite/galera/r/GCF-939.result
@@ -0,0 +1,12 @@
+connection node_2;
+connection node_1;
+connection node_1;
+DROP TABLE t1;
+ERROR 42S02: Unknown table 'test.t1'
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+GRA_.log
+DROP TABLE t1;
+CALL mtr.add_suppression("Ignoring error 'Unknown table 'test.t1'' on query");
+connection node_2;
+CALL mtr.add_suppression("Error 'Unknown table 'test.t1'' on query");
diff --git a/mysql-test/suite/galera/r/MDEV-15443.result b/mysql-test/suite/galera/r/MDEV-15443.result
index 618e5459878..21332b372e8 100644
--- a/mysql-test/suite/galera/r/MDEV-15443.result
+++ b/mysql-test/suite/galera/r/MDEV-15443.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/MW-252.result b/mysql-test/suite/galera/r/MW-252.result
index 795d3fff670..4d458802614 100644
--- a/mysql-test/suite/galera/r/MW-252.result
+++ b/mysql-test/suite/galera/r/MW-252.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
FLUSH TABLES WITH READ LOCK;
diff --git a/mysql-test/suite/galera/r/MW-258.result b/mysql-test/suite/galera/r/MW-258.result
index 1c2a1744c98..22963557daf 100644
--- a/mysql-test/suite/galera/r/MW-258.result
+++ b/mysql-test/suite/galera/r/MW-258.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER);
LOCK TABLE t1 WRITE;
diff --git a/mysql-test/suite/galera/r/MW-259.result b/mysql-test/suite/galera/r/MW-259.result
index 5256a95c52c..9a0f2ccfa23 100644
--- a/mysql-test/suite/galera/r/MW-259.result
+++ b/mysql-test/suite/galera/r/MW-259.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
diff --git a/mysql-test/suite/galera/r/MW-284.result b/mysql-test/suite/galera/r/MW-284.result
index 0f6c0be25fe..b95639c568a 100644
--- a/mysql-test/suite/galera/r/MW-284.result
+++ b/mysql-test/suite/galera/r/MW-284.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
@@ -24,7 +26,9 @@ RESET SLAVE ALL;
CALL mtr.add_suppression('failed registering on master');
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
connection node_1;
+set global wsrep_on=OFF;
RESET MASTER;
+set global wsrep_on=OFF;
CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member');
connection node_2;
CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member');
diff --git a/mysql-test/suite/galera/r/MW-285.result b/mysql-test/suite/galera/r/MW-285.result
index 8c5a21fcbee..762f22d5d25 100644
--- a/mysql-test/suite/galera/r/MW-285.result
+++ b/mysql-test/suite/galera/r/MW-285.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent1 ( id INT PRIMARY KEY, KEY (id) ) ENGINE=InnoDB;
CREATE TABLE parent2 ( id INT PRIMARY KEY, KEY (id) ) ENGINE=InnoDB;
CREATE TABLE child (
diff --git a/mysql-test/suite/galera/r/MW-292.result b/mysql-test/suite/galera/r/MW-292.result
index 5b9214ace2a..81e5a316b63 100644
--- a/mysql-test/suite/galera/r/MW-292.result
+++ b/mysql-test/suite/galera/r/MW-292.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE rand_table (f1 FLOAT);
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
INSERT INTO t1 VALUES (1, 'a');
@@ -10,19 +12,28 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
f1 f2
2 a
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync';
-connection node_1;
-COMMIT;;
-connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
-SET SESSION wsrep_on = 0;
-SET SESSION wsrep_on = 1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
connection node_1;
SELECT TIMEDIFF(SYSDATE(), NOW()) < 2;
TIMEDIFF(SYSDATE(), NOW()) < 2
diff --git a/mysql-test/suite/galera/r/MW-309.result b/mysql-test/suite/galera/r/MW-309.result
index 3dd49a041ee..0169b56e3e1 100644
--- a/mysql-test/suite/galera/r/MW-309.result
+++ b/mysql-test/suite/galera/r/MW-309.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t1 SELECT * FROM t1;
diff --git a/mysql-test/suite/galera/r/MW-313.result b/mysql-test/suite/galera/r/MW-313.result
index dc605ffc370..909caf77f1d 100644
--- a/mysql-test/suite/galera/r/MW-313.result
+++ b/mysql-test/suite/galera/r/MW-313.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t1 SELECT * FROM t1;
diff --git a/mysql-test/suite/galera/r/MW-328A.result b/mysql-test/suite/galera/r/MW-328A.result
index db0301b6bf2..266c5637b9b 100644
--- a/mysql-test/suite/galera/r/MW-328A.result
+++ b/mysql-test/suite/galera/r/MW-328A.result
@@ -14,10 +14,6 @@ connection node_1X;
CALL proc_update();;
connection node_2;
SET SESSION wsrep_retry_autocommit = 0;
-have_successes
-1
-have_deadlocks
-1
connection node_1;
connection node_1X;
Got one of the listed errors
@@ -25,3 +21,17 @@ connection node_1;
DROP PROCEDURE proc_update;
DROP TABLE t1, t2;
CALL mtr.add_suppression("conflict state 3 after post commit");
+CREATE TABLE t1 (i int primary key, j int) engine=innodb;
+INSERT INTO t1 values (1,0);
+BEGIN;
+UPDATE t1 SET j=1 WHERE i=1;
+UPDATE t1 SET j=2 WHERE i=1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+i j
+1 2
+SELECT * FROM t1;
+i j
+1 2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/MW-328B.result b/mysql-test/suite/galera/r/MW-328B.result
index e898e315ca8..d29c3a50f3d 100644
--- a/mysql-test/suite/galera/r/MW-328B.result
+++ b/mysql-test/suite/galera/r/MW-328B.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
INSERT INTO t1 (f1) VALUES (1);
CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/MW-328C.result b/mysql-test/suite/galera/r/MW-328C.result
index d8e164e7b4a..748f9420764 100644
--- a/mysql-test/suite/galera/r/MW-328C.result
+++ b/mysql-test/suite/galera/r/MW-328C.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
INSERT INTO t1 (f1) VALUES (1);
CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/MW-328D.result b/mysql-test/suite/galera/r/MW-328D.result
index 6562136ec27..43e1cefe08f 100644
--- a/mysql-test/suite/galera/r/MW-328D.result
+++ b/mysql-test/suite/galera/r/MW-328D.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (i INT) ENGINE = InnoDB;
INSERT INTO t1 (i) VALUES(1);
CREATE TABLE t2 (i INT) ENGINE = InnoDB;
diff --git a/mysql-test/suite/galera/r/MW-328E.result b/mysql-test/suite/galera/r/MW-328E.result
index 89654ec066a..729fdea1a63 100644
--- a/mysql-test/suite/galera/r/MW-328E.result
+++ b/mysql-test/suite/galera/r/MW-328E.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
create table t1 (i int primary key, j int) engine=innodb;
create table t2 (i int primary key, j int) engine=innodb;
insert into t1 values (1,0);
diff --git a/mysql-test/suite/galera/r/MW-329.result b/mysql-test/suite/galera/r/MW-329.result
index a3cb7277a9c..334ff9f80fb 100644
--- a/mysql-test/suite/galera/r/MW-329.result
+++ b/mysql-test/suite/galera/r/MW-329.result
@@ -1,10 +1,6 @@
CALL mtr.add_suppression("WSREP: .*conflict state . after post commit .*");
CREATE TABLE t1 (f1 INTEGER, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
INSERT INTO t1 (f1) VALUES (1),(65535);
-FLUSH STATUS;
-SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
-VARIABLE_VALUE = 0
-1
CREATE PROCEDURE proc_insert ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
@@ -16,10 +12,7 @@ END|
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1b;
CALL proc_insert();;
-connection node_2;
-CALL mtr.add_suppression("WSREP: Failed to report last committed .*");
-SELECT VARIABLE_VALUE > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
-VARIABLE_VALUE > 0
+wsrep_local_replays
1
connection node_1;
connection node_1b;
diff --git a/mysql-test/suite/galera/r/MW-336.result b/mysql-test/suite/galera/r/MW-336.result
index 0bf8d9d3909..b1509da3856 100644
--- a/mysql-test/suite/galera/r/MW-336.result
+++ b/mysql-test/suite/galera/r/MW-336.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
connection node_1;
SET GLOBAL wsrep_slave_threads = 10;
diff --git a/mysql-test/suite/galera/r/MW-357.result b/mysql-test/suite/galera/r/MW-357.result
index 35855e21233..dc391be4dd3 100644
--- a/mysql-test/suite/galera/r/MW-357.result
+++ b/mysql-test/suite/galera/r/MW-357.result
@@ -1,4 +1,6 @@
connection node_2;
+connection node_1;
+connection node_2;
SET GLOBAL wsrep_slave_threads = 0;
Warnings:
Warning 1292 Truncated incorrect wsrep_slave_threads value: '0'
diff --git a/mysql-test/suite/galera/r/MW-360.result b/mysql-test/suite/galera/r/MW-360.result
new file mode 100644
index 00000000000..f20d5be2135
--- /dev/null
+++ b/mysql-test/suite/galera/r/MW-360.result
@@ -0,0 +1,41 @@
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+DROP TABLE t1, t2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+DROP TABLE t1, t2;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+CREATE TEMPORARY TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+DROP TABLE t1, t2, t3;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+DROP TABLE t1, t2, t3;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+DROP TABLE t1;
+DROP TABLE t1;
+gtid_executed_equal
+1
diff --git a/mysql-test/suite/galera/r/MW-369.result b/mysql-test/suite/galera/r/MW-369.result
index 516904d1b2a..4f36193fd59 100644
--- a/mysql-test/suite/galera/r/MW-369.result
+++ b/mysql-test/suite/galera/r/MW-369.result
@@ -1,25 +1,36 @@
+connection node_2;
+connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
DELETE FROM p WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
INSERT INTO c VALUES (1, 1);
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
SELECT * FROM p;
f1 f2
1 0
@@ -29,6 +40,7 @@ f1 p_id
1 1
DROP TABLE c;
DROP TABLE p;
+connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
f2 INTEGER,
@@ -36,22 +48,30 @@ CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
UPDATE c SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+connection node_2;
SELECT * FROM p;
f1 f2
1 1
@@ -61,28 +81,37 @@ f1 p_id f2
1 1 1
DROP TABLE c;
DROP TABLE p;
+connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
DELETE FROM c WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+connection node_2;
SELECT * FROM p;
f1 f2
1 1
@@ -95,23 +124,31 @@ CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER UNIQUE KEY) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f2)) ;
INSERT INTO p VALUES (1, 0);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
INSERT INTO c VALUES (1, 0);;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
SELECT * FROM p;
f1 f2
1 0
@@ -127,23 +164,31 @@ ON DELETE CASCADE) ;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
+connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
DELETE FROM p WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
UPDATE c SET f2 = 1 WHERE f1 = 1;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
COMMIT;
+connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
SELECT * FROM p;
f1 f2
1 0
diff --git a/mysql-test/suite/galera/r/MW-388.result b/mysql-test/suite/galera/r/MW-388.result
index a2cf02712bb..114938c52d5 100644
--- a/mysql-test/suite/galera/r/MW-388.result
+++ b/mysql-test/suite/galera/r/MW-388.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB;
CREATE PROCEDURE insert_proc ()
@@ -29,7 +31,7 @@ connection node_2;
connection node_1;
SELECT @errno = 1213;
@errno = 1213
-0
+1
SELECT * FROM t1;
f1 f2
1 node 2
diff --git a/mysql-test/suite/galera/r/MW-402.result b/mysql-test/suite/galera/r/MW-402.result
index 9be98d629fb..f692c90d611 100644
--- a/mysql-test/suite/galera/r/MW-402.result
+++ b/mysql-test/suite/galera/r/MW-402.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
@@ -20,14 +22,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -60,14 +62,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -102,14 +104,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -135,14 +137,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
@@ -159,8 +161,10 @@ DROP TABLE p;
connection node_1;
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
-CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER,
-CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE,
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+f2 INTEGER,
+CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ON DELETE CASCADE,
CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1));
INSERT INTO p1 VALUES (1, 0);
INSERT INTO p2 VALUES (1, 0);
@@ -179,14 +183,14 @@ connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
connection node_1;
COMMIT;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
-SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
connection node_2;
@@ -197,4 +201,52 @@ f1 f2
1 2
SELECT * FROM c;
f1 p1_id p2_id f2
+DROP TABLE c;
+DROP TABLE p1;
+DROP TABLE p2;
+connection node_1;
+CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+f2 INTEGER,
+CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ON DELETE CASCADE,
+CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)
+ON DELETE CASCADE);
+INSERT INTO p1 VALUES (1, 0);
+INSERT INTO p2 VALUES (1, 0);
+INSERT INTO c VALUES (1, 1, 1, 0);
+connection node_1a;
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+DELETE FROM p2 WHERE f1=1;
+connection node_1a;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+DELETE FROM p1 WHERE f1=1;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_2;
+SELECT * FROM p1;
+f1 f2
+SELECT * FROM p2;
+f1 f2
+1 0
+SELECT * FROM c;
+f1 p1_id p2_id f2
DROP TABLE c,p1,p2;
diff --git a/mysql-test/suite/galera/r/MW-416.result b/mysql-test/suite/galera/r/MW-416.result
index 05399b213a8..9d72ae177b1 100644
--- a/mysql-test/suite/galera/r/MW-416.result
+++ b/mysql-test/suite/galera/r/MW-416.result
@@ -1,8 +1,9 @@
+connection node_2;
+connection node_1;
CREATE USER 'userMW416'@'localhost';
GRANT SELECT, INSERT, UPDATE ON test.* TO 'userMW416'@'localhost';
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
-Variable_name Value
-wsrep_replicated 2
+connect userMW416, localhost, userMW416,, test, $NODE_MYPORT_1;
+connection userMW416;
ALTER DATABASE db CHARACTER SET = utf8;
ERROR 42000: Access denied for user 'userMW416'@'localhost' to database 'db'
ALTER EVENT ev1 RENAME TO ev2;
@@ -53,16 +54,12 @@ DROP FUNCTION fun1;
Got one of the listed errors
DROP INDEX idx ON t0;
Got one of the listed errors
-DROP LOGFILE GROUP lfg;
-Got one of the listed errors
DROP PROCEDURE proc1;
Got one of the listed errors
DROP SERVEr srv;
Got one of the listed errors
DROP TABLE t0;
Got one of the listed errors
-DROP TABLESPACE tblspc;
-Got one of the listed errors
DROP TRIGGER trg;
Got one of the listed errors
DROP VIEW vw;
@@ -71,8 +68,6 @@ RENAME TABLE t0 TO t1;
Got one of the listed errors
TRUNCATE TABLE t0;
Got one of the listed errors
-ALTER USER myuser PASSWORD EXPIRE;
-Got one of the listed errors
CREATE USER myuser IDENTIFIED BY 'pass';
Got one of the listed errors
DROP USER myuser;
@@ -101,6 +96,7 @@ INSTALL PLUGIN plg SONAME 'plg.so';
Got one of the listed errors
UNINSTALL PLUGIN plg;
Got one of the listed errors
+connection node_1;
DROP USER 'userMW416'@'localhost';
SHOW DATABASES;
Database
@@ -109,6 +105,6 @@ mtr
mysql
performance_schema
test
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
-Variable_name Value
-wsrep_replicated 3
+wsrep_schema
+wsrep_replicated_after_diff
+1
diff --git a/mysql-test/suite/galera/r/MW-86-wait1.result b/mysql-test/suite/galera/r/MW-86-wait1.result
index 00010eaedcb..36cbfadf302 100644
--- a/mysql-test/suite/galera/r/MW-86-wait1.result
+++ b/mysql-test/suite/galera/r/MW-86-wait1.result
@@ -1,11 +1,13 @@
connection node_2;
+connection node_1;
+SET @orig_debug=@@debug;
+connection node_2;
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
+set debug_sync='RESET';
SET SESSION wsrep_sync_wait = 1;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
connection node_1;
CREATE TABLE t_wait1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t_wait1 VALUES (1);
@@ -36,16 +38,11 @@ SHOW TABLES;
SHOW TRIGGERS;
SHOW GLOBAL VARIABLES LIKE 'foo_bar';
SHOW WARNINGS;
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = @orig_debug;
SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
DROP TABLE t_wait1;
-SET GLOBAL debug = NULL;
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
-SET debug_sync='RESET';
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
diff --git a/mysql-test/suite/galera/r/MW-86-wait8.result b/mysql-test/suite/galera/r/MW-86-wait8.result
index 47e0ebc1342..6ac2c5f5e1f 100644
--- a/mysql-test/suite/galera/r/MW-86-wait8.result
+++ b/mysql-test/suite/galera/r/MW-86-wait8.result
@@ -1,11 +1,12 @@
connection node_2;
+connection node_1;
+SET @orig_debug=@@debug;
+connection node_2;
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
SET SESSION wsrep_sync_wait = 8;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
connection node_1;
CREATE TABLE t_wait8 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t_wait8 VALUES (1);
@@ -38,16 +39,11 @@ SHOW TABLES;
SHOW TRIGGERS;
SHOW GLOBAL VARIABLES LIKE 'foo_bar';
SHOW WARNINGS;
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+SET GLOBAL debug_dbug = @orig_debug;
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
DROP TABLE t_wait8;
-SET GLOBAL debug = NULL;
-Warnings:
-Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
-SET debug_sync='RESET';
SELECT @@debug_sync;
@@debug_sync
ON - current signal: ''
diff --git a/mysql-test/suite/galera/r/MW-86.result b/mysql-test/suite/galera/r/MW-86.result
new file mode 100644
index 00000000000..bca9be93191
--- /dev/null
+++ b/mysql-test/suite/galera/r/MW-86.result
@@ -0,0 +1,78 @@
+connection node_2;
+connection node_1;
+connection node_2;
+SET SESSION wsrep_sync_wait = 1;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+Warnings:
+Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
+connection node_1;
+CREATE DATABASE db1;
+CREATE TABLE bar (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO bar VALUES (1);
+connection node_2;
+SHOW BINARY LOGS;
+SHOW BINLOG EVENTS;
+SHOW COLUMNS FROM t1;
+SHOW CREATE DATABASE db1;
+SHOW CREATE EVENT e1;
+SHOW CREATE FUNCTION f1;
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE TABLE t1;
+SHOW CREATE TRIGGER tr1;
+SHOW CREATE VIEW v1;
+SHOW DATABASES;
+SHOW ENGINE InnoDB STATUS;
+SHOW FUNCTION CODE f1;
+SHOW FUNCTION STATUS;
+SHOW GRANTS FOR 'root'@'localhost';
+SHOW INDEX FROM t1;
+SHOW OPEN TABLES;
+SHOW PROCEDURE CODE p1;
+SHOW PROCEDURE STATUS;
+SHOW PRIVILEGES;
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SHOW TABLE STATUS;
+SHOW TABLES;
+SHOW TRIGGERS;
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+SHOW WARNINGS;
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET SESSION wsrep_sync_wait = 8;
+DROP DATABASE db1;
+connection node_2;
+SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT0.1S";
+SET SESSION wsrep_sync_wait = 8;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+connection node_1;
+CREATE TABLE q (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO q VALUES (1);
+connection node_2;
+SHOW BINARY LOGS;
+SHOW BINLOG EVENTS;
+SHOW COLUMNS FROM t1;
+SHOW CREATE DATABASE db1;
+SHOW CREATE EVENT e1;
+SHOW CREATE FUNCTION f1;
+SHOW CREATE PROCEDURE p1;
+SHOW CREATE TABLE t1;
+SHOW CREATE TRIGGER tr1;
+SHOW CREATE VIEW v1;
+SHOW DATABASES;
+SHOW ENGINE InnoDB STATUS;
+SHOW FUNCTION CODE f1;
+SHOW FUNCTION STATUS;
+SHOW GRANTS FOR 'root'@'localhost';
+SHOW INDEX FROM t1;
+SHOW OPEN TABLES;
+SHOW PROCEDURE CODE p1;
+SHOW PROCEDURE STATUS;
+SHOW PRIVILEGES;
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SHOW TABLE STATUS;
+SHOW TABLES;
+SHOW TRIGGERS;
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+SHOW WARNINGS;
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
diff --git a/mysql-test/suite/galera/r/basic.result b/mysql-test/suite/galera/r/basic.result
index e85c805253f..10f180e7a94 100644
--- a/mysql-test/suite/galera/r/basic.result
+++ b/mysql-test/suite/galera/r/basic.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
USE test;
CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
diff --git a/mysql-test/suite/galera/r/binlog_checksum.result b/mysql-test/suite/galera/r/binlog_checksum.result
index e86f3892ac7..4106354eb7d 100644
--- a/mysql-test/suite/galera/r/binlog_checksum.result
+++ b/mysql-test/suite/galera/r/binlog_checksum.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM;
diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result
index a445b32e8bf..6ad94dd3d43 100644
--- a/mysql-test/suite/galera/r/create.result
+++ b/mysql-test/suite/galera/r/create.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-6924 : Server crashed on CREATE TABLE ... SELECT
#
diff --git a/mysql-test/suite/galera/r/enforce_storage_engine.result b/mysql-test/suite/galera/r/enforce_storage_engine.result
index 746aa22bf20..1a453241427 100644
--- a/mysql-test/suite/galera/r/enforce_storage_engine.result
+++ b/mysql-test/suite/galera/r/enforce_storage_engine.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-8831 : enforce_storage_engine doesn't block table creation on
# other nodes (galera cluster)
diff --git a/mysql-test/suite/galera/r/enforce_storage_engine2.result b/mysql-test/suite/galera/r/enforce_storage_engine2.result
index 128994ed221..8b174139eae 100644
--- a/mysql-test/suite/galera/r/enforce_storage_engine2.result
+++ b/mysql-test/suite/galera/r/enforce_storage_engine2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-9312: storage engine not enforced during galera cluster
# replication
diff --git a/mysql-test/suite/galera/r/ev51914.result b/mysql-test/suite/galera/r/ev51914.result
index 3f3d67d01ef..b9d8a82bfa0 100644
--- a/mysql-test/suite/galera/r/ev51914.result
+++ b/mysql-test/suite/galera/r/ev51914.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SAVEPOINT in a stored function should be forbidden
CREATE FUNCTION f1 () RETURNS INT BEGIN
diff --git a/mysql-test/suite/galera/r/fk.result b/mysql-test/suite/galera/r/fk.result
index ab8e1c8f680..17fc99a904e 100644
--- a/mysql-test/suite/galera/r/fk.result
+++ b/mysql-test/suite/galera/r/fk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
USE test;
# On node_1
diff --git a/mysql-test/suite/galera/r/galera#414.result b/mysql-test/suite/galera/r/galera#414.result
index 34dcb6242d3..2c1dccfd131 100644
--- a/mysql-test/suite/galera/r/galera#414.result
+++ b/mysql-test/suite/galera/r/galera#414.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera#500.result b/mysql-test/suite/galera/r/galera#500.result
index 6a07d0359a4..22d38777369 100644
--- a/mysql-test/suite/galera/r/galera#500.result
+++ b/mysql-test/suite/galera/r/galera#500.result
@@ -1,10 +1,16 @@
+connection node_2;
+connection node_1;
+connection node_2;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options="gmcast.isolate=2";
+connection node_1;
SET SESSION wsrep_sync_wait = 0;
SHOW STATUS LIKE 'wsrep_cluster_status';
Variable_name Value
wsrep_cluster_status non-Primary
SET SESSION wsrep_sync_wait = default;
SET GLOBAL wsrep_provider_options="pc.bootstrap=1";
+connection node_2;
SET SESSION wsrep_on=0;
+connection node_2;
CALL mtr.add_suppression("WSREP: exception from gcomm, backend must be restarted: Gcomm backend termination was requested by setting gmcast.isolate=2.");
diff --git a/mysql-test/suite/galera/r/galera_admin.result b/mysql-test/suite/galera/r/galera_admin.result
index ed753247236..3db60e99409 100644
--- a/mysql-test/suite/galera/r/galera_admin.result
+++ b/mysql-test/suite/galera/r/galera_admin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
DROP TABLE IF EXISTS t1, t2;
DROP TABLE IF EXISTS x1, x2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result
index ff6ab792c0e..dfa30441f85 100644
--- a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result
+++ b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
ALTER TABLE t1 ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result
index 389383858ac..b3a9bdd30df 100644
--- a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result
+++ b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_replicate_myisam = TRUE;
CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/galera_alter_table_force.result b/mysql-test/suite/galera/r/galera_alter_table_force.result
index d0a2f81b631..271796422cd 100644
--- a/mysql-test/suite/galera/r/galera_alter_table_force.result
+++ b/mysql-test/suite/galera/r/galera_alter_table_force.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
ALTER TABLE t1 FORCE;
diff --git a/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result b/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result
index a6607906661..11fda5d8aab 100644
--- a/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result
+++ b/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION wsrep_sync_wait = 0;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result b/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result
index 9711100d155..a5aeb6eb366 100644
--- a/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result
+++ b/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION wsrep_sync_wait = 0;
SET SESSION lock_wait_timeout = 60;
diff --git a/mysql-test/suite/galera/r/galera_as_master.result b/mysql-test/suite/galera/r/galera_as_master.result
index 2a7262359fa..4aca328be56 100644
--- a/mysql-test/suite/galera/r/galera_as_master.result
+++ b/mysql-test/suite/galera/r/galera_as_master.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
START SLAVE;
connection node_1;
@@ -54,4 +56,6 @@ STOP SLAVE;
RESET SLAVE ALL;
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
connection node_1;
+set global wsrep_on=OFF;
RESET MASTER;
+set global wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_as_master_gtid.result b/mysql-test/suite/galera/r/galera_as_master_gtid.result
index 8dfe462d495..4f5c38b607a 100644
--- a/mysql-test/suite/galera/r/galera_as_master_gtid.result
+++ b/mysql-test/suite/galera/r/galera_as_master_gtid.result
@@ -5,55 +5,19 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
uuids_do_not_match
1
-SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120;
-Log_name Pos Event_type Server_id End_log_pos Info
-mysqld-bin.000002 120 Previous_gtids 1 151
-mysqld-bin.000002 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1'
-mysqld-bin.000002 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000002 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2'
-mysqld-bin.000002 375 Query 1 452 BEGIN
-mysqld-bin.000002 452 Table_map 1 497 table_id: # (test.t1)
-mysqld-bin.000002 497 Write_rows 1 537 table_id: # flags: STMT_END_F
-mysqld-bin.000002 537 Xid 1 568 COMMIT /* xid=# */
INSERT INTO t1 VALUES(2);
uuids_do_not_match
1
uuids_match
1
-SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
-Log_name Pos Event_type Server_id End_log_pos Info
-mysqld-bin.000003 120 Previous_gtids 2 151
-mysqld-bin.000003 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1'
-mysqld-bin.000003 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000003 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2'
-mysqld-bin.000003 375 Query 1 443 BEGIN
-mysqld-bin.000003 443 Table_map 1 488 table_id: # (test.t1)
-mysqld-bin.000003 488 Write_rows 1 528 table_id: # flags: STMT_END_F
-mysqld-bin.000003 528 Xid 1 559 COMMIT /* xid=# */
-mysqld-bin.000003 559 Gtid 2 607 SET @@SESSION.GTID_NEXT= '<effective_uuid>:3'
-mysqld-bin.000003 607 Query 2 684 BEGIN
-mysqld-bin.000003 684 Table_map 2 729 table_id: # (test.t1)
-mysqld-bin.000003 729 Write_rows 2 769 table_id: # flags: STMT_END_F
-mysqld-bin.000003 769 Xid 2 800 COMMIT /* xid=# */
uuids_do_not_match
1
uuids_match
1
-SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
-Log_name Pos Event_type Server_id End_log_pos Info
-mysqld-bin.000001 120 Previous_gtids 3 151
-mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1'
-mysqld-bin.000001 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000001 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2'
-mysqld-bin.000001 375 Query 1 443 BEGIN
-mysqld-bin.000001 443 Table_map 1 488 table_id: # (test.t1)
-mysqld-bin.000001 488 Write_rows 1 528 table_id: # flags: STMT_END_F
-mysqld-bin.000001 528 Xid 1 559 COMMIT /* xid=# */
-mysqld-bin.000001 559 Gtid 2 607 SET @@SESSION.GTID_NEXT= '<effective_uuid>:3'
-mysqld-bin.000001 607 Query 2 675 BEGIN
-mysqld-bin.000001 675 Table_map 2 720 table_id: # (test.t1)
-mysqld-bin.000001 720 Write_rows 2 760 table_id: # flags: STMT_END_F
-mysqld-bin.000001 760 Xid 2 791 COMMIT /* xid=# */
DROP TABLE t1;
+gtid_executed_equal
+1
+gtid_executed_equal
+1
STOP SLAVE;
RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/r/galera_as_master_large.result b/mysql-test/suite/galera/r/galera_as_master_large.result
index dad74211af9..826d2f32057 100644
--- a/mysql-test/suite/galera/r/galera_as_master_large.result
+++ b/mysql-test/suite/galera/r/galera_as_master_large.result
@@ -2,6 +2,8 @@
# MDEV-9044 : Getting binlog corruption on my Galera cluster (10.1.8)
# making it impossible to async slave.
#
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
START SLAVE;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result
index 60f3216aa9c..2da72af0d9b 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result
@@ -1,5 +1,7 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
+connection node_1;
+connection node_2;
START SLAVE;
connection node_1;
SET SESSION binlog_format='STATEMENT';
@@ -85,4 +87,6 @@ connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
connection node_1;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid.result b/mysql-test/suite/galera/r/galera_as_slave_gtid.result
index 0ef9d208bf4..1262879d992 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_gtid.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid.result
@@ -1,5 +1,7 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
+connection node_1;
+connection node_2;
START SLAVE;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result
new file mode 100644
index 00000000000..9f10efccd22
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result
@@ -0,0 +1,160 @@
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2;
+connection node_1;
+connection node_1;
+RESET MASTER;
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+connection node_2;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+START SLAVE;
+connection node_1;
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+UPDATE test2.t1 SET test2.t1.f2 = 'cde';
+UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz';
+DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO test2.t1 (f1) VALUES (999);
+INSERT INTO test2.t1 (f1) VALUES (9999);
+COMMIT;
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (111);
+INSERT INTO test1.t1 (f1) VALUES (222);
+COMMIT;
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (333);
+INSERT INTO test2.t1 (f1) VALUES (99999);
+COMMIT;
+connection node_2;
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 256 Gtid_list 2 285 []
+master-bin.000001 285 Binlog_checkpoint 2 329 master-bin.000001
+master-bin.000001 329 Gtid 1 371 GTID 0-1-1
+master-bin.000001 371 Query 1 458 CREATE SCHEMA test1
+master-bin.000001 458 Gtid 1 500 GTID 0-1-3
+master-bin.000001 500 Query 1 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB
+master-bin.000001 647 Gtid 1 689 BEGIN GTID 0-1-5
+master-bin.000001 689 Annotate_rows 1 748 INSERT INTO test1.t1 (f1) VALUES (1)
+master-bin.000001 748 Table_map 1 797 table_id: ### (test1.t1)
+master-bin.000001 797 Write_rows_v1 1 839 table_id: ### flags: STMT_END_F
+master-bin.000001 839 Xid 1 870 COMMIT /* xid=### */
+master-bin.000001 870 Gtid 1 912 BEGIN GTID 0-1-7
+master-bin.000001 912 Annotate_rows 1 971 INSERT INTO test1.t1 (f1) VALUES (2)
+master-bin.000001 971 Table_map 1 1020 table_id: ### (test1.t1)
+master-bin.000001 1020 Write_rows_v1 1 1062 table_id: ### flags: STMT_END_F
+master-bin.000001 1062 Xid 1 1093 COMMIT /* xid=### */
+master-bin.000001 1093 Gtid 1 1135 BEGIN GTID 0-1-9
+master-bin.000001 1135 Annotate_rows 1 1194 INSERT INTO test1.t1 (f1) VALUES (3)
+master-bin.000001 1194 Table_map 1 1243 table_id: ### (test1.t1)
+master-bin.000001 1243 Write_rows_v1 1 1285 table_id: ### flags: STMT_END_F
+master-bin.000001 1285 Xid 1 1316 COMMIT /* xid=### */
+master-bin.000001 1316 Gtid 1 1358 BEGIN GTID 0-1-12
+master-bin.000001 1358 Annotate_rows 1 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'
+master-bin.000001 1451 Table_map 1 1500 table_id: ### (test1.t1)
+master-bin.000001 1500 Update_rows_v1 1 1588 table_id: ### flags: STMT_END_F
+master-bin.000001 1588 Xid 1 1619 COMMIT /* xid=### */
+master-bin.000001 1619 Gtid 1 1661 BEGIN GTID 0-1-13
+master-bin.000001 1661 Annotate_rows 1 1795 DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3
+master-bin.000001 1795 Table_map 1 1844 table_id: ### (test1.t1)
+master-bin.000001 1844 Delete_rows_v1 1 1886 table_id: ### flags: STMT_END_F
+master-bin.000001 1886 Xid 1 1917 COMMIT /* xid=### */
+master-bin.000001 1917 Gtid 1 1959 BEGIN GTID 0-1-15
+master-bin.000001 1959 Annotate_rows 1 2020 INSERT INTO test1.t1 (f1) VALUES (111)
+master-bin.000001 2020 Table_map 1 2069 table_id: ### (test1.t1)
+master-bin.000001 2069 Write_rows_v1 1 2111 table_id: ### flags: STMT_END_F
+master-bin.000001 2111 Annotate_rows 1 2172 INSERT INTO test1.t1 (f1) VALUES (222)
+master-bin.000001 2172 Table_map 1 2221 table_id: ### (test1.t1)
+master-bin.000001 2221 Write_rows_v1 1 2263 table_id: ### flags: STMT_END_F
+master-bin.000001 2263 Xid 1 2294 COMMIT /* xid=### */
+master-bin.000001 2294 Gtid 1 2336 BEGIN GTID <effective_uuid>
+master-bin.000001 2336 Annotate_rows 1 2397 INSERT INTO test1.t1 (f1) VALUES (333)
+master-bin.000001 2397 Table_map 1 2446 table_id: ### (test1.t1)
+master-bin.000001 2446 Write_rows_v1 1 2488 table_id: ### flags: STMT_END_F
+master-bin.000001 2488 Xid 1 2519 COMMIT /* xid=### */
+connection node_3;
+gtid_executed_equal
+0
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 256 Gtid_list 3 285 []
+master-bin.000001 285 Binlog_checkpoint 3 329 master-bin.000001
+master-bin.000001 329 Gtid 1 371 GTID 0-1-1
+master-bin.000001 371 Query 1 458 CREATE SCHEMA test1
+master-bin.000001 458 Gtid 1 500 GTID 0-1-2
+master-bin.000001 500 Query 1 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB
+master-bin.000001 647 Gtid 1 689 BEGIN GTID 0-1-3
+master-bin.000001 689 Annotate_rows 1 748 INSERT INTO test1.t1 (f1) VALUES (1)
+master-bin.000001 748 Table_map 1 797 table_id: ### (test1.t1)
+master-bin.000001 797 Write_rows_v1 1 839 table_id: ### flags: STMT_END_F
+master-bin.000001 839 Xid 1 870 COMMIT /* xid=### */
+master-bin.000001 870 Gtid 1 912 BEGIN GTID 0-1-4
+master-bin.000001 912 Annotate_rows 1 971 INSERT INTO test1.t1 (f1) VALUES (2)
+master-bin.000001 971 Table_map 1 1020 table_id: ### (test1.t1)
+master-bin.000001 1020 Write_rows_v1 1 1062 table_id: ### flags: STMT_END_F
+master-bin.000001 1062 Xid 1 1093 COMMIT /* xid=### */
+master-bin.000001 1093 Gtid 1 1135 BEGIN GTID 0-1-5
+master-bin.000001 1135 Annotate_rows 1 1194 INSERT INTO test1.t1 (f1) VALUES (3)
+master-bin.000001 1194 Table_map 1 1243 table_id: ### (test1.t1)
+master-bin.000001 1243 Write_rows_v1 1 1285 table_id: ### flags: STMT_END_F
+master-bin.000001 1285 Xid 1 1316 COMMIT /* xid=### */
+master-bin.000001 1316 Gtid 1 1358 BEGIN GTID 0-1-6
+master-bin.000001 1358 Annotate_rows 1 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'
+master-bin.000001 1451 Table_map 1 1500 table_id: ### (test1.t1)
+master-bin.000001 1500 Update_rows_v1 1 1588 table_id: ### flags: STMT_END_F
+master-bin.000001 1588 Xid 1 1619 COMMIT /* xid=### */
+master-bin.000001 1619 Gtid 1 1661 BEGIN GTID 0-1-7
+master-bin.000001 1661 Annotate_rows 1 1795 DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3
+master-bin.000001 1795 Table_map 1 1844 table_id: ### (test1.t1)
+master-bin.000001 1844 Delete_rows_v1 1 1886 table_id: ### flags: STMT_END_F
+master-bin.000001 1886 Xid 1 1917 COMMIT /* xid=### */
+master-bin.000001 1917 Gtid 1 1959 BEGIN GTID 0-1-8
+master-bin.000001 1959 Annotate_rows 1 2020 INSERT INTO test1.t1 (f1) VALUES (111)
+master-bin.000001 2020 Table_map 1 2069 table_id: ### (test1.t1)
+master-bin.000001 2069 Write_rows_v1 1 2111 table_id: ### flags: STMT_END_F
+master-bin.000001 2111 Annotate_rows 1 2172 INSERT INTO test1.t1 (f1) VALUES (222)
+master-bin.000001 2172 Table_map 1 2221 table_id: ### (test1.t1)
+master-bin.000001 2221 Write_rows_v1 1 2263 table_id: ### flags: STMT_END_F
+master-bin.000001 2263 Xid 1 2294 COMMIT /* xid=### */
+master-bin.000001 2294 Gtid 1 2336 BEGIN GTID 0-1-9
+master-bin.000001 2336 Annotate_rows 1 2397 INSERT INTO test1.t1 (f1) VALUES (333)
+master-bin.000001 2397 Table_map 1 2446 table_id: ### (test1.t1)
+master-bin.000001 2446 Write_rows_v1 1 2488 table_id: ### flags: STMT_END_F
+master-bin.000001 2488 Xid 1 2519 COMMIT /* xid=### */
+include/diff_servers.inc [servers=2 3]
+connection node_3;
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f1 IN (1,2);
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 3 FROM test1.t1 WHERE f1 IN (111,222,333);
+COUNT(*) = 3
+1
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f2 = 'klm';
+COUNT(*) = 2
+1
+USE test2;
+ERROR 42000: Unknown database 'test2'
+connection node_1;
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+connection node_3;
+connection node_2;
+STOP SLAVE;
+RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result
new file mode 100644
index 00000000000..fc10cc01a45
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result
@@ -0,0 +1,315 @@
+RESET MASTER;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+START SLAVE USER='root';
+Warnings:
+Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+SET SESSION wsrep_on=OFF;
+include/wait_for_slave_sql_error.inc [errno=1047]
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+INSERT INTO test1.t1 (f1) VALUES (5);
+INSERT INTO test2.t1 (f1) VALUES (5);
+SET SESSION wsrep_on=ON;
+INSERT INTO test1.t1 (f1) VALUES (6);
+INSERT INTO test2.t1 (f1) VALUES (6);
+START SLAVE;
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 120 Previous_gtids 2 151
+mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:1'
+mysqld-bin.000001 199 Query 1 294 CREATE SCHEMA test1
+mysqld-bin.000001 294 Gtid 1 342 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:2'
+mysqld-bin.000001 342 Query 1 415 BEGIN
+mysqld-bin.000001 415 Query 1 489 COMMIT
+mysqld-bin.000001 489 Gtid 1 537 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:3'
+mysqld-bin.000001 537 Query 1 655 use `test1`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+mysqld-bin.000001 655 Gtid 1 703 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:4'
+mysqld-bin.000001 703 Query 1 776 BEGIN
+mysqld-bin.000001 776 Query 1 850 COMMIT
+mysqld-bin.000001 850 Gtid 1 898 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:5'
+mysqld-bin.000001 898 Query 1 961 BEGIN
+mysqld-bin.000001 961 Table_map 1 1007 table_id: ### (test1.t1)
+mysqld-bin.000001 1007 Write_rows 1 1047 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1047 Xid 1 1078 COMMIT /* xid=### */
+mysqld-bin.000001 1078 Gtid 1 1126 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:6'
+mysqld-bin.000001 1126 Query 1 1189 BEGIN
+mysqld-bin.000001 1189 Query 1 1253 COMMIT
+mysqld-bin.000001 1253 Gtid 1 1301 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:7'
+mysqld-bin.000001 1301 Query 1 1364 BEGIN
+mysqld-bin.000001 1364 Table_map 1 1410 table_id: ### (test1.t1)
+mysqld-bin.000001 1410 Write_rows 1 1450 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1450 Xid 1 1481 COMMIT /* xid=### */
+mysqld-bin.000001 1481 Gtid 1 1529 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:8'
+mysqld-bin.000001 1529 Query 1 1592 BEGIN
+mysqld-bin.000001 1592 Query 1 1656 COMMIT
+mysqld-bin.000001 1656 Gtid 2 1704 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:12'
+mysqld-bin.000001 1704 Query 2 1772 BEGIN
+mysqld-bin.000001 1772 Ignorable 2 1795 # Unrecognized ignorable event
+mysqld-bin.000001 1795 Query 2 1864 COMMIT
+mysqld-bin.000001 1864 Gtid 2 1912 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:13'
+mysqld-bin.000001 1912 Query 2 1980 BEGIN
+mysqld-bin.000001 1980 Ignorable 2 2003 # Unrecognized ignorable event
+mysqld-bin.000001 2003 Query 2 2072 COMMIT
+mysqld-bin.000001 2072 Gtid 1 2120 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:9'
+mysqld-bin.000001 2120 Query 1 2183 BEGIN
+mysqld-bin.000001 2183 Table_map 1 2229 table_id: ### (test1.t1)
+mysqld-bin.000001 2229 Write_rows 1 2269 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2269 Xid 1 2300 COMMIT /* xid=### */
+mysqld-bin.000001 2300 Gtid 1 2348 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:10'
+mysqld-bin.000001 2348 Query 1 2411 BEGIN
+mysqld-bin.000001 2411 Query 1 2475 COMMIT
+mysqld-bin.000001 2475 Gtid 1 2523 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:11'
+mysqld-bin.000001 2523 Query 1 2586 BEGIN
+mysqld-bin.000001 2586 Table_map 1 2632 table_id: ### (test1.t1)
+mysqld-bin.000001 2632 Write_rows 1 2672 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2672 Xid 1 2703 COMMIT /* xid=### */
+mysqld-bin.000001 2703 Gtid 1 2751 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:12'
+mysqld-bin.000001 2751 Query 1 2814 BEGIN
+mysqld-bin.000001 2814 Query 1 2878 COMMIT
+mysqld-bin.000001 2878 Gtid 1 2926 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:13'
+mysqld-bin.000001 2926 Query 1 2989 BEGIN
+mysqld-bin.000001 2989 Table_map 1 3035 table_id: ### (test1.t1)
+mysqld-bin.000001 3035 Write_rows 1 3075 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3075 Xid 1 3106 COMMIT /* xid=### */
+mysqld-bin.000001 3106 Gtid 1 3154 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:14'
+mysqld-bin.000001 3154 Query 1 3217 BEGIN
+mysqld-bin.000001 3217 Query 1 3281 COMMIT
+mysqld-bin.000001 3281 Gtid 1 3329 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:15'
+mysqld-bin.000001 3329 Query 1 3392 BEGIN
+mysqld-bin.000001 3392 Table_map 1 3438 table_id: ### (test1.t1)
+mysqld-bin.000001 3438 Write_rows 1 3478 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3478 Xid 1 3509 COMMIT /* xid=### */
+mysqld-bin.000001 3509 Gtid 1 3557 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:16'
+mysqld-bin.000001 3557 Query 1 3620 BEGIN
+mysqld-bin.000001 3620 Query 1 3684 COMMIT
+mysqld-bin.000001 3684 Gtid 1 3732 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:17'
+mysqld-bin.000001 3732 Query 1 3795 BEGIN
+mysqld-bin.000001 3795 Table_map 1 3841 table_id: ### (test1.t1)
+mysqld-bin.000001 3841 Write_rows 1 3881 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3881 Xid 1 3912 COMMIT /* xid=### */
+mysqld-bin.000001 3912 Gtid 1 3960 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:18'
+mysqld-bin.000001 3960 Query 1 4023 BEGIN
+mysqld-bin.000001 4023 Query 1 4087 COMMIT
+mysqld-bin.000001 4087 Gtid 1 4135 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:19'
+mysqld-bin.000001 4135 Query 1 4198 BEGIN
+mysqld-bin.000001 4198 Table_map 1 4244 table_id: ### (test1.t1)
+mysqld-bin.000001 4244 Write_rows 1 4284 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4284 Xid 1 4315 COMMIT /* xid=### */
+mysqld-bin.000001 4315 Gtid 1 4363 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:20'
+mysqld-bin.000001 4363 Query 1 4426 BEGIN
+mysqld-bin.000001 4426 Query 1 4490 COMMIT
+mysqld-bin.000001 4490 Gtid 1 4538 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:21'
+mysqld-bin.000001 4538 Query 1 4601 BEGIN
+mysqld-bin.000001 4601 Table_map 1 4647 table_id: ### (test1.t1)
+mysqld-bin.000001 4647 Write_rows 1 4687 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4687 Xid 1 4718 COMMIT /* xid=### */
+mysqld-bin.000001 4718 Gtid 1 4766 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:22'
+mysqld-bin.000001 4766 Query 1 4829 BEGIN
+mysqld-bin.000001 4829 Query 1 4893 COMMIT
+mysqld-bin.000001 4893 Gtid 1 4941 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:23'
+mysqld-bin.000001 4941 Query 1 5004 BEGIN
+mysqld-bin.000001 5004 Table_map 1 5050 table_id: ### (test1.t1)
+mysqld-bin.000001 5050 Write_rows 1 5090 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5090 Xid 1 5121 COMMIT /* xid=### */
+mysqld-bin.000001 5121 Gtid 1 5169 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:24'
+mysqld-bin.000001 5169 Query 1 5232 BEGIN
+mysqld-bin.000001 5232 Query 1 5296 COMMIT
+mysqld-bin.000001 5296 Gtid 1 5344 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:25'
+mysqld-bin.000001 5344 Query 1 5407 BEGIN
+mysqld-bin.000001 5407 Table_map 1 5453 table_id: ### (test1.t1)
+mysqld-bin.000001 5453 Write_rows 1 5493 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5493 Xid 1 5524 COMMIT /* xid=### */
+mysqld-bin.000001 5524 Gtid 1 5572 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:26'
+mysqld-bin.000001 5572 Query 1 5635 BEGIN
+mysqld-bin.000001 5635 Query 1 5699 COMMIT
+mysqld-bin.000001 5699 Gtid 1 5747 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:27'
+mysqld-bin.000001 5747 Query 1 5810 BEGIN
+mysqld-bin.000001 5810 Table_map 1 5856 table_id: ### (test1.t1)
+mysqld-bin.000001 5856 Write_rows 1 5896 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5896 Xid 1 5927 COMMIT /* xid=### */
+mysqld-bin.000001 5927 Gtid 1 5975 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:28'
+mysqld-bin.000001 5975 Query 1 6038 BEGIN
+mysqld-bin.000001 6038 Query 1 6102 COMMIT
+mysqld-bin.000001 6102 Gtid 1 6150 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:29'
+mysqld-bin.000001 6150 Query 1 6213 BEGIN
+mysqld-bin.000001 6213 Table_map 1 6259 table_id: ### (test1.t1)
+mysqld-bin.000001 6259 Write_rows 1 6299 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 6299 Xid 1 6330 COMMIT /* xid=### */
+mysqld-bin.000001 6330 Gtid 1 6378 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:30'
+mysqld-bin.000001 6378 Query 1 6441 BEGIN
+mysqld-bin.000001 6441 Query 1 6505 COMMIT
+USE test2;
+ERROR 42000: Unknown database 'test2'
+gtid_executed_equal
+1
+USE test2;
+ERROR 42000: Unknown database 'test2'
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 120 Previous_gtids 4 151
+mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:1'
+mysqld-bin.000001 199 Query 1 294 CREATE SCHEMA test1
+mysqld-bin.000001 294 Gtid 1 342 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:2'
+mysqld-bin.000001 342 Query 1 415 BEGIN
+mysqld-bin.000001 415 Query 1 489 COMMIT
+mysqld-bin.000001 489 Gtid 1 537 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:3'
+mysqld-bin.000001 537 Query 1 655 use `test1`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+mysqld-bin.000001 655 Gtid 1 703 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:4'
+mysqld-bin.000001 703 Query 1 776 BEGIN
+mysqld-bin.000001 776 Query 1 850 COMMIT
+mysqld-bin.000001 850 Gtid 1 898 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:5'
+mysqld-bin.000001 898 Query 1 961 BEGIN
+mysqld-bin.000001 961 Table_map 1 1007 table_id: ### (test1.t1)
+mysqld-bin.000001 1007 Write_rows 1 1047 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1047 Xid 1 1078 COMMIT /* xid=### */
+mysqld-bin.000001 1078 Gtid 1 1126 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:6'
+mysqld-bin.000001 1126 Query 1 1189 BEGIN
+mysqld-bin.000001 1189 Query 1 1253 COMMIT
+mysqld-bin.000001 1253 Gtid 1 1301 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:7'
+mysqld-bin.000001 1301 Query 1 1364 BEGIN
+mysqld-bin.000001 1364 Table_map 1 1410 table_id: ### (test1.t1)
+mysqld-bin.000001 1410 Write_rows 1 1450 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 1450 Xid 1 1481 COMMIT /* xid=### */
+mysqld-bin.000001 1481 Gtid 1 1529 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:8'
+mysqld-bin.000001 1529 Query 1 1592 BEGIN
+mysqld-bin.000001 1592 Query 1 1656 COMMIT
+mysqld-bin.000001 1656 Gtid 4 1704 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:12'
+mysqld-bin.000001 1704 Query 4 1772 BEGIN
+mysqld-bin.000001 1772 Ignorable 4 1795 # Unrecognized ignorable event
+mysqld-bin.000001 1795 Query 4 1864 COMMIT
+mysqld-bin.000001 1864 Gtid 4 1912 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:13'
+mysqld-bin.000001 1912 Query 4 1980 BEGIN
+mysqld-bin.000001 1980 Ignorable 4 2003 # Unrecognized ignorable event
+mysqld-bin.000001 2003 Query 4 2072 COMMIT
+mysqld-bin.000001 2072 Gtid 1 2120 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:9'
+mysqld-bin.000001 2120 Query 1 2183 BEGIN
+mysqld-bin.000001 2183 Table_map 1 2229 table_id: ### (test1.t1)
+mysqld-bin.000001 2229 Write_rows 1 2269 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2269 Xid 1 2300 COMMIT /* xid=### */
+mysqld-bin.000001 2300 Gtid 1 2348 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:10'
+mysqld-bin.000001 2348 Query 1 2411 BEGIN
+mysqld-bin.000001 2411 Query 1 2475 COMMIT
+mysqld-bin.000001 2475 Gtid 1 2523 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:11'
+mysqld-bin.000001 2523 Query 1 2586 BEGIN
+mysqld-bin.000001 2586 Table_map 1 2632 table_id: ### (test1.t1)
+mysqld-bin.000001 2632 Write_rows 1 2672 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 2672 Xid 1 2703 COMMIT /* xid=### */
+mysqld-bin.000001 2703 Gtid 1 2751 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:12'
+mysqld-bin.000001 2751 Query 1 2814 BEGIN
+mysqld-bin.000001 2814 Query 1 2878 COMMIT
+mysqld-bin.000001 2878 Gtid 1 2926 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:13'
+mysqld-bin.000001 2926 Query 1 2989 BEGIN
+mysqld-bin.000001 2989 Table_map 1 3035 table_id: ### (test1.t1)
+mysqld-bin.000001 3035 Write_rows 1 3075 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3075 Xid 1 3106 COMMIT /* xid=### */
+mysqld-bin.000001 3106 Gtid 1 3154 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:14'
+mysqld-bin.000001 3154 Query 1 3217 BEGIN
+mysqld-bin.000001 3217 Query 1 3281 COMMIT
+mysqld-bin.000001 3281 Gtid 1 3329 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:15'
+mysqld-bin.000001 3329 Query 1 3392 BEGIN
+mysqld-bin.000001 3392 Table_map 1 3438 table_id: ### (test1.t1)
+mysqld-bin.000001 3438 Write_rows 1 3478 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3478 Xid 1 3509 COMMIT /* xid=### */
+mysqld-bin.000001 3509 Gtid 1 3557 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:16'
+mysqld-bin.000001 3557 Query 1 3620 BEGIN
+mysqld-bin.000001 3620 Query 1 3684 COMMIT
+mysqld-bin.000001 3684 Gtid 1 3732 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:17'
+mysqld-bin.000001 3732 Query 1 3795 BEGIN
+mysqld-bin.000001 3795 Table_map 1 3841 table_id: ### (test1.t1)
+mysqld-bin.000001 3841 Write_rows 1 3881 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 3881 Xid 1 3912 COMMIT /* xid=### */
+mysqld-bin.000001 3912 Gtid 1 3960 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:18'
+mysqld-bin.000001 3960 Query 1 4023 BEGIN
+mysqld-bin.000001 4023 Query 1 4087 COMMIT
+mysqld-bin.000001 4087 Gtid 1 4135 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:19'
+mysqld-bin.000001 4135 Query 1 4198 BEGIN
+mysqld-bin.000001 4198 Table_map 1 4244 table_id: ### (test1.t1)
+mysqld-bin.000001 4244 Write_rows 1 4284 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4284 Xid 1 4315 COMMIT /* xid=### */
+mysqld-bin.000001 4315 Gtid 1 4363 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:20'
+mysqld-bin.000001 4363 Query 1 4426 BEGIN
+mysqld-bin.000001 4426 Query 1 4490 COMMIT
+mysqld-bin.000001 4490 Gtid 1 4538 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:21'
+mysqld-bin.000001 4538 Query 1 4601 BEGIN
+mysqld-bin.000001 4601 Table_map 1 4647 table_id: ### (test1.t1)
+mysqld-bin.000001 4647 Write_rows 1 4687 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 4687 Xid 1 4718 COMMIT /* xid=### */
+mysqld-bin.000001 4718 Gtid 1 4766 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:22'
+mysqld-bin.000001 4766 Query 1 4829 BEGIN
+mysqld-bin.000001 4829 Query 1 4893 COMMIT
+mysqld-bin.000001 4893 Gtid 1 4941 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:23'
+mysqld-bin.000001 4941 Query 1 5004 BEGIN
+mysqld-bin.000001 5004 Table_map 1 5050 table_id: ### (test1.t1)
+mysqld-bin.000001 5050 Write_rows 1 5090 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5090 Xid 1 5121 COMMIT /* xid=### */
+mysqld-bin.000001 5121 Gtid 1 5169 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:24'
+mysqld-bin.000001 5169 Query 1 5232 BEGIN
+mysqld-bin.000001 5232 Query 1 5296 COMMIT
+mysqld-bin.000001 5296 Gtid 1 5344 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:25'
+mysqld-bin.000001 5344 Query 1 5407 BEGIN
+mysqld-bin.000001 5407 Table_map 1 5453 table_id: ### (test1.t1)
+mysqld-bin.000001 5453 Write_rows 1 5493 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5493 Xid 1 5524 COMMIT /* xid=### */
+mysqld-bin.000001 5524 Gtid 1 5572 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:26'
+mysqld-bin.000001 5572 Query 1 5635 BEGIN
+mysqld-bin.000001 5635 Query 1 5699 COMMIT
+mysqld-bin.000001 5699 Gtid 1 5747 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:27'
+mysqld-bin.000001 5747 Query 1 5810 BEGIN
+mysqld-bin.000001 5810 Table_map 1 5856 table_id: ### (test1.t1)
+mysqld-bin.000001 5856 Write_rows 1 5896 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 5896 Xid 1 5927 COMMIT /* xid=### */
+mysqld-bin.000001 5927 Gtid 1 5975 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:28'
+mysqld-bin.000001 5975 Query 1 6038 BEGIN
+mysqld-bin.000001 6038 Query 1 6102 COMMIT
+mysqld-bin.000001 6102 Gtid 1 6150 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:29'
+mysqld-bin.000001 6150 Query 1 6213 BEGIN
+mysqld-bin.000001 6213 Table_map 1 6259 table_id: ### (test1.t1)
+mysqld-bin.000001 6259 Write_rows 1 6299 table_id: ### flags: STMT_END_F
+mysqld-bin.000001 6299 Xid 1 6330 COMMIT /* xid=### */
+mysqld-bin.000001 6330 Gtid 1 6378 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:30'
+mysqld-bin.000001 6378 Query 1 6441 BEGIN
+mysqld-bin.000001 6441 Query 1 6505 COMMIT
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+STOP SLAVE;
+RESET SLAVE ALL;
+CALL mtr.add_suppression("GTID replication failed");
+CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed");
+CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
+CALL mtr.add_suppression("TO isolation failed for");
+CALL mtr.add_suppression("Slave SQL: Error 'Deadlock found when trying to get lock; try restarting transaction' on query");
+CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query");
+CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047");
diff --git a/mysql-test/suite/galera/r/galera_as_slave_nonprim.result b/mysql-test/suite/galera/r/galera_as_slave_nonprim.result
index 365ea31f292..6baf930aed2 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_nonprim.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_nonprim.result
@@ -1,13 +1,28 @@
+connection node_2;
+connection node_1;
+connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4;
+connection node_2;
START SLAVE;
SET SESSION wsrep_sync_wait = 0;
+connection node_4;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+connection node_1;
+connection node_4;
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+connection node_2;
+connection node_1;
expected_error
1
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_1;
+connection node_2;
START SLAVE;
+connection node_4;
DROP TABLE t1;
+connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
CALL mtr.add_suppression("Slave SQL: Error 'Unknown command' on query");
@@ -15,4 +30,7 @@ CALL mtr.add_suppression("Slave: Unknown command Error_code: 1047");
CALL mtr.add_suppression("Transport endpoint is not connected");
CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed, 'Deadlock found when trying to get lock; try restarting transaction', Error_code: 1213");
CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
+connection node_4;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result
index d0fac1e3d14..0d6a6ebbbc1 100644
--- a/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result
+++ b/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
CREATE PROCEDURE p1 ()
diff --git a/mysql-test/suite/galera/r/galera_bf_abort.result b/mysql-test/suite/galera/r/galera_bf_abort.result
index c2e89965fce..cb4a27c82fd 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(6)) ENGINE=InnoDB;
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
@@ -9,7 +11,7 @@ INSERT INTO t1 VALUES (1,'node_1');
connection node_2a;
connection node_2;
INSERT INTO t1 VALUES (2, 'node_2');
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result b/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result
index 7b98c807efb..1150a9fff63 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_for_update.result b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result
index ec8bddb087a..7dd3053b7bb 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_for_update.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, 10);
connection node_1;
@@ -10,7 +12,7 @@ UPDATE t1 SET f1 = 2;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_bf_aborts_diff
1
connection node_1;
@@ -23,7 +25,7 @@ UPDATE t1 SET f2 = 20;
connection node_1a;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_bf_aborts_diff
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result
index ae1ca6d2157..43ca6089d78 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result
index 8c6c7b7d7a4..0ef2a1a72c6 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2a;
SELECT GET_LOCK("foo", 1000);
@@ -10,7 +12,7 @@ SELECT GET_LOCK("foo", 1000);;
connection node_1;
INSERT INTO t1 VALUES (1);
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result b/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result
new file mode 100644
index 00000000000..52d44c3d510
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result
@@ -0,0 +1,685 @@
+SET SESSION wsrep_sync_wait = 0;
+galera_sr_bf_abort_at_commit = 0
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+galera_sr_bf_abort_at_commit = 1
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+galera_sr_bf_abort_at_commit = 1
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 0;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result
index 81b5816ddbe..e7882e43b6a 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result
new file mode 100644
index 00000000000..6f67d9ce4cc
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result
@@ -0,0 +1,9 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+connection node_2;
+SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue';
+INSERT INTO t1 VALUES (1);
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_abort_sleep.result b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result
index 9cd6abad5a1..00d6600d264 100644
--- a/mysql-test/suite/galera/r/galera_bf_abort_sleep.result
+++ b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET AUTOCOMMIT=OFF;
@@ -6,7 +8,7 @@ SELECT SLEEP(1000);;
connection node_1;
INSERT INTO t1 VALUES (1);
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
wsrep_local_aborts_increment
1
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result
index 7ec524da888..f893848a72d 100644
--- a/mysql-test/suite/galera/r/galera_bf_lock_wait.result
+++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
ALTER TABLE t1 add primary key(a);
CREATE PROCEDURE p1()
diff --git a/mysql-test/suite/galera/r/galera_binlog_cache_size.result b/mysql-test/suite/galera/r/galera_binlog_cache_size.result
index 6aac74ab5f0..c5a09074537 100644
--- a/mysql-test/suite/galera/r/galera_binlog_cache_size.result
+++ b/mysql-test/suite/galera/r/galera_binlog_cache_size.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(767)) ENGINE=InnoDB;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_binlog_checksum.result b/mysql-test/suite/galera/r/galera_binlog_checksum.result
index 7303aa61122..3ef7cf5c41e 100644
--- a/mysql-test/suite/galera/r/galera_binlog_checksum.result
+++ b/mysql-test/suite/galera/r/galera_binlog_checksum.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result
index 46582ff5c4b..b513c491bb0 100644
--- a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result
+++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 VARCHAR(1000));
diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result
index 7b88af5d5af..6c2279bece0 100644
--- a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result
+++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(1000));
INSERT INTO t1 VALUES (REPEAT('x', 1000));
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_binlog_row_image.result b/mysql-test/suite/galera/r/galera_binlog_row_image.result
index d54db61105e..20e6bd9fab8 100644
--- a/mysql-test/suite/galera/r/galera_binlog_row_image.result
+++ b/mysql-test/suite/galera/r/galera_binlog_row_image.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION binlog_row_image=minimal;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_create_function.result b/mysql-test/suite/galera/r/galera_create_function.result
index 9118c2864f3..85fa85d81f1 100644
--- a/mysql-test/suite/galera/r/galera_create_function.result
+++ b/mysql-test/suite/galera/r/galera_create_function.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE USER 'user1';
CREATE
diff --git a/mysql-test/suite/galera/r/galera_create_procedure.result b/mysql-test/suite/galera/r/galera_create_procedure.result
index 98dc4a856dc..24a0bd66b39 100644
--- a/mysql-test/suite/galera/r/galera_create_procedure.result
+++ b/mysql-test/suite/galera/r/galera_create_procedure.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE USER 'user1';
CREATE TABLE t1 (f1 INTEGER);
diff --git a/mysql-test/suite/galera/r/galera_create_table_as_select.result b/mysql-test/suite/galera/r/galera_create_table_as_select.result
new file mode 100644
index 00000000000..6f65ee99f0a
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_create_table_as_select.result
@@ -0,0 +1,103 @@
+connection node_2;
+connection node_1;
+connection node_1;
+SET SESSION default_storage_engine=InnoDB;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t1 AS SELECT * FROM t2;
+ERROR 42S01: Table 't1' already exists
+DROP TABLE t1,t2;
+CREATE TABLE t1 AS SELECT * FROM t2;
+ERROR 42S02: Table 'test.t2' doesn't exist
+CREATE TABLE t1 AS SELECT 1 FROM DUAL;
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+connection node_1;
+DROP TABLE t1;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t1 AS SELECT * FROM t2;
+connection node_2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+connection node_1;
+DROP TABLE t1,t2;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT * FROM t2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_1;
+DROP TABLE t1,t2;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT MAX(f1) AS f1 FROM t2;
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT f1 = 5 FROM t1;
+f1 = 5
+1
+connection node_1;
+DROP TABLE t1,t2;
+connection node_1;
+CREATE PROCEDURE sp1 ()
+BEGIN
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT * FROM t2;
+END|
+CALL sp1();
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+connection node_1;
+DROP TABLE t1, t2;
+DROP PROCEDURE sp1;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT * FROM t2';
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
+connection node_1;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+LOCK TABLE t2 WRITE;
+connection node_1;
+CREATE TABLE t1 AS SELECT * FROM t2;;
+connection node_2;
+SELECT COUNT(*) = 5 FROM t2;
+COUNT(*) = 5
+1
+CREATE TABLE t1 AS SELECT * FROM t2;
+connection node_1a;
+UNLOCK TABLES;
+connection node_1;
+Got one of the listed errors
+DROP TABLE t1, t2;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TEMPORARY TABLE t1 AS SELECT * FROM t2;
+connection node_2;
+SELECT * FROM t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query");
+connection node_1;
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera/r/galera_create_table_like.result b/mysql-test/suite/galera/r/galera_create_table_like.result
index 131ac311bca..82543331ad5 100644
--- a/mysql-test/suite/galera/r/galera_create_table_like.result
+++ b/mysql-test/suite/galera/r/galera_create_table_like.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE SCHEMA schema1;
CREATE SCHEMA schema2;
USE schema1;
diff --git a/mysql-test/suite/galera/r/galera_create_trigger.result b/mysql-test/suite/galera/r/galera_create_trigger.result
index d07a007543e..56b35150d87 100644
--- a/mysql-test/suite/galera/r/galera_create_trigger.result
+++ b/mysql-test/suite/galera/r/galera_create_trigger.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE definer_root (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB;
CREATE TABLE definer_user (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB;
CREATE TABLE definer_current_user (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_ddl_multiline.result b/mysql-test/suite/galera/r/galera_ddl_multiline.result
index 339a91125eb..9e70731a62b 100644
--- a/mysql-test/suite/galera/r/galera_ddl_multiline.result
+++ b/mysql-test/suite/galera/r/galera_ddl_multiline.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result
index 5c5fdabf432..381b334908e 100644
--- a/mysql-test/suite/galera/r/galera_defaults.result
+++ b/mysql-test/suite/galera/r/galera_defaults.result
@@ -1,6 +1,12 @@
-SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
-COUNT(*) = 43
-0
+connection node_2;
+connection node_1;
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '4.dev(r3810)'
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '4.dev(r3810)'
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
+COUNT(*)
+48
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME LIKE 'wsrep_%'
@@ -31,6 +37,7 @@ WSREP_DRUPAL_282555_WORKAROUND OFF
WSREP_FORCED_BINLOG_FORMAT NONE
WSREP_GTID_DOMAIN_ID 0
WSREP_GTID_MODE OFF
+WSREP_IGNORE_APPLY_ERRORS 7
WSREP_LOAD_DATA_SPLITTING ON
WSREP_LOG_CONFLICTS OFF
WSREP_MAX_WS_ROWS 0
@@ -47,17 +54,20 @@ WSREP_RETRY_AUTOCOMMIT 1
WSREP_SLAVE_FK_CHECKS ON
WSREP_SLAVE_THREADS 1
WSREP_SLAVE_UK_CHECKS OFF
+WSREP_SR_STORE table
WSREP_SST_AUTH
WSREP_SST_DONOR
WSREP_SST_DONOR_REJECTS_QUERIES OFF
WSREP_SST_METHOD rsync
WSREP_SYNC_WAIT 15
-<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = no; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>;socket.checksum = 2; socket.recv_buf_size = 212992;
+WSREP_TRX_FRAGMENT_SIZE 0
+WSREP_TRX_FRAGMENT_UNIT bytes
+<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 1; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = yes; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>; socket.checksum = 2; socket.recv_buf_size = 212992;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS
WHERE VARIABLE_NAME LIKE 'wsrep_%'
AND VARIABLE_NAME != 'wsrep_debug_sync_waiters';
COUNT(*)
-58
+63
SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_STATUS
WHERE VARIABLE_NAME LIKE 'wsrep_%'
AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'
@@ -70,10 +80,12 @@ WSREP_CAUSAL_READS
WSREP_CERT_DEPS_DISTANCE
WSREP_CERT_INDEX_SIZE
WSREP_CERT_INTERVAL
+WSREP_CLUSTER_CAPABILITIES
WSREP_CLUSTER_CONF_ID
WSREP_CLUSTER_SIZE
WSREP_CLUSTER_STATE_UUID
WSREP_CLUSTER_STATUS
+WSREP_CLUSTER_WEIGHT
WSREP_COMMIT_OOOE
WSREP_COMMIT_OOOL
WSREP_COMMIT_WINDOW
@@ -107,7 +119,10 @@ WSREP_LOCAL_SEND_QUEUE_MIN
WSREP_LOCAL_STATE
WSREP_LOCAL_STATE_COMMENT
WSREP_LOCAL_STATE_UUID
+WSREP_OPEN_CONNECTIONS
+WSREP_OPEN_TRANSACTIONS
WSREP_PROTOCOL_VERSION
+WSREP_PROVIDER_CAPABILITIES
WSREP_PROVIDER_NAME
WSREP_PROVIDER_VENDOR
WSREP_PROVIDER_VERSION
diff --git a/mysql-test/suite/galera/r/galera_delete_limit.result b/mysql-test/suite/galera/r/galera_delete_limit.result
index f6fb2e56346..9898bfcf169 100644
--- a/mysql-test/suite/galera/r/galera_delete_limit.result
+++ b/mysql-test/suite/galera/r/galera_delete_limit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) Engine=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_desync_overlapped.result b/mysql-test/suite/galera/r/galera_desync_overlapped.result
index f9920e7f7ad..e3f40d444ee 100644
--- a/mysql-test/suite/galera/r/galera_desync_overlapped.result
+++ b/mysql-test/suite/galera/r/galera_desync_overlapped.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_drop_multi.result b/mysql-test/suite/galera/r/galera_drop_multi.result
index 7793ef93b90..1ff8afe3219 100644
--- a/mysql-test/suite/galera/r/galera_drop_multi.result
+++ b/mysql-test/suite/galera/r/galera_drop_multi.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_enum.result b/mysql-test/suite/galera/r/galera_enum.result
index dcf31aa5948..92b72fc69c0 100644
--- a/mysql-test/suite/galera/r/galera_enum.result
+++ b/mysql-test/suite/galera/r/galera_enum.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 ENUM('', 'one', 'two'), KEY (f1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES ('');
@@ -38,7 +40,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1;
SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three';
COUNT(*) = 1
diff --git a/mysql-test/suite/galera/r/galera_events.result b/mysql-test/suite/galera/r/galera_events.result
index f01627aba70..791b0be729d 100644
--- a/mysql-test/suite/galera/r/galera_events.result
+++ b/mysql-test/suite/galera/r/galera_events.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE EVENT event1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO SELECT 1;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result
index 73375ae55c5..291d641db88 100644
--- a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result
+++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE grandparent (
id INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_update.result b/mysql-test/suite/galera/r/galera_fk_cascade_update.result
index 5fe8b532473..5294826a8f9 100644
--- a/mysql-test/suite/galera/r/galera_fk_cascade_update.result
+++ b/mysql-test/suite/galera/r/galera_fk_cascade_update.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE grandparent (
id INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_fk_conflict.result b/mysql-test/suite/galera/r/galera_fk_conflict.result
index a08aa30a82e..f9f151abce4 100644
--- a/mysql-test/suite/galera/r/galera_fk_conflict.result
+++ b/mysql-test/suite/galera/r/galera_fk_conflict.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT PRIMARY KEY,
KEY (id)
@@ -22,6 +24,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE child;
DROP TABLE parent;
diff --git a/mysql-test/suite/galera/r/galera_fk_mismatch.result b/mysql-test/suite/galera/r/galera_fk_mismatch.result
index bdc60c9e099..a030b1214c5 100644
--- a/mysql-test/suite/galera/r/galera_fk_mismatch.result
+++ b/mysql-test/suite/galera/r/galera_fk_mismatch.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id1 INT,
id2 INT,
diff --git a/mysql-test/suite/galera/r/galera_fk_multicolumn.result b/mysql-test/suite/galera/r/galera_fk_multicolumn.result
index f5b6aa23692..b626d963af8 100644
--- a/mysql-test/suite/galera/r/galera_fk_multicolumn.result
+++ b/mysql-test/suite/galera/r/galera_fk_multicolumn.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t0 (
f1 INT PRIMARY KEY,
f2 INT UNIQUE
diff --git a/mysql-test/suite/galera/r/galera_fk_multitable.result b/mysql-test/suite/galera/r/galera_fk_multitable.result
index 04ff7adc3e9..83e1491ab34 100644
--- a/mysql-test/suite/galera/r/galera_fk_multitable.result
+++ b/mysql-test/suite/galera/r/galera_fk_multitable.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t0 (
f0 INT PRIMARY KEY
);
diff --git a/mysql-test/suite/galera/r/galera_fk_no_pk.result b/mysql-test/suite/galera/r/galera_fk_no_pk.result
index e7b5f0b2b64..622e63dbb8f 100644
--- a/mysql-test/suite/galera/r/galera_fk_no_pk.result
+++ b/mysql-test/suite/galera/r/galera_fk_no_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT,
KEY (id)
diff --git a/mysql-test/suite/galera/r/galera_fk_selfreferential.result b/mysql-test/suite/galera/r/galera_fk_selfreferential.result
index 3b4dbf2a8e9..9a64521e7b8 100644
--- a/mysql-test/suite/galera/r/galera_fk_selfreferential.result
+++ b/mysql-test/suite/galera/r/galera_fk_selfreferential.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 INT NOT NULL PRIMARY KEY,
f2 INT,
diff --git a/mysql-test/suite/galera/r/galera_fk_setnull.result b/mysql-test/suite/galera/r/galera_fk_setnull.result
index d4f20fe60a3..afb3fc3b9b8 100644
--- a/mysql-test/suite/galera/r/galera_fk_setnull.result
+++ b/mysql-test/suite/galera/r/galera_fk_setnull.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
diff --git a/mysql-test/suite/galera/r/galera_flush_local.result b/mysql-test/suite/galera/r/galera_flush_local.result
index a8e798a693d..123b8098727 100644
--- a/mysql-test/suite/galera/r/galera_flush_local.result
+++ b/mysql-test/suite/galera/r/galera_flush_local.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
DROP TABLE IF EXISTS t1, t2, x1, x2;
connection node_1;
CREATE TABLE t1 (f1 INTEGER);
diff --git a/mysql-test/suite/galera/r/galera_forced_binlog_format.result b/mysql-test/suite/galera/r/galera_forced_binlog_format.result
index b94e6530886..a94ac0c112d 100644
--- a/mysql-test/suite/galera/r/galera_forced_binlog_format.result
+++ b/mysql-test/suite/galera/r/galera_forced_binlog_format.result
@@ -1,5 +1,10 @@
+connection node_2;
connection node_1;
+connection node_1;
+SEt GLOBAL wsrep_on=OFF;
RESET MASTER;
+SEt GLOBAL wsrep_on=ON;
+FLUSH BINARY LOGS;
SET SESSION binlog_format = 'STATEMENT';
Warnings:
Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT
@@ -13,18 +18,7 @@ SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256;
Log_name Pos Event_type Server_id End_log_pos Info
mysqld-bin.000001 <Pos> Gtid_list 1 <End_log_pos> []
mysqld-bin.000001 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001
-mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1
-mysqld-bin.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB
-mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2
-mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1)
-mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
-mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
-mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
-mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3
-mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (2)
-mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
-mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F
-mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000001 <Pos> Rotate 1 <End_log_pos> mysqld-bin.000002;pos=4
DROP TABLE t1;
#
# MDEV-9401: wsrep_forced_binlog_format with binlog causes crash
@@ -43,6 +37,4 @@ GRANT ALL PRIVILEGES ON `testdb_9401`.`t1` TO 'dummy'@'localhost'
REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
DROP USER dummy@localhost;
DROP DATABASE testdb_9401;
-disconnect node_2;
-disconnect node_1;
# End of tests
diff --git a/mysql-test/suite/galera/r/galera_ftwrl.result b/mysql-test/suite/galera/r/galera_ftwrl.result
index 0565781c051..eae8028a7f4 100644
--- a/mysql-test/suite/galera/r/galera_ftwrl.result
+++ b/mysql-test/suite/galera/r/galera_ftwrl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S";
diff --git a/mysql-test/suite/galera/r/galera_ftwrl_drain.result b/mysql-test/suite/galera/r/galera_ftwrl_drain.result
index 751811b88fd..1e1dc65da3e 100644
--- a/mysql-test/suite/galera/r/galera_ftwrl_drain.result
+++ b/mysql-test/suite/galera/r/galera_ftwrl_drain.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_fulltext.result b/mysql-test/suite/galera/r/galera_fulltext.result
index 18e3bff40fc..a22296278fa 100644
--- a/mysql-test/suite/galera/r/galera_fulltext.result
+++ b/mysql-test/suite/galera/r/galera_fulltext.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result b/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result
index 30ee5772411..45c426dfdf1 100644
--- a/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result
+++ b/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result
@@ -15,5 +15,5 @@ Using --wsrep-start-position when starting mysqld ...
include/diff_servers.inc [servers=1 2]
DROP TABLE t1;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-include/assert_grep.inc [IST first seqno 2 not found from cache, falling back to SST]
+include/assert_grep.inc [IST first seqno [24] not found from cache, falling back to SST]
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
diff --git a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result
index 464a8b7ea97..83eaa0fb7aa 100644
--- a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result
+++ b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result
index ce74f3db433..b97be5733ff 100644
--- a/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result
+++ b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_gra_log.result b/mysql-test/suite/galera/r/galera_gra_log.result
index 777eda42046..33853188965 100644
--- a/mysql-test/suite/galera/r/galera_gra_log.result
+++ b/mysql-test/suite/galera/r/galera_gra_log.result
@@ -1,4 +1,6 @@
connection node_2;
+connection node_1;
+connection node_2;
SET SESSION wsrep_on=OFF;
CREATE TABLE t1 (f1 INTEGER);
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_gtid.result b/mysql-test/suite/galera/r/galera_gtid.result
index acc5eae9876..f27e2590898 100644
--- a/mysql-test/suite/galera/r/galera_gtid.result
+++ b/mysql-test/suite/galera/r/galera_gtid.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY);
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_gtid_slave.result b/mysql-test/suite/galera/r/galera_gtid_slave.result
index f8ca6322d22..4f207659316 100644
--- a/mysql-test/suite/galera/r/galera_gtid_slave.result
+++ b/mysql-test/suite/galera/r/galera_gtid_slave.result
@@ -1,5 +1,7 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
+connection node_1;
+connection node_2;
START SLAVE;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
@@ -25,13 +27,18 @@ SELECT @@global.gtid_binlog_state;
1-1-4,2-2-2,2-3-3
connection node_1;
DROP TABLE t1,t2;
+SET GLOBAL wsrep_on=OFF;
+reset master;
+SET GLOBAL wsrep_on=ON;
connection node_2;
connection node_3;
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
+SET GLOBAL wsrep_on=OFF;
reset master;
+SET GLOBAL wsrep_on=ON;
connection node_3;
+SET GLOBAL wsrep_on=OFF;
reset master;
-connection node_1;
-reset master;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result b/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result
index cdf330643c2..e8b4a4665c5 100644
--- a/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result
+++ b/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result
@@ -1,38 +1,40 @@
-connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2;
+connection node_1;
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
#Connection 2
connection node_2;
START SLAVE;
-#Connection 1
-connection node_1;
+#Connection 3
+connection node_3;
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB;
INSERT INTO t2 VALUES(1,11);
INSERT INTO t2 VALUES(2,22);
INSERT INTO t2 VALUES(3,33);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4
+2-1-4
include/save_master_gtid.inc
#Connection 2
connection node_2;
include/sync_with_master_gtid.inc
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4
+2-1-4
INSERT INTO t2 VALUES(4,44);
INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4,2-2-3
-#Connection 3
-connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+0-2-3,2-1-4
+#Connection 1
+connection node_1;
INSERT INTO t2 VALUES(7,77);
INSERT INTO t2 VALUES(8,88);
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-4,2-2-3,2-3-5
-#Connection 1
-connection node_1;
+1-3-2,2-1-4,2-2-7
+#Connection 3
+connection node_3;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -48,76 +50,78 @@ START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
-#Connection 3
-connection node_3;
+#Connection 1
+connection node_1;
+connection node_1;
connection node_2;
-connection node_3;
-Shutting down server ...
#Connection 2
connection node_2;
+Shutting down server ...
+#Connection 1
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
-#Connection 3
-connection node_3;
+#Connection 2
+connection node_2;
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES ('node3_committed_after');
-INSERT INTO t1 VALUES ('node3_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
-#Connection 2
-connection node_2;
+#Connection 1
+connection node_1;
Select * from t1 order by f1;
f1
node1_committed_before
node1_committed_before
node1_committed_during
node1_committed_during
+node2_committed_after
+node2_committed_after
node2_committed_before
node2_committed_before
-node3_committed_after
-node3_committed_after
-#Connection 3
-connection node_3;
+#Connection 2
+connection node_2;
Select * from t1 order by f1;
f1
node1_committed_before
node1_committed_before
node1_committed_during
node1_committed_during
+node2_committed_after
+node2_committed_after
node2_committed_before
node2_committed_before
-node3_committed_after
-node3_committed_after
+#Connection 1
+connection node_1;
+SELECT @@global.gtid_binlog_state;
+@@global.gtid_binlog_state
+1-3-3,2-1-6,2-2-9
#Connection 2
connection node_2;
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-6,2-2-7,2-3-8
+0-3-7,0-2-8,2-1-6
#Connection 3
connection node_3;
-SELECT @@global.gtid_binlog_state;
-@@global.gtid_binlog_state
-1-1-6,2-2-7,2-3-8
-#Connection 1
-connection node_1;
SET AUTOCOMMIT=ON;
#Connection 2
connection node_2;
SET AUTOCOMMIT=ON;
-#Connection 3
-connection node_3;
+#Connection 1
+connection node_1;
SET AUTOCOMMIT=ON;
#Connection 2
connection node_2;
STOP slave;
INSERT INTO t1 VALUES ('node2_slave_stoped');
-#Connection 1
-connection node_1;
-INSERT INTO t1 VALUES ('node1_normal_entry');
+#Connection 3
+connection node_3;
+INSERT INTO t1 VALUES ('node3_normal_entry');
include/save_master_gtid.inc
#Connection 2
connection node_2;
@@ -130,30 +134,34 @@ count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-7,2-3-8,2-2-11
-#Connection 3
-connection node_3;
+0-3-7,0-2-11,2-1-7
+#Connection 1
+connection node_1;
SELECT count(*) from t1;
count(*)
12
SELECT @@global.gtid_binlog_state;
@@global.gtid_binlog_state
-1-1-7,2-3-8,2-2-11
-#Connection 1
-connection node_1;
+1-3-3,2-1-7,2-2-12
+#Connection 3
+connection node_3;
DROP TABLE t2,t1;
#Connection 2
connection node_2;
-#Connection 3
-connection node_3;
+#Connection 1
+connection node_1;
#Connection 2
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
+set global wsrep_on=OFF;
reset master;
-#Connection 3
-connection node_3;
-reset master;
+set global wsrep_on=ON;
#Connection 1
connection node_1;
+set global wsrep_on=OFF;
+reset master;
+set global wsrep_on=ON;
+#Connection 3
+connection node_3;
reset master;
diff --git a/mysql-test/suite/galera/r/galera_insert_ignore.result b/mysql-test/suite/galera/r/galera_insert_ignore.result
index 7057affaa0e..417524240e7 100644
--- a/mysql-test/suite/galera/r/galera_insert_ignore.result
+++ b/mysql-test/suite/galera/r/galera_insert_ignore.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_sync_wait = 15;
connection node_2;
SET GLOBAL wsrep_sync_wait = 15;
diff --git a/mysql-test/suite/galera/r/galera_insert_multi.result b/mysql-test/suite/galera/r/galera_insert_multi.result
index 913dd42403a..d7a4f01873e 100644
--- a/mysql-test/suite/galera/r/galera_insert_multi.result
+++ b/mysql-test/suite/galera/r/galera_insert_multi.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
@@ -51,7 +53,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
INSERT INTO t1 VALUES (1), (2);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
diff --git a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
index 5421b234ee1..cad00aaee48 100644
--- a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
+++ b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result
@@ -1,4 +1,7 @@
+connection node_2;
+connection node_1;
Performing State Transfer on a server that has been killed and restarted
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -8,6 +11,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -17,6 +21,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Killing server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -31,6 +36,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -38,6 +44,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Performing --wsrep-recover ...
Starting server ...
Using --wsrep-start-position when starting mysqld ...
@@ -49,6 +56,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -63,6 +71,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_kill_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -77,6 +86,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -88,6 +98,7 @@ COMMIT;
SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been killed and restarted
while a DDL was in progress on it
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -96,6 +107,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -103,10 +115,13 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
-SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+connection node_2;
SET wsrep_sync_wait = 0;
Killing server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 (f1) VALUES ('node1_committed_during');
@@ -121,6 +136,7 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
@@ -128,7 +144,9 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Performing --wsrep-recover ...
+connection node_2;
Starting server ...
Using --wsrep-start-position when starting mysqld ...
SET AUTOCOMMIT=OFF;
@@ -139,6 +157,7 @@ INSERT INTO t1 (f1) VALUES ('node2_committed_after');
INSERT INTO t1 (f1) VALUES ('node2_committed_after');
INSERT INTO t1 (f1) VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
@@ -153,6 +172,7 @@ INSERT INTO t1 (f1) VALUES ('node1_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
@@ -170,6 +190,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
COUNT(*) = 2
1
@@ -182,3 +203,4 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
diff --git a/mysql-test/suite/galera/r/galera_ist_progress.result b/mysql-test/suite/galera/r/galera_ist_progress.result
index ed36a217624..4795fc1224b 100644
--- a/mysql-test/suite/galera/r/galera_ist_progress.result
+++ b/mysql-test/suite/galera/r/galera_ist_progress.result
@@ -1,4 +1,9 @@
connection node_2;
+<<<<<<< HEAD
+connection node_1;
+connection node_2;
+=======
+>>>>>>> 10.3
SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
connection node_1;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_ist_recv_bind.result b/mysql-test/suite/galera/r/galera_ist_recv_bind.result
index ffc751d8672..be72aa60ab0 100644
--- a/mysql-test/suite/galera/r/galera_ist_recv_bind.result
+++ b/mysql-test/suite/galera/r/galera_ist_recv_bind.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SELECT @@wsrep_provider_options LIKE '%ist.recv_bind = 127.0.0.1%';
@@wsrep_provider_options LIKE '%ist.recv_bind = 127.0.0.1%'
diff --git a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result
index c81cecfae1c..80d2c90642b 100644
--- a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result
+++ b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
@@ -13,7 +15,6 @@ Loading wsrep_provider ...
SET SESSION wsrep_on=OFF;
SET SESSION wsrep_on=ON;
connection node_1;
-connection node_1;
UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_ist_rsync.result b/mysql-test/suite/galera/r/galera_ist_rsync.result
index 9c0d78d96e9..f5464e4044a 100644
--- a/mysql-test/suite/galera/r/galera_ist_rsync.result
+++ b/mysql-test/suite/galera/r/galera_ist_rsync.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been temporarily disconnected
diff --git a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
index 175e7443a4d..579370fb25c 100644
--- a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
+++ b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result
@@ -1,4 +1,7 @@
+connection node_2;
+connection node_1;
Performing State Transfer on a server that has been temporarily disconnected
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -8,6 +11,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -18,6 +22,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Unloading wsrep provider ...
SET GLOBAL wsrep_provider = 'none';
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -32,6 +37,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -39,6 +45,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Loading wsrep provider ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -48,6 +55,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -62,6 +70,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_disconnect_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -76,6 +85,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -86,6 +96,7 @@ DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been shut down cleanly and restarted
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -95,6 +106,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -104,6 +116,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Shutting down server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -118,6 +131,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -125,6 +139,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -134,6 +149,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -148,6 +164,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_shutdown_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -162,6 +179,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -172,6 +190,7 @@ DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been killed and restarted
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -181,6 +200,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -190,6 +210,7 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Killing server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
@@ -204,6 +225,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -211,6 +233,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Performing --wsrep-recover ...
Starting server ...
Using --wsrep-start-position when starting mysqld ...
@@ -222,6 +245,7 @@ INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
INSERT INTO t1 VALUES ('node1_to_be_committed_after');
@@ -236,6 +260,7 @@ INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_kill_slave;
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
@@ -250,6 +275,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 35 FROM t1;
COUNT(*) = 35
1
@@ -261,6 +287,7 @@ COMMIT;
SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been killed and restarted
while a DDL was in progress on it
+connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -269,6 +296,7 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
@@ -276,10 +304,13 @@ INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
-SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+connection node_2;
SET wsrep_sync_wait = 0;
Killing server ...
+connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 (f1) VALUES ('node1_committed_during');
@@ -294,6 +325,7 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
@@ -301,7 +333,9 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
Performing --wsrep-recover ...
+connection node_2;
Starting server ...
Using --wsrep-start-position when starting mysqld ...
SET AUTOCOMMIT=OFF;
@@ -312,6 +346,7 @@ INSERT INTO t1 (f1) VALUES ('node2_committed_after');
INSERT INTO t1 (f1) VALUES ('node2_committed_after');
INSERT INTO t1 (f1) VALUES ('node2_committed_after');
COMMIT;
+connection node_1;
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
@@ -326,6 +361,7 @@ INSERT INTO t1 (f1) VALUES ('node1_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_committed_after');
INSERT INTO t1 (f1) VALUES ('node1_committed_after');
COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
@@ -343,6 +379,7 @@ COUNT(*) = 0
1
COMMIT;
SET AUTOCOMMIT=ON;
+connection node_1;
SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
COUNT(*) = 2
1
@@ -355,3 +392,4 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
diff --git a/mysql-test/suite/galera/r/galera_kill_ddl.result b/mysql-test/suite/galera/r/galera_kill_ddl.result
index aac316dffe3..33df5889d44 100644
--- a/mysql-test/suite/galera/r/galera_kill_ddl.result
+++ b/mysql-test/suite/galera/r/galera_kill_ddl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_kill_largechanges.result b/mysql-test/suite/galera/r/galera_kill_largechanges.result
index d04bd548949..dcdab11de4b 100644
--- a/mysql-test/suite/galera/r/galera_kill_largechanges.result
+++ b/mysql-test/suite/galera/r/galera_kill_largechanges.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE ten (f1 INTEGER);
diff --git a/mysql-test/suite/galera/r/galera_kill_smallchanges.result b/mysql-test/suite/galera/r/galera_kill_smallchanges.result
index bcd7d6fd15d..45626b8f9a9 100644
--- a/mysql-test/suite/galera/r/galera_kill_smallchanges.result
+++ b/mysql-test/suite/galera/r/galera_kill_smallchanges.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_lock_table.result b/mysql-test/suite/galera/r/galera_lock_table.result
index ce529deb22c..c3df1749ada 100644
--- a/mysql-test/suite/galera/r/galera_lock_table.result
+++ b/mysql-test/suite/galera/r/galera_lock_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_log_bin.result b/mysql-test/suite/galera/r/galera_log_bin.result
index a6f0ef12be1..12e5e59a426 100644
--- a/mysql-test/suite/galera/r/galera_log_bin.result
+++ b/mysql-test/suite/galera/r/galera_log_bin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (id INT) ENGINE=InnoDB;
@@ -66,4 +68,6 @@ mysqld-bin.000003 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER
DROP TABLE t1;
DROP TABLE t2;
connection node_1;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/r/galera_log_output_csv.result b/mysql-test/suite/galera/r/galera_log_output_csv.result
index 5cb61b36332..efe8c73c986 100644
--- a/mysql-test/suite/galera/r/galera_log_output_csv.result
+++ b/mysql-test/suite/galera/r/galera_log_output_csv.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
SELECT COUNT(*) > 0 FROM mysql.general_log;
diff --git a/mysql-test/suite/galera/r/galera_many_columns.result b/mysql-test/suite/galera/r/galera_many_columns.result
index db8a8f5ec9d..64e97f11fa7 100644
--- a/mysql-test/suite/galera/r/galera_many_columns.result
+++ b/mysql-test/suite/galera/r/galera_many_columns.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
INSERT INTO t1 (f1) VALUES (DEFAULT);
connection node_2;
SELECT f1 = 'ABC', f1017 = 'ABC' FROM t1;
@@ -19,7 +21,7 @@ UPDATE t1 SET f2 = 'CDE' WHERE f1 = 'XYZ' AND f1017 = 'XYZ';
COMMIT;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
connection node_2;
ROLLBACK;
diff --git a/mysql-test/suite/galera/r/galera_many_indexes.result b/mysql-test/suite/galera/r/galera_many_indexes.result
index 5691eef4c00..9a1ede485eb 100644
--- a/mysql-test/suite/galera/r/galera_many_indexes.result
+++ b/mysql-test/suite/galera/r/galera_many_indexes.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(767) PRIMARY KEY) ENGINE=InnoDB;
CREATE UNIQUE INDEX i63 ON t1(f1);
CREATE UNIQUE INDEX i62 ON t1(f1);
@@ -129,5 +131,5 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_many_rows.result b/mysql-test/suite/galera/r/galera_many_rows.result
index b06925fea60..28613c20779 100644
--- a/mysql-test/suite/galera/r/galera_many_rows.result
+++ b/mysql-test/suite/galera/r/galera_many_rows.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION innodb_lock_wait_timeout=600;
SET SESSION lock_wait_timeout=600;
@@ -35,6 +37,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE ten;
diff --git a/mysql-test/suite/galera/r/galera_many_tables_nopk.result b/mysql-test/suite/galera/r/galera_many_tables_nopk.result
index 573ce758a13..2a226defcc7 100644
--- a/mysql-test/suite/galera/r/galera_many_tables_nopk.result
+++ b/mysql-test/suite/galera/r/galera_many_tables_nopk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -18,6 +20,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP SCHEMA test;
CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera/r/galera_many_tables_pk.result b/mysql-test/suite/galera/r/galera_many_tables_pk.result
index 67624d5edb0..2700df8ebe4 100644
--- a/mysql-test/suite/galera/r/galera_many_tables_pk.result
+++ b/mysql-test/suite/galera/r/galera_many_tables_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
SELECT COUNT(*) = 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't%';
@@ -23,7 +25,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
include/diff_servers.inc [servers=1 2]
DROP SCHEMA test;
CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera/r/galera_mdev_10812.result b/mysql-test/suite/galera/r/galera_mdev_10812.result
index de0a08a3794..16eacc6beab 100644
--- a/mysql-test/suite/galera/r/galera_mdev_10812.result
+++ b/mysql-test/suite/galera/r/galera_mdev_10812.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-10812: On COM_STMT_CLOSE/COM_QUIT, when wsrep_conflict_state
# is ABORTED, it causes wrong response to be sent to the client
diff --git a/mysql-test/suite/galera/r/galera_mdev_13787.result b/mysql-test/suite/galera/r/galera_mdev_13787.result
index b1caec0283c..4d0770918c0 100644
--- a/mysql-test/suite/galera/r/galera_mdev_13787.result
+++ b/mysql-test/suite/galera/r/galera_mdev_13787.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
create table t(a int);
insert into t select 1;
diff --git a/mysql-test/suite/galera/r/galera_mdl_race.result b/mysql-test/suite/galera/r/galera_mdl_race.result
index 048b2c46a67..e05c1493322 100644
--- a/mysql-test/suite/galera/r/galera_mdl_race.result
+++ b/mysql-test/suite/galera/r/galera_mdl_race.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
INSERT INTO t1 VALUES (1, 'a');
@@ -28,7 +30,7 @@ SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock";
UNLOCK TABLES;
connection node_1;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a';
COUNT(*) = 1
1
diff --git a/mysql-test/suite/galera/r/galera_multi_database.result b/mysql-test/suite/galera/r/galera_multi_database.result
index f6242de663b..a9d58d5d0e2 100644
--- a/mysql-test/suite/galera/r/galera_multi_database.result
+++ b/mysql-test/suite/galera/r/galera_multi_database.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE DATABASE d1;
CREATE TABLE d1.t1(f1 INTEGER) ENGINE=InnoDB;
CREATE DATABASE d2;
diff --git a/mysql-test/suite/galera/r/galera_myisam_autocommit.result b/mysql-test/suite/galera/r/galera_myisam_autocommit.result
index e9578a261e6..6213e8f6380 100644
--- a/mysql-test/suite/galera/r/galera_myisam_autocommit.result
+++ b/mysql-test/suite/galera/r/galera_myisam_autocommit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2), (3);
diff --git a/mysql-test/suite/galera/r/galera_myisam_transactions.result b/mysql-test/suite/galera/r/galera_myisam_transactions.result
index 25796c309d1..091c5ffb6f6 100644
--- a/mysql-test/suite/galera/r/galera_myisam_transactions.result
+++ b/mysql-test/suite/galera/r/galera_myisam_transactions.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
CREATE TABLE t3 (f1 INTEGER) ENGINE=MyISAM;
diff --git a/mysql-test/suite/galera/r/galera_nopk_bit.result b/mysql-test/suite/galera/r/galera_nopk_bit.result
index 21da039df09..97ded793c08 100644
--- a/mysql-test/suite/galera/r/galera_nopk_bit.result
+++ b/mysql-test/suite/galera/r/galera_nopk_bit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BIT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(0),(b'1');
connection node_2;
@@ -28,6 +30,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_nopk_blob.result b/mysql-test/suite/galera/r/galera_nopk_blob.result
index 53e04f72d1e..6a3cee516c9 100644
--- a/mysql-test/suite/galera/r/galera_nopk_blob.result
+++ b/mysql-test/suite/galera/r/galera_nopk_blob.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),('abc');
connection node_2;
@@ -28,6 +30,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_nopk_large_varchar.result b/mysql-test/suite/galera/r/galera_nopk_large_varchar.result
index a83cf7f2d91..6d29306996b 100644
--- a/mysql-test/suite/galera/r/galera_nopk_large_varchar.result
+++ b/mysql-test/suite/galera/r/galera_nopk_large_varchar.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 VARCHAR(8000)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(CONCAT(REPEAT('x', 7999), 'a'));
connection node_2;
@@ -31,6 +33,6 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_nopk_unicode.result b/mysql-test/suite/galera/r/galera_nopk_unicode.result
index b2a8bb63df9..587ba9285da 100644
--- a/mysql-test/suite/galera/r/galera_nopk_unicode.result
+++ b/mysql-test/suite/galera/r/galera_nopk_unicode.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 VARCHAR(255),
KEY (f1)
@@ -19,7 +21,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT f1 = 'текст2' FROM t1;
f1 = 'текст2'
1
diff --git a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result
index ab56a8a2aa6..eac84cb77d2 100644
--- a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result
+++ b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
@@ -8,10 +10,10 @@ INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
connection node_2a;
SET SESSION wsrep_sync_wait=0;
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%';
COUNT(*) = 1
1
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%';
COUNT(*) = 1
1
SELECT COUNT(*) = 0 FROM t1;
diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result
index 827b2aa9dac..f52839b5c8b 100644
--- a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result
+++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -22,7 +24,7 @@ COUNT(DISTINCT f1)
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE
USER = 'system user' AND STATE NOT LIKE 'InnoDB%';
COUNT(*)
-3
+4
connection default;
DROP TABLE t1;
DROP TABLE ten;
diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result
index c8c07221cb1..62b092962bc 100644
--- a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result
+++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_parallel_simple.result b/mysql-test/suite/galera/r/galera_parallel_simple.result
index 3f657a0479e..d95abefdc24 100644
--- a/mysql-test/suite/galera/r/galera_parallel_simple.result
+++ b/mysql-test/suite/galera/r/galera_parallel_simple.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT) ENGINE=InnoDB;
CREATE TABLE t2 (id INT) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result
index 807ab62c548..0b538778204 100644
--- a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result
+++ b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BIGINT SIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(-9223372036854775808, 'min'),
@@ -27,6 +29,6 @@ COMMIT;
SET AUTOCOMMIT=ON;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SET AUTOCOMMIT=ON;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result
index c94b7e2314a..9442f79cd14 100644
--- a/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result
+++ b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 BIGINT UNSIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(18446744073709551615, 'max')
@@ -24,6 +26,6 @@ COMMIT;
SET AUTOCOMMIT=ON;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SET AUTOCOMMIT=ON;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_prepared_statement.result b/mysql-test/suite/galera/r/galera_prepared_statement.result
index d32d412ff46..943f7d0b263 100644
--- a/mysql-test/suite/galera/r/galera_prepared_statement.result
+++ b/mysql-test/suite/galera/r/galera_prepared_statement.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 CHAR(5)) ENGINE=InnoDB;
CREATE TABLE t2 (f1 CHAR(5)) ENGINE=InnoDB;
CREATE TABLE t3 (f1 CHAR(5)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_query_cache.result b/mysql-test/suite/galera/r/galera_query_cache.result
index e64c9438646..8f5bc4b6f37 100644
--- a/mysql-test/suite/galera/r/galera_query_cache.result
+++ b/mysql-test/suite/galera/r/galera_query_cache.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result
index 8c9cece9097..4ee910f9169 100644
--- a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result
+++ b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_read_only.result b/mysql-test/suite/galera/r/galera_read_only.result
index 4c2523f8691..fe8b45fa596 100644
--- a/mysql-test/suite/galera/r/galera_read_only.result
+++ b/mysql-test/suite/galera/r/galera_read_only.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL read_only=TRUE;
diff --git a/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result
index 2470f59c497..3d421216f93 100644
--- a/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result
+++ b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_provider_options = 'repl.key_format=FLAT16';
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_repl_max_ws_size.result b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result
index da24a741351..0528df7b9f6 100644
--- a/mysql-test/suite/galera/r/galera_repl_max_ws_size.result
+++ b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result
@@ -1,8 +1,10 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB;
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
INSERT INTO t1 VALUES (REPEAT('a', 512));
-ERROR HY000: Got error 90 "Message too long" during COMMIT
+ERROR HY000: Got error 5 "Input/output error" during COMMIT
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
diff --git a/mysql-test/suite/galera/r/galera_restart_nochanges.result b/mysql-test/suite/galera/r/galera_restart_nochanges.result
index b35ae50e2fb..09f8d9a586b 100644
--- a/mysql-test/suite/galera/r/galera_restart_nochanges.result
+++ b/mysql-test/suite/galera/r/galera_restart_nochanges.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result
index ba6f30fcf30..6e672c2d444 100644
--- a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result
+++ b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CALL mtr.add_suppression("Aborting");
CALL mtr.add_suppression("unknown option '--galera-unknown-option'");
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_rsu_add_pk.result b/mysql-test/suite/galera/r/galera_rsu_add_pk.result
index 4c79da154e2..9b068ba30d1 100644
--- a/mysql-test/suite/galera/r/galera_rsu_add_pk.result
+++ b/mysql-test/suite/galera/r/galera_rsu_add_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result
index f64649ef4e2..7d731955691 100644
--- a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result
+++ b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_rsu_error.result b/mysql-test/suite/galera/r/galera_rsu_error.result
index 5c16e34b492..f78e8fa544c 100644
--- a/mysql-test/suite/galera/r/galera_rsu_error.result
+++ b/mysql-test/suite/galera/r/galera_rsu_error.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
INSERT INTO t1 VALUES (1), (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_rsu_simple.result b/mysql-test/suite/galera/r/galera_rsu_simple.result
index d0ddcfb4d64..d75ef094065 100644
--- a/mysql-test/suite/galera/r/galera_rsu_simple.result
+++ b/mysql-test/suite/galera/r/galera_rsu_simple.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_2;
SET SESSION wsrep_OSU_method = "RSU";
diff --git a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result
index a103e810588..310611a0e49 100644
--- a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result
+++ b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
SET GLOBAL wsrep_desync=1;
diff --git a/mysql-test/suite/galera/r/galera_sbr.result b/mysql-test/suite/galera/r/galera_sbr.result
index 0bdaeef5b8a..c5fdecece0e 100644
--- a/mysql-test/suite/galera/r/galera_sbr.result
+++ b/mysql-test/suite/galera/r/galera_sbr.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION binlog_format = 'STATEMENT';
Warnings:
diff --git a/mysql-test/suite/galera/r/galera_sbr_binlog.result b/mysql-test/suite/galera/r/galera_sbr_binlog.result
index 0bdaeef5b8a..c5fdecece0e 100644
--- a/mysql-test/suite/galera/r/galera_sbr_binlog.result
+++ b/mysql-test/suite/galera/r/galera_sbr_binlog.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET SESSION binlog_format = 'STATEMENT';
Warnings:
diff --git a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result
index edf20da92c6..fbac9ff4eb7 100644
--- a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result
+++ b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
USE information_schema;
SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads";
VARIABLE_NAME VARIABLE_VALUE
diff --git a/mysql-test/suite/galera/r/galera_serializable.result b/mysql-test/suite/galera/r/galera_serializable.result
index be3f93a081f..e3785663271 100644
--- a/mysql-test/suite/galera/r/galera_serializable.result
+++ b/mysql-test/suite/galera/r/galera_serializable.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
@@ -9,7 +11,7 @@ connection node_2;
INSERT INTO t1 VALUES (1,1);
connection node_1;
SELECT * FROM t1;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
DELETE FROM t1;
connection node_1;
@@ -22,7 +24,7 @@ connection node_2;
UPDATE t1 SET f2 = 2;
connection node_1;
UPDATE t1 SET f2 = 3;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
DELETE FROM t1;
connection node_1;
@@ -33,5 +35,5 @@ connection node_2;
INSERT INTO t1 VALUES (1,2);
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_server.result b/mysql-test/suite/galera/r/galera_server.result
index cc08b826e82..5130dee3459 100644
--- a/mysql-test/suite/galera/r/galera_server.result
+++ b/mysql-test/suite/galera/r/galera_server.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
# On node_1
CREATE SERVER s1
diff --git a/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result
index 14407c917a1..e9f81192386 100644
--- a/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result
+++ b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
SET SESSION sql_log_bin = 0;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/galera_ssl.result b/mysql-test/suite/galera/r/galera_ssl.result
index 022d06319b8..ec3b717e3f3 100644
--- a/mysql-test/suite/galera/r/galera_ssl.result
+++ b/mysql-test/suite/galera/r/galera_ssl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
diff --git a/mysql-test/suite/galera/r/galera_ssl_compression.result b/mysql-test/suite/galera/r/galera_ssl_compression.result
index 333d646376c..0acc4b97eea 100644
--- a/mysql-test/suite/galera/r/galera_ssl_compression.result
+++ b/mysql-test/suite/galera/r/galera_ssl_compression.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump.result b/mysql-test/suite/galera/r/galera_sst_mysqldump.result
index 5c530c32ce6..ec0fedf6664 100644
--- a/mysql-test/suite/galera/r/galera_sst_mysqldump.result
+++ b/mysql-test/suite/galera/r/galera_sst_mysqldump.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
Setting SST method to mysqldump ...
call mtr.add_suppression("WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to '127.0.0.1'");
call mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos");
@@ -56,6 +58,9 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Loading wsrep provider ...
+disconnect node_2;
+connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_after');
@@ -390,6 +395,114 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+Performing State Transfer on a server that has been killed and restarted
+while a DDL was in progress on it
+connection node_1;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+COMMIT;
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+connection node_2;
+SET wsrep_sync_wait = 0;
+Killing server ...
+connection node_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+COMMIT;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
+Performing --wsrep-recover ...
+connection node_2;
+Starting server ...
+Using --wsrep-start-position when starting mysqld ...
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+COMMIT;
+connection node_1;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ROLLBACK;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+COMMIT;
+SET AUTOCOMMIT=ON;
+connection node_1;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+COMMIT;
+SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
connection node_1;
CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
DROP USER sst;
@@ -400,3 +513,4 @@ CALL mtr.add_suppression("Can't open and lock time zone table");
CALL mtr.add_suppression("Can't open and lock privilege tables");
CALL mtr.add_suppression("Info table is not ready to be used");
CALL mtr.add_suppression("Native table .* has the wrong structure");
+CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist");
diff --git a/mysql-test/suite/galera/r/galera_sst_rsync.result b/mysql-test/suite/galera/r/galera_sst_rsync.result
index ff85a7d6c0f..dbeab68fa17 100644
--- a/mysql-test/suite/galera/r/galera_sst_rsync.result
+++ b/mysql-test/suite/galera/r/galera_sst_rsync.result
@@ -1,5 +1,5 @@
-connection node_1;
connection node_2;
+connection node_1;
Performing State Transfer on a server that has been shut down cleanly and restarted
connection node_1;
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result
index fdb5883b590..f371bf1a948 100644
--- a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result
+++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been shut down cleanly and restarted
@@ -286,5 +288,113 @@ COUNT(*) = 0
DROP TABLE t1;
COMMIT;
SET AUTOCOMMIT=ON;
+Performing State Transfer on a server that has been killed and restarted
+while a DDL was in progress on it
+connection node_1;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+COMMIT;
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+connection node_2;
+SET wsrep_sync_wait = 0;
+Killing server ...
+connection node_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+COMMIT;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
+Performing --wsrep-recover ...
+connection node_2;
+Starting server ...
+Using --wsrep-start-position when starting mysqld ...
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+COMMIT;
+connection node_1;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ROLLBACK;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+COMMIT;
+SET AUTOCOMMIT=ON;
+connection node_1;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+COMMIT;
+SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
disconnect node_2;
disconnect node_1;
diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result
index 990e0a29506..409da775d9a 100644
--- a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result
+++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT 1;
1
1
diff --git a/mysql-test/suite/galera/r/galera_status_cluster.result b/mysql-test/suite/galera/r/galera_status_cluster.result
index ad92a51b775..9db0b88adc9 100644
--- a/mysql-test/suite/galera/r/galera_status_cluster.result
+++ b/mysql-test/suite/galera/r/galera_status_cluster.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 2
diff --git a/mysql-test/suite/galera/r/galera_status_local_index.result b/mysql-test/suite/galera/r/galera_status_local_index.result
index 8c36b60cc5f..c67498fff9f 100644
--- a/mysql-test/suite/galera/r/galera_status_local_index.result
+++ b/mysql-test/suite/galera/r/galera_status_local_index.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE wsrep_local_indexes (wsrep_local_index INTEGER);
INSERT INTO wsrep_local_indexes VALUES ((SELECT variable_value FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_local_index'));
diff --git a/mysql-test/suite/galera/r/galera_status_local_state.result b/mysql-test/suite/galera/r/galera_status_local_state.result
index 65713f1975c..3fe988ee6ac 100644
--- a/mysql-test/suite/galera/r/galera_status_local_state.result
+++ b/mysql-test/suite/galera/r/galera_status_local_state.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state';
VARIABLE_VALUE = 4
1
diff --git a/mysql-test/suite/galera/r/galera_suspend_slave.result b/mysql-test/suite/galera/r/galera_suspend_slave.result
index 3b950e82e33..2f35be2da93 100644
--- a/mysql-test/suite/galera/r/galera_suspend_slave.result
+++ b/mysql-test/suite/galera/r/galera_suspend_slave.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_sync_wait_show.result b/mysql-test/suite/galera/r/galera_sync_wait_show.result
index def771ff88d..793da3246ff 100644
--- a/mysql-test/suite/galera/r/galera_sync_wait_show.result
+++ b/mysql-test/suite/galera/r/galera_sync_wait_show.result
@@ -1,4 +1,6 @@
connection node_2;
+connection node_1;
+connection node_2;
SET SESSION wsrep_sync_wait = 8;
connection node_1;
CREATE DATABASE db1;
diff --git a/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result
index 8a86dfd11e2..a23b0523140 100644
--- a/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result
+++ b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_error.result b/mysql-test/suite/galera/r/galera_toi_ddl_error.result
index dafad153867..386dc28bed3 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_error.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_error.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
@@ -19,3 +21,6 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP TABLE ten;
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
+connection node_2;
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result b/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result
index a5db90aa965..a7966e36133 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE parent (
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result
index 68743c024a0..4dd996093ec 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result
@@ -1,32 +1,46 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
connection node_1;
-SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+SET DEBUG_SYNC= 'RESET';
+SET DEBUG_SYNC = 'alter_table_before_open_tables SIGNAL before_open_tables WAIT_FOR continue';
ALTER TABLE t1 ADD COLUMN f2 INTEGER;;
connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now WAIT_FOR before_open_tables';
+SET wsrep_retry_autocommit=0;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
SELECT COUNT(*) = 0 FROM t2;
COUNT(*) = 0
1
-INSERT INTO t1 VALUES (1);
-Got one of the listed errors
+INSERT INTO t1 VALUES (1);;
+connection node_1c;
+SET SESSION wsrep_sync_wait = 0;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t2;
+COUNT(*) = 0
+1
INSERT INTO t2 VALUES (1);
COMMIT;;
connection node_1b;
SET SESSION wsrep_sync_wait = 0;
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
-COUNT(*) = 1
-1
SELECT COUNT(*) = 0 FROM t2;
COUNT(*) = 0
1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
+COUNT(*) = 1
+1
SET DEBUG_SYNC= 'now SIGNAL continue';
connection node_1a;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_1c;
connection node_1;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
@@ -41,9 +55,5 @@ COUNT(*) = 0
SELECT COUNT(*) = 1 FROM t2;
COUNT(*) = 1
1
-connection node_1;
-SET DEBUG_SYNC= 'RESET';
-connection node_1b;
-SET DEBUG_SYNC= 'RESET';
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result
index 3844fa97d82..5412cd3faee 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER);
connection node_2;
ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 123);;
diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result
index 722bb9d9e12..db702b1a59e 100644
--- a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result
+++ b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_toi_drop_database.result b/mysql-test/suite/galera/r/galera_toi_drop_database.result
index 6d88c8ea230..48056c70126 100644
--- a/mysql-test/suite/galera/r/galera_toi_drop_database.result
+++ b/mysql-test/suite/galera/r/galera_toi_drop_database.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE DATABASE database1;
USE database1;
@@ -14,9 +16,9 @@ INSERT INTO t2 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, te
connection node_2;
DROP DATABASE database1;;
connection node_1;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1a;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
connection node_1;
SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'database1';
diff --git a/mysql-test/suite/galera/r/galera_toi_ftwrl.result b/mysql-test/suite/galera/r/galera_toi_ftwrl.result
index 0f13e95b689..fdc8b294c1c 100644
--- a/mysql-test/suite/galera/r/galera_toi_ftwrl.result
+++ b/mysql-test/suite/galera/r/galera_toi_ftwrl.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
FLUSH TABLES WITH READ LOCK;
diff --git a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result
index f5cc14ed0f1..ee8c826fd18 100644
--- a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result
+++ b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
@@ -8,7 +10,7 @@ connection node_2a;
ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=EXCLUSIVE;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1;
INSERT INTO t1 VALUES (2, 2);
SELECT COUNT(*) = 2 FROM t1;
diff --git a/mysql-test/suite/galera/r/galera_toi_lock_shared.result b/mysql-test/suite/galera/r/galera_toi_lock_shared.result
index 950c4d83c70..fe1c88075d5 100644
--- a/mysql-test/suite/galera/r/galera_toi_lock_shared.result
+++ b/mysql-test/suite/galera/r/galera_toi_lock_shared.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_toi_truncate.result b/mysql-test/suite/galera/r/galera_toi_truncate.result
index 933379cade5..14580e55bb7 100644
--- a/mysql-test/suite/galera/r/galera_toi_truncate.result
+++ b/mysql-test/suite/galera/r/galera_toi_truncate.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -9,7 +11,7 @@ connection node_1;
TRUNCATE TABLE t1;;
connection node_1;
connection node_2;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
diff --git a/mysql-test/suite/galera/r/galera_transaction_read_only.result b/mysql-test/suite/galera/r/galera_transaction_read_only.result
index b388f195fb1..55923f58b65 100644
--- a/mysql-test/suite/galera/r/galera_transaction_read_only.result
+++ b/mysql-test/suite/galera/r/galera_transaction_read_only.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_transaction_replay.result b/mysql-test/suite/galera/r/galera_transaction_replay.result
index 7fd837433d2..272086c4eba 100644
--- a/mysql-test/suite/galera/r/galera_transaction_replay.result
+++ b/mysql-test/suite/galera/r/galera_transaction_replay.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
INSERT INTO t1 VALUES (1, 'a');
INSERT INTO t1 VALUES (2, 'a');
@@ -9,19 +11,73 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
f1 f2
2 a
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
-SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync';
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
connection node_1;
-COMMIT;;
+COMMIT;
connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+connection node_1;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+wsrep_local_replays
+1
connection node_2;
-UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+DROP TABLE t1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+connection node_2;
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
connection node_1;
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
COUNT(*) = 1
@@ -46,22 +102,34 @@ SELECT * FROM t1;
i j
1 0
3 0
+SET AUTOCOMMIT=ON;
PREPARE stmt1 FROM "UPDATE t1 SET j = 1 where i > 0";
connection node_1a;
-SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync';
-connection node_1;
-EXECUTE stmt1;;
-connection node_1a;
-SET SESSION wsrep_sync_wait = 0;
-SET SESSION wsrep_on = 0;
-SET SESSION wsrep_on = 1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
INSERT INTO t1 VALUES(2,2);
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+EXECUTE stmt1;
connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
-SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
connection node_1;
+SET SESSION wsrep_sync_wait=7;
SELECT * FROM t1;
i j
1 1
@@ -74,5 +142,7 @@ i j
2 2
3 1
connection node_1;
+wsrep_local_replays
+1
DEALLOCATE PREPARE stmt1;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_truncate.result b/mysql-test/suite/galera/r/galera_truncate.result
index 4f3d72dbca7..c649d9bbaf9 100644
--- a/mysql-test/suite/galera/r/galera_truncate.result
+++ b/mysql-test/suite/galera/r/galera_truncate.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_truncate_temporary.result b/mysql-test/suite/galera/r/galera_truncate_temporary.result
index 183ebd9d24a..81373bda739 100644
--- a/mysql-test/suite/galera/r/galera_truncate_temporary.result
+++ b/mysql-test/suite/galera/r/galera_truncate_temporary.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TEMPORARY TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
INSERT INTO t1 VALUES (1);
TRUNCATE TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_unicode_identifiers.result b/mysql-test/suite/galera/r/galera_unicode_identifiers.result
index 5eb13a83df9..495c508d59f 100644
--- a/mysql-test/suite/galera/r/galera_unicode_identifiers.result
+++ b/mysql-test/suite/galera/r/galera_unicode_identifiers.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_sync_wait = 15;
connection node_2;
SET GLOBAL wsrep_sync_wait = 15;
diff --git a/mysql-test/suite/galera/r/galera_unicode_pk.result b/mysql-test/suite/galera/r/galera_unicode_pk.result
index 0e8965a76e3..bb36fd4f369 100644
--- a/mysql-test/suite/galera/r/galera_unicode_pk.result
+++ b/mysql-test/suite/galera/r/galera_unicode_pk.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 VARCHAR(255) PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -18,7 +20,7 @@ connection node_1;
COMMIT;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT f1 = 'текст2' FROM t1;
f1 = 'текст2'
1
@@ -35,6 +37,6 @@ connection node_2;
COMMIT;
connection node_1;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
COMMIT;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_update_limit.result b/mysql-test/suite/galera/r/galera_update_limit.result
index 20a94e6f504..30c89a38dff 100644
--- a/mysql-test/suite/galera/r/galera_update_limit.result
+++ b/mysql-test/suite/galera/r/galera_update_limit.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER) Engine=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
diff --git a/mysql-test/suite/galera/r/galera_v1_row_events.result b/mysql-test/suite/galera/r/galera_v1_row_events.result
index b0ea2293119..80fe2fb6d8d 100644
--- a/mysql-test/suite/galera/r/galera_v1_row_events.result
+++ b/mysql-test/suite/galera/r/galera_v1_row_events.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method.result b/mysql-test/suite/galera/r/galera_var_OSU_method.result
index 18e8bd2271a..2b0a713e86b 100644
--- a/mysql-test/suite/galera/r/galera_var_OSU_method.result
+++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET SESSION wsrep_OSU_method = "RSU";
diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method2.result b/mysql-test/suite/galera/r/galera_var_OSU_method2.result
index 0e3751645a8..ca4f617d903 100644
--- a/mysql-test/suite/galera/r/galera_var_OSU_method2.result
+++ b/mysql-test/suite/galera/r/galera_var_OSU_method2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET SESSION wsrep_OSU_method = "TOI";
diff --git a/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result
index ba117b4c2d5..86c30fa4b23 100644
--- a/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result
+++ b/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_auto_increment_control = OFF;
SET GLOBAL auto_increment_increment = 1;
@@ -59,7 +61,7 @@ connection node_1a;
COMMIT;
connection node_2a;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_1a;
SELECT * FROM t1;
f1 node
diff --git a/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result b/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result
index ca3844bf6bf..f5472aa931f 100644
--- a/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result
+++ b/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_certify_nonPK = OFF;
connection node_2;
SET GLOBAL wsrep_certify_nonPK = OFF;
diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result
index 378d8ca84f5..cf1e60c8425 100644
--- a/mysql-test/suite/galera/r/galera_var_cluster_address.result
+++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result
@@ -1,7 +1,11 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_2;
SET GLOBAL wsrep_cluster_address = 'foo://';
+SHOW STATUS;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
SET SESSION wsrep_sync_wait=0;
SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
COUNT(*) > 0
@@ -39,7 +43,7 @@ CALL mtr.add_suppression("Failed to initialize backend using 'foo");
CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo");
CALL mtr.add_suppression("gcs connect failed: Socket type not supported");
CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7");
-CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)");
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -[0-9]+ \\(Software caused connection abort\\)");
CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110");
CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)");
CALL mtr.add_suppression("gcs connect failed: Connection timed out");
diff --git a/mysql-test/suite/galera/r/galera_var_desync_on.result b/mysql-test/suite/galera/r/galera_var_desync_on.result
index a26acbd4d6b..06304a6ed35 100644
--- a/mysql-test/suite/galera/r/galera_var_desync_on.result
+++ b/mysql-test/suite/galera/r/galera_var_desync_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result
index 049aa5be3cc..ca10ba38939 100644
--- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result
+++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result
@@ -1,4 +1,3 @@
-connection node_1;
connection node_2;
connection node_1;
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_fkchecks.result b/mysql-test/suite/galera/r/galera_var_fkchecks.result
index 8b1b913a584..42f8085ee1a 100644
--- a/mysql-test/suite/galera/r/galera_var_fkchecks.result
+++ b/mysql-test/suite/galera/r/galera_var_fkchecks.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE parent (
id INT PRIMARY KEY,
KEY (id)
diff --git a/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result b/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result
index 1a8733e2e1a..d2faf5ff463 100644
--- a/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result
+++ b/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
list of GTID variables :
diff --git a/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result
new file mode 100644
index 00000000000..39bab15ef13
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result
@@ -0,0 +1,154 @@
+SET GLOBAL wsrep_ignore_apply_errors = 1;
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+DROP TABLE t1;
+SET GLOBAL wsrep_on = OFF;
+CREATE SCHEMA s1;
+SET GLOBAL wsrep_on = ON;
+DROP SCHEMA s1;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+DROP INDEX idx1 ON t1;
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP INDEX idx1;
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP COLUMN f2;
+DROP TABLE t1;
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+DELETE FROM t1 WHERE f1 = 1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+DELETE FROM t1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+DELETE FROM t1 WHERE f1 = 4;
+DELETE FROM t1 WHERE f1 = 5;
+COMMIT;
+SET AUTOCOMMIT=ON;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET SESSION wsrep_on = OFF;
+DELETE FROM t2 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1,t2;
+CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+INSERT INTO parent VALUES (1),(2),(3);
+CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB;
+INSERT INTO child VALUES (1,1),(2,2),(3,3);
+SET SESSION wsrep_on = OFF;
+DELETE FROM child WHERE parent_id = 2;
+SET SESSION wsrep_on = ON;
+DELETE FROM parent;
+SELECT COUNT(*) = 0 FROM parent;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM child;
+COUNT(*) = 0
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT COUNT(*) = 0 FROM parent;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM child;
+COUNT(*) = 0
+1
+DROP TABLE child, parent;
+SET GLOBAL wsrep_ignore_apply_errors = 4;
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+DROP TABLE t1;
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query. Default database: 'test'. Query: 'DROP TABLE t1', Error_code: 1051");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query. Default database: 'test'. Query: 'DROP SCHEMA s1', Error_code: 1008");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'DROP INDEX idx1 ON t1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP INDEX idx1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'f2'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP COLUMN f2', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query.");
diff --git a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result
index 4db4e539c50..f5ec473fea4 100644
--- a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result
+++ b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
index 3e451abbed1..7c5fd44356e 100644
--- a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
+++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
SET GLOBAL wsrep_load_data_splitting = TRUE;
diff --git a/mysql-test/suite/galera/r/galera_var_log_bin.result b/mysql-test/suite/galera/r/galera_var_log_bin.result
index b0ea2293119..80fe2fb6d8d 100644
--- a/mysql-test/suite/galera/r/galera_var_log_bin.result
+++ b/mysql-test/suite/galera/r/galera_var_log_bin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/galera_var_max_ws_rows.result b/mysql-test/suite/galera/r/galera_var_max_ws_rows.result
index 6bf67a3fb60..16e868f0485 100644
--- a/mysql-test/suite/galera/r/galera_var_max_ws_rows.result
+++ b/mysql-test/suite/galera/r/galera_var_max_ws_rows.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/galera_var_max_ws_size.result b/mysql-test/suite/galera/r/galera_var_max_ws_size.result
index 53bac04fa86..89c9698eed4 100644
--- a/mysql-test/suite/galera/r/galera_var_max_ws_size.result
+++ b/mysql-test/suite/galera/r/galera_var_max_ws_size.result
@@ -1,8 +1,10 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB;
SET GLOBAL wsrep_max_ws_size = 1024;
INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024));
-ERROR HY000: Got error 90 "Message too long" during COMMIT
+ERROR HY000: Got error 5 "Input/output error" during COMMIT
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
diff --git a/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result b/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result
index 202633a020e..d7a38d24722 100644
--- a/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result
+++ b/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB;
SET GLOBAL wsrep_mysql_replication_bundle = 2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_var_node_address.result b/mysql-test/suite/galera/r/galera_var_node_address.result
index b8076958532..2538c913a96 100644
--- a/mysql-test/suite/galera/r/galera_var_node_address.result
+++ b/mysql-test/suite/galera/r/galera_var_node_address.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
call mtr.add_suppression("WSREP: Stray state UUID msg: .* current group state WAIT_STATE_UUID .*");
call mtr.add_suppression("WSREP: Protocol violation. JOIN message sender .* is not in state transfer (.*). Message ignored.");
call mtr.add_suppression("WSREP: Sending JOIN failed: -[0-9]+ (Transport endpoint is not connected). Will retry in new primary component.");
diff --git a/mysql-test/suite/galera/r/galera_var_reject_queries.result b/mysql-test/suite/galera/r/galera_var_reject_queries.result
index 98380238fcb..e986092ea59 100644
--- a/mysql-test/suite/galera/r/galera_var_reject_queries.result
+++ b/mysql-test/suite/galera/r/galera_var_reject_queries.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER);
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result
index 382466b1387..8968f89d11b 100644
--- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result
+++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SET GLOBAL wsrep_replicate_myisam = FALSE;
CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=MyISAM;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result
index 87f8862df7e..716af033e7a 100644
--- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result
+++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_1;
SET GLOBAL wsrep_replicate_myisam = TRUE;
diff --git a/mysql-test/suite/galera/r/galera_var_slave_threads.result b/mysql-test/suite/galera/r/galera_var_slave_threads.result
index 3f0a63ab9d7..6196e6b1b78 100644
--- a/mysql-test/suite/galera/r/galera_var_slave_threads.result
+++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB;
CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB;
@@ -13,13 +15,25 @@ SELECT @@wsrep_slave_threads = 1;
@@wsrep_slave_threads = 1
1
SET GLOBAL wsrep_slave_threads = 1;
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
-COUNT(*)
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = 3
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+COUNT(*) = 1
1
SET GLOBAL wsrep_slave_threads = 64;
connection node_1;
INSERT INTO t1 VALUES (1);
connection node_2;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = @@wsrep_slave_threads + 2
+0
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+COUNT(*) = 1
+1
SET GLOBAL wsrep_slave_threads = 1;
connection node_1;
INSERT INTO t2 VALUES (DEFAULT);
@@ -87,32 +101,188 @@ INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
INSERT INTO t2 VALUES (DEFAULT);
connection node_2;
-SELECT COUNT(*) FROM t2;
-COUNT(*)
-64
+SELECT COUNT(*) = 64 FROM t2;
+COUNT(*) = 64
+1
+SET wsrep_sync_wait=0;
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = @@wsrep_slave_threads + 2
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+COUNT(*) = 1
+1
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
COUNT(*)
1
+SET GLOBAL wsrep_slave_threads = 5;
SET GLOBAL wsrep_slave_threads = 1;
-DROP TABLE t1;
-DROP TABLE t2;
-#
-# lp:1372840 - Changing wsrep_slave_threads causes future connections to hang
-#
+connection node_2;
+Shutting down server ...
+connection node_1;
+SET wsrep_sync_wait=0;
+show status like 'wsrep_cluster_size';
+Variable_name Value
+wsrep_cluster_size 1
+SET GLOBAL wsrep_slave_threads = 6;
+SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL wsrep_cluster_address='';
+SET GLOBAL wsrep_cluster_address='gcomm://';
+SET GLOBAL wsrep_slave_threads = 10;
+connection node_2;
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+COUNT(*) = @@wsrep_slave_threads + 2
+1
+connection node_1;
+SET GLOBAL wsrep_slave_threads = 1;
+connection node_2;
+SET GLOBAL wsrep_slave_threads = 1;
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
connection node_1;
-CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB;
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
+INSERT INTO t2 VALUES (DEFAULT);
connection node_2;
SET GLOBAL wsrep_slave_threads = 4;
+Timeout in wait_condition.inc for SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+Id User Host db Command Time State Info Progress
+2 system user NULL Sleep 42 Waiting on cond NULL 0.000
+1 system user NULL Sleep 42 wsrep aborter idle NULL 0.000
+3 system user NULL Sleep 30 Committed 195 NULL 0.000
+4 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
+5 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
+7 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
+6 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
+8 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
+27 root localhost:53510 test Query 0 Init show full processlist 0.000
+28 system user NULL Sleep 30 NULL NULL 0.000
+30 system user NULL Sleep 30 NULL NULL 0.000
+29 system user NULL Sleep 30 NULL NULL 0.000
SET GLOBAL wsrep_slave_threads = 1;
connection node_1;
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
DROP TABLE t1;
-connection node_2;
-SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%';
-NAME
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
-COUNT(*) = 1
-1
+DROP TABLE t2;
# End of tests
diff --git a/mysql-test/suite/galera/r/galera_var_sst_auth.result b/mysql-test/suite/galera/r/galera_var_sst_auth.result
index 1db83197870..6a5683e2633 100644
--- a/mysql-test/suite/galera/r/galera_var_sst_auth.result
+++ b/mysql-test/suite/galera/r/galera_var_sst_auth.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-10492: Assertion failure on shutdown when wsrep_sst_auth set in config
#
diff --git a/mysql-test/suite/galera/r/galera_var_sync_wait.result b/mysql-test/suite/galera/r/galera_var_sync_wait.result
index 3dfe902767c..80fbd3f3e05 100644
--- a/mysql-test/suite/galera/r/galera_var_sync_wait.result
+++ b/mysql-test/suite/galera/r/galera_var_sync_wait.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-10161: wsrep_sync_wait not enabled when set to 1 in config file
#
diff --git a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result
index 36340f505ff..5323bc9bf60 100644
--- a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result
+++ b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
SET SESSION wsrep_on = FALSE;
diff --git a/mysql-test/suite/galera/r/galera_wan.result b/mysql-test/suite/galera/r/galera_wan.result
index 73100636a0d..ff961c6e633 100644
--- a/mysql-test/suite/galera/r/galera_wan.result
+++ b/mysql-test/suite/galera/r/galera_wan.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4
1
diff --git a/mysql-test/suite/galera/r/galera_wan_restart_ist.result b/mysql-test/suite/galera/r/galera_wan_restart_ist.result
index 8a2a7d0818e..7b87d534d92 100644
--- a/mysql-test/suite/galera/r/galera_wan_restart_ist.result
+++ b/mysql-test/suite/galera/r/galera_wan_restart_ist.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4;
connection node_1;
diff --git a/mysql-test/suite/galera/r/galera_wan_restart_sst.result b/mysql-test/suite/galera/r/galera_wan_restart_sst.result
index 71786cdd023..1296744a9c1 100644
--- a/mysql-test/suite/galera/r/galera_wan_restart_sst.result
+++ b/mysql-test/suite/galera/r/galera_wan_restart_sst.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4
1
diff --git a/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result
index 99c680c7b12..e01825fd944 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff --git a/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result b/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result
index fa49d8c57c2..59883f1ca7e 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (
f1 VARCHAR(255) PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -20,6 +22,6 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2a;
connection node_2;
COMMIT;
-ERROR 40001: Deadlock: wsrep aborted transaction
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
include/assert_grep.inc [cluster conflict due to high priority abort for threads]
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result
index ca388496794..8edf1a02e9d 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
VARIABLE_VALUE = 'Primary'
1
diff --git a/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result b/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result
index f19dc40205b..0f7cd134156 100644
--- a/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result
+++ b/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
call mtr.add_suppression("WSREP\: Unknown parameter 'gmcasts\.segment'");
call mtr.add_suppression("WSREP\: Set options returned 7");
SET GLOBAL wsrep_provider_options="gmcasts.segment=1";
diff --git a/mysql-test/suite/galera/r/galera_zero_length_column.result b/mysql-test/suite/galera/r/galera_zero_length_column.result
index 572d94d6756..fa29264704f 100644
--- a/mysql-test/suite/galera/r/galera_zero_length_column.result
+++ b/mysql-test/suite/galera/r/galera_zero_length_column.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY , f2 VARCHAR(0)) ENGINE=InnoDB;
CREATE TABLE t2 (f1 VARCHAR(0)) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/r/grant.result b/mysql-test/suite/galera/r/grant.result
index a2ca72ee8ec..0b5a34dfce1 100644
--- a/mysql-test/suite/galera/r/grant.result
+++ b/mysql-test/suite/galera/r/grant.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV#6266: Changing password fails on galera cluster
#
diff --git a/mysql-test/suite/galera/r/lp1276424.result b/mysql-test/suite/galera/r/lp1276424.result
index 363758e0d66..be27ee5374f 100644
--- a/mysql-test/suite/galera/r/lp1276424.result
+++ b/mysql-test/suite/galera/r/lp1276424.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INT DEFAULT NULL, UNIQUE KEY i1 (f1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (NULL);
diff --git a/mysql-test/suite/galera/r/lp1347768.result b/mysql-test/suite/galera/r/lp1347768.result
index 7beb167d538..49c8894c081 100644
--- a/mysql-test/suite/galera/r/lp1347768.result
+++ b/mysql-test/suite/galera/r/lp1347768.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE `r8kmb_redirect_links` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`old_url` varchar(255) DEFAULT NULL,
diff --git a/mysql-test/suite/galera/r/lp1376747-2.result b/mysql-test/suite/galera/r/lp1376747-2.result
index b85e130f4f4..5e5b5be6c86 100644
--- a/mysql-test/suite/galera/r/lp1376747-2.result
+++ b/mysql-test/suite/galera/r/lp1376747-2.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/lp1376747-3.result b/mysql-test/suite/galera/r/lp1376747-3.result
index a2c55b5f1f6..62893b85bcf 100644
--- a/mysql-test/suite/galera/r/lp1376747-3.result
+++ b/mysql-test/suite/galera/r/lp1376747-3.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/lp1376747-4.result b/mysql-test/suite/galera/r/lp1376747-4.result
index f1d32aa8f69..d6884cc3746 100644
--- a/mysql-test/suite/galera/r/lp1376747-4.result
+++ b/mysql-test/suite/galera/r/lp1376747-4.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
diff --git a/mysql-test/suite/galera/r/lp1376747.result b/mysql-test/suite/galera/r/lp1376747.result
index 16d4fa3fc52..1b9dd545409 100644
--- a/mysql-test/suite/galera/r/lp1376747.result
+++ b/mysql-test/suite/galera/r/lp1376747.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
connection node_2;
diff --git a/mysql-test/suite/galera/r/lp1438990.result b/mysql-test/suite/galera/r/lp1438990.result
index d48d2435faa..a324121d7da 100644
--- a/mysql-test/suite/galera/r/lp1438990.result
+++ b/mysql-test/suite/galera/r/lp1438990.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
diff --git a/mysql-test/suite/galera/r/lp959512.result b/mysql-test/suite/galera/r/lp959512.result
index 55adfa360b0..589030002db 100644
--- a/mysql-test/suite/galera/r/lp959512.result
+++ b/mysql-test/suite/galera/r/lp959512.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
DROP TABLE IF EXISTS variable;
Warnings:
Note 1051 Unknown table 'test.variable'
diff --git a/mysql-test/suite/galera/r/mdev_10518.result b/mysql-test/suite/galera/r/mdev_10518.result
index 4ccd5fd1d23..252aa244f77 100644
--- a/mysql-test/suite/galera/r/mdev_10518.result
+++ b/mysql-test/suite/galera/r/mdev_10518.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
list of GTID variables :
diff --git a/mysql-test/suite/galera/r/mdev_9290.result b/mysql-test/suite/galera/r/mdev_9290.result
index 276ab9e8ecb..d8fc35b02f4 100644
--- a/mysql-test/suite/galera/r/mdev_9290.result
+++ b/mysql-test/suite/galera/r/mdev_9290.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-9290 : InnoDB: Assertion failure in file trx0sys.cc line 353
# InnoDB: Failing assertion: xid_seqno > trx_sys_cur_xid_seqno
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#110.result b/mysql-test/suite/galera/r/mysql-wsrep#110.result
index 6d4031d71cd..344185f4f4e 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#110.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#110.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#198.result b/mysql-test/suite/galera/r/mysql-wsrep#198.result
index 33f36d407db..5b569ffae27 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#198.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#198.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#201.result b/mysql-test/suite/galera/r/mysql-wsrep#201.result
index fe5725cab27..e55c38ea7cc 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#201.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#201.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (DEFAULT);
connection node_2;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#237.result b/mysql-test/suite/galera/r/mysql-wsrep#237.result
index 19503dd5781..cf6f21f2112 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#237.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#237.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue';
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#247.result b/mysql-test/suite/galera/r/mysql-wsrep#247.result
index e59c6d1a299..704f0ba923c 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#247.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#247.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
SET GLOBAL wsrep_desync=1;
SET wsrep_OSU_method=RSU;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#31.result b/mysql-test/suite/galera/r/mysql-wsrep#31.result
index 1092f4ddb0c..d1d2861ec3a 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#31.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#31.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/mysql-wsrep#90.result b/mysql-test/suite/galera/r/mysql-wsrep#90.result
index 0b8f55e6219..b0fa06ffaf8 100644
--- a/mysql-test/suite/galera/r/mysql-wsrep#90.result
+++ b/mysql-test/suite/galera/r/mysql-wsrep#90.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
connection node_1;
SET GLOBAL wsrep_OSU_method = "RSU";
diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result
index 3835de514aa..774d5ce8f83 100644
--- a/mysql-test/suite/galera/r/partition.result
+++ b/mysql-test/suite/galera/r/partition.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV#4953 Galera: DELETE from a partitioned table is not replicated
#
@@ -123,7 +125,7 @@ SELECT COUNT(*) = 20002 FROM t1;
COUNT(*) = 20002
1
wsrep_last_committed_diff
-1
+AS_EXPECTED_3_or_5
DROP TABLE t1;
# Case 2: wsrep_load_data_splitting = ON & LOAD DATA with 101 entries.
connection node_1;
@@ -148,7 +150,7 @@ SELECT COUNT(*) = 20002 FROM t1;
COUNT(*) = 20002
1
wsrep_last_committed_diff
-1
+AS_EXPECTED_1_or_2
DROP TABLE t1;
connection node_1;
SET GLOBAL wsrep_load_data_splitting = 1;;
diff --git a/mysql-test/suite/galera/r/pxc-421.result b/mysql-test/suite/galera/r/pxc-421.result
index a317b3e40e1..058af15c098 100644
--- a/mysql-test/suite/galera/r/pxc-421.result
+++ b/mysql-test/suite/galera/r/pxc-421.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_1;
diff --git a/mysql-test/suite/galera/r/query_cache.result b/mysql-test/suite/galera/r/query_cache.result
index d497fc87544..489514b437b 100644
--- a/mysql-test/suite/galera/r/query_cache.result
+++ b/mysql-test/suite/galera/r/query_cache.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# Execute FLUSH/RESET commands.
# On node-1
diff --git a/mysql-test/suite/galera/r/rename.result b/mysql-test/suite/galera/r/rename.result
index a7ec431657b..3ad715fa38c 100644
--- a/mysql-test/suite/galera/r/rename.result
+++ b/mysql-test/suite/galera/r/rename.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-8598 : Failed MySQL DDL commands and Galera replication
#
diff --git a/mysql-test/suite/galera/r/rpl_row_annotate.result b/mysql-test/suite/galera/r/rpl_row_annotate.result
index 23de06f015b..61fa2bc286c 100644
--- a/mysql-test/suite/galera/r/rpl_row_annotate.result
+++ b/mysql-test/suite/galera/r/rpl_row_annotate.result
@@ -1,9 +1,15 @@
+connection node_2;
+connection node_1;
# On node_2
connection node_2;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
# On node_1
connection node_1;
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
CREATE TABLE t1(i INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
DELETE FROM t1 WHERE i = 1;
@@ -68,6 +74,4 @@ mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1)
mysqld-bin.000001 # Delete_rows_v1 2 # table_id: # flags: STMT_END_F
mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */
DROP TABLE t1;
-disconnect node_2;
-disconnect node_1;
# End of test
diff --git a/mysql-test/suite/galera/r/sql_log_bin.result b/mysql-test/suite/galera/r/sql_log_bin.result
index c175a0a0e7a..6efd70ca8b8 100644
--- a/mysql-test/suite/galera/r/sql_log_bin.result
+++ b/mysql-test/suite/galera/r/sql_log_bin.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
# On node_1
connection node_1;
diff --git a/mysql-test/suite/galera/r/unique_key.result b/mysql-test/suite/galera/r/unique_key.result
index 9f1fc858389..bb7e22014d9 100644
--- a/mysql-test/suite/galera/r/unique_key.result
+++ b/mysql-test/suite/galera/r/unique_key.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV#5552 Deadlock when inserting NULL column value in column with
# UNIQUE index
diff --git a/mysql-test/suite/galera/r/view.result b/mysql-test/suite/galera/r/view.result
index f8da811f9cc..45d5b422f3f 100644
--- a/mysql-test/suite/galera/r/view.result
+++ b/mysql-test/suite/galera/r/view.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
#
# MDEV-7222: Cluster Node Crash at CREATE DEFINER statement
#
diff --git a/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result
new file mode 100644
index 00000000000..0e8a4088104
--- /dev/null
+++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result
@@ -0,0 +1,25 @@
+connection node_2;
+connection node_1;
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET SESSION wsrep_trx_fragment_size = 0;
+SET SESSION wsrep_trx_fragment_size = 123;
+ERROR 42000: Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SHOW WARNINGS;
+Level Code Message
+Warning 1231 Cannot set 'wsrep_trx_fragment_size' to a value other than 0 because the wsrep_provider does not support streaming replication.
+Error 1231 Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET GLOBAL wsrep_trx_fragment_size = 0;
+SET GLOBAL wsrep_trx_fragment_size = 123;
+ERROR 42000: Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SHOW WARNINGS;
+Level Code Message
+Warning 1231 Cannot set 'wsrep_trx_fragment_size' to a value other than 0 because the wsrep_provider does not support streaming replication.
+Error 1231 Variable 'wsrep_trx_fragment_size' can't be set to the value of '123'
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result
new file mode 100644
index 00000000000..25e7d2dd54c
--- /dev/null
+++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result
@@ -0,0 +1,13 @@
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET SESSION wsrep_trx_fragment_size = 0;
+SET SESSION wsrep_trx_fragment_size = 123;
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+variable_value
+0
+SET GLOBAL wsrep_trx_fragment_size = 0;
+SET GLOBAL wsrep_trx_fragment_size = 123;
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera/t/GAL-419.test b/mysql-test/suite/galera/t/GAL-419.test
index e50b948bf35..07abcbcc47b 100644
--- a/mysql-test/suite/galera/t/GAL-419.test
+++ b/mysql-test/suite/galera/t/GAL-419.test
@@ -5,11 +5,11 @@
--source include/galera_cluster.inc
--source include/big_test.inc
---connection node_2
+--connection node_1
SET SESSION wsrep_sync_wait = 0;
--source include/kill_galera.inc
---connection node_1
+--connection node_2
SET SESSION wsrep_sync_wait = 0;
--source include/kill_galera.inc
diff --git a/mysql-test/suite/galera/t/GCF-1081.test b/mysql-test/suite/galera/t/GCF-1081.test
new file mode 100644
index 00000000000..8296c55f1b6
--- /dev/null
+++ b/mysql-test/suite/galera/t/GCF-1081.test
@@ -0,0 +1,72 @@
+#
+# GCF-1081 - Assertion `!thd->sp_runtime_ctx`
+#
+# Test replaying of stored procedures
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 0), (3, 0);
+
+DELIMITER |;
+CREATE PROCEDURE proc_update ()
+BEGIN
+ UPDATE t1 SET f2 = 1 where f1 > 0;
+END|
+DELIMITER ;|
+
+# Block the SP
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+--send CALL proc_update ();
+
+# Wait until SP is blocked
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--source include/galera_wait_sync_point.inc
+
+# Issue a conflicting insert on node #2
+--connection node_1a
+SET GLOBAL DEBUG = 'd,sync.wsrep_before_BF_victim_unlock';
+
+--connection node_2
+--send INSERT INTO t1 VALUES (2, 2);
+
+# Wait until it BF aborts the SP
+--connection node_1a
+SET SESSION DEBUG_SYNC = 'now WAIT_FOR sync.wsrep_before_BF_victim_unlock_reached';
+SET GLOBAL DEBUG = '';
+
+# Unblock the SP
+--connection node_1a
+--source include/galera_clear_sync_point.inc
+--source include/galera_signal_sync_point.inc
+
+--connection node_2
+--reap
+SELECT * FROM t1;
+
+# SP succeeds
+--connection node_1
+--reap
+SELECT * FROM t1;
+
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old AS wsrep_local_replays;
+--enable_query_log
+
+DROP PROCEDURE proc_update;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/GCF-939.test b/mysql-test/suite/galera/t/GCF-939.test
new file mode 100644
index 00000000000..95d8ce9b22b
--- /dev/null
+++ b/mysql-test/suite/galera/t/GCF-939.test
@@ -0,0 +1,25 @@
+#
+# GCF-939 Avoid creation of GRA log files when applier is successfull
+#
+
+--source include/galera_cluster.inc
+
+--exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/GRA_*.log
+
+--connection node_1
+--error ER_BAD_TABLE_ERROR
+DROP TABLE t1;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Expect only one GRA_*.log file
+--replace_regex /GRA_.+\.log/GRA_.log/
+--list_files $MYSQLTEST_VARDIR/mysqld.2/data GRA_*.log
+
+DROP TABLE t1;
+CALL mtr.add_suppression("Ignoring error 'Unknown table 'test.t1'' on query");
+--connection node_2
+CALL mtr.add_suppression("Error 'Unknown table 'test.t1'' on query");
+
+
diff --git a/mysql-test/suite/galera/t/MW-284.test b/mysql-test/suite/galera/t/MW-284.test
index 5e17baa1bdb..b2245eace84 100644
--- a/mysql-test/suite/galera/t/MW-284.test
+++ b/mysql-test/suite/galera/t/MW-284.test
@@ -63,7 +63,9 @@ CALL mtr.add_suppression('failed registering on master');
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
--connection node_1
+set global wsrep_on=OFF;
RESET MASTER;
+set global wsrep_on=OFF;
CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member');
--connection node_2
diff --git a/mysql-test/suite/galera/t/MW-292.test b/mysql-test/suite/galera/t/MW-292.test
index ecb1273759e..9580d53d85c 100644
--- a/mysql-test/suite/galera/t/MW-292.test
+++ b/mysql-test/suite/galera/t/MW-292.test
@@ -9,7 +9,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
@@ -25,37 +25,51 @@ START TRANSACTION;
UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
-# Block the commit
+# Block the applier on node #1 and issue a conflicting update on node #2
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
---let $galera_sync_point = commit_monitor_enter_sync
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
---connection node_1
---send COMMIT;
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
-# Wait until commit is blocked
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
-# Issue a conflicting update on node #2
---connection node_2
-UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+# Block the commit, send the COMMIT and wait until it gets blocked
-# Wait for both transactions to be blocked
---connection node_1a
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event::find_row%';
---source include/wait_condition.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT';
---source include/wait_condition.inc
+--connection node_1
+--send COMMIT
-# Unblock the commit
--connection node_1a
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
+
+# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
-# Commit succeeds via replay
+# Commit succeeds
--connection node_1
--reap
diff --git a/mysql-test/suite/galera/t/MW-328A.test b/mysql-test/suite/galera/t/MW-328A.test
index 4d6e1ea3625..268ce28f734 100644
--- a/mysql-test/suite/galera/t/MW-328A.test
+++ b/mysql-test/suite/galera/t/MW-328A.test
@@ -3,8 +3,13 @@
#
#
-# Attempt to insert into t2 and check if insert actually inserted rows if
-# a success was reported.
+# test phase 1 is not deterministic
+#
+# Here we attempt to insert into t2 and check if insert actually
+# inserted rows if a success was reported.
+#
+# However, deadlocks may or may not happen in this test execution
+# it all depends on timing.
#
--source include/galera_cluster.inc
@@ -24,7 +29,7 @@ while ($count)
{
TRUNCATE TABLE t2;
- --error 0,1213
+ --error 0,ER_LOCK_DEADLOCK
INSERT IGNORE INTO t2 SELECT f2 FROM t1;
if ($mysql_errno != 1213) {
--inc $successes
@@ -43,14 +48,31 @@ while ($count)
--enable_query_log
+
+--source suite/galera/t/MW-328-footer.inc
+
#
-# Check that the test produced both deadlocks and successes
+# Test phase 2 is deterministic
+# Here we generate a sure conflict in node 1 and verify that
+# insert failed in both nodes
#
+--connection node_1
+CREATE TABLE t1 (i int primary key, j int) engine=innodb;
+INSERT INTO t1 values (1,0);
---disable_query_log
---eval SELECT $successes > 0 AS have_successes
---eval SELECT $deadlocks > 0 AS have_deadlocks
---enable_query_log
+BEGIN;
+UPDATE t1 SET j=1 WHERE i=1;
+--connection node_2
+UPDATE t1 SET j=2 WHERE i=1;
---source suite/galera/t/MW-328-footer.inc
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SELECT * FROM t1;
+--connection node_2
+SELECT * FROM t1;
+--connection node_1
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/MW-329.test b/mysql-test/suite/galera/t/MW-329.test
index 5baa4d14966..78755fc3b42 100644
--- a/mysql-test/suite/galera/t/MW-329.test
+++ b/mysql-test/suite/galera/t/MW-329.test
@@ -11,11 +11,6 @@ CREATE TABLE t1 (f1 INTEGER, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB;
# We start with a populated table
INSERT INTO t1 (f1) VALUES (1),(65535);
-# Clear the wsrep_local_replays counter
-
-FLUSH STATUS;
-SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
-
#
# Run concurrent INSERTs
#
@@ -42,8 +37,9 @@ DELIMITER ;|
#
--connection node_2
-CALL mtr.add_suppression("WSREP: Failed to report last committed .*");
---let $count = 200
+--let $count = 10
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
while ($count)
{
--let $signature = `SELECT LEFT(MD5(RAND()), 10)`
@@ -57,14 +53,28 @@ while ($count)
--die ROW_COUNT() = 0
}
}
- --dec $count
+
+ #
+ # Ensure at least one replay happens
+ #
+
+ --let $wsrep_replays = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+ --disable_query_log
+ if (`SELECT $wsrep_replays - $wsrep_local_replays_old > 0`) {
+ --dec $count
+ }
+ --enable_query_log
}
#
# Confirm that some transaction replays occurred
#
-SELECT VARIABLE_VALUE > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old > 0 AS wsrep_local_replays;
+--enable_query_log
+
#
# Terminate the stored procedure
diff --git a/mysql-test/suite/galera/t/MW-336.test b/mysql-test/suite/galera/t/MW-336.test
index 8cd363aa019..8ccd48fb35f 100644
--- a/mysql-test/suite/galera/t/MW-336.test
+++ b/mysql-test/suite/galera/t/MW-336.test
@@ -10,7 +10,7 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
--connection node_1
SET GLOBAL wsrep_slave_threads = 10;
SET GLOBAL wsrep_slave_threads = 1;
---let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
--connection node_2
@@ -18,11 +18,11 @@ INSERT INTO t1 VALUES (1);
--connection node_1
SET GLOBAL wsrep_slave_threads = 10;
---let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 20;
---let $wait_condition = SELECT COUNT(*) = 21 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 22 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 1;
@@ -40,7 +40,7 @@ INSERT INTO t1 VALUES (9);
--connection node_1
---let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 10;
@@ -60,7 +60,7 @@ INSERT INTO t1 VALUES (19);
INSERT INTO t1 VALUES (20);
--connection node_1
---let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+--let $wait_condition = SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera/t/MW-360-master.opt b/mysql-test/suite/galera/t/MW-360-master.opt
new file mode 100644
index 00000000000..e51c49c3808
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-360-master.opt
@@ -0,0 +1,2 @@
+--gtid-domain-id=1 --log-bin --log-slave-updates
+
diff --git a/mysql-test/suite/galera/t/MW-360.test b/mysql-test/suite/galera/t/MW-360.test
new file mode 100644
index 00000000000..b776631cfff
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-360.test
@@ -0,0 +1,100 @@
+#
+# MW-360 DROP TABLE containing temporary tables results in binlog divergence
+#
+
+--source include/galera_cluster.inc
+--source include/have_binlog_format_row.inc
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connection node_1
+
+#
+# Straightforward temporary table
+#
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+
+--let $local_uuid = `SELECT LEFT(@@global.gtid_executed, 36)`
+
+#
+# A mix of normal and temporary tables
+#
+
+# Temp table first, normal table second
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+DROP TABLE t1, t2;
+
+# Normal table first, temporary table second
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+DROP TABLE t1, t2;
+
+# Temporary table first, normal table second, temp table third
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+CREATE TEMPORARY TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+
+DROP TABLE t1, t2, t3;
+
+# Normal table first, temporary table second, normal table third
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (2);
+
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (3);
+
+DROP TABLE t1, t2, t3;
+
+#
+# A temporary table masking a normal one
+#
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+
+DROP TABLE t1;
+DROP TABLE t1;
+
+--connection node_2
+--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;`
+
+--connection node_1
+--disable_query_log
+# Node 1 has extra GTID set generated by the temporary table drop
+--eval SELECT GTID_SUBSET('$gtid_executed_node2', @@global.gtid_executed) AS gtid_executed_equal;
+--enable_query_log
diff --git a/mysql-test/suite/galera/t/MW-369.inc b/mysql-test/suite/galera/t/MW-369.inc
index 5fd9ef150ae..71df979d6ba 100644
--- a/mysql-test/suite/galera/t/MW-369.inc
+++ b/mysql-test/suite/galera/t/MW-369.inc
@@ -24,7 +24,6 @@
--connection node_1
SET AUTOCOMMIT=ON;
START TRANSACTION;
-
--eval $mw_369_parent_query
#
@@ -51,7 +50,7 @@ SET SESSION wsrep_sync_wait = 0;
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
---let $galera_sync_point = local_monitor_enter_sync
+--let $galera_sync_point = local_monitor_master_enter_sync
--source include/galera_set_sync_point.inc
--connection node_1
@@ -61,7 +60,7 @@ SET SESSION wsrep_sync_wait = 0;
# Wait until both sync points have been reached
#
--connection node_1a
---let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_enter_sync
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync
--source include/galera_wait_sync_point.inc
#
@@ -70,6 +69,6 @@ SET SESSION wsrep_sync_wait = 0;
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
---let $galera_sync_point = local_monitor_enter_sync
+--let $galera_sync_point = local_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
diff --git a/mysql-test/suite/galera/t/MW-369.test b/mysql-test/suite/galera/t/MW-369.test
index 720d6daf518..99242224864 100644
--- a/mysql-test/suite/galera/t/MW-369.test
+++ b/mysql-test/suite/galera/t/MW-369.test
@@ -24,7 +24,6 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER,
diff --git a/mysql-test/suite/galera/t/MW-388.test b/mysql-test/suite/galera/t/MW-388.test
index de1ac52bf3e..ab15fda64eb 100644
--- a/mysql-test/suite/galera/t/MW-388.test
+++ b/mysql-test/suite/galera/t/MW-388.test
@@ -2,7 +2,6 @@
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
-
--connection node_1
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB;
diff --git a/mysql-test/suite/galera/t/MW-402.test b/mysql-test/suite/galera/t/MW-402.test
index 36b691c6295..4b83e25dc50 100644
--- a/mysql-test/suite/galera/t/MW-402.test
+++ b/mysql-test/suite/galera/t/MW-402.test
@@ -1,6 +1,6 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
#
# we must open connection node_1a here, MW-369.inc will use it later
@@ -135,7 +135,6 @@ SELECT * FROM c;
DROP TABLE c;
DROP TABLE p;
-
#
# CASCADE DELETE tests with two parent tables
# Here we cause cascaded operation on child table through
@@ -151,10 +150,11 @@ DROP TABLE p;
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
-CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER,
- CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE,
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+ f2 INTEGER,
+ CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ ON DELETE CASCADE,
CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1));
-
INSERT INTO p1 VALUES (1, 0);
INSERT INTO p2 VALUES (1, 0);
@@ -171,7 +171,51 @@ INSERT INTO c VALUES (1, 1, 1, 0);
--connection node_1
--reap
-# same as previous, but statements in different order
+--connection node_2
+SELECT * FROM p1;
+SELECT * FROM p2;
+SELECT * FROM c;
+
+DROP TABLE c;
+DROP TABLE p1;
+DROP TABLE p2;
+
+#
+# CASCADE DELETE tests with two parent tables
+# Here we cause cascaded operation on child table through
+# one parent table and issue other delete operation through the
+# other parent table. The cascade progresses to same child table row where
+# we should see the conflict to happen
+#
+# As a result, the update on p2 should fail
+#
+--connection node_1
+
+CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
+CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER,
+ f2 INTEGER,
+ CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1)
+ ON DELETE CASCADE,
+ CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)
+ ON DELETE CASCADE);
+
+INSERT INTO p1 VALUES (1, 0);
+INSERT INTO p2 VALUES (1, 0);
+
+INSERT INTO c VALUES (1, 1, 1, 0);
+
+--let $mw_369_parent_query = DELETE FROM p2 WHERE f1=1
+--let $mw_369_child_query = DELETE FROM p1 WHERE f1=1
+
+--connection node_1a
+--source MW-369.inc
+
+# Commit succeeds
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+
--connection node_2
SELECT * FROM p1;
SELECT * FROM p2;
diff --git a/mysql-test/suite/galera/t/MW-416.test b/mysql-test/suite/galera/t/MW-416.test
index df4fa35abc7..d4dd98c0fcf 100644
--- a/mysql-test/suite/galera/t/MW-416.test
+++ b/mysql-test/suite/galera/t/MW-416.test
@@ -1,12 +1,10 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
---source include/wait_until_ready.inc
-
CREATE USER 'userMW416'@'localhost';
GRANT SELECT, INSERT, UPDATE ON test.* TO 'userMW416'@'localhost';
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
+--let $wsrep_replicated_before = `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'wsrep_replicated'`
--connect userMW416, localhost, userMW416,, test, $NODE_MYPORT_1
--connection userMW416
@@ -69,16 +67,18 @@ DROP EVENT ev;
DROP FUNCTION fun1;
--error 1044,1142,1227,1370
DROP INDEX idx ON t0;
---error 1044,1142,1227,1370,1064
-DROP LOGFILE GROUP lfg;
+# DROP LOGFILE is not in MariaDB
+#--error 1044,1142,1227,1370
+#DROP LOGFILE GROUP lfg;
--error 1044,1142,1227,1370
DROP PROCEDURE proc1;
--error 1044,1142,1227,1370
DROP SERVEr srv;
--error 1044,1142,1227,1370
DROP TABLE t0;
---error 1044,1142,1227,1370,1064
-DROP TABLESPACE tblspc;
+# DROP TABLESPACE is not in MariaDB
+#--error 1044,1142,1227,1370
+#DROP TABLESPACE tblspc;
--error 1044,1142,1227,1360,1370
DROP TRIGGER trg;
--error 1044,1142,1227,1370
@@ -93,8 +93,9 @@ TRUNCATE TABLE t0;
# DCL
# account management
---error 1044,1142,1227,1370,1064
-ALTER USER myuser PASSWORD EXPIRE;
+# PASSWORD EXPIRE is not in MariaDB
+#--error 1044,1142,1227,1370
+#ALTER USER myuser PASSWORD EXPIRE;
--error 1044,1142,1227,1370
CREATE USER myuser IDENTIFIED BY 'pass';
--error 1044,1142,1227,1370
@@ -131,4 +132,7 @@ UNINSTALL PLUGIN plg;
--connection node_1
DROP USER 'userMW416'@'localhost';
SHOW DATABASES;
-SHOW GLOBAL STATUS LIKE 'wsrep_replicated';
+--let $wsrep_replicated_after = `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'wsrep_replicated'`
+--disable_query_log
+--eval SELECT $wsrep_replicated_after - $wsrep_replicated_before AS wsrep_replicated_after_diff
+--enable_query_log
diff --git a/mysql-test/suite/galera/t/MW-86-master.opt b/mysql-test/suite/galera/t/MW-86-master.opt
new file mode 100644
index 00000000000..8a755e98b00
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-86-master.opt
@@ -0,0 +1 @@
+--log-bin --log-slave-updates
diff --git a/mysql-test/suite/galera/t/MW-86-wait1.test b/mysql-test/suite/galera/t/MW-86-wait1.test
index 6c0982ad8b3..aee5a0b2486 100644
--- a/mysql-test/suite/galera/t/MW-86-wait1.test
+++ b/mysql-test/suite/galera/t/MW-86-wait1.test
@@ -6,13 +6,15 @@
--source include/galera_cluster.inc
--source include/have_binlog_format_row.inc
--source include/have_debug_sync.inc
+SET @orig_debug=@@debug;
--connection node_2
# Make sure no signals have been leftover from previous tests to surprise us.
SELECT @@debug_sync;
+set debug_sync='RESET';
SET SESSION wsrep_sync_wait = 1;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
--connection node_1
CREATE TABLE t_wait1 (f1 INTEGER) ENGINE=InnoDB;
@@ -90,17 +92,16 @@ SHOW WARNINGS;
--enable_result_log
# Unblock the background INSERT and remove the sync point.
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
-SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb";
+#SET GLOBAL debug_dbug = "-d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = @orig_debug;
+SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
# This will wait for the background INSERT to complete before we quit
# from the test.
DROP TABLE t_wait1;
-SET GLOBAL debug = NULL;
-SET debug_sync='RESET';
-
# Make sure no pending signals are leftover to surprise subsequent tests.
SELECT @@debug_sync;
diff --git a/mysql-test/suite/galera/t/MW-86-wait8.test b/mysql-test/suite/galera/t/MW-86-wait8.test
index 65e612c5c8e..c40cd8b77c7 100644
--- a/mysql-test/suite/galera/t/MW-86-wait8.test
+++ b/mysql-test/suite/galera/t/MW-86-wait8.test
@@ -4,13 +4,14 @@
--source include/galera_cluster.inc
--source include/have_binlog_format_row.inc
--source include/have_debug_sync.inc
+SET @orig_debug=@@debug;
--connection node_2
# Make sure no signals have been leftover from previous tests to surprise us.
SELECT @@debug_sync;
SET SESSION wsrep_sync_wait = 8;
-SET GLOBAL debug = "+d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
--connection node_1
CREATE TABLE t_wait8 (f1 INTEGER) ENGINE=InnoDB;
@@ -112,8 +113,11 @@ SHOW WARNINGS;
--enable_query_log
# Unblock the background INSERT and remove the sync point.
-SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
+#SET GLOBAL debug = "-d,sync.wsrep_apply_cb";
+SET GLOBAL debug_dbug = @orig_debug;
+
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET debug_sync='RESET';
SET SESSION wsrep_sync_wait = default;
@@ -121,8 +125,5 @@ SET SESSION wsrep_sync_wait = default;
# from the test.
DROP TABLE t_wait8;
-SET GLOBAL debug = NULL;
-SET debug_sync='RESET';
-
# Make sure no pending signals are leftover to surprise subsequent tests.
SELECT @@debug_sync;
diff --git a/mysql-test/suite/galera/t/MW-86.test b/mysql-test/suite/galera/t/MW-86.test
new file mode 100644
index 00000000000..2614eb89504
--- /dev/null
+++ b/mysql-test/suite/galera/t/MW-86.test
@@ -0,0 +1,193 @@
+--source include/galera_cluster.inc
+--source include/have_binlog_format_row.inc
+
+#
+# Test 1: SHOW commands no longer obey wsrep_sync_wait = 1
+#
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 1;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+--disable_result_log
+
+--connection node_1
+CREATE DATABASE db1;
+CREATE TABLE bar (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO bar VALUES (1);
+
+--connection node_2
+SHOW BINARY LOGS;
+
+SHOW BINLOG EVENTS;
+
+--error ER_NO_SUCH_TABLE
+SHOW COLUMNS FROM t1;
+
+--error 0
+SHOW CREATE DATABASE db1;
+
+--error ER_EVENT_DOES_NOT_EXIST
+SHOW CREATE EVENT e1;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW CREATE FUNCTION f1;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW CREATE PROCEDURE p1;
+
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t1;
+
+--error ER_TRG_DOES_NOT_EXIST
+SHOW CREATE TRIGGER tr1;
+
+--error ER_NO_SUCH_TABLE
+SHOW CREATE VIEW v1;
+
+SHOW DATABASES;
+
+SHOW ENGINE InnoDB STATUS;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW FUNCTION CODE f1;
+
+SHOW FUNCTION STATUS;
+
+SHOW GRANTS FOR 'root'@'localhost';
+
+--error ER_NO_SUCH_TABLE
+SHOW INDEX FROM t1;
+
+SHOW OPEN TABLES;
+
+--error ER_SP_DOES_NOT_EXIST
+SHOW PROCEDURE CODE p1;
+
+SHOW PROCEDURE STATUS;
+
+SHOW PRIVILEGES;
+
+SHOW STATUS LIKE 'wsrep_cluster_size';
+
+SHOW TABLE STATUS;
+
+SHOW TABLES;
+
+SHOW TRIGGERS;
+
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+
+--error 0
+SHOW WARNINGS;
+
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+
+SET SESSION wsrep_sync_wait = 8;
+DROP DATABASE db1;
+
+
+#
+# Test 2: SHOW commands now obey wsrep_sync_wait = 8
+#
+
+--connection node_2
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT0.1S";
+SET SESSION wsrep_sync_wait = 8;
+SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
+
+--connection node_1
+CREATE TABLE q (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO q VALUES (1);
+
+--connection node_2
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW BINARY LOGS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW BINLOG EVENTS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW COLUMNS FROM t1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE DATABASE db1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE EVENT e1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE FUNCTION f1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE PROCEDURE p1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE TABLE t1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE TRIGGER tr1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW CREATE VIEW v1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW DATABASES;
+
+--error 0
+SHOW ENGINE InnoDB STATUS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW FUNCTION CODE f1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW FUNCTION STATUS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW GRANTS FOR 'root'@'localhost';
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW INDEX FROM t1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW OPEN TABLES;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW PROCEDURE CODE p1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW PROCEDURE STATUS;
+
+--error 0
+SHOW PRIVILEGES;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW STATUS LIKE 'wsrep_cluster_size';
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW TABLE STATUS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW TABLES;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW TRIGGERS;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW GLOBAL VARIABLES LIKE 'foo_bar';
+
+--error 0
+SHOW WARNINGS;
+
+SET GLOBAL DEBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig"
+
+SET SESSION wsrep_sync_wait = 15;
+SET GLOBAL debug_dbug=NULL;
+SET debug_sync='RESET';
+DROP TABLE q, bar;
+SELECT @@debug_sync; \ No newline at end of file
diff --git a/mysql-test/suite/galera/t/disabled.def b/mysql-test/suite/galera/t/disabled.def
new file mode 100644
index 00000000000..43b652200d1
--- /dev/null
+++ b/mysql-test/suite/galera/t/disabled.def
@@ -0,0 +1,13 @@
+galera_wsrep_provider_unset_set : lp1379204 'Unsupported protocol downgrade: incremental data collection disabled. Expect abort.'
+galera_kill_nochanges : mysql-wsrep#24 Galera server does not restart properly if killed
+galera_toi_ddl_fk_insert : qa#39 galera_toi_ddl_fk_insert fails sporadically
+galera_sst_xtrabackup-v2-options : SST Encryption does not work with xtrabackup 2.4.2
+#galera_autoinc_sst_xtrabackup : due to cert index preload, this test will never pass in current form (gcache.size=1)
+GCF-574 : CTAS is not supported together with SR
+galera_split_brain : is worked on with tracker GCF-998
+galera_sr_kill_all_pcrecovery : is worked on with tracker GCF-1068
+galera_var_notify_cmd : is worked on with tracker GCF-1071
+galera_gcache_recover_manytrx : is worked on with tracker GCF-1077
+GCF-1081 : tries to BF abort earlier trx, needs to be reimplemented
+galera_bf_abort_group_commit : requires galera_sr_bf_abort.inc, probably needs reimplementation
+galera_as_slave_gtid_replicate_do_db_cc : assertion
diff --git a/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt b/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt
index d8ecaacaa4c..6f688b39fd5 100644
--- a/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt
+++ b/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt
@@ -1 +1 @@
---lock_wait_timeout=5 --innodb_lock_wait_timeout=5 --wait_timeout=5
+--lock_wait_timeout=5 --innodb_lock_wait_timeout=5 --wait_timeout=60
diff --git a/mysql-test/suite/galera/t/galera_as_master.test b/mysql-test/suite/galera/t/galera_as_master.test
index 49f3c993256..1c439ffff63 100644
--- a/mysql-test/suite/galera/t/galera_as_master.test
+++ b/mysql-test/suite/galera/t/galera_as_master.test
@@ -64,4 +64,6 @@ RESET SLAVE ALL;
CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work');
--connection node_1
+set global wsrep_on=OFF;
RESET MASTER;
+set global wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid.test b/mysql-test/suite/galera/t/galera_as_master_gtid.test
index 9db104b7cab..9be065e448b 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid.test
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid.test
@@ -27,10 +27,6 @@ INSERT INTO t1 VALUES(1);
--eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match;
--enable_query_log
---replace_result $effective_uuid <effective_uuid>
---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/
-SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120;
-
--connection node_2
INSERT INTO t1 VALUES(2);
@@ -39,10 +35,6 @@ INSERT INTO t1 VALUES(2);
--eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match;
--enable_query_log
---replace_result $effective_uuid <effective_uuid>
---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/
-SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
-
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
@@ -55,10 +47,6 @@ SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
--eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match;
--enable_query_log
---replace_result $effective_uuid <effective_uuid>
---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/
-SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
-
--connection node_1
DROP TABLE t1;
@@ -66,5 +54,17 @@ DROP TABLE t1;
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
+--connection node_1
+--let $gtid_executed_node1 = `SELECT @@global.gtid_executed;`
+
+--connection node_2
+--disable_query_log
+--eval SELECT '$gtid_executed_node1' = @@global.gtid_executed AS gtid_executed_equal
+--enable_query_log
+--connection node_3
+--disable_query_log
+--eval SELECT '$gtid_executed_node1' = @@global.gtid_executed AS gtid_executed_equal
+--enable_query_log
+
STOP SLAVE;
RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test
index 23606d7ac4c..61c7eed6543 100644
--- a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test
+++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test
@@ -24,6 +24,8 @@ INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
STOP SLAVE;
--disable_query_log
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_2, MASTER_AUTO_POSITION=1;
diff --git a/mysql-test/suite/galera/t/galera_as_slave.test b/mysql-test/suite/galera/t/galera_as_slave.test
index 849b75eadd1..144c0a4413d 100644
--- a/mysql-test/suite/galera/t/galera_as_slave.test
+++ b/mysql-test/suite/galera/t/galera_as_slave.test
@@ -5,18 +5,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@@ -29,14 +30,14 @@ INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES (2);
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_1
SELECT COUNT(*) = 2 FROM t1;
INSERT INTO t1 VALUES (3);
--connection node_2
SELECT COUNT(*) = 3 FROM t1;
---connection node_1
+--connection node_3
DROP TABLE t1;
--connection node_2
@@ -46,5 +47,7 @@ DROP TABLE t1;
STOP SLAVE;
RESET SLAVE ALL;
---connection node_1
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test
index 59483d0591c..503d409cc57 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test
@@ -5,18 +5,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
##
## Verify the correct operation of the auto-increment when
@@ -62,14 +63,13 @@ select * from t1;
show variables like 'binlog_format';
show variables like 'auto_increment_increment';
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
-
+--connection node_1
select * from t1;
show variables like 'binlog_format';
show variables like 'auto_increment_increment';
---connection node_1
+--connection node_3
DROP TABLE t1;
--connection node_2
@@ -79,5 +79,7 @@ DROP TABLE t1;
STOP SLAVE;
RESET SLAVE ALL;
---connection node_1
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid.test b/mysql-test/suite/galera/t/galera_as_slave_gtid.test
index c2331a2ae05..3b0f191ad83 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_gtid.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid.test
@@ -8,18 +8,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@@ -34,17 +35,21 @@ SELECT LENGTH(@@global.gtid_binlog_state) > 1;
--source include/wait_condition.inc
--disable_query_log
+
--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
+#--eval SELECT GTID_SUBSET('$gtid_executed_node1', @@global.gtid_executed) AS gtid_executed_equal;
+
--enable_query_log
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_1
SELECT COUNT(*) = 1 FROM t1;
--disable_query_log
--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
+#--eval SELECT GTID_SUBSET('$gtid_executed_node1', @@global.gtid_executed) AS gtid_executed_equal;
--enable_query_log
---connection node_1
+--connection node_3
DROP TABLE t1;
#
@@ -55,7 +60,7 @@ DROP TABLE t1;
--sleep 1
---connection node_3
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf
new file mode 100644
index 00000000000..e0852c50c44
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf
@@ -0,0 +1,17 @@
+!include ../galera_2nodes_as_slave.cnf
+
+[mysqld]
+#gtid-mode=ON
+log-bin=master-bin
+log-bin-index=master-bin
+log-slave-updates
+#enforce-gtid-consistency
+binlog-format=ROW
+
+[mysqld.2]
+replicate-do-db=test1
+replicate-wild-do-table=test1.%
+
+[mysqld.3]
+replicate-do-db=test1
+replicate-wild-do-table=test1.%
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test
new file mode 100644
index 00000000000..7071d4901c8
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test
@@ -0,0 +1,150 @@
+#
+# Test Galera as a slave to a MySQL master using GTIDs
+#
+
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+
+# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/galera_cluster.inc
+
+--connection node_1
+RESET MASTER;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+
+--connection node_2
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+--disable_query_log
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1, MASTER_USER='root';
+--enable_query_log
+START SLAVE;
+
+--connection node_1
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB;
+
+#
+# First , some autocommit stuff
+#
+
+# Simple inserts
+
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+
+# Update that only covers test2.t1
+
+UPDATE test2.t1 SET test2.t1.f2 = 'cde';
+
+# Multi-table UPDATE
+
+UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz';
+
+# Multi-table DELETE
+
+DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3;
+
+#
+# Multi-statement transactions
+#
+
+# Transaction which is not replicated at all
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO test2.t1 (f1) VALUES (999);
+INSERT INTO test2.t1 (f1) VALUES (9999);
+COMMIT;
+
+# Transaction that is completely replicated
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (111);
+INSERT INTO test1.t1 (f1) VALUES (222);
+COMMIT;
+
+# Transaction that is partially replicated
+
+START TRANSACTION;
+INSERT INTO test1.t1 (f1) VALUES (333);
+INSERT INTO test2.t1 (f1) VALUES (99999);
+COMMIT;
+
+#
+# Make sure binary logs and gtid_executed strings are equal
+#
+
+--sleep 2
+--connection node_2
+--let $effective_uuid = `SELECT LEFT(@@global.gtid_current_pos, 36)`
+--let $gtid_executed_node2 = `SELECT @@global.gtid_current_pos;`
+
+--replace_result $effective_uuid <effective_uuid>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+
+--connection node_3
+
+--disable_query_log
+--eval SELECT '$gtid_executed_node2' = @@global.gtid_current_pos AS gtid_executed_equal;
+--enable_query_log
+
+--replace_result $effective_uuid <effective_uuid>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256;
+
+#
+# Final consistency checks
+#
+
+--let $diff_servers = 2 3
+--source include/diff_servers.inc
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f1 IN (1,2);
+SELECT COUNT(*) = 3 FROM test1.t1 WHERE f1 IN (111,222,333);
+SELECT COUNT(*) = 2 FROM test1.t1 WHERE f2 = 'klm';
+
+--error 1049
+USE test2;
+
+#
+# Cleanup
+#
+
+--connection node_1
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+
+--sleep 1
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+STOP SLAVE;
+RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test
new file mode 100644
index 00000000000..1604016f3c3
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test
@@ -0,0 +1,176 @@
+#
+# Test the case where a Galera slave to async replication goes non-prim while
+# a stream of replication events including filtered events is arriving
+#
+
+--source include/have_innodb.inc
+--source include/have_log_bin.inc
+--source include/big_test.inc
+
+# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/galera_cluster.inc
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+RESET MASTER;
+SET GLOBAL wsrep_on=ON;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+
+--connection node_2
+SET global wsrep_on=OFF;
+RESET MASTER;
+SET global wsrep_on=ON;
+
+--connection node_2
+--disable_query_log
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1;
+--enable_query_log
+START SLAVE USER='root';
+
+--connection node_1
+CREATE SCHEMA test1;
+CREATE SCHEMA test2;
+USE test1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+USE test2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+INSERT INTO test1.t1 (f1) VALUES (1);
+INSERT INTO test2.t1 (f1) VALUES (1);
+
+INSERT INTO test1.t1 (f1) VALUES (2);
+INSERT INTO test2.t1 (f1) VALUES (2);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 2 FROM test1.t1;
+--source include/wait_condition.inc
+
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+INSERT INTO test1.t1 (f1) VALUES (3);
+INSERT INTO test2.t1 (f1) VALUES (3);
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--let $slave_sql_errno = 1047
+--source include/wait_for_slave_sql_error.inc
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+INSERT INTO test1.t1 (f1) VALUES (4);
+INSERT INTO test2.t1 (f1) VALUES (4);
+
+--connection node_2
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (5);
+INSERT INTO test2.t1 (f1) VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+SET SESSION wsrep_on=ON;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_ready';
+--source include/wait_condition.inc
+
+--connection node_1
+INSERT INTO test1.t1 (f1) VALUES (6);
+INSERT INTO test2.t1 (f1) VALUES (6);
+
+--connection node_2
+START SLAVE;
+
+#
+# Consistency checks
+#
+
+--sleep 2
+--connection node_2
+--let $wait_condition = SELECT COUNT(DISTINCT f1) = 6 FROM test1.t1;
+--source include/wait_condition.inc
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(DISTINCT f1) = 6 FROM test1.t1;
+--source include/wait_condition.inc
+
+--connection node_2
+--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;`
+
+--let $effective_uuid_1 = `SELECT SUBSTRING_INDEX(@@global.gtid_executed, ':', 1)`
+--let $effective_uuid_2 = `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(@@global.gtid_executed, '\n', -1), ':', 1)`
+
+--replace_result $effective_uuid_1 <effective_uuid_1> $effective_uuid_2 <effective_uuid_2>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+
+--error 1049
+USE test2;
+
+--connection node_3
+
+--disable_query_log
+--eval SELECT '$gtid_executed_node2' = @@global.gtid_executed AS gtid_executed_equal;
+--enable_query_log
+
+--error 1049
+USE test2;
+
+--replace_result $effective_uuid_1 <effective_uuid_1> $effective_uuid_2 <effective_uuid_2>
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120;
+
+#
+# Cleanup
+#
+
+--connection node_1
+DROP SCHEMA test1;
+DROP SCHEMA test2;
+
+--sleep 1
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_2
+STOP SLAVE;
+RESET SLAVE ALL;
+CALL mtr.add_suppression("GTID replication failed");
+CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed");
+CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
+CALL mtr.add_suppression("TO isolation failed for");
+CALL mtr.add_suppression("Slave SQL: Error 'Deadlock found when trying to get lock; try restarting transaction' on query");
+CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query");
+CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047");
diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test
index 46a93458271..53b5498a87d 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test
@@ -7,22 +7,23 @@
--source include/have_innodb.inc
--source include/big_test.inc
+--source include/galera_cluster.inc
# Step #1. Establish replication
#
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
-#
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
---source include/galera_cluster.inc
+# As node 4 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_4 connection here
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1, MASTER_USER='root';
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_4, MASTER_USER='root';
--enable_query_log
START SLAVE;
SET SESSION wsrep_sync_wait = 0;
---connection node_1
+--connection node_4
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
--connection node_2
@@ -34,22 +35,21 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
---connection node_3
+--connection node_1
--source include/wait_until_connected_again.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
# Step #3. Force async replication to fail by creating a replication event while the slave is non-prim
---connection node_1
+--connection node_4
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
--connection node_2
--sleep 5
--let $value = query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1)
---connection node_3
+--connection node_1
--disable_query_log
--eval SELECT "$value" IN ("Error 'Unknown command' on query. Default database: 'test'. Query: 'BEGIN'", "Node has dropped from cluster") AS expected_error
--enable_query_log
@@ -58,7 +58,7 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
--connection node_2
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
---connection node_3
+--connection node_1
--source include/wait_until_connected_again.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
@@ -74,7 +74,7 @@ START SLAVE;
--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
--source include/wait_condition.inc
---connection node_1
+--connection node_4
DROP TABLE t1;
--sleep 2
@@ -92,5 +92,7 @@ CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be
CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047");
---connection node_1
+--connection node_4
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_preordered.test b/mysql-test/suite/galera/t/galera_as_slave_preordered.test
index 6f221f83b3a..5b3c78b2cb1 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_preordered.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_preordered.test
@@ -6,14 +6,15 @@
--source include/have_innodb.inc
--source include/have_log_bin.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE USER='root';
@@ -21,7 +22,7 @@ START SLAVE USER='root';
# Issue many large-ish transaction on the async master
#
---connection node_1
+--connection node_3
CREATE TABLE ten (f1 INTEGER);
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
@@ -63,8 +64,7 @@ while ($count)
SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1;
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
---connection node_3
+--connection node_1
SELECT COUNT(*) = 2 * 100 * 10 * 10 FROM t1;
SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1;
@@ -72,7 +72,7 @@ SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1;
# Cleanup
#
---connection node_1
+--connection node_3
DROP TABLE t1;
DROP TABLE ten;
@@ -80,5 +80,8 @@ DROP TABLE ten;
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ten';
+--source include/wait_condition.inc
+
STOP SLAVE;
RESET SLAVE ALL;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test b/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test
index 460e040c010..fa5f3f9c7c6 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test
@@ -5,18 +5,19 @@
#
--source include/have_innodb.inc
-
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
--enable_query_log
START SLAVE;
---connection node_1
+--connection node_3
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
@@ -36,7 +37,7 @@ INSERT INTO t1 VALUES(5);
SELECT COUNT(*) = 4 FROM t1;
# Bundle is now complete, the last INSERT and the DROP are delivered
---connection node_1
+--connection node_3
DROP TABLE t1;
--connection node_2
diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf b/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf
index b4bf5f02171..7e557717744 100644
--- a/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf
+++ b/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
[mysqld.1]
diff --git a/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf
new file mode 100644
index 00000000000..612418c17c0
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf
@@ -0,0 +1,15 @@
+!include ../galera_2nodes.cnf
+
+# We set repl.commit_order=1 in order to disable provider commit
+# ordering.
+
+[mysqld.1]
+log-bin
+log-slave-updates
+wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;repl.commit_order=1'
+
+[mysqld.2]
+
+log-bin
+log-slave-updates
+wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;repl.commit_order=1' \ No newline at end of file
diff --git a/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test
new file mode 100644
index 00000000000..255298565f0
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test
@@ -0,0 +1,76 @@
+#
+# This test uses galera_sr_bf_abort.inc to probe various BF abort points
+# for SR transactions with wsrep provider commit ordering disabled.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Control connection for manipulating sync points on node 1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+
+# SR bf abort on fragment
+--let $wsrep_trx_fragment_size = 1
+--echo galera_sr_bf_abort_at_commit = 0
+--let $galera_sr_bf_abort_at_commit = 0
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+# SR bf abort on commit fragment
+--let $wsrep_trx_fragment_size = 1
+--echo galera_sr_bf_abort_at_commit = 1
+--let $galera_sr_bf_abort_at_commit = 1
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+# Normal bf abort on commit
+--let $wsrep_trx_fragment_size = 0
+--echo galera_sr_bf_abort_at_commit = 1
+--let $galera_sr_bf_abort_at_commit = 1
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source suite/galera/t/galera_sr_bf_abort.inc
+
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test
new file mode 100644
index 00000000000..1e5fec5842a
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test
@@ -0,0 +1,22 @@
+#
+# This test verifies that the server can be shut down even if
+# some of the wsrep transactions are in QUERY_COMMITTING state.
+# In this case the shutdown sequence may do a BF abort for the
+# connection.
+#
+
+--source include/have_innodb.inc
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+
+--connection node_2
+SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue';
+--send INSERT INTO t1 VALUES (1)
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/restart_mysqld.inc
+
+--connection node_1
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_create_table_as_select.test b/mysql-test/suite/galera/t/galera_create_table_as_select.test
new file mode 100644
index 00000000000..a6c1f657280
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_create_table_as_select.test
@@ -0,0 +1,145 @@
+#
+# CREATE TABLE AS SELECT tests
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+SET SESSION default_storage_engine=InnoDB;
+
+# Left table already exists
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 AS SELECT * FROM t2;
+DROP TABLE t1,t2;
+
+# Right table does not exist
+--error ER_NO_SUCH_TABLE
+CREATE TABLE t1 AS SELECT * FROM t2;
+
+# No right table at all
+CREATE TABLE t1 AS SELECT 1 FROM DUAL;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+
+# Empty right table
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t1 AS SELECT * FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+DROP TABLE t1,t2;
+
+# Right table is MyISAM
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT * FROM t2;
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1,t2;
+
+# Right side is a subquery
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE t1 AS SELECT MAX(f1) AS f1 FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT f1 = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1,t2;
+
+# Inside a stored procedure
+
+--connection node_1
+DELIMITER |;
+CREATE PROCEDURE sp1 ()
+BEGIN
+ CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+ INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+ CREATE TABLE t1 AS SELECT * FROM t2;
+END|
+DELIMITER ;|
+CALL sp1();
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1, t2;
+DROP PROCEDURE sp1;
+
+# Inside a prepared statement
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT * FROM t2';
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
+
+#
+# Multi-master conflict
+#
+
+--connection node_1
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+LOCK TABLE t2 WRITE;
+
+--connection node_1
+--send CREATE TABLE t1 AS SELECT * FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t2;
+CREATE TABLE t1 AS SELECT * FROM t2;
+
+--connection node_1a
+UNLOCK TABLES;
+
+--connection node_1
+--error ER_TABLE_EXISTS_ERROR,ER_LOCK_DEADLOCK
+--reap
+
+DROP TABLE t1, t2;
+
+#
+# Temporary table
+#
+
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+
+CREATE TEMPORARY TABLE t1 AS SELECT * FROM t2;
+
+--connection node_2
+--error ER_NO_SUCH_TABLE
+SELECT * FROM t1;
+
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query");
+
+--connection node_1
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera/t/galera_defaults.test b/mysql-test/suite/galera/t/galera_defaults.test
index facc5180f2f..ffa88ea0a01 100644
--- a/mysql-test/suite/galera/t/galera_defaults.test
+++ b/mysql-test/suite/galera/t/galera_defaults.test
@@ -19,7 +19,7 @@ source ../wsrep/include/check_galera_version.inc;
# Global Variables
-SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%';
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@@ -54,8 +54,10 @@ ORDER BY VARIABLE_NAME;
$wsrep_provider_options =~ s/gcs\.recv_q_hard_limit = .*?;/<GCS_RECV_Q_HARD_LIMIT>;/sgio;
$wsrep_provider_options =~ s/ist\.recv_addr = .*?;/<IST_RECV_ADDR>;/sgio;
$wsrep_provider_options =~ s/evs\.evict = .*?;/<EVS_EVICT>;/sgio;
+ $wsrep_provider_options =~ s/repl\.proto_max = .*?;/<REPL_PROTO_MAX>;/sgio;
$wsrep_provider_options =~ s/signal = .*?;\s*//sgio;
$wsrep_provider_options =~ s/dbug = .*?;\s*//sgio;
+ $wsrep_provider_options =~ s/gcs.recv_q_hard_limit = .*?;\s*/<RECV_Q_HARD_LIMIT>;/sgio;
$wsrep_provider_options =~ s/repl.proto_max = .*?;\s*/<REPL_PROTO_MAX>;/sgio;
print $wsrep_provider_options."\n";
EOF
diff --git a/mysql-test/suite/galera/t/galera_forced_binlog_format.test b/mysql-test/suite/galera/t/galera_forced_binlog_format.test
index 364f41529a4..e9d7fa1c3a3 100644
--- a/mysql-test/suite/galera/t/galera_forced_binlog_format.test
+++ b/mysql-test/suite/galera/t/galera_forced_binlog_format.test
@@ -7,7 +7,10 @@
--source include/galera_cluster.inc
--connection node_1
+SEt GLOBAL wsrep_on=OFF;
RESET MASTER;
+SEt GLOBAL wsrep_on=ON;
+FLUSH BINARY LOGS;
SET SESSION binlog_format = 'STATEMENT';
@@ -40,6 +43,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
DROP USER dummy@localhost;
DROP DATABASE testdb_9401;
---source include/galera_end.inc
+#--source include/galera_end.inc
--echo # End of tests
diff --git a/mysql-test/suite/galera/t/galera_ftwrl_drain.test b/mysql-test/suite/galera/t/galera_ftwrl_drain.test
index 690e890cdea..857a1a34485 100644
--- a/mysql-test/suite/galera/t/galera_ftwrl_drain.test
+++ b/mysql-test/suite/galera/t/galera_ftwrl_drain.test
@@ -12,7 +12,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
--connection node_1
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test b/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test
index b7fd9cf3aed..aeca4c6a6ec 100644
--- a/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test
+++ b/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test
@@ -48,8 +48,8 @@ DROP TABLE t1;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
# Confirm that IST did not take place
---let $assert_text = IST first seqno 2 not found from cache, falling back to SST
---let $assert_select = IST first seqno 2 not found from cache, falling back to SST
+--let $assert_text = IST first seqno [24] not found from cache, falling back to SST
+--let $assert_select = IST first seqno [24] not found from cache, falling back to SST
--let $assert_count = 1
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
--let $assert_only_after = starting as process
diff --git a/mysql-test/suite/galera/t/galera_gtid-master.opt b/mysql-test/suite/galera/t/galera_gtid-master.opt
index 8a755e98b00..30317469ae7 100644
--- a/mysql-test/suite/galera/t/galera_gtid-master.opt
+++ b/mysql-test/suite/galera/t/galera_gtid-master.opt
@@ -1 +1 @@
---log-bin --log-slave-updates
+--log-bin --log-slave-updates --loose-new-servers-for-galera_gtid-test
diff --git a/mysql-test/suite/galera/t/galera_gtid_slave.test b/mysql-test/suite/galera/t/galera_gtid_slave.test
index 19bfd8e17db..a356f1fceca 100644
--- a/mysql-test/suite/galera/t/galera_gtid_slave.test
+++ b/mysql-test/suite/galera/t/galera_gtid_slave.test
@@ -58,6 +58,16 @@ SELECT @@global.gtid_binlog_state;
--connection node_1
DROP TABLE t1,t2;
+SET GLOBAL wsrep_on=OFF;
+reset master;
+SET GLOBAL wsrep_on=ON;
+#
+# Unfortunately without the sleep below the following statement fails with "query returned no rows", which
+# is difficult to understand given that it is an aggregate query. A "query execution was interrupted"
+# warning is also reported by MTR, which is also weird.
+#
+
+--sleep 1
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
@@ -70,10 +80,14 @@ DROP TABLE t1,t2;
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
+SET GLOBAL wsrep_on=OFF;
reset master;
+SET GLOBAL wsrep_on=ON;
--connection node_3
+SET GLOBAL wsrep_on=OFF;
reset master;
+SET GLOBAL wsrep_on=ON;
--connection node_1
reset master;
diff --git a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
index 3fe94ad16b7..1b1c2411bc2 100644
--- a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
+++ b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
@@ -8,21 +8,21 @@
--source include/big_test.inc
--source include/have_innodb.inc
-# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
+# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
+# we open the node_3 connection here
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--echo #Connection 2
--connection node_2
--disable_query_log
---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1,master_use_gtid=slave_pos;
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3,master_use_gtid=slave_pos;
--enable_query_log
START SLAVE;
--sleep 1
-
---echo #Connection 1
---connection node_1
+--echo #Connection 3
+--connection node_3
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB;
INSERT INTO t2 VALUES(1,11);
INSERT INTO t2 VALUES(2,22);
@@ -30,7 +30,6 @@ INSERT INTO t2 VALUES(3,33);
SELECT @@global.gtid_binlog_state;
--source include/save_master_gtid.inc
-
--echo #Connection 2
--connection node_2
--source include/sync_with_master_gtid.inc
@@ -40,9 +39,8 @@ INSERT INTO t2 VALUES(4,44);
INSERT INTO t2 VALUES(5,55);
INSERT INTO t2 VALUES(6,66);
SELECT @@global.gtid_binlog_state;
-
---echo #Connection 3
---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't2';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 6 FROM t2;
@@ -53,8 +51,8 @@ INSERT INTO t2 VALUES(8,88);
SELECT @@global.gtid_binlog_state;
#Perform SST
---echo #Connection 1
---connection node_1
+--echo #Connection 3
+--connection node_3
CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -62,7 +60,6 @@ INSERT INTO t1 VALUES ('node1_committed_before');
INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
--source include/save_master_gtid.inc
-
--echo #Connection 2
--connection node_2
--source include/sync_with_master_gtid.inc
@@ -71,22 +68,21 @@ START TRANSACTION;
INSERT INTO t1 VALUES ('node2_committed_before');
INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 4 FROM t1;
--source include/wait_condition.inc
---let $node_1= node_2
---let $node_2= node_3
+--let $node_1= node_1
+--let $node_2= node_2
--source include/auto_increment_offset_save.inc
---echo Shutting down server ...
---source include/shutdown_mysqld.inc
-
-
--echo #Connection 2
--connection node_2
+--echo Shutting down server ...
+--source include/shutdown_mysqld.inc
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
SET AUTOCOMMIT=OFF;
@@ -94,51 +90,46 @@ START TRANSACTION;
INSERT INTO t1 VALUES ('node1_committed_during');
INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 2
+--connection node_2
--echo Starting server ...
--source include/start_mysqld.inc
+
--source include/wait_until_ready.inc
--source include/auto_increment_offset_restore.inc
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES ('node3_committed_after');
-INSERT INTO t1 VALUES ('node3_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
-
---echo #Connection 2
---connection node_2
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 8 FROM t1;
--source include/wait_condition.inc
Select * from t1 order by f1;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 2
+--connection node_2
Select * from t1 order by f1;
#SST Done
--sleep 1
+--echo #Connection 1
+--connection node_1
+SELECT @@global.gtid_binlog_state;
--echo #Connection 2
--connection node_2
SELECT @@global.gtid_binlog_state;
-
--echo #Connection 3
--connection node_3
-SELECT @@global.gtid_binlog_state;
-
---echo #Connection 1
---connection node_1
SET AUTOCOMMIT=ON;
#drop table t1;
#CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
-
--echo #Connection 2
--connection node_2
SET AUTOCOMMIT=ON;
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
SET AUTOCOMMIT=ON;
#
@@ -148,10 +139,9 @@ SET AUTOCOMMIT=ON;
STOP slave;
--sleep 1
INSERT INTO t1 VALUES ('node2_slave_stoped');
-
---echo #Connection 1
---connection node_1
-INSERT INTO t1 VALUES ('node1_normal_entry');
+--echo #Connection 3
+--connection node_3
+INSERT INTO t1 VALUES ('node3_normal_entry');
--source include/save_master_gtid.inc
#start slave
@@ -163,16 +153,14 @@ start slave;
INSERT INTO t1 VALUES ('node2_slave_started');
SELECT count(*) from t1;
SELECT @@global.gtid_binlog_state;
-
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 12 FROM t1;
--source include/wait_condition.inc
SELECT count(*) from t1;
SELECT @@global.gtid_binlog_state;
-
---echo #Connection 1
---connection node_1
+--echo #Connection 3
+--connection node_3
DROP TABLE t2,t1;
# Unfortunately without the sleep below the following statement fails with "query returned no rows", which
@@ -181,27 +169,26 @@ DROP TABLE t2,t1;
#
--sleep 3
-
--echo #Connection 2
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--source include/wait_condition.inc
-
---echo #Connection 3
---connection node_3
+--echo #Connection 1
+--connection node_1
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
-
--echo #Connection 2
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
+set global wsrep_on=OFF;
reset master;
-
---echo #Connection 3
---connection node_3
-reset master;
-
+set global wsrep_on=ON;
--echo #Connection 1
--connection node_1
+set global wsrep_on=OFF;
+reset master;
+set global wsrep_on=ON;
+--echo #Connection 3
+--connection node_3
reset master;
diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf
index 41a1aab382b..1542376b2b8 100644
--- a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf
+++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth=root:
innodb_flush_log_at_trx_commit=0
diff --git a/mysql-test/suite/galera/t/galera_ist_progress.test b/mysql-test/suite/galera/t/galera_ist_progress.test
index 3ba63415c28..dd93161eab8 100644
--- a/mysql-test/suite/galera/t/galera_ist_progress.test
+++ b/mysql-test/suite/galera/t/galera_ist_progress.test
@@ -58,8 +58,8 @@ SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
--let $assert_only_after = Need state transfer
---let $assert_text = Receiving IST: 11 writesets, seqnos
---let $assert_select = Receiving IST: 11 writesets, seqnos
+--let $assert_text = Receiving IST: 1[13] writesets
+--let $assert_select = Receiving IST: 1[13] writesets
--source include/assert_grep.inc
--let $assert_text = Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete
diff --git a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test
index 633318629a6..5e2343aa3e6 100644
--- a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test
+++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test
@@ -7,7 +7,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
# This could cause out of storage if run /dev/shm
--source include/big_test.inc
diff --git a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf
index a762b939f69..75dff78149d 100644
--- a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf
+++ b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth=root:
[mysqld.1]
diff --git a/mysql-test/suite/galera/t/galera_log_bin.test b/mysql-test/suite/galera/t/galera_log_bin.test
index 2f0faa761c5..57df53e29b1 100644
--- a/mysql-test/suite/galera/t/galera_log_bin.test
+++ b/mysql-test/suite/galera/t/galera_log_bin.test
@@ -36,4 +36,6 @@ DROP TABLE t1;
DROP TABLE t2;
--connection node_1
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
diff --git a/mysql-test/suite/galera/t/galera_migrate.cnf b/mysql-test/suite/galera/t/galera_migrate.cnf
index ed48f208e52..2e1e9f161a9 100644
--- a/mysql-test/suite/galera/t/galera_migrate.cnf
+++ b/mysql-test/suite/galera/t/galera_migrate.cnf
@@ -29,11 +29,13 @@ wsrep_sync_wait = 15
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+log-slave-updates
[mysqld.4]
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+log-slave-updates
[ENV]
NODE_MYPORT_1= @mysqld.1.port
diff --git a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test
index 08ed3fac67e..d5ae8e11638 100644
--- a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test
+++ b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test
@@ -32,8 +32,8 @@ INSERT INTO t2 VALUES (1);
--connection node_2a
--sleep 1
SET SESSION wsrep_sync_wait=0;
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%';
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%';
SELECT COUNT(*) = 0 FROM t1;
SELECT COUNT(*) = 0 FROM t2;
diff --git a/mysql-test/suite/galera/t/galera_parallel_simple.test b/mysql-test/suite/galera/t/galera_parallel_simple.test
index 2cd840123cf..51bb1355ba4 100644
--- a/mysql-test/suite/galera/t/galera_parallel_simple.test
+++ b/mysql-test/suite/galera/t/galera_parallel_simple.test
@@ -47,7 +47,7 @@ SET SESSION wsrep_sync_wait = 0;
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock%';
--source include/wait_condition.inc
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'applied write set%';
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committing%';
--source include/wait_condition.inc
UNLOCK TABLES;
diff --git a/mysql-test/suite/galera/t/galera_pc_recovery.test b/mysql-test/suite/galera/t/galera_pc_recovery.test
new file mode 100644
index 00000000000..ae8647eae22
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_pc_recovery.test
@@ -0,0 +1,93 @@
+#
+# Test the pc.recovery=1 option. Killing all nodes simultaneously and
+# restarting them should succeed and the cluster should re-form.
+#
+
+--source include/have_innodb.inc
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Instruct MTR to not restart the nodes automatically when they are killed
+
+--let $NODE_1_PIDFILE = `SELECT @@pid_file`
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+--let $NODE_2_PIDFILE = `SELECT @@pid_file`
+
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--exec kill -9 `cat $NODE_1_PIDFILE` `cat $NODE_2_PIDFILE`
+
+# Perform --wsrep-recover and preserve the positions into variables by placing them in $MYSQL_TMP_DIR/galera_wsrep_start_position.inc and then --source'ing it
+
+--exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.1.log > $MYSQL_TMP_DIR/galera_wsrep_recover.1.log 2>&1
+--exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.2.log > $MYSQL_TMP_DIR/galera_wsrep_recover.2.log 2>&1
+
+--perl
+ use strict;
+ my $wsrep_start_position1 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.1.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`;
+ chomp($wsrep_start_position1);
+
+ my $wsrep_start_position2 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.2.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`;
+ chomp($wsrep_start_position2);
+
+ die if $wsrep_start_position1 eq '' || $wsrep_start_position2 eq '';
+
+ open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/galera_wsrep_start_position.inc") or die;
+ print FILE "--let \$galera_wsrep_start_position1 = $wsrep_start_position1\n";
+ print FILE "--let \$galera_wsrep_start_position2 = $wsrep_start_position2\n";
+ close FILE;
+EOF
+
+--source $MYSQL_TMP_DIR/galera_wsrep_start_position.inc
+
+if ($galera_wsrep_start_position1 == '') {
+ --die "Could not obtain wsrep_start_position."
+}
+
+if ($galera_wsrep_start_position2 == '') {
+ --die "Could not obtain wsrep_start_position."
+}
+
+--remove_file $MYSQL_TMP_DIR/galera_wsrep_start_position.inc
+
+# Instruct MTR to perform the actual restart using --wsrep-start-position . Proper --wsrep_cluster_address is used as my.cnf only contains 'gcomm://' for node #1
+
+--exec echo "restart: --wsrep-start-position=$galera_wsrep_start_position1 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--exec echo "restart: --wsrep-start-position=$galera_wsrep_start_position2 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+
+--sleep 5
+--connection node_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+# Confirm that the cluster has re-formed and data is present
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("points to own listening address, blacklisting");
+CALL mtr.add_suppression("non weight changing install in S_PRIM");
+CALL mtr.add_suppression("No re-merged primary component found");
+
+--connection node_2
+CALL mtr.add_suppression("points to own listening address, blacklisting");
+CALL mtr.add_suppression("non weight changing install in S_PRIM");
+CALL mtr.add_suppression("No re-merged primary component found");
diff --git a/mysql-test/suite/galera/t/galera_split_brain.test b/mysql-test/suite/galera/t/galera_split_brain.test
index a85a2ad9b8d..91a2cc326a2 100644
--- a/mysql-test/suite/galera/t/galera_split_brain.test
+++ b/mysql-test/suite/galera/t/galera_split_brain.test
@@ -1,6 +1,8 @@
#
-# Confirm that with two nodes, killing one causes the other to stop accepting connections
-# The pc.ignore_sb=true wsrep_provider option is tested in the galera_kill_* tests.
+# Confirm that with two nodes, killing one causes the other to stop accepting
+# connections.
+# The pc.ignore_sb=true wsrep_provider option is tested in the galera_kill_*
+# tests.
#
--source include/galera_cluster.inc
diff --git a/mysql-test/suite/galera/t/galera_ssl_upgrade.test b/mysql-test/suite/galera/t/galera_ssl_upgrade.test
index a424942da30..6dc3bf7a5a3 100644
--- a/mysql-test/suite/galera/t/galera_ssl_upgrade.test
+++ b/mysql-test/suite/galera/t/galera_ssl_upgrade.test
@@ -46,4 +46,8 @@ SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_N
--source include/wait_condition.inc
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+# 5. Make sure node_2 is ready as well
+--connection node_2
+--source include/galera_wait_ready.inc
+
# Upgrade complete. Both nodes now use the new key and certificate
diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.test b/mysql-test/suite/galera/t/galera_sst_mysqldump.test
index 835fac94a68..b72fa687411 100644
--- a/mysql-test/suite/galera/t/galera_sst_mysqldump.test
+++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.test
@@ -1,6 +1,6 @@
--source include/big_test.inc
--source include/galera_cluster.inc
-
+--source include/have_innodb.inc
--source suite/galera/include/galera_sst_set_mysqldump.inc
--let $node_1=node_1
@@ -14,7 +14,6 @@
--source suite/galera/include/galera_st_shutdown_slave.inc
--source suite/galera/include/galera_st_clean_slave.inc
-
--source suite/galera/include/galera_st_kill_slave.inc
--source suite/galera/include/galera_st_kill_slave_ddl.inc
diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf
index 3abf2549aae..db17e3f81b7 100644
--- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf
index 0025b259ec5..2aef1376ab6 100644
--- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf
index 63d05104a37..5a989ea8177 100644
--- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf
+++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf
@@ -1,7 +1,7 @@
!include ../galera_2nodes.cnf
[mysqld]
-wsrep_sst_method=xtrabackup-v2
+wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
wsrep_debug=ON
diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_error.test b/mysql-test/suite/galera/t/galera_toi_ddl_error.test
index c586d97bdb5..6ee2a6e9b16 100644
--- a/mysql-test/suite/galera/t/galera_toi_ddl_error.test
+++ b/mysql-test/suite/galera/t/galera_toi_ddl_error.test
@@ -27,3 +27,8 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP TABLE ten;
+
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
+
+--connection node_2
+CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query."); \ No newline at end of file
diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test
index 12c83a1f87a..91bcadc0e5d 100644
--- a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test
+++ b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test
@@ -11,20 +11,31 @@
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
---connection node_1
-SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
---send ALTER TABLE t1 ADD COLUMN f2 INTEGER;
-
--let $galera_connection_name = node_1a
--let $galera_server_number = 1
--source include/galera_connect.inc
+SET SESSION wsrep_sync_wait = 0;
--let $galera_connection_name = node_1b
--let $galera_server_number = 1
--source include/galera_connect.inc
+# node_1c tests write to unrelated table trough a transaction
+--let $galera_connection_name = node_1c
+--let $galera_server_number = 1
+--source include/galera_connect.inc
+
+--connection node_1
+SET DEBUG_SYNC= 'RESET';
+SET DEBUG_SYNC = 'alter_table_before_open_tables SIGNAL before_open_tables WAIT_FOR continue';
+--send ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+--sleep 10
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now WAIT_FOR before_open_tables';
+
+# if we would retry the insert, it would fail for wrong column count
+# on second try
+SET wsrep_retry_autocommit=0;
# Allowed
SELECT COUNT(*) = 0 FROM t1;
@@ -32,33 +43,49 @@ SELECT COUNT(*) = 0 FROM t1;
# Allowed
SELECT COUNT(*) = 0 FROM t2;
-# Not allowed
---error ER_LOCK_DEADLOCK,ER_ERROR_DURING_COMMIT
-INSERT INTO t1 VALUES (1);
+# Not allowed, this will hang because of ALTER
+--send INSERT INTO t1 VALUES (1);
+
+--connection node_1c
+SET SESSION wsrep_sync_wait = 0;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
# Allowed
+SELECT COUNT(*) = 0 FROM t1;
+
+# Allowed
+SELECT COUNT(*) = 0 FROM t2;
+
+# Allowed (until commit)
INSERT INTO t2 VALUES (1);
# Hangs
--send COMMIT;
---sleep 1
--connection node_1b
SET SESSION wsrep_sync_wait = 0;
# The Commit issued above is still not done
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
+--sleep 1
SELECT COUNT(*) = 0 FROM t2;
+
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit';
+
SET DEBUG_SYNC= 'now SIGNAL continue';
--connection node_1a
+--error ER_LOCK_DEADLOCK
+--reap
+
+--connection node_1c
+# this will succeeed, becaus the query will be replayed
--reap
--connection node_1
--reap
+
SELECT COUNT(*) = 0 FROM t1;
SELECT COUNT(*) = 1 FROM t2;
@@ -66,11 +93,5 @@ SELECT COUNT(*) = 1 FROM t2;
SELECT COUNT(*) = 0 FROM t1;
SELECT COUNT(*) = 1 FROM t2;
---connection node_1
-SET DEBUG_SYNC= 'RESET';
-
---connection node_1b
-SET DEBUG_SYNC= 'RESET';
-
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera/t/galera_transaction_replay.test b/mysql-test/suite/galera/t/galera_transaction_replay.test
index 29870829ba3..655714f26c9 100644
--- a/mysql-test/suite/galera/t/galera_transaction_replay.test
+++ b/mysql-test/suite/galera/t/galera_transaction_replay.test
@@ -1,12 +1,25 @@
#
-# This test tests the operation of transaction replay. If a potentially conflicting remote transaction arrives at
-# just the right time during the commit of a local transaction, the local transaction will be aborted and replayed.
+# This test tests the operation of transaction replay. If a potentially
+# conflicting remote transaction arrives at just the right time during
+# the commit of a local transaction, the local transaction will be aborted
+# and replayed.
+#
+# Because the write set with higher sequence number cannot BF abort
+# the victim with lower sequence number, the conflicting remote transaction
+# must be executed first and must be allowed to proceed up to the apply
+# monitor before sending the COMMIT for the transaction to be replayed.
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+######################################################################
+#
+# Scenario #1, the victim will have higher seqno and will be replayed
+#
+######################################################################
--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
@@ -21,34 +34,123 @@ START TRANSACTION;
UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
-# Block the commit
+# Block the applier on node #1 and issue a conflicting update on node #2
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
---let $galera_sync_point = commit_monitor_enter_sync
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Block the commit, send the COMMIT and wait until it gets blocked
+
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_set_sync_point.inc
--connection node_1
---send COMMIT;
+--send COMMIT
-# Wait until commit is blocked
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
--source include/galera_wait_sync_point.inc
-# Issue a conflicting update on node #2
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+# Commit succeeds
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
--connection node_2
-UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+DROP TABLE t1;
+
+#########################################################################
+#
+# Scenario #2, the victim will have lower seqno and will not be replayed
+#
+#########################################################################
+
+--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+
+# Block the commit, send the COMMIT and wait until it gets blocked
+
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+--send COMMIT
-# Wait for both transactions to be blocked
--connection node_1a
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event::find_row%';
---source include/wait_condition.inc
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT';
---source include/wait_condition.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+
+# Set sync point at the end of BF abort, issue a conflicting update
+# and wait for the conflicting update to hit the sync point.
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
-# Unblock the commit
--connection node_1a
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Let the transactions proceed
--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
# Commit succeeds
@@ -58,10 +160,10 @@ UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
-# wsrep_local_replays has increased by 1
+# wsrep_local_replays should have not increased
--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
--disable_query_log
---eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 0 AS wsrep_local_replays;
--enable_query_log
--connection node_2
@@ -70,55 +172,84 @@ SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
DROP TABLE t1;
-#echo "# test for PS replaying"
+########################################
#
# test replaying of prepared statements
#
+########################################
+
--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
CREATE TABLE t1 (i int primary key, j int) ENGINE=INNODB;
INSERT INTO t1 VALUES (1, 0), (3, 0);
SELECT * FROM t1;
-
+SET AUTOCOMMIT=ON;
PREPARE stmt1 FROM "UPDATE t1 SET j = 1 where i > 0";
-# block the commit of PS
+
+# Block the applier on node #1 and issue a conflicting update on node #2
--connection node_1a
---let $galera_sync_point = commit_monitor_enter_sync
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
---connection node_1
---send EXECUTE stmt1;
+--connection node_2
+INSERT INTO t1 VALUES(2,2);
-# Wait until commit is blocked
--connection node_1a
-SET SESSION wsrep_sync_wait = 0;
--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
-# Issue a conflicting update on node_2
---connection node_2
-#UPDATE t1 SET j=2;
-INSERT INTO t1 VALUES(2,2);
+# Block the commit, send the EXECUTE stmt1 and wait until it gets blocked
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
-# Wait until applying begins in node_1
---connection node_1a
---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Write_rows_log_event::write_row%';
---source include/wait_condition.inc
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+--send EXECUTE stmt1
-# Unblock the PS commit
--connection node_1a
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
+
+# Let the conflicting INSERT proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
# Commit succeeds
--connection node_1
--reap
+SET SESSION wsrep_sync_wait=7;
SELECT * FROM t1;
--connection node_2
SELECT * FROM t1;
--connection node_1
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
DEALLOCATE PREPARE stmt1;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test
index 6d99d35cdac..113233715c2 100644
--- a/mysql-test/suite/galera/t/galera_var_cluster_address.test
+++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test
@@ -19,8 +19,8 @@
SET GLOBAL wsrep_cluster_address = 'foo://';
# With wsrep_sync_wait, this returns an error
-#--error ER_LOCK_WAIT_TIMEOUT
-#SHOW STATUS;
+--error ER_LOCK_WAIT_TIMEOUT
+SHOW STATUS;
SET SESSION wsrep_sync_wait=0;
@@ -49,10 +49,9 @@ SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VA
--connection node_2
--disable_query_log
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2';
+--source include/galera_wait_ready.inc
--enable_query_log
---source include/wait_until_connected_again.inc
-
--connection node_1
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
@@ -63,7 +62,7 @@ CALL mtr.add_suppression("Failed to initialize backend using 'foo");
CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo");
CALL mtr.add_suppression("gcs connect failed: Socket type not supported");
CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7");
-CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)");
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -[0-9]+ \\(Software caused connection abort\\)");
CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110");
CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)");
CALL mtr.add_suppression("gcs connect failed: Connection timed out");
diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test
index 1f01c4aac07..dc1698ef497 100644
--- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test
+++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test
@@ -11,11 +11,6 @@
--let $node_2=node_2
--source include/auto_increment_offset_save.inc
-# Save original auto_increment_offset values.
---let $node_1=node_1
---let $node_2=node_2
---source include/auto_increment_offset_save.inc
-
--connection node_2
--let $wsrep_cluster_address_saved = `SELECT @@global.wsrep_cluster_address`
@@ -53,6 +48,7 @@ SET @@session.wsrep_dirty_reads=OFF;
--error ER_UNKNOWN_COM_ERROR
SELECT i, variable_name, variable_value FROM t1, information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads" AND i = 1;
+
SELECT 1;
USE information_schema;
@@ -65,6 +61,7 @@ SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history;
--eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved'
--enable_query_log
--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
--connection node_1
USE test;
@@ -72,8 +69,6 @@ SELECT * FROM t1;
# Cleanup
DROP TABLE t1;
---source include/auto_increment_offset_restore.inc
-
--source include/galera_end.inc
--echo # End of test
diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
new file mode 100644
index 00000000000..269e28465d8
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
@@ -0,0 +1,235 @@
+#
+# Test option wsrep_ignore_apply_errors
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+
+#
+# Ignore reconciling DDL errors on node_2
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 1;
+
+# Drop table that does not exist
+--connection node_1
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+DROP TABLE t1;
+
+# Drop schema that does not exist
+SET GLOBAL wsrep_on = OFF;
+CREATE SCHEMA s1;
+SET GLOBAL wsrep_on = ON;
+DROP SCHEMA s1;
+
+# Drop index that does not exist using DROP INDEX
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+DROP INDEX idx1 ON t1;
+DROP TABLE t1;
+
+# Drop index that does not exist using ALTER TABLE
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+CREATE INDEX idx1 ON t1 (f1);
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP INDEX idx1;
+DROP TABLE t1;
+
+# Drop column that does not exist
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SET GLOBAL wsrep_on = ON;
+ALTER TABLE t1 DROP COLUMN f2;
+DROP TABLE t1;
+
+
+#
+# Ignore reconciling DML errors on node_2
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+
+# Delete row that does not exist
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+DELETE FROM t1 WHERE f1 = 1;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+DROP TABLE t1;
+
+# Delete row that does not exist in a multi statement transaction
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1;
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+#
+# Multi-row delete where only one row does not exist
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+--connection node_1
+DELETE FROM t1;
+
+SELECT COUNT(*) = 0 FROM t1;
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM t1;
+DROP TABLE t1;
+
+#
+# Multi-statement delete where only one row does not exist
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+--connection node_1
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+DELETE FROM t1 WHERE f1 = 4;
+DELETE FROM t1 WHERE f1 = 5;
+COMMIT;
+SET AUTOCOMMIT=ON;
+
+SELECT COUNT(*) = 0 FROM t1;
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM t1;
+DROP TABLE t1;
+
+#
+# Multi-table delete
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 3 FROM t2;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM t2 WHERE f1 = 2;
+DELETE FROM t1 WHERE f1 = 3;
+SET SESSION wsrep_on = ON;
+
+--connection node_1
+DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM t1;
+DROP TABLE t1,t2;
+
+#
+# Foreign keys
+#
+
+--connection node_1
+CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+INSERT INTO parent VALUES (1),(2),(3);
+CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB;
+INSERT INTO child VALUES (1,1),(2,2),(3,3);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 3 FROM child;
+--source include/wait_condition.inc
+
+SET SESSION wsrep_on = OFF;
+DELETE FROM child WHERE parent_id = 2;
+SET SESSION wsrep_on = ON;
+
+--connection node_1
+DELETE FROM parent;
+SELECT COUNT(*) = 0 FROM parent;
+SELECT COUNT(*) = 0 FROM child;
+
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT COUNT(*) = 0 FROM parent;
+SELECT COUNT(*) = 0 FROM child;
+DROP TABLE child, parent;
+
+#
+# Ignore all DDL errors on node_2
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 4;
+
+# Create a table that already exists
+--connection node_2
+SET GLOBAL wsrep_on = OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_on = ON;
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+DROP TABLE t1;
+
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
+
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query. Default database: 'test'. Query: 'DROP TABLE t1', Error_code: 1051");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query. Default database: 'test'. Query: 'DROP SCHEMA s1', Error_code: 1008");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'DROP INDEX idx1 ON t1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP INDEX idx1', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'f2'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP COLUMN f2', Error_code: 1091");
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query.");
diff --git a/mysql-test/suite/galera/t/galera_var_log_bin.cnf b/mysql-test/suite/galera/t/galera_var_log_bin.cnf
index f7f17e3720a..30ccee2024e 100644
--- a/mysql-test/suite/galera/t/galera_var_log_bin.cnf
+++ b/mysql-test/suite/galera/t/galera_var_log_bin.cnf
@@ -3,3 +3,8 @@
[mysqld]
log-bin
+[mysqld.1]
+log-slave-updates
+
+[mysqld.2]
+log-slave-updates
diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.test b/mysql-test/suite/galera/t/galera_var_slave_threads.test
index e5986f7ee12..db8a8879415 100644
--- a/mysql-test/suite/galera/t/galera_var_slave_threads.test
+++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test
@@ -21,7 +21,8 @@ SELECT @@wsrep_slave_threads = 1;
SET GLOBAL wsrep_slave_threads = 1;
# There is a separate wsrep_aborter thread at all times
-SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
#
# Increase the number of slave threads. The change takes effect immediately
@@ -33,7 +34,15 @@ SET GLOBAL wsrep_slave_threads = 64;
INSERT INTO t1 VALUES (1);
--connection node_2
---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
+SELECT COUNT(*) = 1 FROM t1;
+
+#
+# note, in wsrep API #26, we have 2 rollbacker threads, counted as system user's
+#
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%');
--source include/wait_condition.inc
#
@@ -53,51 +62,113 @@ while ($count)
}
--connection node_2
-SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) = 64 FROM t2;
+SET wsrep_sync_wait=0;
---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
--source include/wait_condition.inc
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address`
+--let $wsrep_provider_node2 = `SELECT @@wsrep_provider`
---eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig
+SET GLOBAL wsrep_slave_threads = 5;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
+--source include/wait_condition.inc
-DROP TABLE t1;
-DROP TABLE t2;
+SET GLOBAL wsrep_slave_threads = 1;
---echo #
---echo # lp:1372840 - Changing wsrep_slave_threads causes future connections to hang
---echo #
+#
+# test phase for bug https://github.com/codership/mysql-wsrep/issues/319
+#
+# shutdown node 2
+--connection node_2
+--echo Shutting down server ...
+--source include/shutdown_mysqld.inc
+
+# wait until node_1 is ready as one node cluster
--connection node_1
-CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB;
+SET wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+show status like 'wsrep_cluster_size';
---connection node_2
-SET GLOBAL wsrep_slave_threads = 4;
---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+# step up slave threads to 6, and make sure all appliers and rollbacker thread are running
+SET GLOBAL wsrep_slave_threads = 6;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
--source include/wait_condition.inc
+# change to invalid cluster address
SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL wsrep_cluster_address='';
---connection node_1
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
-INSERT INTO t1 VALUES (DEFAULT);
-DROP TABLE t1;
+# join back to single node cluster
+SET GLOBAL wsrep_cluster_address='gcomm://';
+--source include/wait_until_connected_again.inc
---connection node_2
+# we should have 1 applier thread now
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
+--source include/wait_condition.inc
-# Wait until above DDL is replicated
---let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%';
+# test if we can increase applier count now (fails in bug #319)
+SET GLOBAL wsrep_slave_threads = 10;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
--source include/wait_condition.inc
-SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%';
+# restart node 2
+--connection node_2
+--source include/start_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon';
+#
#
-# make sure that we are left with exactly one applier thread before we leaving the test
+# cleanup to original state
#
---let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+--connection node_1
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig
+
+--connection node_2
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig
+
+# Generate 64 replication events, to help node 1 to purge excessive applier threads
+--let $count = 64
+while ($count)
+{
+ INSERT INTO t2 VALUES (DEFAULT);
+ --dec $count
+}
+
+--connection node_1
+# Generate 64 replication events, to help node 2 to purge excessive applier threads
+--let $count = 64
+while ($count)
+{
+ INSERT INTO t2 VALUES (DEFAULT);
+ --dec $count
+}
+
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
--source include/wait_condition.inc
-SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
+
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads = 4;
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%')
+--source include/wait_condition.inc
+
+SET GLOBAL wsrep_slave_threads = 1;
+
+--connection node_1
+--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'
+--source include/wait_condition.inc
+
+DROP TABLE t1;
+DROP TABLE t2;
--echo # End of tests
diff --git a/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt b/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt
new file mode 100644
index 00000000000..beae84b3862
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt
@@ -0,0 +1 @@
+--log-bin
diff --git a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test
index 6ba8ce786c8..28025363019 100644
--- a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test
+++ b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test
@@ -5,7 +5,6 @@
#
--source include/galera_cluster.inc
---source include/have_innodb.inc
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected';
diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt
new file mode 100644
index 00000000000..beae84b3862
--- /dev/null
+++ b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt
@@ -0,0 +1 @@
+--log-bin
diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test
index bb5a02411c3..7fa6b9e800c 100644
--- a/mysql-test/suite/galera/t/partition.test
+++ b/mysql-test/suite/galera/t/partition.test
@@ -131,9 +131,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY)
--connection node_2
SELECT COUNT(*) = 20002 FROM t1;
-# LOAD-ing 20002 rows causes 3 commits to be registered
+# LOAD-ing 20002 rows causes
+# 3 commits to be registered when the Galera library does not support streaming replication and
+# 5 commits to be registered when the Galera library supports streaming replication
--disable_query_log
---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 3 AS wsrep_last_committed_diff;
+--replace_result 3 AS_EXPECTED_3_or_5 5 AS_EXPECTED_3_or_5
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff;
--enable_query_log
DROP TABLE t1;
@@ -161,7 +164,7 @@ SELECT COUNT(*) = 101 FROM t1;
# LOAD-ing 101 rows causes 1 commit to be registered
--disable_query_log
---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff;
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff;
--enable_query_log
DROP TABLE t1;
@@ -188,9 +191,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY)
--connection node_2
SELECT COUNT(*) = 20002 FROM t1;
-# LOAD-ing 20002 rows causes 1 commit to be registered
+# LOAD-ing 20002 rows causes
+# 1 commit to be registered when the Galera library does not support streaming replication and
+# 2 commits to be registered when the Galera library supports streaming replication
--disable_query_log
---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff;
+--replace_result 1 AS_EXPECTED_1_or_2 2 AS_EXPECTED_1_or_2
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff;
--enable_query_log
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.test b/mysql-test/suite/galera/t/rpl_row_annotate.test
index b1cfdb36639..b9bae724d7f 100644
--- a/mysql-test/suite/galera/t/rpl_row_annotate.test
+++ b/mysql-test/suite/galera/t/rpl_row_annotate.test
@@ -3,11 +3,15 @@
--echo # On node_2
--connection node_2
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
--echo # On node_1
--connection node_1
+SET GLOBAL wsrep_on=OFF;
RESET MASTER;
+SET GLOBAL wsrep_on=ON;
CREATE TABLE t1(i INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
DELETE FROM t1 WHERE i = 1;
@@ -38,5 +42,5 @@ let $start_pos= `select @binlog_start_pos`;
# Cleanup
DROP TABLE t1;
---source include/galera_end.inc
+#--source include/galera_end.inc
--echo # End of test
diff --git a/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test
new file mode 100644
index 00000000000..f189368cc0f
--- /dev/null
+++ b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test
@@ -0,0 +1,26 @@
+-- source include/galera_cluster.inc
+
+-- let $sr = `SELECT variable_value LIKE '%:STREAMING:%' FROM information_schema.session_status WHERE variable_name = 'wsrep_provider_capabilities'`
+
+if ($sr)
+{
+ -- skip The test requires a wsrep provider that does not support streaming replication.
+}
+
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET SESSION wsrep_trx_fragment_size = 0;
+-- error ER_WRONG_VALUE_FOR_VAR
+SET SESSION wsrep_trx_fragment_size = 123;
+SHOW WARNINGS;
+
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET GLOBAL wsrep_trx_fragment_size = 0;
+-- error ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL wsrep_trx_fragment_size = 123;
+SHOW WARNINGS;
+
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test
new file mode 100644
index 00000000000..a970cc09afc
--- /dev/null
+++ b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test
@@ -0,0 +1,22 @@
+-- source include/galera_cluster.inc
+
+-- let $sr = `SELECT variable_value LIKE '%:STREAMING:%' FROM information_schema.session_status WHERE variable_name = 'wsrep_provider_capabilities'`
+
+if (!$sr)
+{
+ -- skip The test requires a wsrep provider that supports streaming replication.
+}
+
+SELECT variable_value FROM information_schema.session_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET SESSION wsrep_trx_fragment_size = 0;
+SET SESSION wsrep_trx_fragment_size = 123;
+
+SELECT variable_value FROM information_schema.global_variables
+WHERE variable_name = 'wsrep_trx_fragment_size';
+
+SET GLOBAL wsrep_trx_fragment_size = 0;
+SET GLOBAL wsrep_trx_fragment_size = 123;
+
+SET GLOBAL wsrep_trx_fragment_size = default;
diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf
index 91aa53ad7b1..cc6107d62ce 100644
--- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf
+++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf
@@ -17,6 +17,7 @@ wsrep-sync-wait=15
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
+#wsrep-new-cluster
wsrep-cluster-address='gcomm://'
wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S'
diff --git a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc
index 3495ad2342b..d4037d8958c 100644
--- a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc
+++ b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc
@@ -9,6 +9,6 @@
my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
- system("kill -19 $mysqld_pid");
+ system("kill -SIGSTOP $mysqld_pid");
exit(0);
EOF
diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result
index b1bbb1406a1..6393a30da6f 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_3;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result
index c2fdfc38dd5..d43b42bec45 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
@@ -12,5 +14,6 @@ INSERT INTO t2 VALUES (1);
connection node_1;
COMMIT;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_3;
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result
index 53e35939a79..56348889cf9 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result
@@ -13,6 +13,3 @@ COUNT(*) = 1
1
DROP TABLE t1;
include/assert_grep.inc [Streaming the backup to joiner at \[::1\]]
-include/assert_grep.inc [async IST sender starting to serve tcp://\[::1\]:]
-include/assert_grep.inc [IST receiver addr using tcp://\[::1\]]
-include/assert_grep.inc [Prepared IST receiver, listening at: tcp://\[::1\]]
diff --git a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result
index 3d4dbcc00b0..7780c3f73b8 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result
@@ -1,3 +1,5 @@
+connection node_2;
+connection node_1;
connection node_1;
connection node_2;
connection node_3;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result
index 69995acb982..ee49330e892 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result
@@ -1,8 +1,15 @@
+connection node_2;
+connection node_1;
CREATE TABLE t1 (f1 INTEGER);
+connection node_1;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
SET SESSION wsrep_sync_wait = 0;
+connection node_2;
SET GLOBAL wsrep_provider_options = 'pc.bootstrap=1';
SHOW STATUS LIKE 'wsrep_cluster_size';
Variable_name Value
@@ -11,15 +18,21 @@ SHOW STATUS LIKE 'wsrep_cluster_status';
Variable_name Value
wsrep_cluster_status Primary
INSERT INTO t1 VALUES (1);
+connection node_2;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_1;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_3;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+connection node_1;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
+connection node_2;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
+connection node_3;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result
index 6fb931638ef..a4dca32ff86 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result
@@ -56,9 +56,6 @@ VARIABLE_VALUE = 4
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
-SET GLOBAL wsrep_provider_options = 'pc.weight=1';
-SET SESSION wsrep_sync_wait=0;
-SET SESSION wsrep_sync_wait=0;
SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 3
1
@@ -116,6 +113,9 @@ VARIABLE_VALUE = 'Synced'
SET GLOBAL wsrep_provider_options = 'pc.weight=1';
CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1');
CALL mtr.add_suppression('overriding reported weight for');
+CALL mtr.add_suppression('SYNC message from member');
+CALL mtr.add_suppression('user message in state LEAVING');
+CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)');
CALL mtr.add_suppression('WSREP: user message in state LEAVING');
-CALL mtr.add_suppression('sending install message failed: Transport endpoint is not connected');
+CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)');
CALL mtr.add_suppression('overriding reported weight for');
diff --git a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
new file mode 100644
index 00000000000..89520a7c565
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
@@ -0,0 +1,77 @@
+connection node_2;
+connection node_1;
+SHOW CREATE TABLE wsrep_schema.cluster;
+Table Create Table
+cluster CREATE TABLE `cluster` (
+ `cluster_uuid` char(36) NOT NULL,
+ `view_id` bigint(20) NOT NULL,
+ `view_seqno` bigint(20) NOT NULL,
+ `protocol_version` int(11) NOT NULL,
+ PRIMARY KEY (`cluster_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE wsrep_schema.members;
+Table Create Table
+members CREATE TABLE `members` (
+ `node_uuid` char(36) NOT NULL,
+ `cluster_uuid` char(36) NOT NULL,
+ `node_name` char(32) NOT NULL,
+ `node_incoming_address` varchar(256) NOT NULL,
+ PRIMARY KEY (`node_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM wsrep_schema.cluster;
+COUNT(*) = 1
+1
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members;
+COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size')
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+COUNT(*) = 1
+1
+SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members;
+node_incoming_address LIKE '127.0.0.1:%'
+1
+1
+1
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+1
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+COUNT(*) = 1
+1
+connection node_2;
+connection node_1;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+COUNT(*) = 2
+1
+connection node_2;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+connection node_1;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid')
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+connection node_1;
+CALL mtr.add_suppression("SYNC message from member");
+connection node_2;
+CALL mtr.add_suppression("SYNC message from member");
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.test b/mysql-test/suite/galera_3nodes/t/GAL-501.test
index 60ed5989227..9e3aff0c437 100644
--- a/mysql-test/suite/galera_3nodes/t/GAL-501.test
+++ b/mysql-test/suite/galera_3nodes/t/GAL-501.test
@@ -7,6 +7,12 @@
--source include/galera_cluster.inc
--source include/have_ipv6.inc
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+--source include/galera_wait_ready.inc
+
# Confirm that initial handshake happened over ipv6
SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses';
diff --git a/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test
index a2ad0765028..5366d2a4a6e 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test
@@ -29,5 +29,7 @@ INSERT INTO t2 VALUES (1);
--error ER_LOCK_DEADLOCK
COMMIT;
+--connection node_3
+--source include/galera_wait_ready.inc
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
index 03236a3cb93..a4767928681 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test
@@ -60,9 +60,9 @@ DROP TABLE t1;
--source include/galera_resume.inc
--source include/wait_until_connected_again.inc
-CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
-
--disable_query_log
--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node3';
--enable_query_log
---source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd.test b/mysql-test/suite/galera_3nodes/t/galera_garbd.test
index a68ba8ce15b..519f992d1b4 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_garbd.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_garbd.test
@@ -32,7 +32,10 @@ INSERT INTO t1 VALUES (1);
SELECT COUNT(*) = 1 FROM t1;
--echo Killing garbd ...
---exec pkill --oldest --full garbd.*$NODE_GALERAPORT_3
+# FreeBSD's /bin/pkill only supports short versions of the options:
+# -o Select only the oldest (least recently started)
+# -f Match against full argument lists
+--exec pkill -o -f garbd.*$NODE_GALERAPORT_3
--sleep 5
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf
index 8a80be0d2a9..5cc8fb04cdd 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf
+++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf
@@ -5,18 +5,22 @@ wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="root:"
[mysqld.1]
+wsrep_node_name='node_1'
wsrep-cluster-address=gcomm://
wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port'
[mysqld.2]
+wsrep_node_name='node_2'
+wsrep_sst_donor='node_1'
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port'
[mysqld.3]
+wsrep_node_name='node_3'
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port'
wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port'
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test
index 84eee017700..6756cce6e02 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test
@@ -42,20 +42,22 @@ DROP TABLE t1;
--let $assert_select = Streaming the backup to joiner at \[::1\]
--source include/assert_grep.inc
---let $assert_count = 1
---let $assert_text = async IST sender starting to serve tcp://\[::1\]:
---let $assert_select = async IST sender starting to serve tcp://\[::1\]:
---source include/assert_grep.inc
-
---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
-
---let $assert_text = IST receiver addr using tcp://\[::1\]
---let $assert_select = IST receiver addr using tcp://\[::1\]
---source include/assert_grep.inc
-
---let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\]
---let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\]
---source include/assert_grep.inc
+# asserts below are not deterministic
+# --let $assert_count = 2
+# --let $assert_text = async IST sender starting to serve tcp://\[::1\]:
+# --let $assert_select = async IST sender starting to serve tcp://\[::1\]:
+# --source include/assert_grep.inc
+#
+# --let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
+#
+# --let $assert_text = IST receiver addr using tcp://\[::1\]
+# --let $assert_select = IST receiver addr using tcp://\[::1\]
+# --source include/assert_grep.inc
+#
+# --let $assert_count = 1
+# --let $assert_text = Prepared IST receiver for 4-7, listening at: tcp://\[::1\]
+# --let $assert_select = Prepared IST receiver for 4-7, listening at: tcp://\[::1\]
+# --source include/assert_grep.inc
diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test
index a67b30e3fa1..9e43c90bfc1 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test
@@ -11,7 +11,7 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
---source suite/galera/include/galera_have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
--let $galera_connection_name = node_3
--let $galera_server_number = 3
diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf
index 57026ce6928..1a61471d581 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf
+++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf
@@ -1,5 +1,7 @@
-# We need a dedicated .cnf file, even if empty, in order to force this test to run
-# alone on a freshly started cluster. Otherwise there are adverse interactions with
-# following tests such as galera_3nodes.galera_var_dirty_reads2
+# We need a dedicated .cnf file, even if empty, in order to force this test
+# to run alone on a freshly started cluster. Otherwise there are adverse
+# interactions with following tests such as
+# galera_3nodes.galera_var_dirty_reads2
+!include ../galera_3nodes.cnf
!include ../galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test
index d69881aa5eb..eeb75392f0d 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test
@@ -1,11 +1,11 @@
#
-# Test the pc.weight wsrep provider option. We set Node #1 to have a high weight and then
-# suspend it. This will cause Nodes #2 and #3 to transition to non-primary component.
+# Test the pc.weight wsrep provider option. We set Node #1 to have a high
+# weight and then suspend it. This will cause Nodes #2 and #3 to transition
+# to non-primary component.
#
--source include/big_test.inc
--source include/galera_cluster.inc
---source include/have_innodb.inc
--connection node_1
SET GLOBAL wsrep_provider_options = 'pc.weight=3';
@@ -49,6 +49,9 @@ SHOW STATUS LIKE 'wsrep_local_state_comment';
--source include/wait_until_connected_again.inc
# For Node #1, we expect a primary component of size 1
+# (NOTE: this is a bit racy as nodes 2 and 3 will try to reconnect ASAP.
+# to avoid the raice they should be suspended first as well, but that's
+# not currently possible)
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
@@ -59,30 +62,18 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state';
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
-SET GLOBAL wsrep_provider_options = 'pc.weight=1';
-
-# Restore the cluster by resetting wsrep_cluster_address on nodes #1 and #2
+# wait for nodes 2 and 3 to reconnect
--connection node_2
---disable_query_log
---eval SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address;
---enable_query_log
-
-SET SESSION wsrep_sync_wait=0;
---source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
--connection node_3
---disable_query_log
---eval SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address;
---enable_query_log
-
-SET SESSION wsrep_sync_wait=0;
---source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
# On all nodes, we now expect a Primary component of size 3, Synced and ready
--connection node_1
---source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected';
@@ -116,8 +107,11 @@ CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1');
--connection node_2
CALL mtr.add_suppression('overriding reported weight for');
+CALL mtr.add_suppression('SYNC message from member');
+CALL mtr.add_suppression('user message in state LEAVING');
+CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)');
--connection node_3
CALL mtr.add_suppression('WSREP: user message in state LEAVING');
-CALL mtr.add_suppression('sending install message failed: Transport endpoint is not connected');
+CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)');
CALL mtr.add_suppression('overriding reported weight for');
diff --git a/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test b/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test
index 3e8b1557e7b..8e73dee70ae 100644
--- a/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test
+++ b/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test
@@ -25,6 +25,7 @@ SELECT COUNT(*) = 1 FROM db2.t2B;
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connection node_3
+--source include/galera_wait_ready.inc
SELECT COUNT(*) = 0 FROM db1.t1;
SELECT COUNT(*) = 1 FROM db2.t2A;
SELECT COUNT(*) = 1 FROM db2.t2B;
diff --git a/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test
new file mode 100644
index 00000000000..9c0b074ab0b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test
@@ -0,0 +1,74 @@
+#
+# This test performs basic checks on the contents of the wsrep_schema
+#
+# wsrep_schema.members_history checks are temporarily disabled until it
+# can be made configurable.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Make the test fail if table structure has changed
+
+SHOW CREATE TABLE wsrep_schema.cluster;
+SHOW CREATE TABLE wsrep_schema.members;
+#disabled SHOW CREATE TABLE wsrep_schema.members_history;
+
+# Checks for the wsrep_schema.cluster table
+
+SELECT COUNT(*) = 1 FROM wsrep_schema.cluster;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+
+# Checks for the wsrep_schema.members table
+
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members;
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+
+SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members;
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members;
+
+# Checks for the wsrep_schema.members_history table
+
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history;
+#disabled SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members_history;
+SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid');
+
+#disabled SELECT last_view_id = (SELECT view_id FROM wsrep_schema.cluster) FROM wsrep_schema.members_history;
+#disabled SELECT last_view_seqno = (SELECT view_seqno FROM wsrep_schema.cluster) FROM wsrep_schema.members_history;
+#disabled SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members_history;
+#disabled SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members_history;
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history;
+#disabled SELECT COUNT(*) = 2 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history);
+
+--connection node_2
+--source include/start_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history);
+
+--connection node_1
+SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster;
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history);
+
+--connection node_1
+CALL mtr.add_suppression("SYNC message from member");
+
+--connection node_2
+CALL mtr.add_suppression("SYNC message from member");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf
new file mode 100644
index 00000000000..62c8214b8f2
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf
@@ -0,0 +1 @@
+!include ../galera_3nodes/galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc b/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc
new file mode 100644
index 00000000000..5c74adc46a2
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc
@@ -0,0 +1,58 @@
+#
+# Test that after an inconsistency vote that kicked out node #2, the
+# cluster is able to recover
+#
+
+# Nodes #1 and #3 remain in the cluster
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+--connect node_3X, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3X
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Node #2 is kicked out
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+SET SESSION wsrep_on=ON;
+
+# Restore cluster
+
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--exec echo "wait" > $_expect_file_name
+# Exclude SHOW commands run during server shutdown from sync waiting
+--disable_query_log
+SET SESSION wsrep_sync_wait = 7;
+--enable_query_log
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--sleep 5
+--source include/start_mysqld.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Confirm that the t1 table is now identical throughout
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+--connection node_3X
+SHOW CREATE TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/my.cnf b/mysql-test/suite/galera_3nodes_ee/my.cnf
new file mode 100644
index 00000000000..bb25b95ceea
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/my.cnf
@@ -0,0 +1 @@
+!include galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result
new file mode 100644
index 00000000000..0d52b668e91
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result
@@ -0,0 +1,23 @@
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f1 INTEGER);
+CREATE TABLE test.t1 (f1 INTEGER);
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status Primary
+DROP TABLE test.t1;
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result
new file mode 100644
index 00000000000..6a0af777277
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result
@@ -0,0 +1,16 @@
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+FLUSH TABLES WITH READ LOCK;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t1 VALUES(2);
+INSERT INTO t1 VALUES(3);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+UNLOCK TABLES;
+DROP TABLE t1;
+SET SESSION wsrep_on = OFF;
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE t1 \\\(f1 INTEGER PRIMARY KEY\\\) ENGINE=InnoDB', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result
new file mode 100644
index 00000000000..ff67cab1303
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result
@@ -0,0 +1,31 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+INSERT INTO t1 VALUES (1, 'b');
+SET SESSION wsrep_sync_wait = 0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_on=ON;
+SELECT * FROM t1;
+f1 f2
+1 a
+SELECT * FROM t1;
+f1 f2
+1 a
+SELECT * FROM t1;
+f1 f2
+1 a
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("WSREP: Vote 0 \\\(success\\\) on (.*) is inconsistent with group. Leaving cluster.");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result
new file mode 100644
index 00000000000..4c699913890
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result
@@ -0,0 +1,48 @@
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+LOCK TABLE t1 WRITE;
+INSERT INTO t1 VALUES (1, 'b');
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+UNLOCK TABLES;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+SHOW STATUS LIKE 'wsrep_cluster_size';
+Variable_name Value
+wsrep_cluster_size 0
+SET GLOBAL wsrep_on=OFF;
+SELECT * FROM t1;
+f1 f2
+1 a
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status Primary
+SHOW STATUS LIKE 'wsrep_cluster_size';
+Variable_name Value
+wsrep_cluster_size 1
+SELECT * FROM t1;
+f1 f2
+1 b
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SELECT * FROM t1;
+f1 f2
+1 b
+SELECT * FROM t1;
+f1 f2
+1 b
+SELECT * FROM t1;
+f1 f2
+1 b
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos (.*), Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event (.*) Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on (.*)");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result
new file mode 100644
index 00000000000..a93b73feafc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result
@@ -0,0 +1,21 @@
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+Killing server ...
+Killing server ...
+DROP TABLE test.t1;
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result
new file mode 100644
index 00000000000..5071d6746d1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result
@@ -0,0 +1,19 @@
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1);
+LOCK TABLE t1 WRITE;
+SET GLOBAL wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+UNLOCK TABLES;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SET GLOBAL wsrep_sync_wait=15;
+DROP TABLE test.t1;
+Killing server ...
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno:");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result
new file mode 100644
index 00000000000..be092572de3
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result
@@ -0,0 +1,32 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)');
+CALL mtr.add_suppression('discarding established');
+CALL mtr.add_suppression('Quorum: No node with complete state');
+ERROR HY000: Lost connection to MySQL server during query
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result
new file mode 100644
index 00000000000..b8b0f1ca130
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result
@@ -0,0 +1,27 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result
new file mode 100644
index 00000000000..29b87232164
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result
@@ -0,0 +1,35 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+Performing --wsrep-recover ...
+Using --wsrep-start-position when starting mysqld ...
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result
new file mode 100644
index 00000000000..0d687a4d43f
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result
@@ -0,0 +1,33 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+Killing server ...
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result
new file mode 100644
index 00000000000..b9b9fabb1bc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result
@@ -0,0 +1,46 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("inconsistent with group");
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result
new file mode 100644
index 00000000000..e16dfc643d0
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result
@@ -0,0 +1,50 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("Non-blocking operation end failed");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result
new file mode 100644
index 00000000000..3efc772cea0
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_OSU_method='NBO';
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+ERROR 42000: Multiple primary key defined
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL mtr.add_suppression("SYNC message from member");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("TO isolation end failed");
+CALL mtr.add_suppression("SYNC message from member");
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result
new file mode 100644
index 00000000000..7aa1ac5d8bf
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
+VARIABLE_VALUE = 'Inconsistent'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error");
+CALL mtr.add_suppression("inconsistent with group");
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result
new file mode 100644
index 00000000000..dd4e3674786
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result
@@ -0,0 +1,42 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+SET SESSION lock_wait_timeout=2;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+ERROR HY000: Got error 6 during COMMIT
+SET SESSION wsrep_sync_wait = 0;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+INSERT INTO t1 VALUES (2,2);
+SET SESSION wsrep_on = OFF;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("Lock wait timeout while waiting NBO end to replicate");
+CALL mtr.add_suppression("Failed to acquire total order isolation for non-blocking DDL end event, provider returned error code 6");
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result
new file mode 100644
index 00000000000..3b7b96d8fde
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result
@@ -0,0 +1,32 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result
new file mode 100644
index 00000000000..79c7990b158
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1,2);
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result
new file mode 100644
index 00000000000..4b704facf24
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result
@@ -0,0 +1,35 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait = 0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+COUNT(*) = 3
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -1");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result b/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result
new file mode 100644
index 00000000000..a0a30f23e25
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result
@@ -0,0 +1,19 @@
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+CREATE SCHEMA test;
+ERROR HY000: Can't create database 'test'; database exists
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+SET SESSION wsrep_sync_wait=0;
+Killing server ...
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+CALL mtr.add_suppression("inconsistent with group");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result
new file mode 100644
index 00000000000..64c8b85d440
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result
@@ -0,0 +1,60 @@
+Setting SST method to mysqldump ...
+GRANT ALL PRIVILEGES ON *.* TO 'sst';
+SET GLOBAL wsrep_sst_auth = 'sst:';
+SET GLOBAL wsrep_sst_method = 'mysqldump';
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'non-Primary'
+1
+SET SESSION wsrep_on=ON;
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+VARIABLE_VALUE = 'Primary'
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_on=ON;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("is inconsistent with group");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that column/key exists'");
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+DROP USER sst;
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found");
+CALL mtr.add_suppression("InnoDB: New log files created");
+CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables");
+CALL mtr.add_suppression("Can't open and lock time zone table");
+CALL mtr.add_suppression("Can't open and lock privilege tables");
+CALL mtr.add_suppression("Info table is not ready to be used");
+CALL mtr.add_suppression("Native table .* has the wrong structure");
diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result
new file mode 100644
index 00000000000..c2b618b86c4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB;
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (5, 'X');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 131070;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (2, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (3, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (4, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (5, REPEAT('A', 65535));
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+START TRANSACTION;
+INSERT INTO t1 VALUES (11, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (12, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (13, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (14, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (15, REPEAT('A', 65535));
+SET SESSION wsrep_on=OFF;
+Starting mysqld
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '5' for key 'PRIMARY'");
+CALL mtr.add_suppression("Write_rows apply failed");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("no THD for trx");
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result b/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result
new file mode 100644
index 00000000000..3a6ad0f620f
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (1);;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test
new file mode 100644
index 00000000000..6dc89594c05
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test
@@ -0,0 +1,59 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+#
+# 1. Create different inconsistencies on nodes 2 and 3
+#
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f1 INTEGER);
+#
+# 2. The following should generate different errors on nodes 2 and 3 and
+# trigger voting with 3 different votes. node_1 should remain alone
+# in the cluster.
+#
+--connection node_1
+CREATE TABLE test.t1 (f1 INTEGER);
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+
+# Test cleanup
+DROP TABLE test.t1;
+#
+# 3. Wait for nodes 2 and 3 to drop out of the cluster and restart them to
+# recover the initial configuration.
+#
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+--source include/restart_mysqld.inc
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+
+--connection node_3
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test
new file mode 100644
index 00000000000..01dbb2147b3
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test
@@ -0,0 +1,47 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+# create inconsistency
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+# block the node
+FLUSH TABLES WITH READ LOCK;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t1 VALUES(2);
+INSERT INTO t1 VALUES(3);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 3 FROM t1
+--source include/wait_condition.inc
+--sleep 1
+
+--connection node_3
+SELECT COUNT(*) = 0 FROM t1;
+UNLOCK TABLES;
+# Wait until the node leaves the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+
+--connection node_1
+# Wait until node #3 leaves the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+DROP TABLE t1;
+
+--connection node_3
+SET SESSION wsrep_on = OFF;
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE t1 \\\(f1 INTEGER PRIMARY KEY\\\) ENGINE=InnoDB', Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf
new file mode 100644
index 00000000000..7b7770e3ad1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf
@@ -0,0 +1,8 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
+
+# [mysqld.3]
+# wsrep-sst-method=mysqldump
+# wsrep_sst_receive_address=127.0.0.2:@mysqld.3.port
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test
new file mode 100644
index 00000000000..0e8e8cc4276
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test
@@ -0,0 +1,68 @@
+#
+# GCF-363 Inconsistency voting: If in a 3-node cluster the nodes with applier
+# error survive, the other node can not join properly
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+
+--connection node_1
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+INSERT INTO t1 VALUES (1, 'b');
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+
+--connection node_1
+# Wait until node #3 leaves the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# need to use another connection to restart the node due to GCF-1000
+--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3a
+# ATM (12.11.2016) mysqldump SST does not seem to be working, rsync SST
+# requires node restart
+# SET GLOBAL wsrep_cluster_address= 'gcomm://127.0.0.1:13001';
+SET SESSION wsrep_on=OFF;
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_on=ON;
+
+--connection node_1
+SELECT * FROM t1;
+
+--connection node_2
+SELECT * FROM t1;
+
+--connection node_3a
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno ");
+
+--connection node_3a
+CALL mtr.add_suppression("WSREP: Vote 0 \\\(success\\\) on (.*) is inconsistent with group. Leaving cluster.");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on ");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test
new file mode 100644
index 00000000000..b4146a12ebd
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test
@@ -0,0 +1,84 @@
+#
+# GCF-376: slaves become inconsistent if master goes non-prim during
+# inconsistency voting
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1, 'a');
+SET GLOBAL wsrep_on=ON;
+
+LOCK TABLE t1 WRITE;
+
+--connection node_1
+INSERT INTO t1 VALUES (1, 'b');
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+
+# --sleep 10
+# Wait until node #1 leaves the cluster
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+UNLOCK TABLES;
+
+# Wait until node #2 leaves the cluster
+--source include/wsrep_wait_disconnect.inc
+
+--connection node_1
+SHOW STATUS LIKE 'wsrep_cluster_status';
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SET GLOBAL wsrep_on=OFF;
+SELECT * FROM t1;
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SHOW STATUS LIKE 'wsrep_cluster_status';
+SHOW STATUS LIKE 'wsrep_cluster_size';
+SELECT * FROM t1;
+
+# reconnect node #1
+--connection node_1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+
+# reconnect node #2
+--connection node_2
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SELECT * FROM t1;
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SELECT * FROM t1;
+
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos (.*), Error_code: 1062");
+CALL mtr.add_suppression("WSREP: Event (.*) Write_rows apply failed: 121, seqno ");
+CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on (.*)");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test
new file mode 100644
index 00000000000..fae92aab4e8
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test
@@ -0,0 +1,67 @@
+#
+# This test tests that one successful node wins over two nodes that fail for
+# different reasons
+#
+--source include/galera_3nodes.inc
+--source include/have_innodb.inc
+
+# create inconsistency on node 2
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+
+# create inconsistency on node 3
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+# wait for nodes 2 and 3 drop from the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+# reconnect nodes 2 and 3, since they failed
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+--connection node_3
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+--connection node_1
+DROP TABLE test.t1;
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1049");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+--connection node_3
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1050");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test
new file mode 100644
index 00000000000..e600db4453b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test
@@ -0,0 +1,61 @@
+#
+# This test tests voting (successful slave wins) in the absence of the master
+# for trasaction.
+#
+--source include/galera_3nodes.inc
+--source include/have_innodb.inc
+
+CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_2
+--let $wsrep_provider_orig = `SELECT @@wsrep_provider`
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_on=OFF;
+INSERT INTO t1 VALUES (1);
+LOCK TABLE t1 WRITE;
+SET GLOBAL wsrep_sync_wait=0;
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connection node_3
+# wait for node_1 to disappear
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+UNLOCK TABLES;
+# wait to go non-Primary due to inconsistency voting
+#--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+#--source include/wait_condition.inc
+# Somehow the above times out so we use connectin to node 3
+
+--connection node_3
+# wait for node_1 to disappear
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+SET GLOBAL wsrep_sync_wait=15;
+DROP TABLE test.t1;
+
+# reconnect node 2, since it is now inconsistent
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+--sleep 1
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST");
+CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno:");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test
new file mode 100644
index 00000000000..4183dfcfaf5
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test
@@ -0,0 +1,75 @@
+# NB-DDL: Assertion `header_size_max() + csize <= size' failed in gu::RecordSetOutBase::write_header
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+# Set the ALTER to block on the master
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+# Wait until the ALTER has blocked on the master
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: alter_table_before_open_tables';
+--source include/wait_condition.inc
+
+# Restart the master
+--source include/kill_galera.inc
+--sleep 5
+
+# Make sure the ALTER is aborted on node #1
+--connection node_1
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'
+--source include/wait_condition.inc
+
+--connection node_2a
+--source include/start_mysqld.inc
+--sleep 5
+
+# Confirm that all nodes have the same view of the database
+--connection node_1
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--let $galera_connection_name = node_2b
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2b
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_3
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)');
+CALL mtr.add_suppression('discarding established');
+CALL mtr.add_suppression('Quorum: No node with complete state');
+
+--connection node_2
+--error 2013
+--reap
+
+--connection node_2b
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test
new file mode 100644
index 00000000000..688ada7a120
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test
@@ -0,0 +1,73 @@
+#
+# This test kills the master (node_2 for this query) while the DDL is running there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+# Set the ALTER to block on the master
+SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue';
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+# Wait until the ALTER has blocked on the master
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: alter_table_before_open_tables';
+--source include/wait_condition.inc
+
+# Restart the master
+--source include/kill_galera.inc
+--sleep 5
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_2a
+--source include/start_mysqld.inc
+--sleep 5
+
+# Confirm that all nodes have the same view of the database
+--connection node_1
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--let $galera_connection_name = node_2b
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2b
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_3
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
+
+# CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)');
+# CALL mtr.add_suppression('discarding established');
+# CALL mtr.add_suppression('Quorum: No node with complete state');
+
+--connection node_2b
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test
new file mode 100644
index 00000000000..8f08f357046
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test
@@ -0,0 +1,73 @@
+#
+# This test kills a slave while a DDL is being applied there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_3
+# Set so that the applier thread will block in mysql_alter_table()
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_3
+# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Kill the slave (node #3)
+--source include/kill_galera.inc
+--sleep 5
+
+# Wait until node #3 is completely out of the cluster
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+
+# Restart node #3
+--connection node_3
+--let $galera_wsrep_recover_server_id=3
+--source suite/galera/include/galera_wsrep_recover.inc
+
+--source include/start_mysqld.inc
+--sleep 10
+
+# Check that all nodes have the same view of the database
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+
+--connection node_1
+--reap
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf
new file mode 100644
index 00000000000..36b1fa112a1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf
@@ -0,0 +1,11 @@
+!include ../galera_3nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1'
+
+[mysqld.2]
+wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1'
+
+[mysqld.3]
+wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=1'
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test
new file mode 100644
index 00000000000..9caf2e7299e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test
@@ -0,0 +1,70 @@
+#
+# This test kills a slave while a DDL is being applied there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_3
+# Set so that the applier thread will block in mysql_alter_table()
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_3
+# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Kill the slave (node #3)
+--source include/kill_galera.inc
+--sleep 5
+
+# Wait until node #3 is completely out of the cluster
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+INSERT INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (2,3);
+INSERT INTO t1 VALUES (3,4);
+INSERT INTO t1 VALUES (4,5);
+INSERT INTO t1 VALUES (5,6);
+
+# Restart node #3
+--connection node_3
+--source include/start_mysqld.inc
+--sleep 10
+
+# Check that all nodes have the same view of the database
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)");
+
+--connection node_1
+--reap
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 5 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test
new file mode 100644
index 00000000000..f7ff2e379a3
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test
@@ -0,0 +1,38 @@
+#
+# Test the situation where the master is in the majority when an NBO DDL fails on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+# Introduce inconsistency on node #2
+
+--connection node_2
+--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address`
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+# Run DDL that will fail on nodes #1 and #3 but succeed on node #2
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("inconsistent with group");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test
new file mode 100644
index 00000000000..3fca44efa2a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test
@@ -0,0 +1,38 @@
+#
+# This test has the master in the majority when an
+# NBO DDL succeeds on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+# Introduce inconsistency on node #2
+--connection node_2
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Error");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("Non-blocking operation end failed");
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test
new file mode 100644
index 00000000000..151ae4f6ad8
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test
@@ -0,0 +1,35 @@
+#
+# This test has the master (node #2) in the minority when an
+# NBO DDL fails on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+SET SESSION wsrep_OSU_method='NBO';
+
+--error ER_MULTIPLE_PRI_KEY
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_1
+DROP TABLE t1;
+CALL mtr.add_suppression("SYNC message from member");
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("Failed to execute TOI action");
+CALL mtr.add_suppression("TO isolation end failed");
+CALL mtr.add_suppression("SYNC message from member");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("SYNC message from member");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test
new file mode 100644
index 00000000000..b6a971a8e01
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test
@@ -0,0 +1,41 @@
+#
+# This test has the master (node #2) in the minority when an
+# NBO DDL succeeds on master
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+# Node #2 goes non-prim because it is in the minority
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--source ../include/galera_check_voting_recovery.inc
+
+--connection node_2
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("Slave SQL: Error");
+
+--connection node_2
+CALL mtr.add_suppression("inconsistent with group");
+
+--connection node_3
+--source include/galera_wait_ready.inc
+CALL mtr.add_suppression("Slave SQL: Error");
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test
new file mode 100644
index 00000000000..79ff032f02b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test
@@ -0,0 +1,92 @@
+#
+# Test the case where a master node (node #2) goes non-primary while a DDL is running
+# The DDL times out and the node leaves the cluster, to rejoin via SST.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Issue a DDL
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+SET SESSION lock_wait_timeout=2;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Isolate the master (node #2)
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+# Confirm that the DDL remains blocked in NBO
+
+--connection node_2a
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'acquiring total order isolation for NBO end'
+--source include/wait_condition.inc
+
+# DDL should now return a failure
+
+--connection node_2
+--error ER_ERROR_DURING_COMMIT
+--reap
+
+# Node #2 is now non-prim
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+--connection node_1
+INSERT INTO t1 VALUES (2,2);
+
+--connection node_2
+# So we restart it to force SST
+SET SESSION wsrep_on = OFF;
+--source include/restart_mysqld.inc
+--source include/wait_until_connected_again.inc
+
+# Confirm that the nodes are identical
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Lock wait timeout while waiting NBO end to replicate");
+CALL mtr.add_suppression("Failed to acquire total order isolation for non-blocking DDL end event, provider returned error code 6");
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test
new file mode 100644
index 00000000000..995828b3ca1
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test
@@ -0,0 +1,80 @@
+#
+# Test the case where a master node (node #2) goes non-primary while a DDL is running
+# The non-prim situation is resolved in time and the DDL completes successfully
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+# Issue a DDL
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Isolate the master (node #2)
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+# Confirm that the DDL remains blocked in NBO
+
+--connection node_2a
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+SET SESSION wsrep_on=OFF;
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'acquiring total order isolation for NBO end'
+--source include/wait_condition.inc
+
+# Reconnect node #2 to cluster
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+# DDL should now be complete
+
+--connection node_2
+--reap
+
+# Confirm that the nodes are identical
+
+--connection node_1
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'
+--source include/wait_condition.inc
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test
new file mode 100644
index 00000000000..58f7f00ed71
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test
@@ -0,0 +1,66 @@
+#
+# This test kills a slave while a DDL is being applied there
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_3
+# Set so that the applier thread will block in mysql_alter_table()
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_3
+# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Shutdown the slave (node #3)
+--source include/shutdown_mysqld.inc
+--sleep 5
+
+# Wait until node #3 is completely out of the cluster
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+INSERT INTO t1 VALUES (1,2);
+
+# Restart node #3
+--connection node_3
+--source include/start_mysqld.inc
+--sleep 10
+
+# Check that all nodes have the same view of the database
+--source include/wait_until_connected_again.inc
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source");
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)");
+
+--connection node_1
+--reap
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test
new file mode 100644
index 00000000000..d4f3a4ffedd
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test
@@ -0,0 +1,69 @@
+#
+# Test the case where a slave node goes non-primary while a DDL is running
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+--source include/wait_until_connected_again.inc
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 3 FROM wsrep_schema.members;
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("gcs_caused\\(\\) returned -1");
+
+--let $galera_connection_name = node_3
+--let $galera_server_number = 3
+--source include/galera_connect.inc
+--connection node_3
+--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test
new file mode 100644
index 00000000000..23cfcd036a0
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test
@@ -0,0 +1,63 @@
+#
+# This test tests that TOI failure on 2 nodes (master and slave) for the
+# same reason, wins over success on a third slave.
+# In particular this tests that master and slave TOI cast the same vote for
+# the same error
+#
+--source include/galera_3nodes.inc
+--source include/have_innodb.inc
+
+# create inconsistency on node 3
+--connection node_3
+SET GLOBAL wsrep_on=OFF;
+DROP SCHEMA test;
+
+# This should fail on nodes 1 and 2 and succeed on node 3
+--connection node_1
+--error ER_DB_CREATE_EXISTS
+CREATE SCHEMA test;
+
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+# wait for node 3 to drop from the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+# wait for node 3 to drop from the cluster
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--connection node_3
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+# reconnect node 3, since it failed
+--connection node_3
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+--connection node_1
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+--connection node_2
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("Error_code: 1007");
+CALL mtr.add_suppression("WSREP: Failed to apply trx: source: ");
+CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: ");
+CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster...");
+
+--connection node_3
+CALL mtr.add_suppression("inconsistent with group");
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf
new file mode 100644
index 00000000000..e255e1d527e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf
@@ -0,0 +1,4 @@
+!include ../galera_3nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test
new file mode 100644
index 00000000000..bc696ed6896
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test
@@ -0,0 +1,80 @@
+#
+# Test that mysqldump SST is possible after a vote without a cluster restart
+#
+
+--source include/galera_cluster.inc
+--source suite/galera/include/galera_sst_set_mysqldump.inc
+
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+# Introduce inconsistency on node #2
+
+--connection node_2
+--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address`
+SET SESSION wsrep_on=OFF;
+ALTER TABLE t1 ADD PRIMARY KEY (f1);
+SET SESSION wsrep_on=ON;
+
+# Run DDL that will fail on nodes #1 and #3 but succeed on node #2
+
+--connection node_1
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY;
+
+# Nodes #1 and #3 remain in the cluster
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Node #2 is kicked out
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+SET SESSION wsrep_on=ON;
+
+# Restore cluster
+
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2'
+--enable_query_log
+--enable_reconnect
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+
+# Confirm that the table is now identical throughout
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SET SESSION wsrep_on=OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+SET SESSION wsrep_on=ON;
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 0 FROM t1;
+CALL mtr.add_suppression("is inconsistent with group");
+
+--connection node_3
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that column/key exists'");
+
+--connection node_1
+--source suite/galera/include/galera_sst_restore.inc
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt
new file mode 100644
index 00000000000..196498bb9fa
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt
@@ -0,0 +1,2 @@
+--wsrep-ignore-apply-errors=0
+
diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test
new file mode 100644
index 00000000000..7655c818de6
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test
@@ -0,0 +1,87 @@
+#
+# Test voting while an SR transaction is in progress
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB;
+
+# Introduce inconsistency
+--connection node_2
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (5, 'X');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+
+# Perform an SR transaction that will hit the inconsistency
+--connection node_1
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 131070;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (2, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (3, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (4, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (5, REPEAT('A', 65535));
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Perform another SR transaction in order to have stuff in the wsrep_schema.SR table
+START TRANSACTION;
+INSERT INTO t1 VALUES (11, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (12, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (13, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (14, REPEAT('A', 65535));
+INSERT INTO t1 VALUES (15, REPEAT('A', 65535));
+
+# Node #2 has dropped from the cluster due to voting
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Bring node #2 back via SST
+--connection node_2
+SET SESSION wsrep_on=OFF;
+--source include/shutdown_mysqld.inc
+
+--sleep 10
+
+--echo Starting mysqld
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
+--source include/wait_condition.inc
+
+# Node #2 should have some entries in its SR table post-restart
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Commit second SR transaction
+--connection node_1
+COMMIT;
+
+# Confirm that all nodes are identical
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 10 FROM t1;
+CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '5' for key 'PRIMARY'");
+CALL mtr.add_suppression("Write_rows apply failed");
+CALL mtr.add_suppression("Inconsistent by consensus");
+CALL mtr.add_suppression("no THD for trx");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test b/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test
new file mode 100644
index 00000000000..95bc16dd42b
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+--send INSERT INTO t1 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+
+--connection node_1
+--reap
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf
new file mode 100644
index 00000000000..62c8214b8f2
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf
@@ -0,0 +1 @@
+!include ../galera_3nodes/galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_sr/my.cnf b/mysql-test/suite/galera_3nodes_sr/my.cnf
new file mode 100644
index 00000000000..bb25b95ceea
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/my.cnf
@@ -0,0 +1 @@
+!include galera_3nodes.cnf
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result
new file mode 100644
index 00000000000..ac3813176c9
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (2);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+ERROR 08S01: WSREP has not yet prepared node for application use
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+DROP TABLE t1;
+CALL mtr.add_suppression("replication aborted");
+CALL mtr.add_suppression("WSREP: fragment replication failed: 3");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result
new file mode 100644
index 00000000000..68a8fde0abc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result
@@ -0,0 +1,23 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) FROM wsrep_schema.SR;
+COUNT(*)
+5
+SELECT COUNT(*) FROM wsrep_schema.SR;
+COUNT(*)
+5
+COMMIT;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+5
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+5
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result
new file mode 100644
index 00000000000..03c7963c6d5
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result
@@ -0,0 +1,23 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+0
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1
+COMMIT;
+SELECT * FROM t1;
+f1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result
new file mode 100644
index 00000000000..52544166e29
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result
@@ -0,0 +1,20 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (31),(32),(33);
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+0
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+0
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result
new file mode 100644
index 00000000000..9064030aa89
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result
@@ -0,0 +1,256 @@
+SET GLOBAL debug="d,crash_last_fragment_commit_before_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_last_fragment_commit_before_fragment_removal
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_last_fragment_commit_after_fragment_removal
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_replicate_fragment_success";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_replicate_fragment_success
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_replicate_fragment_after_certify";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_replicate_fragment_after_certify
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_replicate_fragment_before_certify";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+crash_replicate_fragment_before_certify
+COMMIT;
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result
new file mode 100644
index 00000000000..a0f002ac627
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result
@@ -0,0 +1,100 @@
+SET GLOBAL debug="d,crash_apply_cb_before_append_frag";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+SET GLOBAL debug="d,crash_apply_cb_after_append_frag";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+COMMIT;
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug = '';
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result
new file mode 100644
index 00000000000..cddd8918a2a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result
@@ -0,0 +1,177 @@
+SET GLOBAL debug="d,crash_commit_cb_last_fragment_commit_success";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug="d,crash_commit_cb_before_last_fragment_commit";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug="d,crash_apply_cb_after_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET GLOBAL debug="d,crash_apply_cb_before_fragment_removal";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary');
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary');
+SELECT 1 FROM t1;
+Got one of the listed errors
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result
new file mode 100644
index 00000000000..35a96650037
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result
@@ -0,0 +1,33 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_on = OFF;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result
new file mode 100644
index 00000000000..7680f0380af
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result
@@ -0,0 +1,15 @@
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+CREATE TABLE t1 (f1 VARCHAR(30)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+COMMIT;
+ERROR HY000: Lost connection to MySQL server during query
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result
new file mode 100644
index 00000000000..5ecf1b6ec00
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result
@@ -0,0 +1,62 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("failed to send SR rollback for");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result
new file mode 100644
index 00000000000..eb539eba919
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result
@@ -0,0 +1,25 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+COMMIT;
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result
new file mode 100644
index 00000000000..dcf291bacc7
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result
new file mode 100644
index 00000000000..a849a44832e
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result
@@ -0,0 +1,38 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+COUNT(*) = 15
+1
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 15 FROM t1;
+COUNT(*) = 15
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result
new file mode 100644
index 00000000000..7bc36c3d0af
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result
@@ -0,0 +1,44 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+COUNT(*) = 15
+1
+ROLLBACK;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result
new file mode 100644
index 00000000000..8b015c26977
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result
@@ -0,0 +1,31 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing server ...
+INSERT INTO t1 VALUES (6);
+ROLLBACK;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result
new file mode 100644
index 00000000000..285421c4d25
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result
@@ -0,0 +1,27 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+CREATE TABLE t2 (f1 INTEGER);
+LOCK TABLE t2 WRITE;
+INSERT INTO t2 VALUES (1);
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result
new file mode 100644
index 00000000000..0daf6484d04
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result
@@ -0,0 +1,84 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (200);
+INSERT INTO t1 VALUES (201);
+INSERT INTO t1 VALUES (202);
+INSERT INTO t1 VALUES (203);
+INSERT INTO t1 VALUES (204);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (300);
+INSERT INTO t1 VALUES (301);
+INSERT INTO t1 VALUES (302);
+INSERT INTO t1 VALUES (303);
+INSERT INTO t1 VALUES (304);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+wsrep_gcomm_uuid_match
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+COUNT(DISTINCT node_uuid) = 1
+1
+wsrep_gcomm_uuid_match
+1
+INSERT INTO t1 VALUES (30);
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (33);
+INSERT INTO t1 VALUES (34);
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34
+1 1 1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34
+1 1 1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34
+1 1 1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test
new file mode 100644
index 00000000000..ea8bed454ca
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test
@@ -0,0 +1,47 @@
+--source include/galera_cluster.inc
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+SET SESSION wsrep_sync_wait=0;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (2);
+--error ER_UNKNOWN_COM_ERROR
+COMMIT;
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
+--source include/wait_condition.inc
+DROP TABLE t1;
+
+CALL mtr.add_suppression("replication aborted");
+CALL mtr.add_suppression("WSREP: fragment replication failed: 3");
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--source include/galera_wait_ready.inc
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test
new file mode 100644
index 00000000000..ab029594f4d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--source include/start_mysqld.inc
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+SELECT COUNT(*) FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) FROM wsrep_schema.SR;
+COMMIT;
+SELECT COUNT(*) FROM t1;
+
+--connection node_2
+SELECT COUNT(*) FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test
new file mode 100644
index 00000000000..34d8ec55f1a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test
@@ -0,0 +1,80 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the case where the cluster splits 3 ways.
+# The master transitions to a non-prim view and back to prim. Its ongoing
+# should fail to commit.
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+
+--connection node_1
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+#
+# Isolate node_2 into a separate non-primary component
+#
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+--disable_query_log
+SET WSREP_ON=OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+SET WSREP_ON=ON;
+--enable_query_log
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+#
+# Confirm that node_1 has no transactions in SR table
+#
+
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+#
+# Restore cluster
+#
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_1
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT * FROM t1;
+COMMIT;
+
+--connection node_1
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); \ No newline at end of file
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test
new file mode 100644
index 00000000000..6e5da4bf349
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test
@@ -0,0 +1,30 @@
+#
+# GCF-609 SR: Assertion wsrep_apply_cb on slave after master causes a duplicate key error
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+INSERT INTO t1 VALUES (31),(32),(33);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test
new file mode 100644
index 00000000000..38d95556e48
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test
@@ -0,0 +1,137 @@
+#
+# Exercise the crash points which crash the server at various points important to SR
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+#
+# crash_last_fragment_commit_before_fragment_removal
+#
+
+--connection node_2
+--enable_reconnect
+SET GLOBAL debug="d,crash_last_fragment_commit_before_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_last_fragment_commit_before_fragment_removal
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_last_fragment_commit_after_fragment_removal
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_last_fragment_commit_after_fragment_removal
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_last_fragment_commit_success
+#
+# Case crash_last_fragment_commit_success is commented out,
+# the changes will be visible on slave due to succesful commit,
+# so the galera_sr_crash_post_check will fail.
+#
+
+# --connection node_2
+# SET GLOBAL debug="d,crash_last_fragment_commit_success";
+# --source suite/galera_3nodes/include/galera_expect_node_crash.inc
+# --source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+# --echo crash_last_fragment_commit_success
+
+# --connection node_2
+# --error 2006,2013
+# COMMIT;
+
+# --source include/start_mysqld.inc
+# --source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_replicate_fragment_success
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_replicate_fragment_success";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_replicate_fragment_success
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_replicate_fragment_after_certify
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_replicate_fragment_after_certify";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_replicate_fragment_after_certify
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+#
+# crash_replicate_fragment_before_certify
+#
+
+--connection node_2
+SET GLOBAL debug="d,crash_replicate_fragment_before_certify";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc
+
+--echo crash_replicate_fragment_before_certify
+
+--connection node_2
+--error 2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc
+
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test
new file mode 100644
index 00000000000..24a518af9f7
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test
@@ -0,0 +1,49 @@
+#
+# Exercise the crash points which crash the server at various points important to SR
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+#
+# crash_apply_cb_before_append_frag
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_before_append_frag";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes2.inc
+
+--connection node_3
+--error 0,2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--sleep 5
+--source suite/galera_3nodes/include/galera_sr_crash_post_check2.inc
+
+#
+# crash_apply_cb_after_append_frag
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_after_append_frag";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes2.inc
+
+--connection node_3
+--error 0,2006,2013
+COMMIT;
+
+--source include/start_mysqld.inc
+--sleep 5
+--source suite/galera_3nodes/include/galera_sr_crash_post_check2.inc
+
+--connection node_1
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test
new file mode 100644
index 00000000000..79948e5a46d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test
@@ -0,0 +1,70 @@
+#
+# Exercise the crash points which crash the server at various points important to SR
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--enable_reconnect
+--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+#
+# crash_commit_cb_last_fragment_commit_success
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_commit_cb_last_fragment_commit_success";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+#
+# crash_commit_cb_before_last_fragment_commit
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_commit_cb_before_last_fragment_commit";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+#
+# crash_apply_cb_after_fragment_removal
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_after_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+#
+# crash_apply_cb_before_fragment_removal
+#
+
+--connection node_3
+SET GLOBAL debug="d,crash_apply_cb_before_fragment_removal";
+--source suite/galera_3nodes/include/galera_expect_node_crash.inc
+--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc
+
+--source include/start_mysqld.inc
+--sleep 5
+--source include/galera_wait_ready.inc
+--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test
new file mode 100644
index 00000000000..c585aba78d4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test
@@ -0,0 +1,101 @@
+#
+# GCF-817 SR: master removes SR trx in non-primary view
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--connection node_1a
+# Force node #1 to go non-primary
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1';
+
+SET SESSION wsrep_on = OFF;
+--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+# SR table on master should still contain entries after going non-Prim
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# SR table on slave should eventually clean up entries when master goes non-Prim
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Restore node #1 to primary
+
+--connection node_1a
+#
+# The following sleep is a workaround for issue GCF-861.
+# Normally it's sufficient to make sure that the CC happened
+# by checking that wsrep_cluster_size has shrinked, as above.
+# However that is not always enough, so we sleep a few seconds.
+# See GCF-861 on how to reproduce.
+#
+
+--connection node_1a
+--sleep 6
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0';
+
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--source include/galera_wait_ready.inc
+
+# SR table on master should contain no entries after going back to Prim state
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+--connection node_2
+# And none on slave
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+# SR table is now empty everywhere
+--connection node_1a
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test
new file mode 100644
index 00000000000..95d40803506
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test
@@ -0,0 +1,36 @@
+#
+# GCF-832 SR: wsrep_schema.SR table remains populated on all nodes after crash
+# followed by immediate recovery
+#
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+--connection node_2
+SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal";
+
+--let $_server_id= `SELECT @@server_id`
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
+--exec echo "wait" > $_expect_file_name
+
+CREATE TABLE t1 (f1 VARCHAR(30)) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary');
+--error 2013
+COMMIT;
+
+--source include/start_mysqld.inc
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--enable_reconnect
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/disabled.def b/mysql-test/suite/galera_3nodes_sr/t/disabled.def
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/disabled.def
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test
new file mode 100644
index 00000000000..a55109e57e4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test
@@ -0,0 +1,127 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of gmcast.isolate on master during an SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM t1;
+
+#
+# Trigger gmcast.isolate=1 .
+# The transaction is aborted and we expect the SR tables to be cleaned up
+#
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--source include/galera_wait_ready.inc
+
+#
+# Expect that the transaction is cleaned up entirely across the cluster and in all wsrep_schema.SR tables
+#
+
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_3
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+#
+# Restore cluster
+#
+
+--connection node_1a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_3
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_1a
+--source include/galera_wait_ready.inc
+
+#
+# Confirm that the previous transaction is gone on Node #1 as well
+#
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# Confirm that the transaction can be retried
+#
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+CALL mtr.add_suppression("failed to send SR rollback for");
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test
new file mode 100644
index 00000000000..ff892aa20a6
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test
@@ -0,0 +1,56 @@
+#
+# This test kills the slave before a Streaming Replication transaction has started
+# and restarts it when the transaction is already in progress. IST should
+# bring the slave up to date so that it can receive the complete transaction.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+COMMIT;
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 10 FROM t1;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 10 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test
new file mode 100644
index 00000000000..50b8ef0302f
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test
@@ -0,0 +1,56 @@
+#
+# This test kills the master while a Streaming Replication transaction is in progress
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/kill_galera.inc
+
+--connection node_3
+# We expect that uncommitted values are no longer present
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# and we can insert them again
+--error 0
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+--source include/start_mysqld.inc
+# --sleep 5
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--sleep 1
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test
new file mode 100644
index 00000000000..7b11dfeddea
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test
@@ -0,0 +1,75 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# and after a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+
+--connection node_2
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+
+--connection node_1
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 15 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member");
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test
new file mode 100644
index 00000000000..2e62810cef4
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test
@@ -0,0 +1,76 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# and after a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent even if ROLLBACK
+# is issued on the SR transaction after restart.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+
+--connection node_2
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 15 FROM wsrep_schema.SR;
+
+--connection node_1
+ROLLBACK;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test
new file mode 100644
index 00000000000..603483a419c
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test
@@ -0,0 +1,56 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# and after a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+ROLLBACK;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_2
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test
new file mode 100644
index 00000000000..267552afb60
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test
@@ -0,0 +1,71 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in progress
+# but before a fragment has already been applied on the slave. It is expected that
+# after the slave restarts, the cluster will continue to be consistent.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+
+# Block node #2's applier before table t1's inserts have come into play
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+LOCK TABLE t2 WRITE;
+
+--connection node_1
+INSERT INTO t2 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+# Expect that the SR table will get some entries after the restart
+# --let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+# --source include/wait_conditions.inc
+
+# SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+# SELECT COUNT(*) > 0 FROM t1;
+
+--connection node_1
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf
new file mode 100644
index 00000000000..910d945949a
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf
@@ -0,0 +1,5 @@
+!include ../galera_3nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.weight=3'
+
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test
new file mode 100644
index 00000000000..82d693eb28d
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test
@@ -0,0 +1,169 @@
+#
+# Test the case where the cluster splits 3 ways . The master remains in the
+# primary component and is able to commit its transaction.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+#
+# Begin a separate SR transaction on every node and confirm that each node
+# has SR table entries for every transaction
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (200);
+INSERT INTO t1 VALUES (201);
+INSERT INTO t1 VALUES (202);
+INSERT INTO t1 VALUES (203);
+INSERT INTO t1 VALUES (204);
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 2 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (300);
+INSERT INTO t1 VALUES (301);
+INSERT INTO t1 VALUES (302);
+INSERT INTO t1 VALUES (303);
+INSERT INTO t1 VALUES (304);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+--connection node_1a
+--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 3 FROM wsrep_schema.SR
+--source include/wait_condition.inc
+
+#
+# Isolate nodes #2 and #3 into separate non-primary components
+#
+
+--connection node_2a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_3a
+SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (21);
+INSERT INTO t1 VALUES (22);
+INSERT INTO t1 VALUES (23);
+INSERT INTO t1 VALUES (24);
+
+#
+# Restore cluster
+#
+
+--connection node_2a
+--source include/wsrep_wait_disconnect.inc
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+
+--connection node_3a
+--source include/wsrep_wait_disconnect.inc
+SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
+--source include/galera_wait_ready.inc
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+--let $node_1_gcomm_uuid = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'`
+
+--connection node_2a
+--source include/wait_condition.inc
+
+--connection node_3a
+--source include/wait_condition.inc
+
+
+#
+# Confirm that the rejoined nodes only have node #1's transaction in their SR tables
+#
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+--disable_query_log
+--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM wsrep_schema.SR;
+--enable_query_log
+
+--connection node_3
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR;
+--disable_query_log
+--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM wsrep_schema.SR;
+--enable_query_log
+
+#
+# Finalize transaction on node #1
+#
+
+--connection node_1
+INSERT INTO t1 VALUES (30);
+INSERT INTO t1 VALUES (31);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (33);
+INSERT INTO t1 VALUES (34);
+COMMIT;
+
+#
+# Confirm that transaction is replicated correctly and SR tables are empty at the end of the test
+#
+
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SET AUTOCOMMIT=ON;
+
+--connection node_2
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SET AUTOCOMMIT=ON;
+
+--connection node_3
+COMMIT;
+SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SET AUTOCOMMIT=ON;
+
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+--connection node_2
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
+--connection node_3
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); \ No newline at end of file
diff --git a/mysql-test/suite/galera_ee/galera_2nodes.cnf b/mysql-test/suite/galera_ee/galera_2nodes.cnf
new file mode 100644
index 00000000000..0412b5654dd
--- /dev/null
+++ b/mysql-test/suite/galera_ee/galera_2nodes.cnf
@@ -0,0 +1 @@
+!include ../galera/galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_ee/galera_4nodes.cnf b/mysql-test/suite/galera_ee/galera_4nodes.cnf
new file mode 100644
index 00000000000..7b37e62c314
--- /dev/null
+++ b/mysql-test/suite/galera_ee/galera_4nodes.cnf
@@ -0,0 +1 @@
+!include ../galera/galera_4nodes.cnf
diff --git a/mysql-test/suite/galera_ee/my.cnf b/mysql-test/suite/galera_ee/my.cnf
new file mode 100644
index 00000000000..ca163a540d9
--- /dev/null
+++ b/mysql-test/suite/galera_ee/my.cnf
@@ -0,0 +1 @@
+!include galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_ee/r/GCF-329A.result b/mysql-test/suite/galera_ee/r/GCF-329A.result
new file mode 100644
index 00000000000..c429b0b8973
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-329A.result
@@ -0,0 +1,30 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
+CALL mtr.add_suppression("Failed to send NBO-end");
+CALL mtr.add_suppression("Failed to acquire total order isolation");
+CALL mtr.add_suppression("Aborting");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+CALL mtr.add_suppression("Slave SQL: Error 'Got error 7 during COMMIT'");
diff --git a/mysql-test/suite/galera_ee/r/GCF-329B.result b/mysql-test/suite/galera_ee/r/GCF-329B.result
new file mode 100644
index 00000000000..2a56bd4964a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-329B.result
@@ -0,0 +1,16 @@
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+Killing server ...
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+COUNT(*) = 2
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+COUNT(*) = 2
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-360.result b/mysql-test/suite/galera_ee/r/GCF-360.result
new file mode 100644
index 00000000000..7dc9ba37c19
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-360.result
@@ -0,0 +1,416 @@
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+ERROR 42S02: Unknown table 'test.nonexisting_table'
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 4
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
diff --git a/mysql-test/suite/galera_ee/r/GCF-421.result b/mysql-test/suite/galera_ee/r/GCF-421.result
new file mode 100644
index 00000000000..78dab709e32
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-421.result
@@ -0,0 +1,14 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);;
+DROP TABLE t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("TO isolation failed for");
+CALL mtr.add_suppression("TO isolation failed for");
diff --git a/mysql-test/suite/galera_ee/r/GCF-546.result b/mysql-test/suite/galera_ee/r/GCF-546.result
new file mode 100644
index 00000000000..dde91db8422
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-546.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables';
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+ERROR 42000: Multiple primary key defined
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+CALL mtr.add_suppression("TO isolation failed");
+CALL mtr.add_suppression("ALTER TABLE isolation failure");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+CALL mtr.add_suppression("Slave SQL: Error");
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-563.result b/mysql-test/suite/galera_ee/r/GCF-563.result
new file mode 100644
index 00000000000..8de6dfd36e7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-563.result
@@ -0,0 +1,52 @@
+SET GLOBAL wsrep_slave_threads=2;
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t2 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP TABLE t2;
+SET GLOBAL wsrep_slave_threads=1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-849.result b/mysql-test/suite/galera_ee/r/GCF-849.result
new file mode 100644
index 00000000000..599d5451f2a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-849.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/GCF-854.result b/mysql-test/suite/galera_ee/r/GCF-854.result
new file mode 100644
index 00000000000..0752a169d73
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/GCF-854.result
@@ -0,0 +1,16 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+INSERT INTO t1 VALUES (2,2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera-features#117.result b/mysql-test/suite/galera_ee/r/galera-features#117.result
new file mode 100644
index 00000000000..f44269df9f0
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera-features#117.result
@@ -0,0 +1,29 @@
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f2 INTEGER);
+SET GLOBAL wsrep_on=ON;
+CREATE TABLE test.t1 (f1 INTEGER);
+ERROR 42S01: Table 't1' already exists
+SET SESSION wsrep_sync_wait=0;
+SHOW CREATE TABLE test.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status Primary
+DROP TABLE test.t1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_on=OFF;
+SHOW CREATE TABLE test.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW STATUS LIKE 'wsrep_cluster_status';
+Variable_name Value
+wsrep_cluster_status non-Primary
+Killing server ...
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("WSREP: Failed to execute TOI action");
+CALL mtr.add_suppression("WSREP: TO isolation end failed");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result
new file mode 100644
index 00000000000..0090878afd8
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result
@@ -0,0 +1,14 @@
+SET GLOBAL wsrep_slave_threads=2;
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f2);;
+SET SESSION wsrep_sync_wait=0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Multiple primary key defined' on query");
+SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result
new file mode 100644
index 00000000000..abc6c3f4148
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result
@@ -0,0 +1,44 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=COPY, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (2);
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3);
+INSERT INTO t1 VALUES (3);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result
new file mode 100644
index 00000000000..1f1d58cdd76
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result
@@ -0,0 +1,22 @@
+SET GLOBAL wsrep_replicate_myisam=ON;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+SET GLOBAL wsrep_replicate_myisam=FALSE;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result
new file mode 100644
index 00000000000..252fe9d6740
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result
@@ -0,0 +1,30 @@
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(1);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+INSERT INTO t1 VALUES (1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 7 FROM t1;
+COUNT(*) = 7
+1
+ALTER IGNORE TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+Warnings:
+Warning 1681 'IGNORE' is deprecated and will be removed in a future release.
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result
new file mode 100644
index 00000000000..21e6c51374b
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result
@@ -0,0 +1,37 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 LOCK=EXCLUSIVE, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (3);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result
new file mode 100644
index 00000000000..70ef1bc083e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result
@@ -0,0 +1,39 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method='NBO';
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (2);
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f2 INTEGER;
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t1 VALUES (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3,4);
+INSERT INTO t1 VALUES (3);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f3 INTEGER;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result
new file mode 100644
index 00000000000..923df0d13cf
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1), ADD COLUMN f2 INTEGER;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result
new file mode 100644
index 00000000000..eb780a6b264
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result
@@ -0,0 +1,29 @@
+SET GLOBAL wsrep_slave_threads=2;
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD KEY (f2);;
+SET SESSION wsrep_sync_wait=0;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) NOT NULL,
+ PRIMARY KEY (`f1`),
+ KEY `f2` (`f2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) NOT NULL,
+ PRIMARY KEY (`f1`),
+ KEY `f2` (`f2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET GLOBAL wsrep_slave_threads = 1;
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result
new file mode 100644
index 00000000000..6a15c68c393
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result
@@ -0,0 +1,45 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables:d,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t2 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t3 VALUES (1);
+INSERT INTO t3 VALUES (2);
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t3;
+COUNT(*) = 2
+1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t3;
+COUNT(*) = 2
+1
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result
new file mode 100644
index 00000000000..d66cfd5234c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED PARTITION BY HASH(f1) PARTITIONS 8;
+INSERT INTO t1 VALUES (1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY HASH (f1)
+PARTITIONS 8 */
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+ALTER TABLE t1 LOCK=SHARED REMOVE PARTITIONING;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result
new file mode 100644
index 00000000000..22d9dfbc26a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result
@@ -0,0 +1,19 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t2;
+ERROR 42S01: Table 't2' already exists
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t3;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 1 FROM t3;
+COUNT(*) = 1
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t2;
+DROP TABLE t3;
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query.");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result
new file mode 100644
index 00000000000..3ac59facc0f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result
@@ -0,0 +1,38 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+ALTER TABLE t2 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) DEFAULT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) DEFAULT NULL,
+ `f2` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result b/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result
new file mode 100644
index 00000000000..4c43149e28d
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result
@@ -0,0 +1,36 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(1);
+SET SESSION wsrep_osu_method=NBO;
+CREATE INDEX i1 ON t1 (f1);
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+CREATE UNIQUE INDEX i1 ON t1 (f1) LOCK=SHARED;
+ERROR 23000: Duplicate entry '1' for key 'i1'
+CREATE INDEX i1 ON t1 (f1) LOCK=SHARED;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ KEY `i1` (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ KEY `i1` (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT COUNT(*) = 3 FROM t1;
+COUNT(*) = 3
+1
+DROP INDEX i1 ON t1 LOCK=EXCLUSIVE;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result b/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result
new file mode 100644
index 00000000000..8715790653a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+ERROR 42S21: Duplicate column name 'f2'
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f3 INTEGER;
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f4 INTEGER;
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 4
+1
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 4
+1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error 'Duplicate column name");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result b/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result
new file mode 100644
index 00000000000..f45f100b73c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result
@@ -0,0 +1,13 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result b/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result
new file mode 100644
index 00000000000..476e35eac95
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+CREATE TABLE t2 (f1 INTEGER);
+LOCK TABLE t1 WRITE;
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;;
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t2 VALUES (1);;
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t2 VALUES (1);
+CREATE TABLE t3 (t4 INTEGER);
+UNLOCK TABLES;
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result b/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result
new file mode 100644
index 00000000000..d17e5c5a777
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result
@@ -0,0 +1,35 @@
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+COUNT(*) = 3
+1
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method='NBO';
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 1
+1
+ERROR HYN: You are not owner of thread N
+ERROR HYN: You are not owner of thread N
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_opened_table';
+SET SESSION wsrep_sync_wait = 7;
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 ADD COLUMN f2 INTEGER';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+COUNT(*) = 2
+1
+INSERT INTO t1 VALUES (1,2);
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN t3 INTEGER;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result b/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result
new file mode 100644
index 00000000000..76ff10dc4d7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result
@@ -0,0 +1,23 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;;
+SET SESSION wsrep_sync_wait = 0;
+include/assert_grep.inc [Master should report that it can not donate SST]
+include/assert_grep.inc [Slave should report that it could not join]
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.alter_locked_tables_inplace';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`f1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+CALL mtr.add_suppression("Non-blocking operation in progress, cannot donate SST");
+CALL mtr.add_suppression("Resource temporarily unavailable");
+CALL mtr.add_suppression("Resource temporarily unavailable");
+CALL mtr.add_suppression("Will never receive state");
+CALL mtr.add_suppression("terminated unexpectedly");
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result b/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result
new file mode 100644
index 00000000000..17d26ed6b8e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result
@@ -0,0 +1,14 @@
+RESET MASTER;
+RESET MASTER;
+CREATE TEMPORARY TABLE t1 (f1 INTEGER, f2 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result b/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result
new file mode 100644
index 00000000000..545e8ad3969
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method='NBO';
+CREATE TABLE t2 (f1 INTEGER);
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+RENAME TABLE t1 TO t2;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+ALTER TABLE t1 LOCK=DEFAULT, ADD COLUMN f2 INTEGER;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+ALTER TABLE t2 LOCK=NONE, ADD COLUMN f2 INTEGER;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+DROP TABLE t1;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+REPAIR TABLE t1;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+CREATE USER u1 IDENTIFIED BY 'p1';
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+DROP USER u1;
+ERROR 42000: wsrep_OSU_method NBO not supported for query
+SET SESSION wsrep_osu_method=TOI;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL mtr.add_suppression('ALTER TABLE isolation failure');
diff --git a/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result
new file mode 100644
index 00000000000..361e1f71258
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result
@@ -0,0 +1,44 @@
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+SET SESSION wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_on=ON;
+DROP TABLE t1;
+CREATE TABLE t2 (f1 INTEGER);
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+SET SESSION wsrep_on=OFF;
+Killing server ...
+Starting mysqld
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("inconsistent with group");
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+COUNT(*) = 1
+1
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result
new file mode 100644
index 00000000000..e3dd272e1d3
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result
@@ -0,0 +1,47 @@
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'A');
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (2, 'B');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+SET SESSION wsrep_on=OFF;
+Killing server ...
+Starting mysqld
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+CALL mtr.add_suppression("inconsistent with group");
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result
new file mode 100644
index 00000000000..089d0303750
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result
@@ -0,0 +1,5 @@
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET GLOBAL wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result
new file mode 100644
index 00000000000..b513ef9d560
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result
@@ -0,0 +1,7 @@
+SET SESSION wsrep_OSU_method=TOI;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+SET SESSION wsrep_OSU_method=NBO;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result
new file mode 100644
index 00000000000..3a6ad0f620f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t1 VALUES (1);;
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result
new file mode 100644
index 00000000000..50e5f97fdb7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+ALTER TABLE t1 ADD PRIMARY KEY (f1), ALGORITHM=INPLACE, LOCK=SHARED;;
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (1);
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+SELECT COUNT(*) = 1 FROM t2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t2;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/GCF-329A.test b/mysql-test/suite/galera_ee/t/GCF-329A.test
new file mode 100644
index 00000000000..284aa971b44
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-329A.test
@@ -0,0 +1,42 @@
+#
+# GCF-329: NB-DDL: "no corresponding NBO begin found for NBO end" when restarting slave
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+--source include/restart_mysqld.inc
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+--source include/galera_wait_ready.inc
+
+SELECT COUNT(*) = 1 FROM t1;
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+SHOW CREATE TABLE t1;
+
+--connection node_1
+--reap
+SHOW CREATE TABLE t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order");
+CALL mtr.add_suppression("Failed to send NBO-end");
+CALL mtr.add_suppression("Failed to acquire total order isolation");
+CALL mtr.add_suppression("Aborting");
+CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown");
+CALL mtr.add_suppression("Slave SQL: Error 'Got error 7 during COMMIT'");
diff --git a/mysql-test/suite/galera_ee/t/GCF-329B.test b/mysql-test/suite/galera_ee/t/GCF-329B.test
new file mode 100644
index 00000000000..248301280cc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-329B.test
@@ -0,0 +1,53 @@
+#
+# GCF-329 NB-DDL: "no corresponding NBO begin found for NBO end" when restarting slave
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--connection node_1
+
+# Enable the master to continue running during the split-brain situation that
+# occurs when the slave is killed
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_2
+--source include/kill_galera.inc
+
+--let $galera_connection_name = node_1a
+--let $galera_server_number = 1
+--source include/galera_connect.inc
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/start_mysqld.inc
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+SET SESSION wsrep_OSU_method=TOI;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-360.cnf b/mysql-test/suite/galera_ee/t/GCF-360.cnf
new file mode 100644
index 00000000000..28e51f87e8e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-360.cnf
@@ -0,0 +1,17 @@
+!include ../galera_4nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port'
+wsrep_ignore_apply_errors=0
+
+[mysqld.2]
+wsrep_provider_options='base_port=@mysqld.2.#galera_port'
+wsrep_ignore_apply_errors=0
+
+[mysqld.3]
+wsrep_provider_options='base_port=@mysqld.3.#galera_port'
+wsrep_ignore_apply_errors=0
+
+[mysqld.4]
+wsrep_provider_options='base_port=@mysqld.4.#galera_port'
+wsrep_ignore_apply_errors=0
diff --git a/mysql-test/suite/galera_ee/t/GCF-360.test b/mysql-test/suite/galera_ee/t/GCF-360.test
new file mode 100644
index 00000000000..e2684135810
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-360.test
@@ -0,0 +1,64 @@
+#
+# GCF-360 Inconsistency voting: node goes non-prim on DDL that fails everywhere
+#
+# We issue 400 DDLs in total to make this test more stressful#
+#
+
+--source include/galera_cluster.inc
+
+--let $count = 100
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+
+--disable_query_log
+while ($count)
+{
+ --connection node_1
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_2
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_3
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_4
+ --send DROP TABLE nonexisting_table;
+
+ --connection node_1
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --connection node_2
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --connection node_3
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --connection node_4
+ --error ER_BAD_TABLE_ERROR
+ --reap
+
+ --dec $count
+}
+
+--enable_query_log
+
+--connection node_1
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_2
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_3
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_4
+SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
diff --git a/mysql-test/suite/galera_ee/t/GCF-421.test b/mysql-test/suite/galera_ee/t/GCF-421.test
new file mode 100644
index 00000000000..2fca972e88f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-421.test
@@ -0,0 +1,46 @@
+#
+# GCF-421 NB-DDL: Applier thread fails with concurrent DDL
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+
+--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%ALTER%'
+--source include/wait_condition.inc
+
+--error ER_LOCK_DEADLOCK
+DROP TABLE t1;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+DROP TABLE t1;
+
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+
+--connection node_1
+--reap
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+CALL mtr.add_suppression("TO isolation failed for");
+
+--connection node_2
+CALL mtr.add_suppression("TO isolation failed for");
+
+
diff --git a/mysql-test/suite/galera_ee/t/GCF-546.test b/mysql-test/suite/galera_ee/t/GCF-546.test
new file mode 100644
index 00000000000..5c3e0aacc8a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-546.test
@@ -0,0 +1,47 @@
+#
+# GCF-546 NB-DDL: Assertion `thd->wsrep_trx_meta.gtid.seqno == (-1)' failed in wsrep_to_isolation_begin with conflicting DDL on same table
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL DEBUG = 'd,sync.alter_locked_tables';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--error ER_LOCK_DEADLOCK
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+
+--connection node_1
+--reap
+
+--connection node_2
+--error ER_MULTIPLE_PRI_KEY
+ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+SHOW CREATE TABLE t1;
+
+CALL mtr.add_suppression("TO isolation failed");
+CALL mtr.add_suppression("ALTER TABLE isolation failure");
+
+--connection node_1
+SHOW CREATE TABLE t1;
+CALL mtr.add_suppression("Slave SQL: Error");
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-563.test b/mysql-test/suite/galera_ee/t/GCF-563.test
new file mode 100644
index 00000000000..91a92ce2766
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-563.test
@@ -0,0 +1,63 @@
+#
+# GCF-563 NB-DDL: Assertion `kep->ref_trx(ke.key().prefix()) == ts' failed in do_clean_nbo with two independent DDLs running at the same time
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads=2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t2 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_1
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+SET GLOBAL wsrep_slave_threads=1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-849.test b/mysql-test/suite/galera_ee/t/GCF-849.test
new file mode 100644
index 00000000000..20389cfea64
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-849.test
@@ -0,0 +1,39 @@
+#
+# GCF-849 NB-DDL: Assertion `last_seen_seqno_ < global_seqno_' failed in galera::TrxHandleSlave::unserialize during IST
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Shut down node #2 and wait until it is completely gone
+--connection node_2
+--source include/shutdown_mysqld.inc
+--sleep 2
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Perform an ALTER under NBO
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+# Restart node #2 so that IST happens
+
+--connection node_2
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/GCF-854.test b/mysql-test/suite/galera_ee/t/GCF-854.test
new file mode 100644
index 00000000000..0f09720457d
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/GCF-854.test
@@ -0,0 +1,42 @@
+#
+# GCF-854 NB-DDL: Assertion `0' failed in Table_cache_manager::free_table with IST
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Shut down node #2 and wait until it is completely gone
+--connection node_2
+--source include/shutdown_mysqld.inc
+--sleep 2
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Perform an ALTER under NBO
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+INSERT INTO t1 VALUES (2,2);
+
+# Restart node #2 so that IST happens
+
+--connection node_2
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/wait_until_connected_again.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera-features#117.cnf b/mysql-test/suite/galera_ee/t/galera-features#117.cnf
new file mode 100644
index 00000000000..e20ed7fc08a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera-features#117.cnf
@@ -0,0 +1,4 @@
+!include ../galera_2nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_ee/t/galera-features#117.test b/mysql-test/suite/galera_ee/t/galera-features#117.test
new file mode 100644
index 00000000000..fa4af22a385
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera-features#117.test
@@ -0,0 +1,37 @@
+#
+# This test tests voting for DDLs (TOI events)
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+CREATE TABLE test.t1 (f2 INTEGER);
+SET GLOBAL wsrep_on=ON;
+
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE test.t1 (f1 INTEGER);
+
+--connection node_1
+# wait for node_2 to disappear
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+SHOW CREATE TABLE test.t1;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+DROP TABLE test.t1;
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+--let $wait_condition = SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+SET GLOBAL wsrep_on=OFF;
+SHOW CREATE TABLE test.t1;
+SHOW STATUS LIKE 'wsrep_cluster_status';
+--source include/kill_galera.inc
+--sleep 1
+--source include/start_mysqld.inc
+
+CALL mtr.add_suppression("Inconsistent by consensus.");
+CALL mtr.add_suppression("WSREP: Failed to execute TOI action");
+CALL mtr.add_suppression("WSREP: TO isolation end failed");
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test
new file mode 100644
index 00000000000..adcb0fee2cc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test
@@ -0,0 +1,57 @@
+#
+# Test that wsrep can process two ALTERs on the same table that are conflicting
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads=2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f2);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--sleep 1
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--error 0,ER_MULTIPLE_PRI_KEY
+--reap
+
+--connection node_1a
+--error 0,ER_MULTIPLE_PRI_KEY
+--reap
+
+SET SESSION wsrep_OSU_method=TOI;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Error 'Multiple primary key defined' on query");
+
+SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test
new file mode 100644
index 00000000000..fbb7e7e606b
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test
@@ -0,0 +1,67 @@
+#
+# Test that ALTER ALGORITHM = COPY works with NBO
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+
+--send ALTER TABLE t1 ALGORITHM=COPY, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Confirm that unrelated tables can be modified
+INSERT INTO t2 VALUES (2);
+
+# Confirm that the ALTER-ed table can not be modified on either node
+SET SESSION lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3);
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (3);
+
+# Unblock the ALTER and confirm that it executed on all nodes
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 2 FROM t2;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 2 FROM t2;
+
+SET SESSION wsrep_OSU_method=TOI;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test
new file mode 100644
index 00000000000..ef463c96543
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test
@@ -0,0 +1,31 @@
+#
+# Test NBO and ALTER ENGINE
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+SET GLOBAL wsrep_replicate_myisam=ON;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_OSU_method=NBO;
+
+ALTER TABLE t1 LOCK=SHARED, ENGINE=InnoDB;
+INSERT INTO t1 VALUES (2);
+
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+
+DROP TABLE t1;
+
+--connection node_1
+SET GLOBAL wsrep_replicate_myisam=FALSE;
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test
new file mode 100644
index 00000000000..5a65791db1f
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test
@@ -0,0 +1,34 @@
+#
+# Test NBO and a duplicate key error
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(1);
+
+--connection node_1
+SET SESSION wsrep_OSU_method=NBO;
+
+--error ER_DUP_ENTRY
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+INSERT INTO t1 VALUES (1);
+
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 7 FROM t1;
+
+--connection node_1
+ALTER IGNORE TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) = 5 FROM t1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test
new file mode 100644
index 00000000000..dafd8f22dbd
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test
@@ -0,0 +1,64 @@
+#
+# Test that ALTER LOCK=EXCLUSIVE works with NBO
+# All DML and SELECTs are expected to be blocked.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 LOCK=EXCLUSIVE, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Confirm that the ALTER-ed table can not be modified on either node
+SET SESSION lock_wait_timeout=1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (1);
+
+--error ER_LOCK_WAIT_TIMEOUT
+SELECT * FROM t1;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION lock_wait_timeout=1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (3);
+
+--error ER_LOCK_WAIT_TIMEOUT
+SELECT * FROM t1;
+
+# Unblock the ALTER and confirm that it executed on all nodes
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 0 FROM t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test
new file mode 100644
index 00000000000..f0dd0c14937
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test
@@ -0,0 +1,67 @@
+#
+# Test that ALTER ALGORITHM = INPLACE works with NBO
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method='NBO';
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Confirm that unrelated tables can be modified
+INSERT INTO t2 VALUES (2);
+
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f2 INTEGER;
+
+# Confirm that the ALTER-ed table can not be modified on either node
+SET SESSION lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION lock_wait_timeout=1;
+INSERT INTO t2 VALUES (3,4);
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (3);
+
+ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f3 INTEGER;
+
+# Unblock the ALTER and confirm that it executed on all nodes
+--connection node_2
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't1'
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_2
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test
new file mode 100644
index 00000000000..417ef75e9bb
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test
@@ -0,0 +1,15 @@
+#
+# Test multi-item ALTER TABLE under NBO
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1), ADD COLUMN f2 INTEGER;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test
new file mode 100644
index 00000000000..a0975649182
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test
@@ -0,0 +1,57 @@
+#
+# Test that wsrep can process two ALTERs on the same table that are not conflicting
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads=2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD KEY (f2);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--sleep 1
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+SET GLOBAL wsrep_slave_threads = 1;
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test
new file mode 100644
index 00000000000..4799e7b997e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test
@@ -0,0 +1,65 @@
+#
+# Test that wsrep parallel apply can run two unrelated DDLs at the same time
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables:d,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t2 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTERs to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Check that the processing of unrelated events is not affected
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+INSERT INTO t3 VALUES (1);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t3;
+INSERT INTO t3 VALUES (2);
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_1
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+SELECT COUNT(*) = 2 FROM t3;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+SELECT COUNT(*) = 2 FROM t3;
+
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test
new file mode 100644
index 00000000000..46e65038a8c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test
@@ -0,0 +1,29 @@
+#
+# Test that ALTER TABLE works with NBO and partitions
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method=NBO;
+ALTER TABLE t1 LOCK=SHARED PARTITION BY HASH(f1) PARTITIONS 8;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+ALTER TABLE t1 LOCK=SHARED REMOVE PARTITIONING;
+INSERT INTO t1 VALUES (2);
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 2 FROM t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test
new file mode 100644
index 00000000000..a4892dc085b
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test
@@ -0,0 +1,31 @@
+#
+# Test ALTER TABLE RENAME TO with NBO
+# All DML and SELECTs are expected to be blocked.
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_TABLE_EXISTS_ERROR
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t2;
+
+ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t3;
+
+--connection node_2
+SHOW CREATE TABLE t3;
+SELECT COUNT(*) = 1 FROM t3;
+
+
+SET SESSION wsrep_osu_method=TOI;
+
+DROP TABLE t2;
+DROP TABLE t3;
+
+CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query.");
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test
new file mode 100644
index 00000000000..2858f3b51f7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test
@@ -0,0 +1,53 @@
+#
+# Test that NBO TOI can coexist with a concurrent, non-conflicting TOI DDL
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+ALTER TABLE t2 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTERs to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET GLOBAL debug = '';
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+--let $wait_condition = SELECT COUNT(*) < 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%';
+--source include/wait_condition.inc
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+--connection node_1
+--reap
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+
+SET SESSION wsrep_osu_method=TOI;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test b/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test
new file mode 100644
index 00000000000..665ab5137a6
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test
@@ -0,0 +1,34 @@
+#
+# GCF-852 Allow CREATE/DROP INDEX in NBO mode
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(1);
+
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_NOT_SUPPORTED_YET
+CREATE INDEX i1 ON t1 (f1);
+
+--error ER_DUP_ENTRY
+CREATE UNIQUE INDEX i1 ON t1 (f1) LOCK=SHARED;
+
+--error 0
+CREATE INDEX i1 ON t1 (f1) LOCK=SHARED;
+INSERT INTO t1 VALUES (2);
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+SELECT COUNT(*) = 3 FROM t1;
+
+--connection node_1
+DROP INDEX i1 ON t1 LOCK=EXCLUSIVE;
+SHOW CREATE TABLE t1;
+
+--connection node_2
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test b/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test
new file mode 100644
index 00000000000..614c133418a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test
@@ -0,0 +1,38 @@
+#
+# Test that DDL errors are handled correctly under NBO
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+
+SET SESSION wsrep_OSU_method=NBO;
+
+--error ER_DUP_FIELDNAME
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_1
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+--connection node_1
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f3 INTEGER;
+
+--connection node_2
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f4 INTEGER;
+
+--connection node_1
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+--connection node_2
+SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("Slave SQL: Error 'Duplicate column name");
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test b/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test
new file mode 100644
index 00000000000..71205648c8c
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test
@@ -0,0 +1,21 @@
+#
+# Test the case where the DDL produces an error on all nodes
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_osu_method=NBO;
+
+--error ER_DUP_ENTRY
+ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_1
+SHOW CREATE TABLE t1;
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test b/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test
new file mode 100644
index 00000000000..dc4fc8e3e35
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test
@@ -0,0 +1,55 @@
+#
+# Test that if a local MDL lock prevents a particular NBO DDL from completing then:
+# * all operations on the local node are blocked
+# * all operations on remote node are allowed
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
+CREATE TABLE t2 (f1 INTEGER);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+LOCK TABLE t1 WRITE;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;
+
+
+# Confirm that the ALTER is blocked
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Waiting for table metadata lock'
+--source include/wait_condition.inc
+
+# Local DML blocks
+--send INSERT INTO t2 VALUES (1);
+
+# Confirm that the INSERT is blocked
+--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1c
+SET SESSION wsrep_sync_wait = 0;
+
+--let $wait_condition = SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t2 VALUES (1)' AND STATE = 'query end'
+--source include/wait_condition.inc
+
+# Remote operations are allowed
+--connection node_2
+INSERT INTO t2 VALUES (1);
+CREATE TABLE t3 (t4 INTEGER);
+
+--connection node_1a
+UNLOCK TABLES;
+
+--connection node_1
+--reap
+
+--connection node_1b
+--reap
+
+DROP TABLE t1, t2, t3;
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test b/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test
new file mode 100644
index 00000000000..e5c5885c8df
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test
@@ -0,0 +1,81 @@
+#
+# Check that non-blocking DDL indeed runs in a separate thread as seen in SHOW PROCESSLIST
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--connection node_2
+# At the start, we only have 2 applier threads, 1 standard applier and
+# 1 aborter and 1 post aborter
+SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+
+# Set ALTER TABLE to block in the applier thread. wsrep_sync_wait = 0 for the duration, as causal reads will be blocked
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.alter_opened_table';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method='NBO';
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_2
+# There is a separate applier thread for the ALTER TABLE
+--let $wait_condition = SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+--source include/wait_condition.inc
+
+# The applier thread is blocked
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER';
+
+--let $ddl_applier_id = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'`
+
+# The DDL has not yet been applied
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+# The DDL applier thread can not be killed
+--disable_query_log
+--replace_regex /[0-9]+/N/
+--error ER_KILL_DENIED_ERROR
+--eval KILL CONNECTION $ddl_applier_id;
+
+--replace_regex /[0-9]+/N/
+--error ER_KILL_DENIED_ERROR
+--eval KILL QUERY $ddl_applier_id;
+--enable_query_log
+
+# Then, if we unblock the applier thread
+--disable_query_log
+--eval SET GLOBAL debug = '$debug_orig';
+--enable_query_log
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_opened_table';
+SET SESSION wsrep_sync_wait = 7;
+
+# ... the applier thread will terminate
+--let $wait_condition = SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE USER = 'system user'
+AND STATE = 'debug sync point: now'
+AND INFO = 'ALTER TABLE t1 ADD COLUMN f2 INTEGER';
+
+# The alter has now been applied
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
+
+# Both DDL and DML are now possible
+
+INSERT INTO t1 VALUES (1,2);
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN t3 INTEGER;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+--connection node_1
+--reap
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test b/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test
new file mode 100644
index 00000000000..38be1674f97
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test
@@ -0,0 +1,89 @@
+#
+# This test attempts to perform SST on slave while DDL is still in progress on master
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/big_test.inc
+
+# Shut down node #2 and wait until it is completely gone
+--connection node_2
+--let $MYSQLD2_DATADIR = `SELECT @@datadir`
+--source include/shutdown_mysqld.inc
+--sleep 2
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Remove grastate.dat from node #2 so that SST is guaranteed
+--remove_file $MYSQLD2_DATADIR/grastate.dat
+
+# Begin an ALTER and block
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+SET SESSION wsrep_osu_method=NBO;
+--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+# Attempt to restart node #2. With grastate.dat removed, SST should be attempted
+
+--connection node_2
+--exec echo "restart" > $_expect_file_name
+--sleep 1
+--exec echo "wait" > $_expect_file_name
+--sleep 5
+
+--connection node_1a
+--let $assert_text= Master should report that it can not donate SST
+--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err
+--let $assert_select= Non-blocking operation in progress, cannot donate SST
+--let $assert_match= Non-blocking operation in progress, cannot donate SST
+--source include/assert_grep.inc
+
+--let $assert_text= Slave should report that it could not join
+--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err
+--let $assert_select= Will never receive state
+--let $assert_match= Will never receive state
+--source include/assert_grep.inc
+
+
+# Restart node_2 again, now with the DDL out of the way
+--connection node_1a
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.alter_locked_tables_inplace';
+
+--connection node_1
+--reap
+
+--connection node_2
+--source include/start_mysqld.inc
+SHOW CREATE TABLE t1;
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
+--source include/wait_condition.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+SET SESSION wsrep_osu_method=TOI;
+DROP TABLE t1;
+
+--connection node_1
+CALL mtr.add_suppression("Non-blocking operation in progress, cannot donate SST");
+CALL mtr.add_suppression("Resource temporarily unavailable");
+
+--connection node_2
+CALL mtr.add_suppression("Resource temporarily unavailable");
+CALL mtr.add_suppression("Will never receive state");
+CALL mtr.add_suppression("terminated unexpectedly");
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt
new file mode 100644
index 00000000000..4a13f55f2dc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt
@@ -0,0 +1,2 @@
+--log-slave-updates --log-bin
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test
new file mode 100644
index 00000000000..a8db548688a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test
@@ -0,0 +1,37 @@
+#
+# Test that performing NBO operations on TEMPORARY tables does not cause
+# undue replication or binlogging
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+RESET MASTER;
+
+--connection node_2
+RESET MASTER;
+
+--connection node_1
+CREATE TEMPORARY TABLE t1 (f1 INTEGER, f2 INTEGER);
+
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+
+--connection node_1
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_2
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_1
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test b/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test
new file mode 100644
index 00000000000..1d80c0614d7
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test
@@ -0,0 +1,42 @@
+#
+# Test that various statements not supported under NBO return error
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+
+SET SESSION wsrep_osu_method='NBO';
+
+--error ER_NOT_SUPPORTED_YET
+CREATE TABLE t2 (f1 INTEGER);
+
+--error ER_NOT_SUPPORTED_YET
+RENAME TABLE t1 TO t2;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE t1 LOCK=DEFAULT, ADD COLUMN f2 INTEGER;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE t2 LOCK=NONE, ADD COLUMN f2 INTEGER;
+
+--error ER_NOT_SUPPORTED_YET
+DROP TABLE t1;
+
+--error ER_NOT_SUPPORTED_YET
+REPAIR TABLE t1;
+
+--error ER_NOT_SUPPORTED_YET
+CREATE USER u1 IDENTIFIED BY 'p1';
+
+--error ER_NOT_SUPPORTED_YET
+DROP USER u1;
+
+SET SESSION wsrep_osu_method=TOI;
+
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CALL mtr.add_suppression('ALTER TABLE isolation failure');
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf
new file mode 100644
index 00000000000..8f0fa4a30bc
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf
@@ -0,0 +1,5 @@
+!include ../galera_4nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
+
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test
new file mode 100644
index 00000000000..1aff71a454e
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test
@@ -0,0 +1,87 @@
+#
+# Test the case where a node that dropped prior to an inconsistency vote is able
+# to rejoin via IST after the vote is complete
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Isolate node #4
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+--connection node_4
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+
+# Wait for node #4 to leave cluster
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Introduce inconsistency on node #3
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_on=ON;
+DROP TABLE t1;
+
+# Wait for node #3 to be voted out
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Do some more stuff on the cluster to add to the IST stream
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER);
+
+# Rejoin node #4
+--connection node_4
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+--source include/galera_wait_ready.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good
+--connection node_4
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+
+# Rejoin node #3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+--source include/kill_galera.inc
+--sleep 1
+--echo Starting mysqld
+--source include/start_mysqld.inc
+
+# Confirm node #3 has rejoined
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good and all nodes have identical data
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+CALL mtr.add_suppression("Slave SQL: Error 'Unknown table");
+
+--connection node_3
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+CALL mtr.add_suppression("inconsistent with group");
+
+--connection node_4
+SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
+
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf
new file mode 100644
index 00000000000..b2cba42c0bd
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf
@@ -0,0 +1,4 @@
+!include ../galera_4nodes.cnf
+
+[mysqld]
+wsrep-ignore-apply-errors=0
diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test
new file mode 100644
index 00000000000..8dd910c85ee
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test
@@ -0,0 +1,91 @@
+#
+# Test the case where a node that dropped prior to an inconsistency vote is able
+# to rejoin via IST after the vote is complete
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+# Isolate node #4
+--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
+--connection node_4
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
+
+# Wait for node #4 to leave cluster
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'A');
+
+# Introduce inconsistency on node #3
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+INSERT INTO t1 VALUES (2, 'B');
+SET SESSION wsrep_on=ON;
+DELETE FROM t1 WHERE f1 = 2;
+
+# Wait for node #3 to be voted out
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Rejoin node #4
+--connection node_4
+--source include/wsrep_wait_disconnect.inc
+SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
+--source include/galera_wait_ready.inc
+
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good
+--connection node_4
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+
+# Rejoin node #3
+--connection node_3
+SET SESSION wsrep_on=OFF;
+--source include/kill_galera.inc
+--sleep 1
+--echo Starting mysqld
+--source include/start_mysqld.inc
+
+# Confirm node #3 has rejoined
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+
+# Confirm that all is good and all nodes have identical data
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows");
+CALL mtr.add_suppression("Delete_rows apply failed");
+
+--connection node_3
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+CALL mtr.add_suppression("inconsistent with group");
+
+--connection node_4
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B';
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test
new file mode 100644
index 00000000000..ddbf77838ce
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test
@@ -0,0 +1,16 @@
+# NB-DDL: Assertion `thd == _current_thd()' failed in check_stack_overrun
+
+--source include/galera_cluster.inc
+
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+SET GLOBAL wsrep_OSU_method=NBO;
+
+--connection node_2
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+
+--connection node_1
+SET GLOBAL wsrep_OSU_method=TOI;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt
new file mode 100644
index 00000000000..d9d2edc09af
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt
@@ -0,0 +1 @@
+--wsrep_OSU_method=NBO
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test
new file mode 100644
index 00000000000..33d15f10ec3
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test
@@ -0,0 +1,11 @@
+# NB-DDL: Assertion `thd->wsrep_nbo_ctx' failed in lock_table_names when starting server with --wsrep-OSU-method=NBO
+
+--source include/galera_cluster.inc
+
+SET SESSION wsrep_OSU_method=TOI;
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION wsrep_OSU_method=NBO;
+ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
+SET SESSION wsrep_OSU_method=NBO;
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test
new file mode 100644
index 00000000000..f7e2ccbf828
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test
@@ -0,0 +1,38 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+
+# Wait for the ALTER to block in sync point
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now';
+--source include/wait_condition.inc
+
+--send INSERT INTO t1 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+--connection node_1
+--reap
+
+SET SESSION wsrep_OSU_method=TOI;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test
new file mode 100644
index 00000000000..d7110d0791a
--- /dev/null
+++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+--source include/have_debug.inc
+
+
+CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+SET SESSION wsrep_osu_method=NBO;
+
+--connection node_2
+SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace';
+
+--connection node_1
+--send ALTER TABLE t1 ADD PRIMARY KEY (f1), ALGORITHM=INPLACE, LOCK=SHARED;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'
+--source include/wait_condition.inc
+
+SET SESSION wsrep_sync_wait=0;
+INSERT INTO t2 VALUES (1);
+
+SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace';
+SET GLOBAL debug = '';
+
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 1 FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+
diff --git a/mysql-test/suite/galera_sr/galera_2nodes.cnf b/mysql-test/suite/galera_sr/galera_2nodes.cnf
new file mode 100644
index 00000000000..0412b5654dd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/galera_2nodes.cnf
@@ -0,0 +1 @@
+!include ../galera/galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_sr/my.cnf b/mysql-test/suite/galera_sr/my.cnf
new file mode 100644
index 00000000000..ca163a540d9
--- /dev/null
+++ b/mysql-test/suite/galera_sr/my.cnf
@@ -0,0 +1 @@
+!include galera_2nodes.cnf
diff --git a/mysql-test/suite/galera_sr/r/GCF-1008.result b/mysql-test/suite/galera_sr/r/GCF-1008.result
new file mode 100644
index 00000000000..a0f320c7dd0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1008.result
@@ -0,0 +1,50 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'x');
+SET GLOBAL wsrep_provider_options = 'dbug=d,before_local_commit_monitor_enter';
+COMMIT;
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+REPLACE INTO t1 VALUES (1,'y');
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET GLOBAL wsrep_provider_options = 'signal=before_local_commit_monitor_enter';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'x');
+SET GLOBAL wsrep_provider_options = 'dbug=d,before_certify_apply_monitor_enter';
+COMMIT;
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+REPLACE INTO t1 VALUES (1,'y');
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET GLOBAL wsrep_provider_options = 'signal=before_certify_apply_monitor_enter';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1018.result b/mysql-test/suite/galera_sr/r/GCF-1018.result
new file mode 100644
index 00000000000..fc624aec10d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1018.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+INSERT INTO t1 (f2) VALUES ('a');
+INSERT INTO t1 (f2) VALUES ('b');
+INSERT INTO t1 (f2) VALUES ('c');
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_certify_apply_monitor_enter';
+SET SESSION wsrep_trx_fragment_size = 64;
+DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+INSERT INTO t1 (f2) VALUES ('d'),('e');
+SET GLOBAL wsrep_provider_options = 'signal=after_certify_apply_monitor_enter';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+Got one of the listed errors
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1018B.result b/mysql-test/suite/galera_sr/r/GCF-1018B.result
new file mode 100644
index 00000000000..b1c7efed7a6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1018B.result
@@ -0,0 +1,8 @@
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1043A.result b/mysql-test/suite/galera_sr/r/GCF-1043A.result
new file mode 100644
index 00000000000..1aef0ddd660
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1043A.result
@@ -0,0 +1,15 @@
+Running a concurrent test with the following queries:
+DELETE FROM t1
+REPLACE INTO t1 VALUES (1,'y'),(2,'x')
+REPLACE INTO t1 VALUES (1,'y'),(2,'y'),(3,'y')
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE t1;
+Concurrent test end
diff --git a/mysql-test/suite/galera_sr/r/GCF-1043B.result b/mysql-test/suite/galera_sr/r/GCF-1043B.result
new file mode 100644
index 00000000000..c86857b0a3f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1043B.result
@@ -0,0 +1,15 @@
+Running a concurrent test with the following queries:
+DELETE FROM t1
+INSERT INTO t1 VALUES (1,'y'),(2,'x')
+UPDATE t1 SET f2 = 'y' WHERE f1 = 1 OR f1 = 2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE t1;
+Concurrent test end
diff --git a/mysql-test/suite/galera_sr/r/GCF-1051.result b/mysql-test/suite/galera_sr/r/GCF-1051.result
new file mode 100644
index 00000000000..92e815a3733
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1051.result
@@ -0,0 +1,37 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (2);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-1060.result b/mysql-test/suite/galera_sr/r/GCF-1060.result
new file mode 100644
index 00000000000..bddb3182e46
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-1060.result
@@ -0,0 +1,15 @@
+Running a concurrent test with the following queries:
+TRUNCATE TABLE t1
+INSERT INTO t1 VALUE (1,'x'),(2,'x'),(3,'x')
+INSERT INTO t1 VALUE (4, 'z');
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;;;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE t1;
+Concurrent test end
diff --git a/mysql-test/suite/galera_sr/r/GCF-437.result b/mysql-test/suite/galera_sr/r/GCF-437.result
new file mode 100644
index 00000000000..5d04022655f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-437.result
@@ -0,0 +1,12 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 2 * 1024 * 1024;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+ERROR HY000: Writing one row to the row-based binary log failed
+CALL mtr.add_suppression("InnoDB: The total blob data length*");
+CALL mtr.add_suppression("WSREP: Error writing into wsrep_schema.SR: 139");
+CALL mtr.add_suppression("WSREP: Failed to write to frag table: 1");
+CALL mtr.add_suppression("WSREP: Failed to append frag to persistent storage");
+DROP TABLE t1;
+DROP table ten;
diff --git a/mysql-test/suite/galera_sr/r/GCF-561.result b/mysql-test/suite/galera_sr/r/GCF-561.result
new file mode 100644
index 00000000000..a3c7ab585e4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-561.result
@@ -0,0 +1,42 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t1 DROP COLUMN f2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 21S01: Column count doesn't match value count at row 1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-571.result b/mysql-test/suite/galera_sr/r/GCF-571.result
new file mode 100644
index 00000000000..502c7393289
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-571.result
@@ -0,0 +1,56 @@
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+SAVEPOINT A;
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+COUNT(*) = 1
+1
+ROLLBACK TO SAVEPOINT A;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+COUNT(*) = 1
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+COUNT(*) = 1
+1
+ROLLBACK;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-572.result b/mysql-test/suite/galera_sr/r/GCF-572.result
new file mode 100644
index 00000000000..8836f3777d6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-572.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'node1');
+INSERT INTO t1 VALUES (5, 'node2');
+INSERT INTO t1 VALUES (5, 'node1');
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+5 node2
+SET SESSION wsrep_trx_fragment_size = 10000;
+START TRANSACTION;
+INSERT INTO t1 VALUE (10, 'node1');
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+INSERT INTO t1 VALUES(15, 'node2');
+SELECT * FROM t1;
+f1 f2
+5 node2
+10 node1
+INSERT INTO t1 VALUES(15, 'node1');
+ERROR 23000: Duplicate entry '15' for key 'PRIMARY'
+COMMIT;
+SELECT * FROM t1;
+f1 f2
+5 node2
+10 node1
+15 node2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-574.result b/mysql-test/suite/galera_sr/r/GCF-574.result
new file mode 100644
index 00000000000..bbf817c8c6c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-574.result
@@ -0,0 +1,11 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+wsrep_last_committed_delta
+1
+SELECT COUNT(*) = 10000 FROM t1;
+COUNT(*) = 10000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/GCF-580.result b/mysql-test/suite/galera_sr/r/GCF-580.result
new file mode 100644
index 00000000000..83cbdde092a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-580.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+last_committed_matches_fragment_count
+1
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-585.result b/mysql-test/suite/galera_sr/r/GCF-585.result
new file mode 100644
index 00000000000..6305c4ad31e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-585.result
@@ -0,0 +1,25 @@
+create table t1 (f1 integer primary key) engine=innodb;
+set autocommit=off;
+set session wsrep_trx_fragment_size=1;
+start transaction;
+insert into t1 values (1);
+insert into t1 values (2),(1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+alter table t1 drop primary key;
+drop table t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+update t1 set f1 = 100 where f1 = 10;
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+SET SESSION wsrep_trx_fragment_size=1;
+SET SESSION innodb_lock_wait_timeout=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+delete from t1 where f1 > 10;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+delete from t1 where f1 > 10 and f1 < 100;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-597.result b/mysql-test/suite/galera_sr/r/GCF-597.result
new file mode 100644
index 00000000000..e2f35e95e28
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-597.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-620.result b/mysql-test/suite/galera_sr/r/GCF-620.result
new file mode 100644
index 00000000000..ac02d49e086
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-620.result
@@ -0,0 +1,14 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 200;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-623.result b/mysql-test/suite/galera_sr/r/GCF-623.result
new file mode 100644
index 00000000000..790eb1fd89d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-623.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-627.result b/mysql-test/suite/galera_sr/r/GCF-627.result
new file mode 100644
index 00000000000..6c8fad03ed4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-627.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+DROP TABLE t1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (2);
+ERROR 42S02: Table 'test.t1' doesn't exist
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/GCF-845.result b/mysql-test/suite/galera_sr/r/GCF-845.result
new file mode 100644
index 00000000000..3fa6d1bb704
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-845.result
@@ -0,0 +1,14 @@
+CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE = InnoDB;
+SET SESSION AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (161);
+COMMIT;
+DELETE FROM t1 WHERE f1 > 13;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+include/assert_grep.inc [No BF-BF log line found]
diff --git a/mysql-test/suite/galera_sr/r/GCF-851.result b/mysql-test/suite/galera_sr/r/GCF-851.result
new file mode 100644
index 00000000000..6da002ec081
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-851.result
@@ -0,0 +1,24 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+SET SESSION AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+START TRANSACTION;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM t1;
+COUNT(*) > 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-867.result b/mysql-test/suite/galera_sr/r/GCF-867.result
new file mode 100644
index 00000000000..0aa19bbd537
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-867.result
@@ -0,0 +1,2 @@
+CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-889.result b/mysql-test/suite/galera_sr/r/GCF-889.result
new file mode 100644
index 00000000000..b5402f105a4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-889.result
@@ -0,0 +1,18 @@
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_on = ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+DELETE FROM t1 WHERE f1 = 1;
+SET SESSION wsrep_trx_fragment_size = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1;
+COUNT(*) = 1
+1
+CALL mtr.add_suppression("Could not execute Delete_rows event on table");
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/GCF-900.result b/mysql-test/suite/galera_sr/r/GCF-900.result
new file mode 100644
index 00000000000..e4eab9fbebe
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/GCF-900.result
@@ -0,0 +1,13 @@
+CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 128;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 0);
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (2, 0);
+ALTER TABLE t1 DROP COLUMN f2;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (3, 0);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera-features#56.result b/mysql-test/suite/galera_sr/r/galera-features#56.result
new file mode 100644
index 00000000000..16975217838
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera-features#56.result
@@ -0,0 +1,21 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) Engine=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET GLOBAL wsrep_slave_threads = 4;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;;
+INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;;
+INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;;
+SELECT COUNT(*) = 30000 FROM t1;
+COUNT(*) = 30000
+1
+SELECT COUNT(DISTINCT f1) = 30000 FROM t1;
+COUNT(DISTINCT f1) = 30000
+1
+SELECT COUNT(*) = 6 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+COUNT(*) = 6
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result
new file mode 100644
index 00000000000..ad274b0cb7f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result
@@ -0,0 +1,448 @@
+SET SESSION wsrep_sync_wait = 0;
+galera_sr_bf_abort_at_commit = 0
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+INSERT INTO t1 VALUES (3);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+galera_sr_bf_abort_at_commit = 1
+after_replicate_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+local_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+apply_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+commit_monitor_master_enter_sync
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+f1
+1
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+ROLLBACK;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT * FROM t1;
+f1
+1
+2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_blob.result b/mysql-test/suite/galera_sr/r/galera_sr_blob.result
new file mode 100644
index 00000000000..c1c51f843c4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_blob.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 TEXT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+wsrep_last_committed_delta
+1
+COMMIT;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT LENGTH(f1) = 65535 FROM t1;
+LENGTH(f1) = 65535
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result
new file mode 100644
index 00000000000..35b014979bb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result
@@ -0,0 +1,45 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+Got one of the listed errors
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT * FROM wsrep_schema.SR;
+node_uuid trx_id seqno flags frag
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result
new file mode 100644
index 00000000000..a2c61693c61
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result
@@ -0,0 +1,46 @@
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (16);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result
new file mode 100644
index 00000000000..60cf5ca2633
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t2;
+COUNT(*) = 5
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result
new file mode 100644
index 00000000000..be28892edbb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result
@@ -0,0 +1,14 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+INSERT INTO t1 VALUES(1);;
+COMMIT;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result
new file mode 100644
index 00000000000..ef68cd7ade0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result
new file mode 100644
index 00000000000..d2e8bc592bf
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result
@@ -0,0 +1,19 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+INSERT INTO t1 VALUES (5);;
+COMMIT;
+ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result
new file mode 100644
index 00000000000..3f735746d95
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result
new file mode 100644
index 00000000000..ce94576cb95
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result
@@ -0,0 +1,41 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+INSERT INTO t1 VALUES (6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES (1);
+INSERT INTO t1 (f1) VALUES (2);
+INSERT INTO t1 (f1) VALUES (3);
+INSERT INTO t1 (f1) VALUES (4);
+INSERT INTO t1 (f1) VALUES (5);
+INSERT INTO t1 (f1) VALUES (6);
+COMMIT;
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result
new file mode 100644
index 00000000000..2227336cfad
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+DROP SCHEMA test;
+SELECT COUNT(*) = 0 FROM test.t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+INSERT INTO test.t1 VALUES (6, 6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO test.t1 VALUES (6, 6);
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result
new file mode 100644
index 00000000000..a3c7ab585e4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result
@@ -0,0 +1,42 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t1 DROP COLUMN f2;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (6, 6);
+ERROR 21S01: Column count doesn't match value count at row 1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result
new file mode 100644
index 00000000000..e9edcc9ea34
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result
@@ -0,0 +1,34 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+ALTER TABLE t2 DROP COLUMN f2;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+INSERT INTO t1 VALUES (6, 6);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result
new file mode 100644
index 00000000000..5ea1adee877
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result
@@ -0,0 +1,36 @@
+CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB;
+CREATE UNIQUE INDEX i1 ON t1 (f1(512));
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1024;
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+COMMIT;
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result
new file mode 100644
index 00000000000..839a3ef1f71
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result
@@ -0,0 +1,34 @@
+CREATE TABLE grandparent (
+id INT NOT NULL PRIMARY KEY
+) ENGINE=InnoDB;
+CREATE TABLE parent (
+id INT NOT NULL PRIMARY KEY,
+grandparent_id INT,
+FOREIGN KEY (grandparent_id)
+REFERENCES grandparent(id)
+ON UPDATE CASCADE
+) ENGINE=InnoDB;
+CREATE TABLE child (
+id INT NOT NULL PRIMARY KEY,
+grandparent_id INT,
+FOREIGN KEY (grandparent_id)
+REFERENCES parent(grandparent_id)
+ON UPDATE CASCADE
+) ENGINE=InnoDB;
+INSERT INTO grandparent VALUES (1),(2),(3),(4);
+INSERT INTO parent VALUES (1,1), (2,2);
+INSERT INTO child VALUES (1,1), (2,2);
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+UPDATE grandparent SET id = 5 WHERE id = 1;
+SET SESSION innodb_lock_wait_timeout = 1;
+UPDATE grandparent SET id = 10 WHERE id = 5;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+DELETE FROM child;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+COMMIT;
+include/diff_servers.inc [servers=1 2]
+DROP TABLE child;
+DROP TABLE parent;
+DROP TABLE grandparent;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_gtid.result b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result
new file mode 100644
index 00000000000..5e89752d7cb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result
@@ -0,0 +1,65 @@
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_trx_fragment_size=1;
+UPDATE t1 SET f1 = 2;
+SET SESSION wsrep_trx_fragment_size=0;
+SET SESSION wsrep_trx_fragment_size=0;
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+gtid_executed_equal
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000002 <Pos> Previous_gtids 1 <End_log_pos> <GTID>:1-2
+mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:3'
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INT PRIMARY KEY)
+mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:4'
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> BEGIN
+mysqld-bin.000002 <Pos> Ignorable 1 <End_log_pos> # Unrecognized ignorable event
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> COMMIT
+mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:5'
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> BEGIN
+mysqld-bin.000002 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000002 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000002 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:6'
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> BEGIN
+mysqld-bin.000002 <Pos> Ignorable 1 <End_log_pos> # Unrecognized ignorable event
+mysqld-bin.000002 <Pos> Query 1 <End_log_pos> COMMIT
+mysqld-bin.000002 <Pos> Gtid 2 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:7'
+mysqld-bin.000002 <Pos> Query 2 <End_log_pos> BEGIN
+mysqld-bin.000002 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000002 <Pos> Update_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000002 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+SELECT 1 FROM DUAL;
+1
+1
+SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000003 <Pos> Previous_gtids 2 <End_log_pos> <GTID>:1-2
+mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:3'
+mysqld-bin.000003 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INT PRIMARY KEY)
+mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:4'
+mysqld-bin.000003 <Pos> Query 1 <End_log_pos> BEGIN
+mysqld-bin.000003 <Pos> Ignorable 1 <End_log_pos> # Unrecognized ignorable event
+mysqld-bin.000003 <Pos> Query 1 <End_log_pos> COMMIT
+mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:5'
+mysqld-bin.000003 <Pos> Query 1 <End_log_pos> BEGIN
+mysqld-bin.000003 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000003 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000003 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+mysqld-bin.000003 <Pos> Gtid 2 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:6'
+mysqld-bin.000003 <Pos> Query 2 <End_log_pos> BEGIN
+mysqld-bin.000003 <Pos> Ignorable 2 <End_log_pos> # Unrecognized ignorable event
+mysqld-bin.000003 <Pos> Query 2 <End_log_pos> COMMIT
+mysqld-bin.000003 <Pos> Gtid 2 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:7'
+mysqld-bin.000003 <Pos> Query 2 <End_log_pos> BEGIN
+mysqld-bin.000003 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1)
+mysqld-bin.000003 <Pos> Update_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+mysqld-bin.000003 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result
new file mode 100644
index 00000000000..2b85b5ec58c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result
@@ -0,0 +1,11 @@
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result
new file mode 100644
index 00000000000..8108e3b60cb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result
@@ -0,0 +1,21 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result
new file mode 100644
index 00000000000..6a274b7f2ae
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result
new file mode 100644
index 00000000000..6a274b7f2ae
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+Killing server ...
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result
new file mode 100644
index 00000000000..4968ba1e0b6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result
@@ -0,0 +1,25 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result
new file mode 100644
index 00000000000..f85870ec76a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result
@@ -0,0 +1,17 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+Killing query ...
+ERROR 70100: Query execution was interrupted
+INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3;
+SELECT COUNT(*) = 1000 FROM t1;
+COUNT(*) = 1000
+1
+SELECT COUNT(*) = 1000 FROM t1;
+COUNT(*) = 1000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result
new file mode 100644
index 00000000000..758f306189c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result
@@ -0,0 +1,39 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+CREATE TABLE t2 (f1 INTEGER);
+LOCK TABLE t2 WRITE;
+INSERT INTO t2 VALUES (1);
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+Killing server ...
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 15 FROM t1;
+COUNT(*) = 15
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result
new file mode 100644
index 00000000000..f1a445bf7d4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result
@@ -0,0 +1,28 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1024 * 1024 * 10;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 50000 FROM t1;
+COUNT(*) > 50000
+1
+ROLLBACK;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result
new file mode 100644
index 00000000000..1310ed318b6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result
@@ -0,0 +1,8 @@
+SET SESSION wsrep_trx_fragment_size = 512;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 20000 FROM t1;
+COUNT(*) = 20000
+1
+wsrep_last_committed_diff
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result
new file mode 100644
index 00000000000..b25a8877005
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result
@@ -0,0 +1,9 @@
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_load_data_splitting = TRUE;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 95000 FROM t1;
+COUNT(*) = 95000
+1
+wsrep_last_committed_diff
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result
new file mode 100644
index 00000000000..22f44df1e6a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result
@@ -0,0 +1,87 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t4 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+RESET MASTER;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+RESET MASTER;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t3 VALUES (1);
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t4 VALUES (1);
+INSERT INTO t1 VALUES (2);
+COMMIT;
+INSERT INTO t2 VALUES (2);
+COMMIT;
+INSERT INTO t3 VALUES (2);
+COMMIT;
+INSERT INTO t4 VALUES (2);
+COMMIT;
+SELECT COUNT(*) = 2 FROM t4;
+COUNT(*) = 2
+1
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 2 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 2 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+SELECT COUNT(*) = 2 FROM t4;
+COUNT(*) = 2
+1
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 2 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 2 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4)
+0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result
new file mode 100644
index 00000000000..b44436c9cea
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result
@@ -0,0 +1,28 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 100000 FROM t1;
+COUNT(*) = 100000
+1
+ROLLBACK;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
+COUNT(*) = 0
+1
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_myisam.result b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result
new file mode 100644
index 00000000000..7d2a84814ba
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result
@@ -0,0 +1,11 @@
+CREATE TABLE t1 (f1 TEXT) ENGINE=MyISAM;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET GLOBAL wsrep_replicate_myisam = TRUE;
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT LENGTH(f1) = 65535 FROM t1;
+LENGTH(f1) = 65535
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result
new file mode 100644
index 00000000000..9d47bddb9b4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result
@@ -0,0 +1,40 @@
+Setting SST method to mysqldump ...
+GRANT ALL PRIVILEGES ON *.* TO 'sst';
+SET GLOBAL wsrep_sst_auth = 'sst:';
+SET GLOBAL wsrep_sst_method = 'mysqldump';
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1000;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+UPDATE t1 SET f2 = REPEAT('y', 255);
+Shutting down server ...
+Starting server ...
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+UPDATE t1 SET f2 = REPEAT('z', 255);
+COMMIT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 1000 FROM t1;
+COUNT(*) = 1000
+1
+SELECT COUNT(*) = 1000 FROM t1 WHERE f2 = REPEAT('z', 255);
+COUNT(*) = 1000
+1
+DROP TABLE t1;
+DROP TABLE ten;
+SET SESSION wsrep_trx_fragment_size=0;
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+DROP USER sst;
+CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query");
+CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found");
+CALL mtr.add_suppression("InnoDB: New log files created");
+CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables");
+CALL mtr.add_suppression("Can't open and lock time zone table");
+CALL mtr.add_suppression("Can't open and lock privilege tables");
+CALL mtr.add_suppression("Info table is not ready to be used");
+CALL mtr.add_suppression("Native table .* has the wrong structure");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result
new file mode 100644
index 00000000000..d63418adabe
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result
@@ -0,0 +1,26 @@
+SET GLOBAL wsrep_slave_threads = 5;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+ROLLBACK;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result
new file mode 100644
index 00000000000..c99dd3df549
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result
new file mode 100644
index 00000000000..8af64da9a19
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+ROLLBACK;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result
new file mode 100644
index 00000000000..d1b8985be82
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result
@@ -0,0 +1,33 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+ROLLBACK TO SAVEPOINT s1;
+INSERT INTO t1 VALUES (21, 'c');
+INSERT INTO t1 VALUES (22, 'c');
+INSERT INTO t1 VALUES (23, 'c');
+INSERT INTO t1 VALUES (24, 'c');
+INSERT INTO t1 VALUES (25, 'c');
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'a';
+COUNT(*) = 5
+1
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 5
+1
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result
new file mode 100644
index 00000000000..21e6ef4b057
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result
@@ -0,0 +1,22 @@
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+ALTER TABLE t1 CHANGE f1 f1 INTEGER;
+ALTER TABLE t1 DROP PRIMARY KEY;
+INSERT INTO t1 VALUES (1, 'abc');
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t2 SELECT * FROM t1;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+INSERT INTO t2 VALUES (1, 'abc');
+INSERT INTO t2 VALUES (2, 'abc');
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 2 FROM t2;
+COUNT(*) = 2
+1
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_sbr.result b/mysql-test/suite/galera_sr/r/galera_sr_sbr.result
new file mode 100644
index 00000000000..c83db3d5ea6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_sbr.result
@@ -0,0 +1,16 @@
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION BINLOG_FORMAT='STATEMENT';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SELECT COUNT(*) = 5 FROM t1;
+COUNT(*) = 5
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result
new file mode 100644
index 00000000000..d3e1739af93
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result
@@ -0,0 +1,20 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT COUNT(*) = 3 FROM t1;
+COUNT(*) = 3
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result
new file mode 100644
index 00000000000..98488dc773e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13);
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (21),(22),(23);
+INSERT INTO t1 VALUES (14),(15),(16);
+COMMIT;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16);
+COUNT(*) = 6
+1
+INSERT INTO t1 VALUES (24),(25),(26);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 12 FROM t1;
+COUNT(*) = 12
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result
new file mode 100644
index 00000000000..b1be41eb762
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result
@@ -0,0 +1,10 @@
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+SELECT COUNT(*) = 10000 FROM t1;
+COUNT(*) = 10000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result b/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result
new file mode 100644
index 00000000000..29bb71704e2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result
@@ -0,0 +1,198 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+Start of Simple Insert
+INSERT INTO t1 VALUES (4);
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 193
+<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 234
+<ISO TIMESTAMP> server id 1 end_log_pos 150 Write_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Simple Insert
+
+ROLLBACK;
+Start of Multi-row Update
+UPDATE t1 SET f1 = f1 + 10;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 193
+<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 234
+<ISO TIMESTAMP> server id 1 end_log_pos 156 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 197 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 239 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 280 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 322 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Multi-row Update
+
+ROLLBACK;
+Start of Multi-table Update
+UPDATE t1, t2 SET t1.f1 = t1.f1 + 100, t2.f1 = t2.f1 + 100;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 82 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 123 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 243
+<ISO TIMESTAMP> server id 1 end_log_pos 164 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 284
+<ISO TIMESTAMP> server id 1 end_log_pos 206 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 247 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 288 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 330 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 371 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 412 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 454 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 495 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 536 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 578 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 619 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 660 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 702 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 743 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 784 Table_map: `test`.`t2` mapped to number <TABLE_ID>
+# at 202
+<ISO TIMESTAMP> server id 1 end_log_pos 826 Update_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Multi-table Update
+
+ROLLBACK;
+Start of Savepoint
+INSERT INTO t1 VALUES (1000);
+SAVEPOINT X;
+INSERT INTO t1 VALUES (2000);
+ROLLBACK TO SAVEPOINT X;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+BEGIN
+/*!*/;
+# at 193
+<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 234
+<ISO TIMESTAMP> server id 1 end_log_pos 150 Write_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 231 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+SAVEPOINT `X`
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 272 Table_map: `test`.`t1` mapped to number <TABLE_ID>
+# at 161
+<ISO TIMESTAMP> server id 1 end_log_pos 308 Write_rows: table id <TABLE_ID> flags: STMT_END_F
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DELIMITER /*!*/;
+# at 120
+<ISO TIMESTAMP> server id 1 end_log_pos 391 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0
+SET TIMESTAMP=<TIMESTAMP>/*!*/;
+/*!\C latin1 *//*!*/;
+ROLLBACK TO `X`
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+End of Savepoint
+
+ROLLBACK;
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result
new file mode 100644
index 00000000000..7527b4ede31
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result
@@ -0,0 +1,101 @@
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+wsrep_local_replays
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'x' WHERE f1 = 1;
+SET SESSION wsrep_trx_fragment_size = 0;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync';
+COMMIT;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+wsrep_local_replays
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DELETE FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result
new file mode 100644
index 00000000000..0a81812f7c0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result
@@ -0,0 +1,18 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 3;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+INSERT INTO t1 VALUES (6);
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result
new file mode 100644
index 00000000000..2987430b9e1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+COMMIT;
+SET AUTOCOMMIT=ON;
+UPDATE t1 SET f1 = 2 WHERE f1 = 1;
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result
new file mode 100644
index 00000000000..bbd1f8c9585
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result
@@ -0,0 +1,29 @@
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=4096';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+COMMIT;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 100 FROM t1;
+COUNT(*) = 100
+1
+DROP TABLE t1;
+DROP TABLE ten;
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result
new file mode 100644
index 00000000000..e1a15b591ef
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+SET SESSION wsrep_trx_fragment_size = 256;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=128';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1, ten AS a2;
+Got one of the listed errors
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE ten;
+call mtr.add_suppression('WSREP: SR rollback replication failure.*');
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: SR rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
+call mtr.add_suppression('WSREP: fragment replication failed:');
+call mtr.add_suppression('WSREP: post commit failed for SR rollback');
+call mtr.add_suppression('WSREP: pre_commit for SR rollback returned 2, thd:*');
+call mtr.add_suppression('WSREP: wsrep_rollback failed to send SR ROLLBACK for *');
diff --git a/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result
new file mode 100644
index 00000000000..97c32d7c00e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result
@@ -0,0 +1,22 @@
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SET SESSION wsrep_trx_fragment_size = 0;
+DROP TABLE t1;
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result
new file mode 100644
index 00000000000..84564cabe6b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result
@@ -0,0 +1,88 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 2;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+INSERT INTO t1 VALUES (2);
+Got one of the listed errors
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+TRUNCATE TABLE t1;
+SET SESSION wsrep_trx_fragment_size = 10;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t1 VALUES (2);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+TRUNCATE TABLE t1;
+SET SESSION wsrep_trx_fragment_size = 200;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+INSERT INTO t1 VALUES (1);
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t1;
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result
new file mode 100644
index 00000000000..7039af8fd64
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result
@@ -0,0 +1,41 @@
+RESET MASTER;
+RESET MASTER;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+COMMIT;
+SET SESSION wsrep_trx_fragment_size = 0;
+INSERT INTO t1 VALUES (3),(4);
+COMMIT;
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+0.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+SELECT COUNT(*) = 4 FROM t1;
+COUNT(*) = 4
+1
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+Log_name Pos Event_type Server_id End_log_pos Info
+0.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+0.000001 <Pos> Query 1 <End_log_pos> BEGIN
+0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1)
+0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F
+0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result
new file mode 100644
index 00000000000..efe056b92b4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result
@@ -0,0 +1,17 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SELECT flags FROM wsrep_schema.SR;
+flags
+64
+0
+ROLLBACK;
+INSERT INTO t1 VALUES (3),(4);
+SELECT flags FROM wsrep_schema.SR;
+flags
+64
+0
+ROLLBACK;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result
new file mode 100644
index 00000000000..9e122f554b2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result
@@ -0,0 +1,8 @@
+CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result
new file mode 100644
index 00000000000..65d1a2e1ec0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result
@@ -0,0 +1,27 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (6),(7),(8),(9),(10),(1);
+SET GLOBAL wsrep_slave_threads = 2;
+SET GLOBAL DEBUG = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);;
+INSERT INTO t1 SELECT * FROM t2;;
+INSERT INTO t1 VALUES (6), (7), (8), (9), (10);
+COMMIT;
+Got one of the listed errors
+SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SELECT COUNT(*) = 10 FROM t1;
+COUNT(*) = 10
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result
new file mode 100644
index 00000000000..5f50f7fd9a7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result
@@ -0,0 +1,8 @@
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result
new file mode 100644
index 00000000000..fe0761d186d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result
@@ -0,0 +1,752 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+START TRANSACTION;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (3, 'c');
+SELECT * FROM t1;
+f1 f2
+1 x
+2 x
+4 x
+5 x
+UPDATE t1 SET f2 = 'a' WHERE f1 = 2;
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+SELECT * FROM t1;
+f1 f2
+1 a
+2 a
+3 x
+4 a
+5 a
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result
new file mode 100644
index 00000000000..1cbd9c3d1b7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+ERROR HY000: Lost connection to MySQL server during query
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result
new file mode 100644
index 00000000000..efc86106ab1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result
@@ -0,0 +1,46 @@
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SET GLOBAL wsrep_cluster_address = '';
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+COUNT(*) > 0
+1
+SELECT count(*) > 0 FROM wsrep_schema.SR;
+count(*) > 0
+1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result
new file mode 100644
index 00000000000..a8cf599aacd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+ROLLBACK TO SAVEPOINT s1;
+INSERT INTO t1 VALUES (21, 'c');
+COMMIT;
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+SELECT COUNT(*) = 6 FROM t1;
+COUNT(*) = 6
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result
new file mode 100644
index 00000000000..e92fc207895
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result
@@ -0,0 +1,17 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result
new file mode 100644
index 00000000000..29b17ea07d6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result
@@ -0,0 +1,14 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION binlog_format = STATEMENT;
+create table t1 (id int not null, f_id int not null, f int not null,
+primary key(f_id, id)) engine=innodb;
+create table t2 (id int not null,s_id int not null,s varchar(200),
+primary key(id)) engine=innodb;
+INSERT INTO t1 VALUES (8, 1, 3);
+INSERT INTO t1 VALUES (1, 2, 1);
+INSERT INTO t2 VALUES (1, 0, '');
+INSERT INTO t2 VALUES (8, 1, '');
+DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
+WHERE mm.id IS NULL;
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result
new file mode 100644
index 00000000000..6e62108f23a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result
@@ -0,0 +1,22 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SET AUTOCOMMIT=OFF;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+START TRANSACTION;
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (5);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ROLLBACK;
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result
new file mode 100644
index 00000000000..7eeb83bdc5c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+INSERT INTO t1 VALUES (1);;
+COMMIT;
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+Got one of the listed errors
+ROLLBACK;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result
new file mode 100644
index 00000000000..a959589d241
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result
@@ -0,0 +1,27 @@
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
+SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%';
+COUNT(*) = 13
+1
+INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz');
+COUNT(f2) = 10000
+1
+UPDATE t1 SET f2 = 'abcdefjhk';
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk');
+COUNT(f2) = 10000
+1
+DROP TABLE t1;
+CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB;
+INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz');
+COUNT(f1) = 1000
+1
+UPDATE t1 SET f1 = 'abcdefjhk';
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
+COUNT(f1) = 1000
+1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result
new file mode 100644
index 00000000000..694b51a9260
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result
@@ -0,0 +1,12 @@
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+Killing server ...
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+COUNT(*) = 2
+1
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+VARIABLE_VALUE = 2
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result
new file mode 100644
index 00000000000..1287af618c1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+START TRANSACTION;
+SAVEPOINT a;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT a;
+INSERT INTO t1 values (2);
+COMMIT;
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+COUNT(*) = 0
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result
new file mode 100644
index 00000000000..fa79196a910
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result
@@ -0,0 +1,26 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+CREATE TABLE t2 (f2 VARCHAR(32));
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2),(1);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+INSERT INTO t2 VALUES ('abc');
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 1 FROM t2;
+COUNT(*) = 1
+1
+ROLLBACK;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+SELECT COUNT(*) = 0 FROM t2;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1008.inc b/mysql-test/suite/galera_sr/t/GCF-1008.inc
new file mode 100644
index 00000000000..69245b3a91f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1008.inc
@@ -0,0 +1,36 @@
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'x');
+
+--connection node_2a
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+--send COMMIT
+
+--connection node_2b
+--sleep 1
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 1;
+SELECT COUNT(*) = 1 FROM t1;
+REPLACE INTO t1 VALUES (1,'y');
+
+--connection node_2b
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2a
+--source include/galera_signal_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+--connection node_2
+--reap
+SELECT COUNT(*) = 1 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1008.test b/mysql-test/suite/galera_sr/t/GCF-1008.test
new file mode 100644
index 00000000000..c6926840bd1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1008.test
@@ -0,0 +1,18 @@
+#
+# GCF-1008 SR trx fails to apply because previous trx is not committed yet on applier
+#
+
+--source include/have_debug_sync.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/galera_have_debug_sync.inc
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--let $galera_sync_point = before_local_commit_monitor_enter
+--source GCF-1008.inc
+
+--let $galera_sync_point = before_certify_apply_monitor_enter
+--source GCF-1008.inc
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-1018.test b/mysql-test/suite/galera_sr/t/GCF-1018.test
new file mode 100644
index 00000000000..1ff8f81e824
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1018.test
@@ -0,0 +1,38 @@
+#
+# SR: Node hang with one thread waiting in InnoDB
+#
+--source include/have_debug_sync.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/galera_have_debug_sync.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+INSERT INTO t1 (f2) VALUES ('a');
+INSERT INTO t1 (f2) VALUES ('b');
+INSERT INTO t1 (f2) VALUES ('c');
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET SESSION wsrep_sync_wait = 0;
+--let $galera_sync_point = after_certify_apply_monitor_enter
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 64;
+--send DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;
+
+--connection node_2a
+--source include/galera_wait_sync_point.inc
+
+--connection node_1
+INSERT INTO t1 (f2) VALUES ('d'),('e');
+
+--connection node_2a
+--source include/galera_signal_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+--connection node_2
+--error ER_LOCK_DEADLOCK, ER_QUERY_INTERRUPTED
+--reap
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1018B.test b/mysql-test/suite/galera_sr/t/GCF-1018B.test
new file mode 100644
index 00000000000..f11309080c0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1018B.test
@@ -0,0 +1,40 @@
+#
+# SR: Node hang with one thread waiting in InnoDB
+#
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_trx_fragment_size = 64;
+SET SESSION innodb_lock_wait_timeout = 1000;
+
+--let $count = 500
+--disable_query_log
+while ($count)
+{
+ --connection node_1
+ --send INSERT INTO t1 (f2) VALUES ('abc'),('abc');
+
+ --connection node_2
+ --send DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;
+
+ --connection node_1
+ --error 0,ER_LOCK_DEADLOCK,ER_DUP_ENTRY,ER_LOCK_WAIT_TIMEOUT,ER_QUERY_INTERRUPTED
+ --reap
+
+ --connection node_2
+ --error 0,ER_LOCK_DEADLOCK,ER_DUP_ENTRY,ER_LOCK_WAIT_TIMEOUT,ER_QUERY_INTERRUPTED
+ --reap
+
+ --dec $count
+}
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-1043A.test b/mysql-test/suite/galera_sr/t/GCF-1043A.test
new file mode 100644
index 00000000000..c76623742d7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1043A.test
@@ -0,0 +1,13 @@
+#
+# Assertion `retval == WSREP_OK || retval == WSREP_TRX_FAIL || retval == WSREP_BF_ABORT || retval == WSREP_CONN_FAIL' failed with SR
+#
+
+--source include/galera_cluster.inc
+
+--let $count = 1000;
+--let $wsrep_trx_fragment_size = 1;
+--let $query_node_1 = DELETE FROM t1
+--let $query_node_1a = REPLACE INTO t1 VALUES (1,'y'),(2,'x')
+--let $query_node_2 = REPLACE INTO t1 VALUES (1,'y'),(2,'y'),(3,'y')
+
+--source suite/galera/include/galera_concurrent_test.inc
diff --git a/mysql-test/suite/galera_sr/t/GCF-1043B.test b/mysql-test/suite/galera_sr/t/GCF-1043B.test
new file mode 100644
index 00000000000..e3b6b7439ca
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1043B.test
@@ -0,0 +1,13 @@
+#
+# Assertion `retval == WSREP_OK || retval == WSREP_TRX_FAIL || retval == WSREP_BF_ABORT || retval == WSREP_CONN_FAIL' failed with SR
+#
+
+--source include/galera_cluster.inc
+
+--let $count = 1000;
+--let $wsrep_trx_fragment_size = 1;
+--let $query_node_1 = DELETE FROM t1
+--let $query_node_1a = INSERT INTO t1 VALUES (1,'y'),(2,'x')
+--let $query_node_2 = UPDATE t1 SET f2 = 'y' WHERE f1 = 1 OR f1 = 2;
+
+--source suite/galera/include/galera_concurrent_test.inc
diff --git a/mysql-test/suite/galera_sr/t/GCF-1051.test b/mysql-test/suite/galera_sr/t/GCF-1051.test
new file mode 100644
index 00000000000..511cae93784
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1051.test
@@ -0,0 +1,52 @@
+#
+# Test the case where SR is rolled back to savepoint that points to the
+# very beginning of the transaction. This results in regular rollback
+# rather than rollback to savepoint.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size=1;
+
+#
+# Test 1: regular transaction
+#
+--connection node_1
+START TRANSACTION;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# Test 2: AUTOCOMMIT OFF
+#
+--connection node_1
+SET AUTOCOMMIT=OFF;
+SAVEPOINT A;
+INSERT INTO t1 VALUES (2);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-1060.test b/mysql-test/suite/galera_sr/t/GCF-1060.test
new file mode 100644
index 00000000000..714a5ef9f90
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-1060.test
@@ -0,0 +1,9 @@
+--source include/galera_cluster.inc
+
+--let $count = 100;
+--let $wsrep_trx_fragment_size = 1;
+--let $query_node_1 = TRUNCATE TABLE t1
+--let $query_node_1a = INSERT INTO t1 VALUE (1,'x'),(2,'x'),(3,'x')
+--let $query_node_2 = INSERT INTO t1 VALUE (4, 'z');
+
+--source suite/galera/include/galera_concurrent_test.inc
diff --git a/mysql-test/suite/galera_sr/t/GCF-437.test b/mysql-test/suite/galera_sr/t/GCF-437.test
new file mode 100644
index 00000000000..4101bac7446
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-437.test
@@ -0,0 +1,21 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=MyISAM;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 2 * 1024 * 1024;
+
+--error ER_BINLOG_ROW_LOGGING_FAILED
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+
+CALL mtr.add_suppression("InnoDB: The total blob data length*");
+CALL mtr.add_suppression("WSREP: Error writing into wsrep_schema.SR: 139");
+CALL mtr.add_suppression("WSREP: Failed to write to frag table: 1");
+CALL mtr.add_suppression("WSREP: Failed to append frag to persistent storage");
+
+DROP TABLE t1;
+DROP table ten;
diff --git a/mysql-test/suite/galera_sr/t/GCF-561.test b/mysql-test/suite/galera_sr/t/GCF-561.test
new file mode 100644
index 00000000000..e092e194c14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-561.test
@@ -0,0 +1,65 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of DDL on a concurrent SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+ALTER TABLE t1 DROP COLUMN f2;
+
+# SR applied before the DDL is no longer visible
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+# Transaction can not continue due to DDL, implicit ROLLBACK
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (6, 6);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# DDL is now in effect
+--error ER_WRONG_VALUE_COUNT_ON_ROW
+INSERT INTO t1 VALUES (6, 6);
+
+# But it should be possible to reissue the transaction
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-571.test b/mysql-test/suite/galera_sr/t/GCF-571.test
new file mode 100644
index 00000000000..3ad32493a35
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-571.test
@@ -0,0 +1,54 @@
+#
+# GCF-571 ROLLBACK TO SAVEPOINT causes all SR records to be deleted
+#
+
+--source include/galera_cluster.inc
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+INSERT INTO t1 VALUES ('%abcdef%');
+SAVEPOINT A;
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+INSERT INTO t1 VALUES ('xyzxyz');
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+
+--connection node_1
+ROLLBACK TO SAVEPOINT A;
+
+--connection node_1a
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%';
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%';
+SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%';
+
+--connection node_1
+ROLLBACK;
+
+--connection node_1a
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-572.test b/mysql-test/suite/galera_sr/t/GCF-572.test
new file mode 100644
index 00000000000..8bf57a38fdd
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-572.test
@@ -0,0 +1,54 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+#
+# Test 1: statement rollback is not safe
+# (some fragments were already replicated)
+#
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'node1');
+
+--connection node_1a
+INSERT INTO t1 VALUES (5, 'node2');
+
+--connection node_1
+# If we try to INSERT a duplicate key, ER_LOCK_DEADLOCK is the only possible
+# outcome at this point. Notice that ER_DUP_ENTRY is NOT an option here
+# because we were forced to rollback the whole transaction (not just the
+# statement)
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (5, 'node1');
+
+SELECT * FROM t1;
+
+#
+# Test 2: statement rollback is safe
+# (no fragments have been replicated)
+#
+
+SET SESSION wsrep_trx_fragment_size = 10000;
+
+START TRANSACTION;
+INSERT INTO t1 VALUE (10, 'node1');
+SELECT * FROM wsrep_schema.SR;
+
+--connection node_1a
+INSERT INTO t1 VALUES(15, 'node2');
+
+--connection node_1
+SELECT * FROM t1;
+# This time, only the statement is rolled back and we expect ER_DUP_ENTRY.
+--error ER_DUP_ENTRY
+INSERT INTO t1 VALUES(15, 'node1');
+
+COMMIT;
+SELECT * FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-574.test b/mysql-test/suite/galera_sr/t/GCF-574.test
new file mode 100644
index 00000000000..c9d7c405d14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-574.test
@@ -0,0 +1,27 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test CREATE TABLE ... SELECT with Streaming Replication
+#
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+--disable_query_log
+--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) > 1 AS wsrep_last_committed_delta;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 10000 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/GCF-580.test b/mysql-test/suite/galera_sr/t/GCF-580.test
new file mode 100644
index 00000000000..165b1abcc7a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-580.test
@@ -0,0 +1,27 @@
+#
+# GCF-580 wsrep_last_committed_counter increases twice for every SR fragment
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+
+--let $fragments_count = `SELECT COUNT(*) FROM wsrep_schema.SR`
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+--disable_query_log
+--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) = $fragments_count AS last_committed_matches_fragment_count
+--enable_query_log
+
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-585.test b/mysql-test/suite/galera_sr/t/GCF-585.test
new file mode 100644
index 00000000000..af800154b0b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-585.test
@@ -0,0 +1,40 @@
+#
+# GCF-585 SR: Assertion `total_length + wsrep_get_fragment_base(thd) == saved_pos' failed in wsrep_write_cache_once after SQL error
+#
+
+--source include/galera_cluster.inc
+
+# Test case #1
+
+create table t1 (f1 integer primary key) engine=innodb;
+set autocommit=off;
+set session wsrep_trx_fragment_size=1;
+start transaction;
+insert into t1 values (1);
+--error ER_LOCK_DEADLOCK
+insert into t1 values (2),(1);
+alter table t1 drop primary key;
+drop table t1;
+
+# Test case #2
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+update t1 set f1 = 100 where f1 = 10;
+
+--connection node_2
+INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+SET SESSION wsrep_trx_fragment_size=1;
+SET SESSION innodb_lock_wait_timeout=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+--error ER_LOCK_DEADLOCK
+delete from t1 where f1 > 10;
+--error ER_LOCK_DEADLOCK
+delete from t1 where f1 > 10 and f1 < 100;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-597.test b/mysql-test/suite/galera_sr/t/GCF-597.test
new file mode 100644
index 00000000000..d3d80ffc4f8
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-597.test
@@ -0,0 +1,29 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+
+SET wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+ROLLBACK;
+
+DROP TABLE t1; \ No newline at end of file
diff --git a/mysql-test/suite/galera_sr/t/GCF-620.test b/mysql-test/suite/galera_sr/t/GCF-620.test
new file mode 100644
index 00000000000..abfba47ee5a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-620.test
@@ -0,0 +1,22 @@
+#
+# GCF-620 SR: ROLLBACK TO SAVEPOINT causes slave crash if wsrep_trx_fragment_size does not fall on boundary
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 200;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (1);
+SAVEPOINT A;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT A;
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-623.test b/mysql-test/suite/galera_sr/t/GCF-623.test
new file mode 100644
index 00000000000..daf9eccfa74
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-623.test
@@ -0,0 +1,31 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1; \ No newline at end of file
diff --git a/mysql-test/suite/galera_sr/t/GCF-627.test b/mysql-test/suite/galera_sr/t/GCF-627.test
new file mode 100644
index 00000000000..7c9faff78a8
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-627.test
@@ -0,0 +1,30 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER);
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+
+--connection node_2
+DROP TABLE t1;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--error ER_NO_SUCH_TABLE
+INSERT INTO t1 VALUES (2);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/GCF-845.test b/mysql-test/suite/galera_sr/t/GCF-845.test
new file mode 100644
index 00000000000..9651bde014d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-845.test
@@ -0,0 +1,30 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE = InnoDB;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (161);
+COMMIT;
+DELETE FROM t1 WHERE f1 > 13;
+--disconnect node_1a
+--sleep 2
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+
+--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
+--let $assert_count = 0
+--let $assert_select = BF-BF X
+--let $assert_text = No BF-BF log line found
+--let $assert_only_after = CURRENT_TEST
+--source include/assert_grep.inc
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-851.test b/mysql-test/suite/galera_sr/t/GCF-851.test
new file mode 100644
index 00000000000..a9b7725c155
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-851.test
@@ -0,0 +1,24 @@
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+SET SESSION AUTOCOMMIT=OFF;
+
+INSERT INTO t1 VALUES (10);
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+START TRANSACTION;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) > 0 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM t1;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-867.test b/mysql-test/suite/galera_sr/t/GCF-867.test
new file mode 100644
index 00000000000..73ae43237c9
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-867.test
@@ -0,0 +1,42 @@
+#
+# Test many ongoing SR transactions
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
+--disable_query_log
+
+--let $connections = 120
+
+--let $count = $connections
+while ($count)
+{
+--connect $count, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION wsrep_sync_wait = 0;
+--dec $count
+}
+
+
+--let $count = $connections
+while ($count)
+{
+--connection $count
+START TRANSACTION;
+--send_eval INSERT INTO t1 VALUES ($count)
+--dec $count
+}
+
+--let $count = $connections
+while ($count)
+{
+--connection $count
+--reap
+COMMIT;
+--dec $count
+}
+
+--enable_query_log
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/GCF-889.test b/mysql-test/suite/galera_sr/t/GCF-889.test
new file mode 100644
index 00000000000..fa2a417d8ce
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-889.test
@@ -0,0 +1,28 @@
+--source include/galera_cluster.inc
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET SESSION wsrep_on = ON;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+DELETE FROM t1 WHERE f1 = 1;
+SET SESSION wsrep_trx_fragment_size = 0;
+
+INSERT INTO t1 VALUES (1);
+
+SELECT COUNT(*) = 1;
+
+--connection node_2
+SELECT COUNT(*) = 1;
+CALL mtr.add_suppression("Could not execute Delete_rows event on table");
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+
+--connection node_1
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_sr/t/GCF-900.test b/mysql-test/suite/galera_sr/t/GCF-900.test
new file mode 100644
index 00000000000..3f1b53630b6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/GCF-900.test
@@ -0,0 +1,28 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 128;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 0);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (2, 0);
+
+--connection node_2
+ALTER TABLE t1 DROP COLUMN f2;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--connection node_1a
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (3, 0);
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/disabled.def b/mysql-test/suite/galera_sr/t/disabled.def
new file mode 100644
index 00000000000..e5511d18860
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/disabled.def
@@ -0,0 +1,4 @@
+mysql-wsrep-features#29 : binlog_format=STATEMENT not supported with SR
+GCF-574 : CTAS is not supported together with SR
+galera_sr_bf_abort : is worked on with tracker GCF-1015
+galera_sr_sbr : binlog_format=STATEMENT not supported with SR
diff --git a/mysql-test/suite/galera_sr/t/galera-features#56.test b/mysql-test/suite/galera_sr/t/galera-features#56.test
new file mode 100644
index 00000000000..0497952e355
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera-features#56.test
@@ -0,0 +1,55 @@
+##
+## This test tests parallel application of multiple auto-increment insert transactions
+##
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Create a second connection to node1 so that we can run transactions concurrently
+--let $galera_connection_name = node_1a
+--let $galera_server_number = 1
+--source include/galera_connect.inc
+SET SESSION wsrep_trx_fragment_size = 1;
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) Engine=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+
+--connection node_2
+--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads`
+SET GLOBAL wsrep_slave_threads = 4;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+--connection node_1
+--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_1a
+--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_1
+--reap
+
+--connection node_1a
+--reap
+
+--connection node_2
+--reap
+
+SELECT COUNT(*) = 30000 FROM t1;
+SELECT COUNT(DISTINCT f1) = 30000 FROM t1;
+SELECT COUNT(*) = 6 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user';
+
+--disable_query_log
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
+--enable_query_log
+
+--connection default
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc
new file mode 100644
index 00000000000..eba84eddb93
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc
@@ -0,0 +1,145 @@
+#
+# Test SR BF abort for all sync points in master side code path
+#
+# The procedure in all test cases is the following:
+# 1) Start SR transaction on node 1, do INSERT + SELECT .. FOR UPDATE
+# 2) Set up sync point on node 1 to block slave thread processing
+# in apply monitor
+# 3) Do write on node 2 which will conflict with SELECT .. FOR UPDATE
+# 4) Set up desired sync point on master side and commit
+# 5) Wait until commit reaches master side sync point, clear sync points
+# and release all sync point waiters
+# 6) COMMIT on node 1 should return deadlock error
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--eval SET SESSION wsrep_trx_fragment_size = $wsrep_trx_fragment_size
+SET AUTOCOMMIT=OFF;
+
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 FOR UPDATE;
+
+# Set up sync point
+--connection node_1a
+--let galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+# Conflicting insert
+--connection node_2
+
+SET AUTOCOMMIT=ON;
+INSERT INTO t1 VALUES (2);
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = $galera_sr_bf_abort_sync_point
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+if ($galera_sr_bf_abort_at_commit)
+{
+ --send COMMIT
+}
+if (!$galera_sr_bf_abort_at_commit)
+{
+ --send INSERT INTO t1 VALUES (3)
+}
+
+--connection node_1a
+
+--let $cmp = `SELECT STRCMP('apply_monitor_slave_enter_sync', '$galera_sr_bf_abort_sync_point') = -1`
+
+if ($cmp)
+{
+ --let $galera_sync_point = apply_monitor_slave_enter_sync $galera_sr_bf_abort_sync_point
+}
+if (!$cmp)
+{
+ --let $galera_sync_point = $galera_sr_bf_abort_sync_point apply_monitor_slave_enter_sync
+}
+--source include/galera_wait_sync_point.inc
+
+# Let conflicting insert proceed, make sure it hits abort_trx_end and
+# let both threads continue.
+
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end $galera_sr_bf_abort_sync_point
+
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = $galera_sr_bf_abort_sync_point
+--source include/galera_signal_sync_point.inc
+
+# Deadlock should now be retured by node_1
+--connection node_1
+if (!$galera_sr_bf_abort_at_commit)
+{
+ --error ER_LOCK_DEADLOCK
+ --reap
+}
+if ($galera_sr_bf_abort_at_commit)
+{
+ --reap
+}
+
+ROLLBACK;
+
+# Release slave insert
+--connection node_1a
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+
+# Verify that nodes are consistent
+
+# End result:
+# If the statement which was BF aborted was commit,
+# node_1 must replay the transaction so that the table
+# will have rows 1, 2. If it in turn was INSERT,
+# node_1 must abort the transaction so that only
+# INSERT ... VALUES (2) survives.
+
+--connection node_1
+SELECT * FROM t1;
+if ($galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+if (!$galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+--connection node_2
+SELECT * FROM t1;
+if ($galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1;
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+if (!$galera_sr_bf_abort_at_commit)
+{
+ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+}
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Delete entery to verify that node is unblocked
+--connection node_1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 0;
+DELETE FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test
new file mode 100644
index 00000000000..711ef69bd14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test
@@ -0,0 +1,48 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--let $wsrep_trx_fragment_size = 1
+
+# Control connection for manipulating sync points on node 1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+
+--echo galera_sr_bf_abort_at_commit = 0
+--let $galera_sr_bf_abort_at_commit = 0
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo galera_sr_bf_abort_at_commit = 1
+--let $galera_sr_bf_abort_at_commit = 1
+
+--echo after_replicate_sync
+--let $galera_sr_bf_abort_sync_point = after_replicate_sync
+--source galera_sr_bf_abort.inc
+
+--echo local_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo apply_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+--echo commit_monitor_master_enter_sync
+--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync
+--source galera_sr_bf_abort.inc
+
+CALL mtr.add_suppression("WSREP: fragment replication failed: 1");
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_blob.test b/mysql-test/suite/galera_sr/t/galera_sr_blob.test
new file mode 100644
index 00000000000..ed314d09f5a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_blob.test
@@ -0,0 +1,38 @@
+#
+# Test that a single-blob will be replicated using SR if it is sufficiently
+# large.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 TEXT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--connection node_1
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+
+--connection node_2
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+# Confirm that exactly one fragment was replicated
+
+--disable_query_log
+--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) = 1 AS wsrep_last_committed_delta;
+--enable_query_log
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT LENGTH(f1) = 65535 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test
new file mode 100644
index 00000000000..7a4e1706402
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test
@@ -0,0 +1,87 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction
+# We use SET GLOBAL wsrep_cluster_address = '' to cause the master (node_2) to temporarily
+# leave the cluster.
+#
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+
+--sleep 2
+--connection node_2
+
+--error 2013,ER_UNKNOWN_COM_ERROR
+INSERT INTO t1 VALUES (6);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2a
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+
+--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2b
+--source include/galera_wait_ready.inc
+SELECT * FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Repeat transaction to confirm no locks are left from previous transaction
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+
+--connection node_2b
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for");
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test
new file mode 100644
index 00000000000..148539bf5b0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test
@@ -0,0 +1,86 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction
+# We use SET GLOBAL wsrep_cluster_address = '' to cause the slave (node_2) to temporarily
+# leave the cluster.
+#
+
+# Start with a clean slate
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction should be able to continue
+#
+
+--connection node_2
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+--sleep 2
+
+--connection node_1
+# Continue generating events in the transaction
+
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+--source include/galera_wait_ready.inc
+
+# Confirm that the SR table still contains entries from ongoing transaction
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Continue and finalize transaction
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (16);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that transaction was replicated properly
+# and SR table is cleaned up afterwards.
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test b/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test
new file mode 100644
index 00000000000..9ec7143d25c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test
@@ -0,0 +1,45 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test two concurrent SR-replicated transactions
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+
+--connection node_1
+COMMIT;
+
+--connection node_1a
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 5 FROM t2;
+
+--connection node_1
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict.test
new file mode 100644
index 00000000000..dd033fec9c7
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict.test
@@ -0,0 +1,45 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# A conflict between a streaming replication fragment and a local transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+# Wait until a streaming replication fragment has arrived
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+# Attempt a conflicting INSERT. This will block
+--send INSERT INTO t1 VALUES(1);
+
+# Observe the block from a separate connection
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'update';
+--source include/wait_condition.inc
+
+# Commit the remote transaction, causing the local transaction to return an error
+--connection node_1
+COMMIT;
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test
new file mode 100644
index 00000000000..6675321641f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test
@@ -0,0 +1,45 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #2 begins a transaction
+# 2. Node #1 begins conflicting transaction that is SR replicated
+# 3. Node #2 attempts to commit, gets a deadlock error, even before #1 has committed
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+--connection node_1
+COMMIT;
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test
new file mode 100644
index 00000000000..0ea52290bb6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test
@@ -0,0 +1,46 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #1 begins a transaction that is SR replicated
+# 2. Node #2 begins a conflicting transaction, hangs
+# 3. Node #1 comits
+# 4. Node #2 gets a dup key error
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--send INSERT INTO t1 VALUES (5);
+
+--sleep 1
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+--error ER_DUP_ENTRY
+--reap
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test
new file mode 100644
index 00000000000..cb96fae0122
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test
@@ -0,0 +1,44 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #2 begins a transaction
+# 2. Node #1 begins conflicting transaction that is SR replicated
+# 3. Node #1 rolls back
+# 4. Node #2 can not commit because it was BF-aborted even though the SR transaction was rolled back
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test
new file mode 100644
index 00000000000..105d395df6b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test
@@ -0,0 +1,63 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events on the master:
+#
+# 1. Connection #1 begins a SR transaction
+# 2. Connection #2 issues DDL
+# 3. Connection #1 attempts to continue the transaction, gets deadlock
+# 4. Connection #1 retries the transaction and succeeds
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+# SR replication is triggered and rows have been delivered to the slave
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (6);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Check that the transaction thus aborted could be reissued
+
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO t1 (f1) VALUES (1);
+INSERT INTO t1 (f1) VALUES (2);
+INSERT INTO t1 (f1) VALUES (3);
+INSERT INTO t1 (f1) VALUES (4);
+INSERT INTO t1 (f1) VALUES (5);
+INSERT INTO t1 (f1) VALUES (6);
+COMMIT;
+
+SELECT COUNT(*) = 6 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test
new file mode 100644
index 00000000000..a3045773387
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test
@@ -0,0 +1,43 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of DROP SCHEMA DDL on a concurrent SR transaction
+# Most other DDL tests work on a table level, so this test exercises a
+# different granularity.
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+DROP SCHEMA test;
+
+--error ER_NO_SUCH_TABLE
+SELECT COUNT(*) = 0 FROM test.t1;
+
+--connection node_1
+
+# Transaction can not continue due to DDL
+--error ER_LOCK_DEADLOCK
+INSERT INTO test.t1 VALUES (6, 6);
+
+# DDL is now in effect
+--error ER_NO_SUCH_TABLE
+INSERT INTO test.t1 VALUES (6, 6);
+
+CREATE SCHEMA test;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test
new file mode 100644
index 00000000000..e092e194c14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test
@@ -0,0 +1,65 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of DDL on a concurrent SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+ALTER TABLE t1 DROP COLUMN f2;
+
+# SR applied before the DDL is no longer visible
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+# Transaction can not continue due to DDL, implicit ROLLBACK
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (6, 6);
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# DDL is now in effect
+--error ER_WRONG_VALUE_COUNT_ON_ROW
+INSERT INTO t1 VALUES (6, 6);
+
+# But it should be possible to reissue the transaction
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test
new file mode 100644
index 00000000000..49155017d3f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test
@@ -0,0 +1,53 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of unrelated DDL on a concurrent SR transaction
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t1 VALUES (3, 3);
+INSERT INTO t1 VALUES (4, 4);
+INSERT INTO t1 VALUES (5, 5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+ALTER TABLE t2 DROP COLUMN f2;
+
+# SR applied before the DDL is still visible
+SELECT COUNT(*) = 5 FROM t1;
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+
+# Transaction can continue, even after the DDL
+--error 0
+INSERT INTO t1 VALUES (6, 6);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test
new file mode 100644
index 00000000000..c9d7770736b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test
@@ -0,0 +1,57 @@
+#
+# Test the case where a duplicate key error happens in the middle of an SR transaction
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB;
+CREATE UNIQUE INDEX i1 ON t1 (f1(512));
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1024;
+
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+
+# Confirm that the wsrep_schema table is now empty, as it was a full transaction rollback
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that the transaction can be restarted on either node
+
+--connection node_1
+INSERT INTO t1 VALUES (REPEAT('d', 512));
+INSERT INTO t1 VALUES (REPEAT('e', 512));
+INSERT INTO t1 VALUES (REPEAT('f', 512));
+COMMIT;
+
+--connection node_2
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (REPEAT('a', 512));
+INSERT INTO t1 VALUES (REPEAT('b', 512));
+INSERT INTO t1 VALUES (REPEAT('c', 512));
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 6 FROM t1;
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test b/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test
new file mode 100644
index 00000000000..b83deaee244
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test
@@ -0,0 +1,62 @@
+#
+# Test Foreign Key with SR
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE grandparent (
+ id INT NOT NULL PRIMARY KEY
+) ENGINE=InnoDB;
+
+CREATE TABLE parent (
+ id INT NOT NULL PRIMARY KEY,
+ grandparent_id INT,
+ FOREIGN KEY (grandparent_id)
+ REFERENCES grandparent(id)
+ ON UPDATE CASCADE
+) ENGINE=InnoDB;
+
+CREATE TABLE child (
+ id INT NOT NULL PRIMARY KEY,
+ grandparent_id INT,
+ FOREIGN KEY (grandparent_id)
+ REFERENCES parent(grandparent_id)
+ ON UPDATE CASCADE
+) ENGINE=InnoDB;
+
+INSERT INTO grandparent VALUES (1),(2),(3),(4);
+INSERT INTO parent VALUES (1,1), (2,2);
+INSERT INTO child VALUES (1,1), (2,2);
+
+# Start and SR transaction
+
+--connection node_1
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+
+UPDATE grandparent SET id = 5 WHERE id = 1;
+
+# No conflicting transactions are allowed to proceed on slave
+
+--connection node_2
+SET SESSION innodb_lock_wait_timeout = 1;
+
+--error ER_LOCK_WAIT_TIMEOUT
+UPDATE grandparent SET id = 10 WHERE id = 5;
+
+--error ER_LOCK_WAIT_TIMEOUT
+DELETE FROM child;
+
+# SR transaction succesffull
+
+--connection node_1
+COMMIT;
+
+--let $diff_servers = 1 2
+--source include/diff_servers.inc
+
+DROP TABLE child;
+DROP TABLE parent;
+DROP TABLE grandparent;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt
new file mode 100644
index 00000000000..d5176463cdb
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt
@@ -0,0 +1 @@
+--gtid-mode=ON --log-bin --log-slave-updates --enforce-gtid-consistency --loose-galera-sr-gtid-unique
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_gtid.test b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test
new file mode 100644
index 00000000000..fbb61588452
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test
@@ -0,0 +1,46 @@
+#
+# Test basic Galera operation under --gtid-mode=ON
+#
+
+--source include/have_log_bin.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY);
+
+SET SESSION wsrep_trx_fragment_size=1;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+SET SESSION wsrep_trx_fragment_size=1;
+UPDATE t1 SET f1 = 2;
+
+--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;`
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size=0;
+
+--connection node_2
+SET SESSION wsrep_trx_fragment_size=0;
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+
+--disable_query_log
+--eval SELECT '$gtid_executed_node2' = @@global.gtid_executed AS gtid_executed_equal;
+--enable_query_log
+
+--replace_regex /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<GTID>/ /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120;
+
+--connection node_2
+# Perform causal wait
+SELECT 1 FROM DUAL;
+--replace_regex /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<GTID>/ /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test b/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test
new file mode 100644
index 00000000000..01481db5a8b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test
@@ -0,0 +1,33 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test large INSERT ... SELECT with SR
+#
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+# Insert 10K rows.
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 99 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1;
+
+--connection node_1
+
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test
new file mode 100644
index 00000000000..2730af7f9f4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test
@@ -0,0 +1,52 @@
+#
+# Kill entire cluster during SR while pc.bootstrap is in effect
+# after restart, confirm that the wsrep_schema.SR table is empty
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--connection node_1
+--source include/kill_galera.inc
+
+--sleep 1
+
+# Bootstrap the cluster from scratch
+
+--connection node_1
+--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/start_mysqld.inc
+
+--connection node_2
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf
new file mode 100644
index 00000000000..6422d7541ba
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf
@@ -0,0 +1,4 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.recovery=false'
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test
new file mode 100644
index 00000000000..dc99521f40e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test
@@ -0,0 +1,53 @@
+#
+# Kill entire cluster during SR while pc.recovery is NOT in effect
+# after restart, confirm that the wsrep_schema.SR table is empty
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--connection node_1
+--source include/kill_galera.inc
+
+--sleep 1
+
+--connection node_1
+--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat
+--let $start_mysqld_params = "--wsrep-new-cluster"
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/start_mysqld.inc
+
+--connection node_2
+--let $start_mysqld_params = ""
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test
new file mode 100644
index 00000000000..e6b1a9c5d27
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test
@@ -0,0 +1,54 @@
+#
+# Kill entire cluster during SR while pc.recovery is in effect
+# after restart, confirm that the wsrep_schema.SR table is empty
+#
+
+--source include/galera_cluster.inc
+--source include/big_test.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/kill_galera.inc
+--connection node_1
+--source include/kill_galera.inc
+
+--sleep 1
+
+# Bootstrap the cluster from scratch
+
+--connection node_1
+--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/start_mysqld.inc
+
+--connection node_2
+--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+
+--connection node_1
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test
new file mode 100644
index 00000000000..03d09f33fab
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test
@@ -0,0 +1,59 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test KILL CONNECTION on a transaction that has already replicated some data via SR
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+# Confirm that the transaction is SR-replicated
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+# Kill the transaction by killing the entire connection
+
+--connection node_1
+--let $connection_id = `SELECT CONNECTION_ID()`
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--disable_query_log
+--eval KILL CONNECTION $connection_id
+--enable_query_log
+
+# Confirm that the disconnection caused the updates made so far to be removed
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+# Confirm that the transaction can be reissued in its entirety on the slave without a conflict
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+COMMIT;
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1a
+SELECT COUNT(*) = 5 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test
new file mode 100644
index 00000000000..c7f10ed570d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test
@@ -0,0 +1,53 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+#
+# Test KILL QUERY on a statement that has already replicated some data via SR
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $connection_id = `SELECT CONNECTION_ID()`
+--send INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;
+
+# Wait for some SR to arrive on the slave.
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT TABLE_ROWS > 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--connection node_1
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--echo Killing query ...
+--disable_query_log
+--eval KILL QUERY $connection_id
+--enable_query_log
+
+--connection node_1
+--error ER_QUERY_INTERRUPTED
+--reap
+
+# Confirm that the kill caused the updates made so far to be removed
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+# Confirm that the transaction can be reissued in its entirety on the slave without a conflict
+
+INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3;
+SELECT COUNT(*) = 1000 FROM t1;
+
+--connection node_1a
+SELECT COUNT(*) = 1000 FROM t1;
+
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf
new file mode 100644
index 00000000000..290d8fe196e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf
@@ -0,0 +1,4 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.weight=2'
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test
new file mode 100644
index 00000000000..9abce126d44
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test
@@ -0,0 +1,80 @@
+#
+# This test kills the slave while a Streaming Replication transaction is in
+# progress but before a fragment has already been applied on the slave. It
+# is expected that after the slave restarts, the cluster will continue to
+# be consistent.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Block node #2's applier before table t1's inserts have come into play
+
+--connection node_2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+CREATE TABLE t2 (f1 INTEGER);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+LOCK TABLE t2 WRITE;
+
+--connection node_1
+INSERT INTO t2 VALUES (1);
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--sleep 2
+
+--connection node_2
+--source include/kill_galera.inc
+--sleep 1
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+--connection node_2
+--source include/start_mysqld.inc
+--sleep 1
+
+--source include/wait_until_connected_again.inc
+--source include/galera_wait_ready.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+--sleep 5
+SELECT COUNT(*) = 15 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt
new file mode 100644
index 00000000000..132c6aed246
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt
@@ -0,0 +1 @@
+--innodb_log_file_size=1G --binlog-row-event-max-size=100M
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test
new file mode 100644
index 00000000000..ca54f9e6851
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test
@@ -0,0 +1,58 @@
+#
+# Test the replication and subsequent cleanup of a few, very large fragments
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1024 * 1024 * 10;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) > 50000 FROM t1;
+
+--connection node_1
+ROLLBACK;
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_2';
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_1 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_1';
+
+DROP TABLE ten;
+DROP TABLE t1;
+
+CALL mtr.add_suppression('InnoDB: Resizing redo log from');
+CALL mtr.add_suppression('InnoDB: Starting to delete and rewrite log files');
+CALL mtr.add_suppression('InnoDB: New log files created, LSN=');
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test
new file mode 100644
index 00000000000..b430ace5d69
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test
@@ -0,0 +1,39 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test Streaming Replication + LOAD DATA
+#
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 512;
+
+# Create a file for LOAD DATA with 20K entries
+--perl
+open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_sr_load_data.csv") or die;
+foreach my $i (1..20000) {
+ print FILE "$i\n";
+}
+EOF
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Record wsrep_last_committed as it was before LOAD DATA
+--connection node_2
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--connection node_1
+--disable_query_log
+--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_sr_load_data.csv' INTO TABLE t1;
+--enable_query_log
+
+--connection node_2
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+SELECT COUNT(*) = 20000 FROM t1;
+# LOAD-ing 20K rows causes 3 commits to be registered
+--disable_query_log
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 3 AS wsrep_last_committed_diff;
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test
new file mode 100644
index 00000000000..40e63e7c67f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test
@@ -0,0 +1,50 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+#
+# Test Streaming Replication and LOAD DATA splitting operating at the same time
+#
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting`
+
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_load_data_splitting = TRUE;
+
+
+# Create a file for LOAD DATA with 95K entries
+--perl
+open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_sr_load_data.csv") or die;
+foreach my $i (1..95000) {
+ print FILE "$i\n";
+}
+EOF
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Record wsrep_last_committed as it was before LOAD DATA
+--connection node_2
+--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+--connection node_1
+--disable_query_log
+--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_sr_load_data.csv' INTO TABLE t1;
+--enable_query_log
+
+--connection node_2
+--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`
+
+SELECT COUNT(*) = 95000 FROM t1;
+
+# LOAD-ing 95K rows causes 10 'commits' to be registered
+--disable_query_log
+--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 10 AS wsrep_last_committed_diff;
+--enable_query_log
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig;
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt
new file mode 100644
index 00000000000..03fcb5d040d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt
@@ -0,0 +1 @@
+--log-slave-updates --log-bin
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test
new file mode 100644
index 00000000000..069b9f44591
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test
@@ -0,0 +1,66 @@
+#
+# Interleave SR and non-SR transactions and confirm that the binlog is in correct order
+#
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB;
+CREATE TABLE t4 (f1 INTEGER) ENGINE=InnoDB;
+
+--source include/galera_cluster.inc
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+RESET MASTER;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t2 VALUES (1);
+
+--connection node_2
+RESET MASTER;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t3 VALUES (1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t4 VALUES (1);
+
+--connection node_1
+INSERT INTO t1 VALUES (2);
+COMMIT;
+
+--connection node_1a
+INSERT INTO t2 VALUES (2);
+COMMIT;
+
+--connection node_2
+INSERT INTO t3 VALUES (2);
+COMMIT;
+--connection node_2a
+INSERT INTO t4 VALUES (2);
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 2 FROM t4;
+
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t4;
+
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test
new file mode 100644
index 00000000000..b3bac7df059
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test
@@ -0,0 +1,53 @@
+#
+# Test the replication and subsequent cleanup of a large number of small transaction fragments
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 100000 FROM t1;
+
+--connection node_1
+ROLLBACK;
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_2';
+
+--connection node_1
+SET SESSION wsrep_sync_wait = 0;
+--let $wsrep_provider_options_node_1 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'`
+SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M';
+SET SESSION wsrep_sync_wait = 7;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_1';
+
+DROP TABLE ten;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_myisam.test b/mysql-test/suite/galera_sr/t/galera_sr_myisam.test
new file mode 100644
index 00000000000..b037f817610
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_myisam.test
@@ -0,0 +1,29 @@
+#
+# Test that the basic MyISAM replication works even with SR enabled
+# We basically check that the data arrived on the slave and that there
+# were no assertions.
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 TEXT) ENGINE=MyISAM;
+
+--let $wsrep_replicate_myisam_orig = `SELECT @@wsrep_replicate_myisam`
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET GLOBAL wsrep_replicate_myisam = TRUE;
+
+INSERT INTO t1 VALUES (REPEAT('x', 65535));
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT LENGTH(f1) = 65535 FROM t1;
+
+DROP TABLE t1;
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig;
+--enable_query_log
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf
new file mode 100644
index 00000000000..574ae28b54a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf
@@ -0,0 +1,11 @@
+!include ../galera_2nodes.cnf
+
+# We do not set mysqldump-related SST options here because doing so on startup
+# causes the first MTR connection to be forefully dropped by Galera, which in turn confuses MTR
+
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true'
+
+[mysqld.2]
+wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true'
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test
new file mode 100644
index 00000000000..88249c22f7a
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test
@@ -0,0 +1,79 @@
+#
+# Test mysqldump SST on slave if SR transaction is in progress
+#
+
+--source include/big_test.inc
+--source include/galera_cluster.inc
+
+--source suite/galera/include/galera_sst_set_mysqldump.inc
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size = 1000;
+START TRANSACTION;
+# Insert 1000 rows
+INSERT INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+
+# Update 1000 rows
+UPDATE t1 SET f2 = REPEAT('y', 255);
+
+# Wait for SR replication to kick in
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+# Restart node #2
+
+--connection node_2
+--let $MYSQLD2_DATADIR = `SELECT @@datadir`
+
+--echo Shutting down server ...
+--source include/shutdown_mysqld.inc
+
+# Force SST
+--remove_file $MYSQLD2_DATADIR/grastate.dat
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+--connection node_2
+--echo Starting server ...
+--let $start_mysqld_params = --wsrep_sst_auth=sst:sst --wsrep_sst_method=mysqldump --wsrep-sst-receive-address=127.0.0.1:$NODE_MYPORT_2
+--source include/start_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
+--source include/wait_condition.inc
+
+# Check that node #2 is caught up with the SR transaction that is still in progress
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+# Finalize transaction
+--connection node_1
+UPDATE t1 SET f2 = REPEAT('z', 255);
+COMMIT;
+
+# Confirm proper replication of entire transaction to node #2
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 1000 FROM t1;
+SELECT COUNT(*) = 1000 FROM t1 WHERE f2 = REPEAT('z', 255);
+
+DROP TABLE t1;
+DROP TABLE ten;
+
+--connection node_1
+# galera_sst_restore.inc uses DROP USER internally which is incompatible
+# with SR, need to disable SR before that.
+SET SESSION wsrep_trx_fragment_size=0;
+--source suite/galera/include/galera_sst_restore.inc
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test b/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test
new file mode 100644
index 00000000000..83a7acbe3e0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test
@@ -0,0 +1,59 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test SR with parallel apply
+#
+
+--connection node_2
+--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads`
+SET GLOBAL wsrep_slave_threads = 5;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+INSERT INTO t1 (f2) VALUES (1);
+--send INSERT INTO t1 (f2) VALUES (1);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+INSERT INTO t1 (f2) VALUES (2);
+--send INSERT INTO t1 (f2) VALUES (2);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1 WHERE f2 = 1;
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1 WHERE f2 = 2;
+--source include/wait_condition.inc
+
+--connection node_1
+--reap
+COMMIT;
+
+--connection node_1a
+--reap
+ROLLBACK;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+
+--connection node_2
+--disable_query_log
+--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig;
+--enable_query_log
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback.test
new file mode 100644
index 00000000000..33a318f8ae3
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback.test
@@ -0,0 +1,76 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that ROLLBACK works correctly with streaming replication
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) >= 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK;
+
+#
+# After ROLLBACK, the table on node #2 should be empty
+#
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+#
+# It should be possible to re-insert the values we just rolled back
+#
+
+--connection node_1
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) >= 9 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) >= 10 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test
new file mode 100644
index 00000000000..c6c443a0828
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test
@@ -0,0 +1,55 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that a SR transaction that was just ROLLBACKed on one node can be
+# run against another node without any conflicts
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK;
+
+#
+# After ROLLBACK, the table on node #2 should be empty
+#
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
+
+#
+# It should be possible to reissue the same transaction against node #2
+#
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+COMMIT;
+
+SELECT COUNT(*) = 5 FROM t1;
+
+--connection node_1
+SELECT COUNT(*) = 5 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test
new file mode 100644
index 00000000000..93ff7a948c4
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test
@@ -0,0 +1,51 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that ROLLBACK TO SAVEPOINT works correctly with streaming replication
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 5 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK TO SAVEPOINT s1;
+
+INSERT INTO t1 VALUES (21, 'c');
+INSERT INTO t1 VALUES (22, 'c');
+INSERT INTO t1 VALUES (23, 'c');
+INSERT INTO t1 VALUES (24, 'c');
+INSERT INTO t1 VALUES (25, 'c');
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'a';
+SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c';
+
+--connection node_1
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test
new file mode 100644
index 00000000000..74350faf5a2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test
@@ -0,0 +1,61 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the case where a statement is rolled back due to an error while Streaming Replication
+# is in effect. We construct an INSERT ... SELECT statement that will fail with a duplicate
+# key error towards the end of the statement, after a portion has already been replicated via SR.
+#
+
+--disable_query_log
+--let $auto_increment_offset_orig = `SELECT @@auto_increment_offset`
+SET GLOBAL auto_increment_offset=1;
+--enable_query_log
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB;
+
+INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3;
+ALTER TABLE t1 CHANGE f1 f1 INTEGER;
+ALTER TABLE t1 DROP PRIMARY KEY;
+
+# This poison value is used to cause the INSERT ... SELECT below to fail
+INSERT INTO t1 VALUES (1, 'abc');
+
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+--error ER_DUP_ENTRY
+INSERT INTO t2 SELECT * FROM t1;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t2;
+--source include/wait_condition.inc
+
+# Cluster continues to operate after the implicit ROLLBACK;
+--connection node_1
+INSERT INTO t2 VALUES (1, 'abc');
+
+--connection node_2
+INSERT INTO t2 VALUES (2, 'abc');
+
+--connection node_1
+SELECT COUNT(*) = 2 FROM t2;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t2;
+
+--connection node_1
+
+--disable_query_log
+--eval SET GLOBAL auto_increment_offset=$auto_increment_offset_orig;
+--enable_query_log
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_sbr.test b/mysql-test/suite/galera_sr/t/galera_sr_sbr.test
new file mode 100644
index 00000000000..a24a520af60
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_sbr.test
@@ -0,0 +1,31 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that SR does not assert in the presence of statement-based replication events
+#
+
+--connection node_1
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION BINLOG_FORMAT='STATEMENT';
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+--connection node_2
+SELECT COUNT(*) = 5 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test
new file mode 100644
index 00000000000..721f1dec06d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test
@@ -0,0 +1,45 @@
+#
+# Shut down master (node #2) while an SR transaction is in progress
+#
+
+--source include/galera_cluster.inc
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1),(2),(3);
+
+--connection node_1
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--connection node_2
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+# Confirm that SR table on slave is empty
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2
+--source include/start_mysqld.inc
+
+# SR table on master should be empty too
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that the INSERT can be re-issued
+INSERT INTO t1 VALUES (1),(2),(3);
+
+--connection node_1
+SELECT COUNT(*) = 3 FROM t1;
+
+DROP TABLE t1;
+
+--connection node_2
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); \ No newline at end of file
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test
new file mode 100644
index 00000000000..53f6fd7885c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test
@@ -0,0 +1,63 @@
+#
+# Shut down slave (node #2) while an SR transaction is in progress
+#
+
+--source include/galera_cluster.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB;
+
+# We start two transactions on the master so that we can commit one while the slave
+# is down and commit the other after the slave has rejoined
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (11),(12),(13);
+
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (21),(22),(23);
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+--source include/wait_condition.inc
+
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+# Commit one transaction while the slave is down
+--connection node_1a
+INSERT INTO t1 VALUES (14),(15),(16);
+COMMIT;
+
+# Restart slave
+--connection node_2
+--source include/start_mysqld.inc
+
+# Confirm SR table on slave has entries
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16);
+
+# Commit the second transaction on master after the slave has rejoined
+--connection node_1b
+INSERT INTO t1 VALUES (24),(25),(26);
+COMMIT;
+
+# Confirm that SR table on slave is empty
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+SELECT COUNT(*) = 12 FROM t1;
+
+# SR table on master should be empty too
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf
new file mode 100644
index 00000000000..c8e17436e71
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf
@@ -0,0 +1,6 @@
+!include ../galera_2nodes.cnf
+[mysqld.1]
+wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=16K'
+[mysqld.2]
+wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=16K'
+
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test
new file mode 100644
index 00000000000..403b44286d9
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test
@@ -0,0 +1,21 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# A simple test with a very low value for gcache.size - 16K
+#
+
+--connection node_1
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+SELECT COUNT(*) = 10000 FROM t1;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test b/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test
new file mode 100644
index 00000000000..92d29fe4ca2
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test
@@ -0,0 +1,49 @@
+#
+# This test dumps the contents of the SR table under various circumstances
+#
+
+--source include/galera_cluster.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+
+CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--echo
+--echo Start of Simple Insert
+INSERT INTO t1 VALUES (4);
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Simple Insert
+--echo
+ROLLBACK;
+
+--echo Start of Multi-row Update
+UPDATE t1 SET f1 = f1 + 10;
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Multi-row Update
+--echo
+ROLLBACK;
+
+--echo Start of Multi-table Update
+UPDATE t1, t2 SET t1.f1 = t1.f1 + 100, t2.f1 = t2.f1 + 100;
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Multi-table Update
+--echo
+ROLLBACK;
+
+--echo Start of Savepoint
+INSERT INTO t1 VALUES (1000);
+SAVEPOINT X;
+INSERT INTO t1 VALUES (2000);
+ROLLBACK TO SAVEPOINT X;
+--source suite/galera/include/galera_dump_sr_table.inc
+--echo End of Savepoint
+--echo
+ROLLBACK;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test b/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test
new file mode 100644
index 00000000000..ca20dcdde24
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test
@@ -0,0 +1,260 @@
+#
+# This test tests the operation of SR transaction replay. If a
+# potentially conflicting remote transaction arrives at
+# just the right time during the commit of a local transaction,
+# the local transaction will be aborted and replayed.
+#
+# This test is divided in two sections:
+# 1) Test the scenario where the last fragment does not have write set
+# payload, just commit flag is replicated
+# 2) Test the scenario where the last fragment has write set payload
+# and commit flag
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+# Control connection for manipulating galera sync points
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+
+#########################################################################
+#
+# 1) Replay without commit fragment write set payload
+#
+#########################################################################
+
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+
+#
+# Block the commit from node_2
+#
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Issue conflicting UPDATE from node_2 and wait until it hits the
+# apply monitor (but does not apply yet)
+#
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Set a new sync point to block in local monitor on node_1 commit
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Send the commit on node_1
+#
+--connection node_1
+--send COMMIT
+
+#
+# Wait until commit reaches sync point
+#
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release conflicting slave transaction and wait until it has BF
+# aborted pending COMMIT
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = abort_trx_end local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release both threads, local thread will now replay
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+#
+# Commit must succeed
+#
+--connection node_1
+--reap
+
+
+#
+# Check the outcome and that wsrep schema SR table is empty
+#
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# wsrep_local_replays has increased by 1
+#
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DELETE FROM t1;
+
+#########################################################################
+#
+# 2) Replay with commit fragment write set payload
+#
+#########################################################################
+
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+
+#
+# Do first update SR on
+#
+UPDATE t1 SET f2 = 'x' WHERE f1 = 1;
+
+#
+# Disable SR for following statements
+#
+SET SESSION wsrep_trx_fragment_size = 0;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+
+#
+# Block the commit from node_2
+#
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Issue conflicting UPDATE from node_2 and wait until it hits the
+# apply monitor (but does not apply yet)
+#
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Set a new sync point to block in local monitor on node_1 commit
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+#
+# Send the commit on node_1
+#
+--connection node_1
+--send COMMIT
+
+#
+# Wait until commit reaches sync point
+#
+--connection node_1a
+SET SESSION wsrep_sync_wait = 0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release conflicting slave transaction and wait until it has BF
+# aborted pending COMMIT
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = abort_trx_end local_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+#
+# Release both threads, local thread will now replay
+#
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+
+--let $galera_sync_point = local_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+#
+# Commit must succeed
+#
+--connection node_1
+--reap
+
+
+#
+# Check the outcome and that wsrep schema SR table is empty
+#
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# wsrep_local_replays has increased by 1
+#
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 2 AS wsrep_local_replays;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DELETE FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test
new file mode 100644
index 00000000000..390d4c73ac1
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test
@@ -0,0 +1,47 @@
+#
+# Test wsrep_fragment_unit = statements
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 3;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+
+--connection node_1
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+
+# The table count on the slave should jump from 0
+--connection node_2
+--sleep 1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 0 FROM t1;
+
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+# to 3
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 3 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+INSERT INTO t1 VALUES (6);
+
+# and then to to 6
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 6 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt
new file mode 100644
index 00000000000..0b5f8bf7104
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt
@@ -0,0 +1 @@
+--log-bin-use-v1-row-events=1 --wsrep-trx-fragment-size=1
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test
new file mode 100644
index 00000000000..d3d4d2d0c14
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test
@@ -0,0 +1,27 @@
+#
+# Test that Galera SR continues to run even with --log-bin-use-v1-row-events=1
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+SELECT COUNT(*) = 1 FROM t1;
+
+--connection node_1
+COMMIT;
+
+SET AUTOCOMMIT=ON;
+UPDATE t1 SET f1 = 2 WHERE f1 = 1;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test b/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test
new file mode 100644
index 00000000000..98f6e796ef6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test
@@ -0,0 +1,70 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that SR transaction is cumulatively allowed to grow beyond repl.max_ws_size
+# if individual fragements are below that size
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+
+SET SESSION wsrep_trx_fragment_size = 512;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=4096';
+
+#
+# Create a transaction larger than repl.max_ws_size
+#
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1;
+
+#
+# We expect that the transaction can proceed successfully
+#
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 10 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+# Commit succeeds
+COMMIT;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 100 FROM t1;
+
+#
+# Cleanup
+#
+
+DROP TABLE t1;
+DROP TABLE ten;
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test b/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test
new file mode 100644
index 00000000000..2b9bc4819b8
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test
@@ -0,0 +1,62 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test that if wsrep_trx_fragment_size > repl.max_ws_size, no SR takes place and
+# the transaction is properly aborted.
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB;
+CREATE TABLE ten (f1 INTEGER);
+INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+
+SET SESSION wsrep_trx_fragment_size = 256;
+SET GLOBAL wsrep_provider_options='repl.max_ws_size=128';
+
+#
+# Create a transaction larger than repl.max_ws_size
+#
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+--error ER_ERROR_DURING_COMMIT,ER_ERROR_ON_WRITE,ER_BINLOG_ROW_LOGGING_FAILED
+INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1, ten AS a2;
+
+#
+# We expect that the transaction can not complete successfully
+#
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--sleep 2
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT COUNT(*) = 0 FROM t1;
+
+#
+# Cleanup
+#
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_trx_fragment_size = $wsrep_trx_fragment_size_orig;
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+DROP TABLE t1;
+DROP TABLE ten;
+
+call mtr.add_suppression('WSREP: SR rollback replication failure.*');
+call mtr.add_suppression('WSREP: transaction size limit.*');
+call mtr.add_suppression('WSREP: SR rbr write fail.*');
+call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*');
+call mtr.add_suppression('WSREP: transaction size exceeded.*');
+call mtr.add_suppression('WSREP: fragment replication failed:');
+call mtr.add_suppression('WSREP: post commit failed for SR rollback');
+call mtr.add_suppression('WSREP: pre_commit for SR rollback returned 2, thd:*');
+call mtr.add_suppression('WSREP: wsrep_rollback failed to send SR ROLLBACK for *');
diff --git a/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test
new file mode 100644
index 00000000000..8b8d7197c1c
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test
@@ -0,0 +1,37 @@
+#
+# Test option wsrep_ignore_apply_errors
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Delete row that does not exist using SR transaction
+#
+
+--connection node_2
+SET GLOBAL wsrep_ignore_apply_errors = 2;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER);
+INSERT INTO t1 VALUES (2);
+SET GLOBAL wsrep_on = OFF;
+INSERT INTO t1 VALUES (1);
+SET GLOBAL wsrep_on = ON;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (3);
+DELETE FROM t1 WHERE f1 = 1;
+DELETE FROM t1 WHERE f1 = 2;
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 1 FROM t1;
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+
+SET SESSION wsrep_trx_fragment_size = 0;
+DROP TABLE t1;
+
+SET GLOBAL wsrep_ignore_apply_errors = 7;
+CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event");
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test
new file mode 100644
index 00000000000..45c2b9514df
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test
@@ -0,0 +1,161 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the following sequence of events:
+#
+# 1. Node #1 begins a transaction
+# 2. Node #2 performs a conflicting insert
+# 3. Node #1 attempts to SR-replicate a conflicting transaction
+#
+
+# to sync node_1 appliers
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
+SET SESSION wsrep_trx_fragment_size = 2;
+SET SESSION wsrep_trx_fragment_unit = 'statements';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+#
+# processlist is good to see manually that applier reached sync point
+# but is not deterministic in testing, commenting out
+# SHOW PROCESSLIST;
+--connection node_1a
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_2
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+#
+# TODO: check here that applier is parked in the sync point
+#
+SELECT COUNT(*) = 0 FROM t1;
+INSERT INTO t1 VALUES (1);
+
+--connection node_1a
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK,ER_QUERY_INTERRUPTED
+INSERT INTO t1 VALUES (2);
+
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+#
+# Similar test with BYTES unit
+#
+--connection node_1
+TRUNCATE TABLE t1;
+
+SET SESSION wsrep_trx_fragment_size = 10;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+--connection node_1a
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_2
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+--send INSERT INTO t1 VALUES (1)
+#
+# WHY sleep here?
+# without this sleep, applier would be released with following signal
+# and applier would have chance to BF abort the SR trx.
+# We don't want this to happen, but instead let the SR trx to replicate
+# and notice the certification failure.
+# TODO: sleep is not good, this should be refactored somehow to guarantee
+# correct order for cert failure vs BF abort
+#
+--sleep 2
+
+--connection node_1a
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+INSERT INTO t1 VALUES (2);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 2 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+
+#
+# One more test with BYTES unit, but now fragment size is adjusted so
+# that second insert should trigger fragment replication.
+# Currently 200 bytes is good choice here, but this may change with
+# future MySQL versions.
+# => If this test fails after some MySQL merge, check if frgament size
+# needs to be tuned to spot at second insert statement.
+#
+--connection node_1
+TRUNCATE TABLE t1;
+
+SET SESSION wsrep_trx_fragment_size = 200;
+SET SESSION wsrep_trx_fragment_unit = 'bytes';
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_2
+INSERT INTO t1 VALUES (1);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM t1;
+
+INSERT INTO t1 VALUES (1);
+
+--send INSERT INTO t1 VALUES (2)
+#
+# WHY sleep here?
+# See above comment, same reason here
+#
+--sleep 2
+
+--connection node_1a
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET GLOBAL debug = '';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt
new file mode 100644
index 00000000000..03fcb5d040d
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt
@@ -0,0 +1 @@
+--log-slave-updates --log-bin
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test
new file mode 100644
index 00000000000..96736889cd5
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test
@@ -0,0 +1,37 @@
+# SR transactions are not binlogged #136
+
+--source include/galera_cluster.inc
+
+--connection node_1
+RESET MASTER;
+
+--connection node_2
+RESET MASTER;
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+COMMIT;
+
+SET SESSION wsrep_trx_fragment_size = 0;
+INSERT INTO t1 VALUES (3),(4);
+COMMIT;
+
+--connection node_1
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_2
+# Wait for all updates to arrive before dumping binlog
+SELECT COUNT(*) = 4 FROM t1;
+
+--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/
+--replace_column 2 <Pos> 5 <End_log_pos>
+SHOW BINLOG EVENTS IN '0.000001' FROM 120;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test
new file mode 100644
index 00000000000..2e67e730f79
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test
@@ -0,0 +1,25 @@
+# SR: two identical transactions have different value for the WSREP_FLAG_PA_UNSAFE flag
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+
+--connection node_2
+SELECT flags FROM wsrep_schema.SR;
+
+--connection node_1
+ROLLBACK;
+INSERT INTO t1 VALUES (3),(4);
+
+--connection node_2
+SELECT flags FROM wsrep_schema.SR;
+
+--connection node_1
+ROLLBACK;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test
new file mode 100644
index 00000000000..deeb890fa0b
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test
@@ -0,0 +1,21 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+
+COMMIT;
+
+DROP TABLE t1;
+
+--connection node_2
+--source include/galera_wait_ready.inc
+
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test
new file mode 100644
index 00000000000..5210b9ce99e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test
@@ -0,0 +1,60 @@
+# statement rollback for SR transaction causes slave crash for inconsistency
+
+# We test the following:
+# 1. Create a transaction that is blocked by an SR transaction
+# 2. Force the SR transaction to have a statement rollback
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (6),(7),(8),(9),(10),(1);
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads = 2;
+SET GLOBAL DEBUG = 'd,sync.wsrep_apply_cb';
+
+# Begin SR transaction
+--connection node_1
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+
+# Begin non-SR transaction that will block waiting for the SR transaction
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+--send INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+
+# Cause the SR transaction to fail with a duplicate key error
+--connection node_1
+--send INSERT INTO t1 SELECT * FROM t2;
+
+# Continue and commit the non-SR transaction.
+--connection node_1a
+--reap
+INSERT INTO t1 VALUES (6), (7), (8), (9), (10);
+COMMIT;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK,ER_DUP_ENTRY
+--reap
+
+--connection node_2
+SET GLOBAL wsrep_slave_threads = 1;
+SET GLOBAL DEBUG = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+
+SELECT COUNT(*) = 10 FROM t1;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test
new file mode 100644
index 00000000000..4aaff058b30
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test
@@ -0,0 +1,17 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (id INT) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc
new file mode 100644
index 00000000000..29755ab6c2e
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc
@@ -0,0 +1,104 @@
+# --source include/galera_cluster.inc
+# --source include/have_debug_sync.inc
+
+#
+# This test attempts to catch a race condition between autocommit
+# transaction and transaction which is rolling back due to
+# deadlock.
+#
+# Test outline:
+# * Trx 1a makes updates
+# * SR trx 1b writes a row 3, then makes updates
+# * AC trx 1c will attempt to write row 3 and will wait for lock
+# held by 1b
+# * Sync point is set for 1b to delay SR rollback
+# * SR trx 1b makes an update which makes it conflict with trx 1a
+# * Slave shows BF - BF conflict and fails in applying write event
+
+--connection node_1
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x');
+
+# --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+# --connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+# --connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+--connection node_1a
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'a' WHERE f1 = 1;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 4;
+UPDATE t1 SET f2 = 'a' WHERE f1 = 5;
+
+
+--connection node_1b
+START TRANSACTION;
+SET SESSION wsrep_trx_fragment_size = 1;
+INSERT INTO t1 VALUES (3, 'b');
+UPDATE t1 SET f2 = 'b' WHERE f1 = 2;
+
+--connection node_2
+SELECT * FROM t1;
+
+# Will block, waiting for 1b
+--connection node_1c
+SET AUTOCOMMIT=ON;
+--send INSERT INTO t1 VALUES (3, 'c')
+
+--connection node_2
+SELECT * FROM t1;
+
+# Will block, waiting for 1b
+--connection node_1a
+--send UPDATE t1 SET f2 = 'a' WHERE f1 = 2
+
+# Will deadlock
+--connection node_1b
+SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue';
+--send UPDATE t1 SET f2 = 'b' WHERE f1 = 1
+
+# Wait until 1b hits rollback
+--connection node_1
+SET DEBUG_SYNC = 'now WAIT_FOR wait';
+
+# UPDATE 12.06.2016: as of recent wsrep API changes, rollbacking thread no
+# longer queues ROLLBACKs and blocks on ROLLBACK replication before performing
+# the actual rollback. As a result this test is moot as both node_1a and node_1c
+# connections are hanging now until sync point is released. Thus sync point
+# release had to be moved above to release the connections. However it is not
+# impossible that further changes in the code may reintroduce the race, so
+# leaving the test as close to original as possible.
+#
+# --connection node_1a
+# --reap
+# COMMIT;
+#
+# --connection node_1c
+# --reap
+#
+# UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+
+--connection node_1
+SET DEBUG_SYNC = 'now SIGNAL continue';
+
+--connection node_1c
+--reap
+
+UPDATE t1 SET f2 = 'x' WHERE f1 = 3;
+
+--connection node_1a
+--reap
+COMMIT;
+
+--connection node_1b
+--error ER_LOCK_DEADLOCK
+--reap
+
+--connection node_1
+SELECT * FROM t1;
+--connection node_2
+SELECT * FROM t1;
+
+--connection node_1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test
new file mode 100644
index 00000000000..85d501288b0
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test
@@ -0,0 +1,41 @@
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+#
+# This test attempts to catch a race condition between autocommit
+# transaction and transaction which is rolling back due to
+# deadlock.
+#
+# Since it is trying to catch a race condition which may not reliably
+# occur, several runs are necessary for certainty. Hence the body of
+# the test was placed into the .inc file and sourced several times below
+#
+# Test outline:
+# * Trx 1a makes updates
+# * SR trx 1b writes a row 3, then makes updates
+# * AC trx 1c will attempt to write row 3 and will wait for lock
+# held by 1b
+# * Sync point is set for 1b to delay SR rollback
+# * SR trx 1b makes an update which makes it conflict with trx 1a
+# * Slave shows BF - BF conflict and fails in applying write event
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1
+
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
+--source mysql-wsrep-features#165.inc
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test
new file mode 100644
index 00000000000..99bbf505bf6
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test
@@ -0,0 +1,63 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction
+# We use SET GLOBAL wsrep_cluster_address = '' to cause the master (node_2) to temporarily
+# leave the cluster.
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+
+--connection node_2
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up
+#
+
+--connection node_2a
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+--sleep 2
+
+--connection node_2
+# Changing wsrep_cluster_address causes the server to drop all other
+# connections. Expect CR_SERVER_LOST error
+--error 2013
+INSERT INTO t1 VALUES (6);
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2a
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+
+--source include/galera_wait_ready.inc
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+
+DROP TABLE t1;
+
+CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test
new file mode 100644
index 00000000000..8c3dfb8b801
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test
@@ -0,0 +1,86 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Test the effect of Cluster Configuration Change on a concurrently-running
+# SR transaction. We use SET GLOBAL wsrep_cluster_address = '' to cause the
+# slave (node_2) to temporarily leave the cluster.
+#
+
+# Start with a clean slate
+--connection node_2
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+--connection node_1
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+--connection node_2
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+#
+# Trigger CC . The transaction should be able to continue
+#
+
+--connection node_2
+--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
+SET GLOBAL wsrep_cluster_address = '';
+--sleep 2
+
+--connection node_1
+# Continue generating events in the transaction
+
+INSERT INTO t1 VALUES (6);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (10);
+
+SELECT COUNT(*) > 0 FROM wsrep_schema.SR;
+
+# Restore cluster
+
+--connection node_2
+--disable_query_log
+--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1';
+--enable_query_log
+--sleep 2
+--source include/galera_wait_ready.inc
+
+# Confirm that the SR table still contains entries from ongoing transaction
+SELECT count(*) > 0 FROM wsrep_schema.SR;
+
+# Continue and finalize transaction
+--connection node_1
+INSERT INTO t1 VALUES (11);
+INSERT INTO t1 VALUES (12);
+INSERT INTO t1 VALUES (13);
+INSERT INTO t1 VALUES (14);
+INSERT INTO t1 VALUES (15);
+COMMIT;
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+# Confirm that transaction was replicated properly
+# and SR table is cleaned up afterwards.
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 15 FROM t1;
+--source include/wait_condition.inc
+
+SELECT COUNT(*) = 0 FROM wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test
new file mode 100644
index 00000000000..544109dadee
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test
@@ -0,0 +1,47 @@
+# Assertion `total_length + thd->wsrep_fragment_base == saved_pos' failed in wsrep_write_cache_inc() with ROLLBACK TO SAVEPOINT and SR
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+SET SESSION wsrep_trx_fragment_size=1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+INSERT INTO t1 VALUES (3, 'a');
+INSERT INTO t1 VALUES (4, 'a');
+INSERT INTO t1 VALUES (5, 'a');
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) = 5 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+SAVEPOINT s1;
+INSERT INTO t1 VALUES (11, 'b');
+INSERT INTO t1 VALUES (12, 'b');
+INSERT INTO t1 VALUES (13, 'b');
+INSERT INTO t1 VALUES (14, 'b');
+INSERT INTO t1 VALUES (15, 'b');
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 10 FROM t1;
+--source include/wait_condition.inc
+
+--connection node_1
+ROLLBACK TO SAVEPOINT s1;
+
+INSERT INTO t1 VALUES (21, 'c');
+
+COMMIT;
+
+--connection node_1
+SELECT COUNT(*) = 6 FROM t1;
+
+
+--connection node_2
+SELECT COUNT(*) = 6 FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test
new file mode 100644
index 00000000000..f9c09391f8f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test
@@ -0,0 +1,29 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_2
+--sleep 2
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test
new file mode 100644
index 00000000000..2349fe9979f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test
@@ -0,0 +1,23 @@
+#
+# mysql-wsrep-features#29 Unwarranted deadlock error with SR and a single-node cluster
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+SET SESSION binlog_format = STATEMENT;
+
+create table t1 (id int not null, f_id int not null, f int not null,
+primary key(f_id, id)) engine=innodb;
+
+create table t2 (id int not null,s_id int not null,s varchar(200),
+primary key(id)) engine=innodb;
+
+INSERT INTO t1 VALUES (8, 1, 3);
+INSERT INTO t1 VALUES (1, 2, 1);
+INSERT INTO t2 VALUES (1, 0, '');
+INSERT INTO t2 VALUES (8, 1, '');
+
+DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id)
+WHERE mm.id IS NULL;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt
new file mode 100644
index 00000000000..a6ef074a120
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt
@@ -0,0 +1 @@
+--innodb-lock-wait-timeout=1
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test
new file mode 100644
index 00000000000..72c7a7b5e82
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test
@@ -0,0 +1,44 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# mysql-wsrep-features#32 Assertion `meta->gtid.seqno == wsrep_thd_trx_seqno(thd)' failed in wsrep_commit_cb with SR
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+--let $wait_condition = SELECT COUNT(*) > 0 FROM t1;
+--source include/wait_condition.inc
+
+SET AUTOCOMMIT=OFF;
+
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (9);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (7);
+INSERT INTO t1 VALUES (6);
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 VALUES (5);
+ROLLBACK;
+
+--connection node_1
+COMMIT;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test
new file mode 100644
index 00000000000..ec78747949f
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test
@@ -0,0 +1,46 @@
+--source include/have_debug_sync.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+# Block node #2's applier so that it is able to issue a conflicting INSERT before
+# node #1 INSERTs have been applied on it.
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+SELECT COUNT(*) = 0 FROM t1;
+SET SESSION wsrep_sync_wait = 0;
+--let $debug_orig = `SELECT @@debug`
+SET GLOBAL debug = 'd,sync.wsrep_apply_cb';
+SET SESSION wsrep_sync_wait = 0;
+
+--connection node_1
+--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size`
+SET SESSION wsrep_trx_fragment_size = 1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (3);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (5);
+
+--connection node_2
+SET SESSION wsrep_sync_wait = 0;
+SELECT COUNT(*) = 0 FROM t1;
+--send INSERT INTO t1 VALUES (1);
+
+--connection node_1
+COMMIT;
+
+--connection node_2a
+SET GLOBAL debug = '';
+SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb';
+
+--connection node_2
+--error ER_DUP_ENTRY,ER_LOCK_DEADLOCK
+--reap
+ROLLBACK;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test
new file mode 100644
index 00000000000..55210386044
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test
@@ -0,0 +1,63 @@
+--source include/big_test.inc
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# InnoDB FULLTEXT indexes
+#
+
+SET SESSION wsrep_trx_fragment_size = 1;
+CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
+INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+#
+# Fulltext index creation causes the creation of multiple system tables
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
+
+--connection node_2
+SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%';
+
+#
+# Fulltext insertion causes a flurry of updates on those system tables
+#
+
+--connection node_1
+# Insert 10K rows
+INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
+
+--connection node_2
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz');
+
+UPDATE t1 SET f2 = 'abcdefjhk';
+
+--connection node_1
+SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk');
+
+--connection node_2
+
+DROP TABLE t1;
+
+#
+# Same on a table with no PK
+#
+
+--connection node_1
+CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB;
+
+--connection node_2
+# We insert only 1K rows here, because updates without a PK are very slow
+INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
+
+--connection node_1
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz');
+
+UPDATE t1 SET f1 = 'abcdefjhk';
+
+--connection node_2
+SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
+
+DROP TABLE t1;
+DROP TABLE ten;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test
new file mode 100644
index 00000000000..cbecf40fadf
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test
@@ -0,0 +1,44 @@
+#
+# mysql-wsrep-features#9 Hang in galera::ReplicatorSMM::cert with Streaming Replication
+# when running the galera_kill_ddl.test test
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/big_test.inc
+
+--connection node_1
+
+# Enable the master to continue running during the split-brain situation that
+# occurs when the slave is killed
+--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options`
+SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
+
+SET SESSION wsrep_trx_fragment_size = 1;
+
+CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
+
+--connection node_2
+--source include/kill_galera.inc
+
+--connection node_1
+ALTER TABLE t1 ADD COLUMN f2 INTEGER;
+
+--connection node_2
+--source include/start_mysqld.inc
+--source include/galera_wait_ready.inc
+
+--let $galera_connection_name = node_2a
+--let $galera_server_number = 2
+--source include/galera_connect.inc
+--connection node_2a
+
+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1';
+SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+
+--connection node_1
+--disable_query_log
+--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig';
+--enable_query_log
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test
new file mode 100644
index 00000000000..ba82473ae79
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test
@@ -0,0 +1,29 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# This test sets a SAVEPOINT at the very beginning
+# of the transaction. When ROLLBACK TO SAVEPOINT is
+# issued, mysql performs a full rollback on SEs that
+# where not part of the transaction.
+# Test that SR transactions are rolled back, and
+# cleaned up properly in this case.
+#
+
+CREATE TABLE t1 (f1 INTEGER);
+SET SESSION WSREP_TRX_FRAGMENT_SIZE=1;
+
+START TRANSACTION;
+
+SAVEPOINT a;
+INSERT INTO t1 VALUES (1);
+ROLLBACK TO SAVEPOINT a;
+
+INSERT INTO t1 values (2);
+COMMIT;
+
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+--connection node_2
+SELECT COUNT(*) = 0 from wsrep_schema.SR;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test
new file mode 100644
index 00000000000..c773b310183
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test
@@ -0,0 +1,45 @@
+# mysql-wsrep-features#96 - "Sanity check failed" with SR and statement rolled back due to error
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+
+--connection node_1
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+CREATE TABLE t2 (f2 VARCHAR(32));
+
+SET SESSION wsrep_trx_fragment_size=1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
+INSERT INTO t1 VALUES (1);
+
+# This statement causes full transaction rollback
+# rather than just statement rollback, as it is run under SR
+
+--error ER_LOCK_DEADLOCK
+INSERT INTO t1 VALUES (2),(1);
+INSERT INTO t2 VALUES ('abc');
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 1 FROM t2;
+
+--connection node_1
+ROLLBACK;
+
+--connection node_2
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+
+SELECT COUNT(*) = 0 FROM t1;
+SELECT COUNT(*) = 0 FROM t2;
+
+--connection node_1
+DROP TABLE t1;
+DROP TABLE t2;
+
+
+
+
diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result
index 47fc8e8b840..6ec5a72db25 100644
--- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result
@@ -118,7 +118,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a1
test/child a2
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -310,7 +310,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a1
test/child a2
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -336,7 +336,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a2
test/child a3
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -373,7 +373,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a1
test/child a2
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
@@ -410,7 +410,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati
name name
test/child a2
test/child a3
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
NAME
SYS_DATAFILES
SYS_FOREIGN
diff --git a/mysql-test/suite/innodb/t/galera.skip b/mysql-test/suite/innodb/t/galera.skip
new file mode 100644
index 00000000000..1991ce10cc4
--- /dev/null
+++ b/mysql-test/suite/innodb/t/galera.skip
@@ -0,0 +1,53 @@
+innodb : deadlock, failure in UPDATE IGNORE, lp1372296
+innodb_ctype_ldml : Test contains statements unsafe to replicate in statement-based replication
+innodb-autoinc : deadlock, failure in REPLACE, lp1372296
+innodb_mysql : deadlock due to DDL
+innodb_buffer_pool_load : Test contains statements unsafe to replicate in statement-based replication
+innodb-autoinc-56228 : deadlock, lp1372301
+innodb_lock_wait_timeout_1 : Test contains statements unsafe to replicate in statement-based replication
+innodb-consistent : Test contains statements unsafe to replicate in statement-based replication
+innodb-semi-consistent : Test contains statements unsafe to replicate in statement-based replication
+innodb-index : DDL concurrent with transaction
+innodb-lock : deadlock on INSERT IGNORE, lp1372296
+innodb-status-output : Test performs server restart
+innodb-wl5522 : Test contains statements unsafe to replicate in statement-based replication
+innodb-wl6445 : Test performs server restart
+innodb_bug40360 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug40565 : Galera git bug #137 - Invalid deadlock on UPDATE to NULL without a PK
+innodb_bug42419 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug49164 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug45357 : impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging
+innodb_bug52663 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug59733 : Test contains statements unsafe to replicate in statement-based replication
+innodb_gis : Test contains statements unsafe to replicate in statement-based replication
+innodb_prefix_index_restart_server : crash, lp1372288
+innodb_stats_external_pages : Test contains statements unsafe to replicate in statement-based replication
+innodb-2byte-collation : Unsafe statement written to the binary log
+innodb-change-buffer-recovery : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug53756 : Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT
+innodb-alter-autoinc : AUTO_INCREMENT differences
+innodb_bug13635833 : Test contains statements unsafe to replicate in statement-based replication
+innodb_bug13867871 : mysql-wsrep#3 - innodb_bug13867871 test fails with wsrep loaded
+innodb_bug14006907 : DDL lock wait timeout
+innodb_bug38231 : Deadlock on UNLOCK TABLE
+innodb_bug-13628249 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb-wl6445-1 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb-wl6445-2 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb_bug12400341 : Test does not account for applier threads when performing SHOW PROCESSLIST
+innodb-blob : 'Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging'
+innodb_corrupt_bit : 'Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'
+innodb-index-online : ALTER succeeds as it is given a higher priority
+innodb-table-online : ALTER succeeds as it is given a higher priority
+innodb-index-online-purge : ALTER succeeds as it is given a higher priority
+innodb-wl5522-debug : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.
+innodb_stats_table_flag_auto_recalc : Performs multiple restarts in a row which causes '1047: Unknown command' errors
+innodb-lock-inherit-read_commited : Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT
+innodb-index-debug : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT
+flush-hang : Unsafe statement written to the binary log
+innodb_deadlock_with_autoinc : Test uses autoinc_lock_mode = 0
+innodb_stats_del_mark : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.
+ibuf_not_empty : InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb_force_recovery : InnoDB: Failing assertion: !srv_read_only_mode with server restart
+innodb-system-table-view : Result depends on whether galera is loaded or not
+innodb-wl5980-linux : Fails because portability_wl5980_linux.zip does not contain wsrep_schema
+innodb-multiple-tablespaces : No changes to SR table are allowed if innodb-force-recovery > 0 \ No newline at end of file
diff --git a/mysql-test/suite/innodb/t/innodb-index-online-fk.test b/mysql-test/suite/innodb/t/innodb-index-online-fk.test
index 5c8954064ce..dd185a9843a 100644
--- a/mysql-test/suite/innodb/t/innodb-index-online-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-index-online-fk.test
@@ -105,7 +105,7 @@ SELECT * FROM information_schema.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
# this should succeed, since we disabled the foreign key check
INSERT INTO child VALUES(5,4);
@@ -287,7 +287,7 @@ SET DEBUG_DBUG = @saved_debug_dbug;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
# This should be successful. It will also check any left over
# from previous failed operation (if dictionary entries not cleaned,
@@ -300,7 +300,7 @@ ALGORITHM = INPLACE;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
SHOW CREATE TABLE child;
@@ -317,7 +317,7 @@ ALGORITHM = INPLACE;
SELECT * from information_schema.INNODB_SYS_FOREIGN;
SELECT * from information_schema.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
SHOW CREATE TABLE child;
@@ -333,7 +333,7 @@ ALGORITHM = INPLACE;
SELECT * from information_schema.INNODB_SYS_FOREIGN;
SELECT * from information_schema.INNODB_SYS_FOREIGN_COLS;
SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name;
-SELECT NAME FROM information_schema.INNODB_SYS_TABLES;
+SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%';
SHOW CREATE TABLE child;
diff --git a/packaging/deb-in/CMakeLists.txt b/packaging/deb-in/CMakeLists.txt
new file mode 100644
index 00000000000..aa14eb42425
--- /dev/null
+++ b/packaging/deb-in/CMakeLists.txt
@@ -0,0 +1,357 @@
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ RETURN()
+ENDIF()
+IF (NOT DEFINED DEB_CODENAME)
+ execute_process(
+ COMMAND lsb_release -cs
+ OUTPUT_VARIABLE DEB_CODENAME
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ SET (DEB_CODENAME ${DEB_CODENAME} CACHE STRING "")
+ENDIF()
+IF (DEFINED WITH_NDBCLUSTER_STORAGE_ENGINE)
+ SET (DEB_BASE_PRODUCT "cluster-")
+ SET (DEB_BASE_PRODUCTC "Cluster ")
+ SET (DEB_BASE_VERSION ${NDBVERSION})
+ SET (DEB_CONTROL_SERVER_CONFLICT_NDB "mysql-community-server, mysql-commercial-server")
+ SET (DEB_CONTROL_CLIENT_CONFLICT_NDB "mysql-community-client, mysql-commercial-client")
+ELSE()
+ SET (DEB_BASE_PRODUCT "")
+ SET (DEB_BASE_PRODUCTC "")
+ SET (DEB_BASE_VERSION ${VERSION})
+ SET (DEB_CONTROL_SERVER_CONFLICT_NDB "mysql-cluster-community-server, mysql-cluster-commercial-server")
+ SET (DEB_CONTROL_CLIENT_CONFLICT_NDB "mysql-cluster-community-client, mysql-cluster-commercial-client")
+ENDIF()
+
+SET (DEB_BASE_VERSION "${DEB_BASE_VERSION}-${WSREP_VERSION}")
+
+# Commercial or community
+IF (DEB_PRODUCT STREQUAL "commercial")
+ message (FATAL_ERROR "mysql-wsrep is GPL only, no commercial builds")
+ SET (DEB_COPYRIGHT_UPSTREAMNAME "MySQL Commercial Server ${MYSQL_BASE_VERSION}")
+ SET (DEB_PRODUCTNAME "${DEB_BASE_PRODUCT}commercial")
+ SET (DEB_PRODUCTNAMEC "${DEB_BASE_PRODUCTC}Commercial")
+ SET (DEB_NOTPRODUCTNAME "${DEB_BASE_PRODUCT}community")
+ SET (DEB_LICENSENAME "Advanced")
+ SET (DEB_INSTALL_LICENSEFILE "LICENSE.mysql")
+ SET (DEB_SERVERVERSION "${DEB_BASE_VERSION}+commercial.1")
+ SET (DEB_PLUGIN_SETPERMISSION "")
+ SET (DEB_MAN_SETPERMISSION "")
+ # List of plugins that are only in commercial packages
+ # Plugins that are in both community and commercial should NOT be added here
+ SET (DEB_INCLUDE_BINARIES_EXTRA
+"
+debian/extra/audit_log-plugin
+debian/extra/authentication_pam-plugin
+debian/extra/firewall-plugin
+debian/extra/openssl_udf-plugin
+debian/extra/thread_pool-plugin
+")
+ SET (DEB_INSTALL_SERVER_PLUGINS
+"
+usr/lib/mysql/plugin/audit_log.so
+usr/lib/mysql/plugin/authentication_pam.so
+usr/lib/mysql/plugin/openssl_udf.so
+usr/lib/mysql/plugin/thread_pool.so
+usr/lib/mysql/plugin/firewall.so
+usr/lib/mysql/plugin/debug/audit_log.so
+usr/lib/mysql/plugin/debug/authentication_pam.so
+usr/lib/mysql/plugin/debug/keyring_okv.so
+usr/lib/mysql/plugin/debug/openssl_udf.so
+usr/lib/mysql/plugin/debug/thread_pool.so
+usr/lib/mysql/plugin/debug/firewall.so
+")
+ SET (DEB_REMOVEPATTERN "gpl.in")
+ELSE()
+ SET (DEB_PRODUCT "${DEB_BASE_PRODUCT}community")
+ SET (DEB_COPYRIGHT_UPSTREAMNAME "MySQL Server ${MYSQL_BASE_VERSION}")
+ SET (DEB_PRODUCTNAME "${DEB_BASE_PRODUCT}community")
+ SET (DEB_PRODUCTNAMEC "${DEB_BASE_PRODUCTC}Community")
+ SET (DEB_NOTPRODUCTNAME "${DEB_BASE_PRODUCT}commercial")
+ SET (DEB_LICENSENAME "GPL")
+ SET (DEB_INSTALL_LICENSEFILE "COPYING")
+ SET (DEB_SERVERVERSION "${DEB_BASE_VERSION}+1")
+ SET (DEB_REMOVEPATTERN "com.in")
+ SET (DEB_PLUGIN_SETPERMISSION "usr/bin/mysql_setpermission")
+ SET (DEB_MAN_SETPERMISSION "usr/share/man/man1/mysql_setpermission.1")
+ENDIF()
+
+# mysql-wsrep !
+SET (DEB_PRODUCTNAME "wsrep")
+SET (DEB_PRODUCTNAMEC "Wsrep")
+SET (DEB_PRODUCTSERIES "-5.6")
+SET (DEB_WSREP_README "README-wsrep")
+
+
+SET (FILES_STARTUP_SYSV
+"
+etc/init.d/mysql
+usr/bin/mysqld_safe
+")
+SET (FILES_STARTUP_UPSTART
+"
+Not Yet Implememted: Upstart File List
+")
+
+# Platform specifics. The differences are generally only distro version
+# and whether or not Systemd and/or apparmor are available
+IF (DEB_CODENAME STREQUAL "wheezy")
+ SET (DEB_PLATFORMRELEASE "debian7")
+ # Following the Oracle example, we package for Debian 7
+ # using only SysV init and no Apparmor.
+ SET (DEB_CONTROL_BDEPS "")
+ SET (DEB_INSTALL_SOURCE_XZ "")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR "")
+ SET (DEB_RULES_APPARMOR_LOAD "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "jessie")
+ SET (DEB_PLATFORMRELEASE "debian8")
+ # Improving on Oracle, we would prefer to package for Debian 8
+ # using both SysV init and Systemd, but still no Apparmor.
+ SET (DEB_CONTROL_BDEPS "")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR "")
+ SET (DEB_RULES_APPARMOR_LOAD "")
+ SET (DEB_SYSTEMD_SERVICE_NAME "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "")
+ # Debian 8 comes with both SysV init and Systemd,
+ # but "scripts/CMakeLists.txt" enforces an either-or.
+ SET (DEB_STARTUP "SYSV")
+ # For now, we go with Systemd only.
+ELSEIF(DEB_CODENAME STREQUAL "stretch")
+ SET (DEB_PLATFORMRELEASE "debian9")
+ SET (DEB_CONTROL_BDEPS "")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR "")
+ SET (DEB_RULES_APPARMOR_LOAD "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_INIT_APPARMOR "")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "precise")
+ SET (DEB_PLATFORMRELEASE "ubuntu12.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor")
+ SET (DEB_INSTALL_SOURCE_XZ "")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "trusty")
+ SET (DEB_PLATFORMRELEASE "ubuntu14.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor")
+ SET (DEB_INSTALL_SOURCE_XZ "")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "wily")
+ SET (DEB_PLATFORMRELEASE "ubuntu15.10")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD
+ "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-community-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_SYSTEMD_SERVICE_NAME "mysql")
+ SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --no-enable --name=mysql")
+ SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE
+ "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre")
+ SET (DEB_SERVICE_SERVER_EXECPOST
+ "ExecStartPost=/usr/share/mysql/mysql-systemd-start post")
+ SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSTEMD")
+ELSEIF(DEB_CODENAME STREQUAL "xenial")
+ SET (DEB_PLATFORMRELEASE "ubuntu16.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD "")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_SYSTEMD_SERVICE_NAME "")
+ SET (DEB_RULES_SYSTEMD_ENABLE "")
+ SET (DEB_RULES_SYSTEMD_START "")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE "")
+ SET (DEB_SERVICE_SERVER_EXECPOST "")
+ SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSV")
+ELSEIF(DEB_CODENAME STREQUAL "yakkety")
+ SET (DEB_PLATFORMRELEASE "ubuntu16.10")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD
+ "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_SYSTEMD_SERVICE_NAME "mysql")
+ SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --no-enable --name=mysql")
+ SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE
+ "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre")
+ SET (DEB_SERVICE_SERVER_EXECPOST
+ "ExecStartPost=/usr/share/mysql/mysql-systemd-start post")
+ SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld")
+ SET (DEB_STARTUP "SYSTEMD")
+ELSEIF(DEB_CODENAME STREQUAL "zesty")
+ SET (DEB_PLATFORMRELEASE "ubuntu17.04")
+ SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)")
+ SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/")
+ SET (DEB_RULES_INSTALL_SYSTEMD
+ "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/")
+ SET (DEB_RULES_INSTALL_APPARMOR
+ "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_RULES_APPARMOR_LOAD
+ "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld")
+ SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --name=mysql")
+ SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade")
+ SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start")
+ SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld")
+ SET (DEB_SERVICE_SERVER_EXECPRE
+ "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre")
+ SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld")
+ELSE()
+ MESSAGE(STATUS
+ "Skipping deb packaging on unsupported platform ${DEB_CODENAME}.")
+ RETURN()
+ENDIF()
+
+# All files are configured and copied to the debian/ directory, which is used
+# by debuild to make the packages
+# 5.7.11 builds out-of-source. Hack: have duplicate debian/
+SET (DEB_ROOT ${CMAKE_SOURCE_DIR}/packaging/deb-in)
+FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/debian)
+FILE(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/debian)
+FILE(GLOB_RECURSE SOURCEFILES RELATIVE "${DEB_ROOT}" "${DEB_ROOT}/*")
+# Skip the copyright file from the "other" product type
+LIST(REMOVE_ITEM SOURCEFILES "copyright.${DEB_REMOVEPATTERN}")
+LIST(REMOVE_ITEM SOURCEFILES "CMakeLists.txt")
+# Combine the list of all startup files to be included,
+# skip Debian magical init files unless needed
+IF(DEB_PRODUCTNAME STREQUAL "wsrep")
+ SET(COMMON_WSREP_CONFLICTS "mysql-common (>= 5.7)")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.install.in")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.dirs.in")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.postinst.in")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-common.postrm.in")
+ENDIF()
+IF(DEB_STARTUP MATCHES ".*SYSV.*")
+ SET (DEB_FILES_STARTUP ${FILES_STARTUP_SYSV})
+ELSE()
+ LIST(REMOVE_ITEM SOURCEFILES
+ "mysql-packagesource-server-SERIES.mysql.init.in")
+ENDIF()
+IF(DEB_STARTUP MATCHES ".*SYSTEMD.*")
+ SET (DEB_FILES_STARTUP
+ ${DEB_FILES_STARTUP}
+ ${FILES_STARTUP_SYSTEMD})
+ELSE()
+ LIST(REMOVE_ITEM SOURCEFILES
+ "mysql-packagesource-server-SERIES.mysql.service.in")
+ENDIF()
+# Don't install systemd file on systems without systemd
+IF(DEB_INSTALL_SERVER_SYSTEMD STREQUAL "")
+ LIST(REMOVE_ITEM SOURCEFILES "mysql-packagesource-server.mysql.service.in")
+ENDIF()
+
+FOREACH (SOURCEFILE ${SOURCEFILES})
+ STRING(REGEX REPLACE "-packagesource-" "-${DEB_PRODUCTNAME}-"
+ TMPFILE ${SOURCEFILE})
+ STRING(REGEX REPLACE "-SERIES" "${DEB_PRODUCTSERIES}" TMPFILE ${TMPFILE})
+ # Strip away the input file endings from the destination filenames
+ STRING(REGEX REPLACE ".in$" "" TMPFILE ${TMPFILE})
+ STRING(REGEX REPLACE ".gpl$" "" TMPFILE ${TMPFILE})
+ STRING(REGEX REPLACE ".com$" "" DESTFILE ${TMPFILE})
+ CONFIGURE_FILE("${DEB_ROOT}/${SOURCEFILE}"
+ "${CMAKE_BINARY_DIR}/debian/${DESTFILE}" @ONLY)
+ CONFIGURE_FILE("${DEB_ROOT}/${SOURCEFILE}"
+ "${CMAKE_SOURCE_DIR}/debian/${DESTFILE}" @ONLY)
+ENDFOREACH()
+EXECUTE_PROCESS(
+ COMMAND chmod +x ${CMAKE_BINARY_DIR}/debian/rules
+)
+IF(DEB_PRODUCTNAME STREQUAL "wsrep")
+FILE(APPEND "${CMAKE_BINARY_DIR}/debian/control" "
+Package: mysql-common
+Architecture: any
+Pre-depends: debconf (>= 0.2.17),
+ \${misc:Pre-Depends}
+Multi-Arch: foreign
+Depends: \${misc:Depends},
+ \${shlibs:Depends},
+ mysql-wsrep-common
+Description: MySQL Common
+ The MySQL(TM) software delivers a very fast, multi-threaded, multi-user,
+ and robust SQL (Structured Query Language) database server. MySQL Server
+ is intended for mission-critical, heavy-load production systems as well
+ as for embedding into mass-deployed software. MySQL is a trademark of
+ Oracle. This package contains common files needed by MySQL client
+ library and the MySQL database server.
+ This package is a dummy replacement for the case when using mysql WSREP
+ implementation to satisfy dependencies of other packages
+ like libmysqlclient18. It depends on any mysql-wsrep-common
+")
+ENDIF()
diff --git a/plugin/wsrep_info/plugin.cc b/plugin/wsrep_info/plugin.cc
index 428bcc5dcfc..ab871e81ed6 100644
--- a/plugin/wsrep_info/plugin.cc
+++ b/plugin/wsrep_info/plugin.cc
@@ -202,9 +202,11 @@ static int wsrep_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond)
->store(view.state_id.seqno, 0);
table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID]->store(view.view, 0);
+#ifdef OLD_MARIADB
const char *gap= (view.state_gap == true) ? "YES" : "NO";
table->field[COLUMN_WSREP_STATUS_GAP]->store(gap, strlen(gap),
system_charset_info);
+#endif
table->field[COLUMN_WSREP_STATUS_PROTO_VERSION]->store(view.proto_ver, 0);
if (schema_table_store_record(thd, table))
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 5797bdc68d7..5f09ac3c235 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -265,7 +265,16 @@ wsrep_recover_position() {
wsrep_start_position_opt="--wsrep_start_position=$start_pos"
fi
- [ $ret -eq 0 ] && rm $wr_logfile
+ if [ $ret -eq 0 ] ; then
+ local wr_logfile_permanent="$DATADIR/wsrep_recovery.ok"
+ else
+ local wr_logfile_permanent="$DATADIR/wsrep_recovery.fail"
+ fi
+ touch $wr_logfile_permanent
+ [ "$euid" = "0" ] && chown $user $wr_logfile_permanent
+ chmod 600 $wr_logfile_permanent
+ cat "$wr_logfile" >> $wr_logfile_permanent
+ rm -f "$wr_logfile"
return $ret
}
diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh
index faa3f10639b..10663216ca5 100644
--- a/scripts/wsrep_sst_mysqldump.sh
+++ b/scripts/wsrep_sst_mysqldump.sh
@@ -25,6 +25,7 @@ EINVAL=22
local_ip()
{
[ "$1" = "127.0.0.1" ] && return 0
+ [ "$1" = "127.0.0.2" ] && return 0
[ "$1" = "localhost" ] && return 0
[ "$1" = "[::1]" ] && return 0
[ "$1" = "$(hostname -s)" ] && return 0
diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh
index 79442d415e9..7f19131d0fe 100644
--- a/scripts/wsrep_sst_xtrabackup-v2.sh
+++ b/scripts/wsrep_sst_xtrabackup-v2.sh
@@ -647,7 +647,7 @@ wait_for_listen()
local HOST=$1
local PORT=$2
local MODULE=$3
- local LSOF_OUT
+ #local LSOF_OUT
for i in {1..300}
do
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 0037ff23153..8d5f0c1ce2d 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -18,17 +18,23 @@
IF(WITH_WSREP AND NOT EMBEDDED_LIBRARY)
SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep)
SET(WSREP_SOURCES
+ wsrep_utils.cc
+ wsrep_xid.cc
wsrep_check_opts.cc
- wsrep_hton.cc
- wsrep_mysqld.cc
+ wsrep_mysqld.cc
wsrep_notify.cc
wsrep_sst.cc
- wsrep_utils.cc
wsrep_var.cc
wsrep_binlog.cc
wsrep_applier.cc
wsrep_thd.cc
- wsrep_xid.cc
+ wsrep_sr_file.cc
+ wsrep_sr_table.cc
+ wsrep_thd_pool.cc
+ wsrep_schema.cc
+ wsrep_sr.cc
+ wsrep_trans_observer.cc
+ wsrep_plugin.cc
)
SET(WSREP_LIB wsrep)
ELSE()
@@ -42,7 +48,6 @@ ${PCRE_INCLUDES}
${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}/sql
-${WSREP_INCLUDES}
)
diff --git a/sql/events.cc b/sql/events.cc
index af020d5240e..6b8aad4f1d1 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -341,7 +341,6 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
DBUG_RETURN(TRUE);
-
if (check_db_dir_existence(parse_data->dbname.str))
{
my_error(ER_BAD_DB_ERROR, MYF(0), parse_data->dbname.str);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 262e791ec7a..61420e7ff25 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -405,6 +405,13 @@ const char *ha_partition::table_type() const
// we can do this since we only support a single engine type
return m_file[0]->table_type();
}
+#ifdef WITH_WSREP
+int ha_partition::wsrep_db_type() const
+{
+ // we can do this since we only support a single engine type
+ return ha_legacy_type(m_file[0]->ht);
+}
+#endif /* WITH_WSREP */
/*
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 8a251016703..79ef6355812 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1505,5 +1505,8 @@ public:
friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2);
friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2);
+#ifdef WITH_WSREP
+ virtual int wsrep_db_type() const;
+#endif /* WITH_WSREP */
};
#endif /* HA_PARTITION_INCLUDED */
diff --git a/sql/handler.cc b/sql/handler.cc
index b3481c7e429..cb3f156be81 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -55,6 +55,12 @@
#include "wsrep_mysqld.h"
#include "wsrep.h"
#include "wsrep_xid.h"
+#ifdef WITH_WSREP
+#include "wsrep_sr.h"
+#endif
+#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
+#include "log.h"
/*
While we have legacy_db_type, we have this array to
@@ -1168,8 +1174,8 @@ static int prepare_or_error(handlerton *ht, THD *thd, bool all)
{
/* avoid sending error, if we're going to replay the transaction */
#ifdef WITH_WSREP
- if (ht != wsrep_hton ||
- err == EMSGSIZE || thd->wsrep_conflict_state != MUST_REPLAY)
+ if (ht->db_type != DB_TYPE_UNKNOWN ||
+ err == EMSGSIZE || thd->wsrep_conflict_state() != MUST_REPLAY)
#endif
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
}
@@ -1248,6 +1254,18 @@ ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
{
+#ifdef WITH_WSREP
+ /*
+ Thd has wsrep_schema.SR open and may operate it
+ during prepare phase, set InnoDB ha_info read_write.
+ */
+ if (WSREP_CLIENT(thd) && thd->wsrep_is_streaming() &&
+ wsrep_SR_store && wsrep_SR_store_type == WSREP_SR_STORE_TABLE &&
+ ha_info->ht()->db_type == DB_TYPE_INNODB)
+ {
+ ha_info->set_trx_read_write();
+ }
+#endif /* WITH_WSREP */
if (ha_info->is_trx_read_write())
++rw_ha_count;
@@ -1460,6 +1478,13 @@ int ha_commit_trans(THD *thd, bool all)
need_prepare_ordered= FALSE;
need_commit_ordered= FALSE;
xid= thd->transaction.xid_state.xid.get_my_xid();
+#ifdef WITH_WSREP
+ if (WSREP(thd) && wsrep_before_prepare(thd, all))
+ {
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT);
+ goto wsrep_err;
+ }
+#endif /* WITH_WSREP */
for (Ha_trx_info *hi= ha_info; hi; hi= hi->next())
{
@@ -1483,6 +1508,13 @@ int ha_commit_trans(THD *thd, bool all)
}
DEBUG_SYNC(thd, "ha_commit_trans_after_prepare");
DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE(););
+#ifdef WITH_WSREP
+ if (WSREP(thd) && wsrep_after_prepare(thd, all))
+ {
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT);
+ goto err;
+ }
+#endif /* WITH_WSREP */
#ifdef WITH_WSREP
if (!error && WSREP_ON && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid))
@@ -1502,13 +1534,29 @@ int ha_commit_trans(THD *thd, bool all)
cookie= tc_log->log_and_order(thd, xid, all, need_prepare_ordered,
need_commit_ordered);
if (!cookie)
+ {
+ WSREP_DEBUG("log_and_order has failed %lu %d", thd->thread_id, cookie);
goto err;
+ }
DEBUG_SYNC(thd, "ha_commit_trans_after_log_and_order");
DBUG_EXECUTE_IF("crash_commit_after_log", DBUG_SUICIDE(););
error= commit_one_phase_2(thd, all, trans, is_real_trans) ? 2 : 0;
-
+#ifdef WITH_WSREP
+ if (error)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_exec_mode == LOCAL_COMMIT &&
+ thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ (void)tc_log->unlog(cookie, xid);
+ goto wsrep_err;
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+}
+#endif /* WITH_WSREP */
DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
if (tc_log->unlog(cookie, xid))
{
@@ -1530,6 +1578,20 @@ done:
goto end;
/* Come here if error and we need to rollback. */
+#ifdef WITH_WSREP
+ wsrep_err:
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_exec_mode == LOCAL_COMMIT &&
+ thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ WSREP_DEBUG("BF abort has happened after prepare & certify");
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ ha_rollback_trans(thd, TRUE);
+ }
+ else
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+#endif /* WITH_WSREP */
err:
error= 1; /* Transaction was rolled back */
/*
@@ -1539,7 +1601,10 @@ err:
*/
if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec))
ha_rollback_trans(thd, all);
-
+ else
+ {
+ WSREP_DEBUG("WTF, rollback skipped %d %d",thd->rgi_slave, thd->rgi_slave->is_parallel_exec);
+ }
end:
if (rw_trans && mdl_request.ticket)
{
@@ -1673,7 +1738,6 @@ int ha_rollback_trans(THD *thd, bool all)
*/
DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
trans == &thd->transaction.stmt);
-
#ifdef HAVE_REPLICATION
if (is_real_trans)
{
@@ -1708,6 +1772,9 @@ int ha_rollback_trans(THD *thd, bool all)
DBUG_RETURN(1);
}
+#ifdef WITH_WSREP
+ (void) wsrep_before_rollback(thd, all);
+#endif // WITH_WSREP
if (ha_info)
{
/* Close all cursors that can not survive ROLLBACK */
@@ -1723,9 +1790,9 @@ int ha_rollback_trans(THD *thd, bool all)
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
#ifdef WITH_WSREP
- WSREP_WARN("handlerton rollback failed, thd %llu %lld conf %d SQL %s",
- thd->thread_id, thd->query_id, thd->wsrep_conflict_state,
- thd->query());
+ WSREP_WARN("handlerton rollback failed, thd %lld %lld conf %d SQL %s",
+ thd->thread_id, thd->query_id, thd->wsrep_conflict_state(),
+ thd->query());
#endif /* WITH_WSREP */
}
status_var_increment(thd->status_var.ha_rollback_count);
@@ -1744,6 +1811,15 @@ int ha_rollback_trans(THD *thd, bool all)
thd->transaction.xid_state.xa_state != XA_NOTR)
thd->transaction.xid_state.rm_error= thd->get_stmt_da()->sql_errno();
+#ifdef WITH_WSREP
+ if (thd->is_error())
+ {
+ WSREP_DEBUG("ha_rollback_trans(%lld, %s) rolled back: %s: %s; is_real %d",
+ thd->thread_id, all?"TRUE":"FALSE", WSREP_QUERY(thd),
+ thd->get_stmt_da()->message(), is_real_trans);
+ }
+ (void) wsrep_after_rollback(thd, all);
+#endif
/* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
{
@@ -2296,6 +2372,14 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
{
int err;
handlerton *ht= ha_info->ht();
+#ifdef WITH_WSREP
+ if (ht->db_type == DB_TYPE_INNODB)
+ {
+ WSREP_DEBUG("ha_rollback_to_savepoint: run before_rollbackha_rollback_trans hook");
+ (void) wsrep_before_rollback(thd, !thd->in_sub_stmt);
+
+ }
+#endif // WITH_WSREP
if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
{ // cannot happen
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
@@ -6021,6 +6105,16 @@ static int binlog_log_row_internal(TABLE* table,
bool error= 0;
THD *const thd= table->in_use;
+#ifdef WITH_WSREP
+ /* only InnoDB tables will be replicated through binlog emulation */
+ if (WSREP_EMULATE_BINLOG(thd) &&
+ table->file->ht->db_type != DB_TYPE_INNODB &&
+ !(table->file->ht->db_type == DB_TYPE_PARTITION_DB &&
+ (((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB)))
+ {
+ return 0;
+ }
+#endif /* WITH_WSREP */
/*
If there are no table maps written to the binary log, this is
the first row handled in this statement. In that case, we need
@@ -6055,20 +6149,6 @@ int binlog_log_row(TABLE* table, const uchar *before_record,
table->file->partition_ht()->db_type != DB_TYPE_INNODB) ||
(thd->wsrep_ignore_table == true))
return 0;
-
- /* enforce wsrep_max_ws_rows */
- if (WSREP(thd) && table->s->tmp_table == NO_TMP_TABLE)
- {
- thd->wsrep_affected_rows++;
- if (wsrep_max_ws_rows &&
- thd->wsrep_exec_mode != REPL_RECV &&
- thd->wsrep_affected_rows > wsrep_max_ws_rows)
- {
- trans_rollback_stmt(thd) || trans_rollback(thd);
- my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
- return ER_ERROR_DURING_COMMIT;
- }
- }
#endif
if (!table->file->check_table_binlog_row_based(1))
@@ -6180,6 +6260,31 @@ int handler::ha_reset()
DBUG_RETURN(reset());
}
+#ifdef WITH_WSREP
+static int wsrep_after_row(THD *thd)
+{
+ DBUG_ENTER("wsrep_after_row");
+ /* enforce wsrep_max_ws_rows */
+ thd->wsrep_affected_rows++;
+ if (wsrep_max_ws_rows &&
+ thd->wsrep_exec_mode != REPL_RECV &&
+ thd->wsrep_affected_rows > wsrep_max_ws_rows)
+ {
+ trans_rollback_stmt(thd) || trans_rollback(thd);
+ my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
+ DBUG_RETURN(ER_ERROR_DURING_COMMIT);
+ }
+ else if (wsrep_after_row(thd, false))
+ {
+ if (!thd->get_stmt_da()->is_error())
+ {
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ }
+ DBUG_RETURN(ER_LOCK_DEADLOCK);
+ }
+ DBUG_RETURN(0);
+}
+#endif /* WITH_WSREP */
int handler::ha_write_row(uchar *buf)
{
@@ -6202,7 +6307,16 @@ int handler::ha_write_row(uchar *buf)
{
rows_changed++;
error= binlog_log_row(table, 0, buf, log_func);
+#ifdef WITH_WSREP
+ THD *thd= current_thd;
+ if (table_share->tmp_table == NO_TMP_TABLE &&
+ WSREP(thd) && (error= wsrep_after_row(thd)))
+ {
+ DBUG_RETURN(error);
+ }
+#endif /* WITH_WSREP */
}
+
DEBUG_SYNC_C("ha_write_row_end");
DBUG_RETURN(error);
}
@@ -6234,6 +6348,14 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
{
rows_changed++;
error= binlog_log_row(table, old_data, new_data, log_func);
+#ifdef WITH_WSREP
+ THD *thd= current_thd;
+ if (table_share->tmp_table == NO_TMP_TABLE &&
+ WSREP(thd) && (error= wsrep_after_row(thd)))
+ {
+ return error;
+ }
+#endif /* WITH_WSREP */
}
return error;
}
@@ -6289,6 +6411,14 @@ int handler::ha_delete_row(const uchar *buf)
{
rows_changed++;
error= binlog_log_row(table, buf, 0, log_func);
+#ifdef WITH_WSREP
+ THD *thd= current_thd;
+ if (table_share->tmp_table == NO_TMP_TABLE &&
+ WSREP(thd) && (error= wsrep_after_row(thd)))
+ {
+ return error;
+ }
+#endif /* WITH_WSREP */
}
return error;
}
@@ -6494,51 +6624,15 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal)
DBUG_RETURN(0);
}
-
void ha_fake_trx_id(THD *thd)
{
- DBUG_ENTER("ha_fake_trx_id");
-
- bool no_fake_trx_id= true;
-
- if (!WSREP(thd))
- {
- DBUG_VOID_RETURN;
- }
-
- if (thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID)
+ DBUG_ENTER("ha_wsrep_fake_trx_id");
+ if (!WSREP(thd))
{
- WSREP_DEBUG("fake trx id skipped: %lu", thd->wsrep_ws_handle.trx_id);
DBUG_VOID_RETURN;
}
- /* Try statement transaction if standard one is not set. */
- THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all :
- &thd->transaction.stmt;
-
- Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
-
- for (; ha_info; ha_info= ha_info_next)
- {
- handlerton *hton= ha_info->ht();
- if (hton->fake_trx_id)
- {
- hton->fake_trx_id(hton, thd);
-
- /* Got a fake trx id. */
- no_fake_trx_id= false;
-
- /*
- We need transaction ID from just one storage engine providing
- fake_trx_id (which will most likely be the case).
- */
- break;
- }
- ha_info_next= ha_info->next();
- }
-
- if (unlikely(no_fake_trx_id))
- WSREP_WARN("Cannot get fake transaction ID from storage engine.");
+ (void *)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, thd->query_id);
DBUG_VOID_RETURN;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index d9b007d4728..f183076ad84 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -3193,6 +3193,45 @@ protected:
};
#endif
+#ifdef WITH_WSREP
+class Create_func_wsrep_last_written_gtid : public Create_func_arg0
+{
+public:
+ virtual Item *create_builder(THD *thd);
+
+ static Create_func_wsrep_last_written_gtid s_singleton;
+
+protected:
+ Create_func_wsrep_last_written_gtid() {}
+ virtual ~Create_func_wsrep_last_written_gtid() {}
+};
+
+
+class Create_func_wsrep_last_seen_gtid : public Create_func_arg0
+{
+public:
+ virtual Item *create_builder(THD *thd);
+
+ static Create_func_wsrep_last_seen_gtid s_singleton;
+
+protected:
+ Create_func_wsrep_last_seen_gtid() {}
+ virtual ~Create_func_wsrep_last_seen_gtid() {}
+};
+
+
+class Create_func_wsrep_sync_wait_upto : public Create_native_func
+{
+public:
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
+
+ static Create_func_wsrep_sync_wait_upto s_singleton;
+
+protected:
+ Create_func_wsrep_sync_wait_upto() {}
+ virtual ~Create_func_wsrep_sync_wait_upto() {}
+};
+#endif /* WITH_WSREP */
#ifdef HAVE_SPATIAL
class Create_func_x : public Create_func_arg1
@@ -6886,6 +6925,63 @@ Create_func_within::create_2_arg(THD *thd, Item *arg1, Item *arg2)
}
#endif
+#ifdef WITH_WSREP
+Create_func_wsrep_last_written_gtid
+Create_func_wsrep_last_written_gtid::s_singleton;
+
+Item*
+Create_func_wsrep_last_written_gtid::create_builder(THD *thd)
+{
+ current_thd->lex->safe_to_cache_query= 0;
+ return new (thd->mem_root) Item_func_wsrep_last_written_gtid(thd);
+}
+
+
+Create_func_wsrep_last_seen_gtid
+Create_func_wsrep_last_seen_gtid::s_singleton;
+
+Item*
+Create_func_wsrep_last_seen_gtid::create_builder(THD *thd)
+{
+ current_thd->lex->safe_to_cache_query= 0;
+ return new (thd->mem_root) Item_func_wsrep_last_seen_gtid(thd);
+}
+
+
+Create_func_wsrep_sync_wait_upto
+Create_func_wsrep_sync_wait_upto::s_singleton;
+
+Item*
+Create_func_wsrep_sync_wait_upto::create_native(THD *thd,
+ LEX_CSTRING *name,
+ List<Item> *item_list)
+{
+ Item *func= NULL;
+ int arg_count= 0;
+ Item *param_1, *param_2;
+
+ if (item_list != NULL)
+ arg_count= item_list->elements;
+
+ switch (arg_count)
+ {
+ case 1:
+ param_1= item_list->pop();
+ func= new (thd->mem_root) Item_func_wsrep_sync_wait_upto(thd, param_1);
+ break;
+ case 2:
+ param_1= item_list->pop();
+ param_2= item_list->pop();
+ func= new (thd->mem_root) Item_func_wsrep_sync_wait_upto(thd, param_1, param_2);
+ break;
+ default:
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ break;
+ }
+ current_thd->lex->safe_to_cache_query= 0;
+ return func;
+}
+#endif /* WITH_WSREP */
#ifdef HAVE_SPATIAL
Create_func_x Create_func_x::s_singleton;
@@ -7328,7 +7424,11 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("WEEKDAY") }, BUILDER(Create_func_weekday)},
{ { STRING_WITH_LEN("WEEKOFYEAR") }, BUILDER(Create_func_weekofyear)},
{ { STRING_WITH_LEN("WITHIN") }, GEOM_BUILDER(Create_func_within)},
- { { STRING_WITH_LEN("X") }, GEOM_BUILDER(Create_func_x)},
+#ifdef WITH_WSREP
+ { { STRING_WITH_LEN("WSREP_LAST_WRITTEN_GTID") }, BUILDER(Create_func_wsrep_last_written_gtid)},
+ { { STRING_WITH_LEN("WSREP_LAST_SEEN_GTID") }, BUILDER(Create_func_wsrep_last_seen_gtid)},
+ { { STRING_WITH_LEN("WSREP_SYNC_WAIT_UPTO_GTID") }, BUILDER(Create_func_wsrep_sync_wait_upto)},
+#endif /* WITH_WSREP */ { { STRING_WITH_LEN("X") }, GEOM_BUILDER(Create_func_x)},
{ { STRING_WITH_LEN("Y") }, GEOM_BUILDER(Create_func_y)},
{ { STRING_WITH_LEN("YEARWEEK") }, BUILDER(Create_func_year_week)},
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 12618d68c27..38338174ae7 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -5264,3 +5264,105 @@ String *Item_temptable_rowid::val_str(String *str)
str_value.set((char*)(table->file->ref), max_length, &my_charset_bin);
return &str_value;
}
+
+#ifdef WITH_WSREP
+
+#include "wsrep_mysqld.h"
+
+String * Item_func_wsrep_last_written_gtid::val_str_ascii(String *str)
+{
+ wsrep_gtid_t gtid;
+ wsrep_thd_last_written_gtid(current_thd, &gtid);
+
+ if (gtid_str.alloc(WSREP_GTID_STR_LEN))
+ {
+ my_error(ER_OUTOFMEMORY, WSREP_GTID_STR_LEN);
+ null_value= true;
+ return NULL;
+ }
+ int gtid_len = wsrep_gtid_print(&gtid,
+ (char*)gtid_str.ptr(),
+ WSREP_GTID_STR_LEN);
+ if (gtid_len < 0)
+ {
+ my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(),
+ "wsrep_gtid_print failed");
+ null_value= true;
+ return NULL;
+ }
+ gtid_str.length(gtid_len);
+ return &gtid_str;
+}
+
+String * Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str)
+{
+ wsrep_gtid_t gtid;
+ wsrep_last_committed_id(&gtid);
+
+ if (gtid_str.alloc(WSREP_GTID_STR_LEN))
+ {
+ my_error(ER_OUTOFMEMORY, WSREP_GTID_STR_LEN);
+ null_value= true;
+ return NULL;
+ }
+ int gtid_len= wsrep_gtid_print(&gtid,
+ (char*)gtid_str.ptr(),
+ WSREP_GTID_STR_LEN);
+ if (gtid_len < 0)
+ {
+ my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(),
+ "wsrep_gtid_print failed");
+ null_value= true;
+ return NULL;
+ }
+ gtid_str.length(gtid_len);
+ return &gtid_str;
+}
+
+longlong Item_func_wsrep_sync_wait_upto::val_int()
+{
+ int timeout = -1;
+ String* gtid_str= args[0]->val_str(&value);
+ if (gtid_str == NULL)
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
+ return 0LL;
+ }
+
+ if (arg_count == 2)
+ {
+ timeout = args[1]->val_int();
+ }
+
+ wsrep_gtid_t gtid;
+ int gtid_len= wsrep_gtid_scan(gtid_str->ptr(), gtid_str->length(), &gtid);
+ if (gtid_len < 0)
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
+ return 0LL;
+ }
+
+ if (gtid.seqno == WSREP_SEQNO_UNDEFINED &&
+ wsrep_uuid_compare(&gtid.uuid, &WSREP_UUID_UNDEFINED) == 0)
+ {
+ return 1LL;
+ }
+
+ wsrep_status_t status= wsrep_sync_wait_upto(current_thd, &gtid, timeout);
+
+ if (status != WSREP_OK)
+ {
+ int err;
+ switch (status) {
+ case WSREP_TRX_MISSING:
+ err= ER_WRONG_ARGUMENTS;
+ break;
+ default:
+ err= ER_LOCK_WAIT_TIMEOUT;
+ }
+ my_error(err, MYF(0), func_name());
+ return 0LL;
+ }
+ return 1LL;
+}
+#endif /* WITH_WSREP */
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 7c4ab93dc80..5fd13725b45 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -1805,4 +1805,56 @@ public:
{ return get_item_copy<Item_temptable_rowid>(thd, this); }
};
+#ifdef WITH_WSREP
+
+#include "../wsrep/wsrep_api.h"
+
+class Item_func_wsrep_last_written_gtid: public Item_str_ascii_func
+{
+ String gtid_str;
+public:
+ Item_func_wsrep_last_written_gtid(THD *thd): Item_str_ascii_func(thd) {}
+ const char *func_name() const { return "wsrep_last_written_gtid"; }
+ String *val_str_ascii(String *);
+ bool fix_length_and_dec()
+ {
+ max_length = WSREP_GTID_STR_LEN;
+ maybe_null = true;
+ return false;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_wsrep_last_written_gtid>(thd, this); }
+};
+
+class Item_func_wsrep_last_seen_gtid: public Item_str_ascii_func
+{
+ String gtid_str;
+public:
+ Item_func_wsrep_last_seen_gtid(THD *thd): Item_str_ascii_func(thd) {}
+ const char *func_name() const { return "wsrep_last_seen_gtid"; }
+ String *val_str_ascii(String *);
+ bool fix_length_and_dec()
+ {
+ max_length = WSREP_GTID_STR_LEN;
+ maybe_null = true;
+ return false;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_wsrep_last_seen_gtid>(thd, this); }
+};
+
+class Item_func_wsrep_sync_wait_upto: public Item_int_func
+{
+ String value;
+public:
+ Item_func_wsrep_sync_wait_upto(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_wsrep_sync_wait_upto(THD *thd, Item *a, Item* b): Item_int_func(thd, a, b) {}
+ const Type_handler *type_handler() const { return &type_handler_string; }
+ const char *func_name() const { return "wsrep_sync_wait_upto_gtid"; }
+ longlong val_int();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_wsrep_sync_wait_upto>(thd, this); }
+};
+#endif /* WITH_WSREP */
+
#endif /* ITEM_STRFUNC_INCLUDED */
diff --git a/sql/lock.cc b/sql/lock.cc
index 17629f17291..3f0ceb259f4 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1134,9 +1134,6 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
make_global_read_lock_block_commit(), do nothing.
*/
- if (m_state != GRL_ACQUIRED)
- DBUG_RETURN(0);
-
#ifdef WITH_WSREP
if (WSREP(thd) && m_mdl_blocks_commits_lock)
{
@@ -1146,6 +1143,10 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
}
#endif /* WITH_WSREP */
+ if (m_state != GRL_ACQUIRED)
+ DBUG_RETURN(0);
+
+
mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT);
if (thd->mdl_context.acquire_lock(&mdl_request,
@@ -1194,20 +1195,12 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
}
else if (ret != -ENOSYS) /* -ENOSYS - no provider */
{
- long long ret = wsrep->pause(wsrep);
- if (ret >= 0)
- {
- wsrep_locked_seqno= ret;
- }
- else if (ret != -ENOSYS) /* -ENOSYS - no provider */
- {
- WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret));
+ WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret));
- DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL);
- wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
- my_error(ER_LOCK_DEADLOCK, MYF(0));
- DBUG_RETURN(TRUE);
- }
+ DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL);
+ wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
+ DBUG_RETURN(TRUE);
}
#endif /* WITH_WSREP */
DBUG_RETURN(FALSE);
diff --git a/sql/log.cc b/sql/log.cc
index 6975b58dfb7..1199cab5c78 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -59,6 +59,8 @@
#include "sp_rcontext.h"
#include "sp_head.h"
+#include "wsrep_trans_observer.h"
+
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_TIME_SIZE 32
@@ -406,8 +408,49 @@ public:
Cache to store data before copying it to the binary log.
*/
IO_CACHE cache_log;
+#ifdef WITH_WSREP
+ void wsrep_reset_fragment_base(ulong size)
+ {
+ wsrep_fragment_base = size;
+ }
+
+ void wsrep_reset_fragment_fill(ulong size)
+ {
+ wsrep_fragment_fill = size;
+ }
+
+ void wsrep_reset_SR_trans()
+ {
+ wsrep_reset_fragment_fill(0);
+ wsrep_reset_fragment_base(0);
+ }
+
+ ulong wsrep_get_fragment_fill()
+ {
+ return (wsrep_fragment_fill);
+ }
+
+ void wsrep_append_fill_rate(ulong size)
+ {
+ wsrep_fragment_fill += size;
+ }
+
+ void wsrep_step_fragment_base(ulong size)
+ {
+ wsrep_fragment_base += size;
+ }
+ ulong wsrep_get_fragment_base()
+ {
+ return(wsrep_fragment_base);
+ }
+#endif /* WITH_WSREP */
private:
+#ifdef WITH_WSREP
+ ulong wsrep_fragment_fill;
+ ulong wsrep_fragment_base;
+#endif /* WITH_WSREP */
+
/*
Pending binrows event. This event is the event where the rows are currently
written.
@@ -533,6 +576,9 @@ public:
using_xa= FALSE;
last_commit_pos_file[0]= 0;
last_commit_pos_offset= 0;
+#ifdef WITH_WSREP
+ trx_cache.wsrep_reset_SR_trans();
+#endif /* WITH_WSREP */
}
}
@@ -1699,7 +1745,8 @@ static int binlog_close_connection(handlerton *hton, THD *thd)
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
#ifdef WITH_WSREP
if (cache_mngr && !cache_mngr->trx_cache.empty()) {
- IO_CACHE* cache= get_trans_log(thd);
+ //IO_CACHE* cache= wsrep_get_trans_cache(thd);
+ IO_CACHE* cache= cache_mngr->get_binlog_cache_log(true);
uchar *buf;
size_t len=0;
wsrep_write_cache_buf(cache, &buf, &len);
@@ -2293,8 +2340,17 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
non-transactional table. Otherwise, truncate the binlog cache starting
from the SAVEPOINT command.
*/
+#ifdef WITH_WSREP
+ /* for streaming replication, we must replicate savepoint rollback so that
+ slaves can maintain SR transactions
+ */
+ if (unlikely(thd->wsrep_is_streaming() ||
+ (trans_has_updated_non_trans_table(thd)) ||
+ (thd->variables.option_bits & OPTION_KEEP_LOG)))
+#else
if (unlikely(trans_has_updated_non_trans_table(thd) ||
(thd->variables.option_bits & OPTION_KEEP_LOG)))
+#endif /* WITH_WSREP */
{
char buf[1024];
String log_query(buf, sizeof(buf), &my_charset_bin);
@@ -7699,7 +7755,30 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
DEBUG_SYNC(entry->thd, "commit_loop_entry_commit_ordered");
++num_commits;
if (entry->cache_mngr->using_xa && !entry->error)
+#ifdef WITH_WSREP
+ {
+ if (WSREP(entry->thd) && entry->thd->wsrep_trx_must_order_commit() &&
+ wsrep_before_commit(entry->thd, entry->all))
+ {
+ return (true);
+ }
+#endif /* WITH_WSREP */
run_commit_ordered(entry->thd, entry->all);
+#ifdef WITH_WSREP
+ if (WSREP(entry->thd) && entry->thd->wsrep_trx_must_order_commit())
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(entry->thd, entry->all, wsrep_apply_error());
+ if (!error)
+ {
+ (void) wsrep_after_commit(entry->thd, entry->all);
+ }
+ }
+ }
+#endif /* WITH_WSREP */
group_commit_entry *next= entry->next;
if (!next)
@@ -8083,7 +8162,31 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
++num_commits;
if (current->cache_mngr->using_xa && likely(!current->error) &&
DBUG_EVALUATE_IF("skip_commit_ordered", 0, 1))
+#ifdef WITH_WSREP
+ {
+ if (WSREP(current->thd) && current_thd->wsrep_trx_must_order_commit() &&
+ wsrep_before_commit(current->thd, current->all))
+ {
+ DBUG_VOID_RETURN;
+ }
+#endif /* WITH_WSREP */
run_commit_ordered(current->thd, current->all);
+#ifdef WITH_WSREP
+ if (WSREP(current->thd) && current_thd->wsrep_trx_must_order_commit())
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(current->thd, current->all, wsrep_apply_error());
+ //if (!error) (void) wsrep_after_commit(current->thd, current->all);
+ if (!error)
+ {
+ (void) wsrep_after_commit(current->thd, current->all);
+ }
+ }
+ }
+#endif /* WITH_WSREP */
current->thd->wakeup_subsequent_commits(current->error);
/*
@@ -8923,9 +9026,31 @@ int TC_LOG_MMAP::log_and_order(THD *thd, my_xid xid, bool all,
/* Only run commit_ordered() if log_xid was successful. */
if (cookie)
{
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_trx_must_order_commit() &&
+ wsrep_before_commit(thd, all))
+ {
+ return(0);
+ }
+#endif /* WITH_WSREP */
mysql_mutex_lock(&LOCK_commit_ordered);
run_commit_ordered(thd, all);
mysql_mutex_unlock(&LOCK_commit_ordered);
+#ifdef WITH_WSREP
+ //if (WSREP(thd) && !thd->wsrep_apply_toi)
+ if (WSREP(thd) && thd->wsrep_trx_must_order_commit())
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(thd, all, wsrep_apply_error());
+ if (!error)
+ {
+ (void) wsrep_after_commit(thd, all);
+ }
+ }
+#endif /* WITH_WSREP */
}
if (need_prepare_ordered)
@@ -9623,6 +9748,30 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all,
if (err)
DBUG_RETURN(0);
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_exec_mode != REPL_RECV &&
+ thd->wsrep_trx_must_order_commit() &&
+ wsrep_before_commit(thd, all))
+ {
+ return(0);
+ }
+#endif /* WITH_WSREP */
+#ifdef WITH_WSREP
+ //if (WSREP(thd) && !thd->wsrep_apply_toi)
+ if (WSREP(thd) && thd->wsrep_exec_mode != REPL_RECV &&
+ thd->wsrep_trx_must_order_commit())
+ {
+ /*
+ TODO: Ordered commit should be done after the transaction
+ has been queued for group commit.
+ */
+ int error= wsrep_ordered_commit(thd, all, wsrep_apply_error());
+ if (!error)
+ {
+ (void) wsrep_after_commit(thd, all);
+ }
+ }
+#endif /* WITH_WSREP */
bool need_unlog= cache_mngr->need_unlog;
/*
@@ -10589,7 +10738,44 @@ maria_declare_plugin(binlog)
maria_declare_plugin_end;
#ifdef WITH_WSREP
-IO_CACHE * get_trans_log(THD * thd)
+#include "wsrep_trans_observer.h"
+#include "wsrep_mysqld.h"
+
+static int wsrep_plugin_init(void *p)
+{
+ WSREP_INFO("wsrep_plugin_init()");
+ return wsrep_register_trans_observer(p);
+}
+
+static int wsrep_plugin_deinit(void *p)
+{
+ WSREP_INFO("wsrep_plugin_deinit()");
+ return wsrep_unregister_trans_observer(p);
+}
+
+struct Mysql_replication wsrep_plugin= {
+ MYSQL_REPLICATION_INTERFACE_VERSION
+};
+
+maria_declare_plugin(wsrep)
+{
+ MYSQL_REPLICATION_PLUGIN,
+ &wsrep_plugin,
+ "wsrep",
+ "Codership Oy",
+ "Wsrep replication plugin",
+ PLUGIN_LICENSE_GPL,
+ wsrep_plugin_init,
+ wsrep_plugin_deinit,
+ 0x0100,
+ NULL, /* Status variables */
+ NULL, /* System variables */
+ "1.0", /* Version (string) */
+ MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */
+}
+maria_declare_plugin_end;
+
+IO_CACHE *wsrep_get_trans_cache(THD * thd)
{
DBUG_ASSERT(binlog_hton->slot != HA_SLOT_UNDEF);
binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*)
@@ -10603,15 +10789,115 @@ IO_CACHE * get_trans_log(THD * thd)
}
-bool wsrep_trans_cache_is_empty(THD *thd)
+uint wsrep_get_trans_cache_position(THD *thd)
{
+ if (binlog_hton)
+ {
+ my_off_t pos = 0;
+ binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*)
+ thd_get_ha_data(thd, binlog_hton);
+ if (cache_mngr) binlog_trans_log_savepos(thd, &pos);
+ return (pos);
+ }
+ return 0;
+}
+
+void wsrep_reset_SR_trans(THD *thd)
+{
+ DBUG_ENTER("wsrep_reset_SR_trans");
+ if (!binlog_hton || !WSREP(thd)) DBUG_VOID_RETURN;
+ thd->wsrep_fragments_sent = 0;
+
binlog_cache_mngr *const cache_mngr=
- (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
- return (!cache_mngr || cache_mngr->trx_cache.empty());
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ if (cache_mngr)
+ {
+ cache_mngr->trx_cache.wsrep_reset_fragment_base(0);
+ cache_mngr->trx_cache.wsrep_reset_fragment_fill(0);
+ }
+ DBUG_VOID_RETURN;
+}
+
+void wsrep_step_fragment_base(THD *thd, ulong size)
+{
+ DBUG_ASSERT(binlog_hton && WSREP(thd) &&
+ thd->variables.wsrep_trx_fragment_size > 0);
+ if (!binlog_hton || !WSREP(thd) ||
+ thd->variables.wsrep_trx_fragment_size == 0) return;
+
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+ if (cache_mngr)
+ {
+ cache_mngr->trx_cache.wsrep_step_fragment_base(size);
+ }
+}
+
+ulong wsrep_get_fragment_base(THD *thd)
+{
+ if (!binlog_hton || !WSREP(thd)) return 0;
+
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+
+ if (cache_mngr)
+ {
+ return cache_mngr->trx_cache.wsrep_get_fragment_base();
+ }
+ return 0;
+}
+void wsrep_append_fill_rate(THD *thd, ulong size)
+{
+ DBUG_ASSERT(binlog_hton && WSREP(thd) &&
+ thd->variables.wsrep_trx_fragment_size > 0);
+ if (!binlog_hton || !WSREP(thd) ||
+ thd->variables.wsrep_trx_fragment_size == 0) return;
+
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+ if (cache_mngr)
+ {
+ cache_mngr->trx_cache.wsrep_append_fill_rate(size);
+ }
+}
+
+void wsrep_reset_fragment_fill(THD *thd, ulong size)
+{
+ DBUG_ASSERT(binlog_hton && WSREP(thd) &&
+ thd->variables.wsrep_trx_fragment_size > 0);
+ if (!binlog_hton || !WSREP(thd) ||
+ thd->variables.wsrep_trx_fragment_size == 0) return;
+
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+ if (cache_mngr)
+ {
+ cache_mngr->trx_cache.wsrep_reset_fragment_fill(size);
+ }
}
+ulong wsrep_get_fragment_fill(THD *thd)
+{
+ DBUG_ASSERT(binlog_hton && WSREP(thd) &&
+ thd->variables.wsrep_trx_fragment_size > 0);
+ if (!binlog_hton || !WSREP(thd) ||
+ thd->variables.wsrep_trx_fragment_size == 0) return 0;
-void thd_binlog_trx_reset(THD * thd)
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+ if (cache_mngr)
+ {
+ return cache_mngr->trx_cache.wsrep_get_fragment_fill();
+ }
+ return 0;
+}
+
+void wsrep_thd_binlog_trx_reset(THD * thd)
{
/*
todo: fix autocommit select to not call the caller
@@ -10643,4 +10929,85 @@ void thd_binlog_rollback_stmt(THD * thd)
if (cache_mngr)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
}
+
+int wsrep_thd_binlog_prepare(THD* thd, bool all)
+{
+ /* applier and replayer can skip binlog prepare */
+ if (WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV))
+ return binlog_hton->prepare(binlog_hton, thd, all);
+ else
+ return ha_prepare(thd);
+}
+
+bool wsrep_stmt_rollback_is_safe(THD* thd)
+{
+ bool ret(true);
+
+ DBUG_ENTER("wsrep_binlog_stmt_rollback_is_safe");
+
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+
+ if (binlog_hton && cache_mngr)
+ {
+ binlog_cache_data * trx_cache = &cache_mngr->trx_cache;
+ if (thd->wsrep_fragments_sent > 0 &&
+ (trx_cache->get_prev_position() == MY_OFF_T_UNDEF ||
+ trx_cache->get_prev_position() < trx_cache->wsrep_get_fragment_base()))
+ {
+ WSREP_DEBUG("statement rollback is not safe for streaming replication"
+ " pre-stmt_pos: %llu, frag repl pos: %lu\nThread: %llu, SQL: %s",
+ trx_cache->get_prev_position(), trx_cache->wsrep_get_fragment_base(),
+ thd->thread_id, thd->query());
+ ret = false;
+ }
+ }
+ DBUG_RETURN(ret);
+}
+
+void wsrep_register_binlog_handler(THD *thd, bool trx)
+{
+ DBUG_ENTER("register_binlog_handler");
+ /*
+ If this is the first call to this function while processing a statement,
+ the transactional cache does not have a savepoint defined. So, in what
+ follows:
+ . an implicit savepoint is defined;
+ . callbacks are registered;
+ . binary log is set as read/write.
+
+ The savepoint allows for truncating the trx-cache transactional changes
+ fail. Callbacks are necessary to flush caches upon committing or rolling
+ back a statement or a transaction. However, notifications do not happen
+ if the binary log is set as read/write.
+ */
+ //binlog_cache_mngr *cache_mngr= thd_get_cache_mngr(thd);
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ /* cache_mngr may be missing e.g. in mtr test ev51914.test */
+ if (cache_mngr && cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
+ {
+ /*
+ Set an implicit savepoint in order to be able to truncate a trx-cache.
+ */
+ my_off_t pos= 0;
+ binlog_trans_log_savepos(thd, &pos);
+ cache_mngr->trx_cache.set_prev_position(pos);
+
+ /*
+ Set callbacks in order to be able to call commmit or rollback.
+ */
+ if (trx)
+ trans_register_ha(thd, TRUE, binlog_hton);
+ trans_register_ha(thd, FALSE, binlog_hton);
+
+ /*
+ Set the binary log as read/write otherwise callbacks are not called.
+ */
+ thd->ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
+ }
+ DBUG_VOID_RETURN;
+}
+
#endif /* WITH_WSREP */
diff --git a/sql/log.h b/sql/log.h
index 7dfdb36c442..1aa83eaabb1 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -96,6 +96,11 @@ extern PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
extern PSI_mutex_key key_LOCK_after_binlog_sync;
extern PSI_cond_key key_COND_prepare_ordered;
#endif
+#ifdef WITH_WSREP
+int wsrep_thd_binlog_commit(THD *thd, bool all);
+int wsrep_thd_binlog_rollback(THD *thd, bool all);
+int wsrep_thd_binlog_prepare(THD *thd, bool all);
+#endif /* WITH_WSREP */
class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
{
@@ -103,6 +108,11 @@ public:
TC_LOG_DUMMY() {}
int open(const char *opt_name) { return 0; }
void close() { }
+#ifdef WITH_WSREP
+ int commit(THD *thd, bool all) {
+ return wsrep_thd_binlog_commit(thd, all);
+ }
+#endif /* WITH_WSREP */
/*
TC_LOG_DUMMY is only used when there are <= 1 XA-capable engines, and we
only use internal XA during commit when >= 2 XA-capable engines
@@ -1211,6 +1221,15 @@ static inline TC_LOG *get_tc_log_implementation()
return &mysql_bin_log;
return &tc_log_mmap;
}
+#ifdef WITH_WSREP
+IO_CACHE* wsrep_get_trans_cache(THD *);
+void wsrep_thd_binlog_trx_reset(THD * thd);
+#define WSREP_BINLOG_FORMAT(my_format) \
+ ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
+ wsrep_forced_binlog_format : my_format)
+#else
+#define WSREP_BINLOG_FORMAT(my_format) my_format
+#endif /* WITH_WSREP */
class Gtid_list_log_event;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 13690a8be60..cfbf0a2232c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5743,6 +5743,14 @@ compare_errors:
"unexpected success or fatal error"),
thd->get_db(), query_arg);
thd->is_slave_error= 1;
+#ifdef WITH_WSREP
+ if (thd->wsrep_apply_toi && wsrep_must_ignore_error(thd))
+ {
+ thd->clear_error(1);
+ thd->killed= NOT_KILLED;
+ thd->wsrep_has_ignored_error= true;
+ }
+#endif /* WITH_WSREP */
}
/*
@@ -11264,10 +11272,10 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
thd->get_stmt_da()->sql_errno(),
thd->is_fatal_error,
thd->wsrep_exec_mode,
- thd->wsrep_conflict_state,
+ thd->wsrep_conflict_state_unsafe(),
(long long)wsrep_thd_trx_seqno(thd));
}
-#endif
+#endif /* WITH_WSREP */
if ((thd->is_slave_error || thd->is_fatal_error) &&
!is_parallel_retry_error(rgi, actual_error))
{
@@ -11520,6 +11528,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
bool ignored_error= (idempotent_error == 0 ?
ignored_error_code(actual_error) : 0);
+#ifdef WITH_WSREP
+ if (WSREP(thd) && wsrep_ignored_error_code(this, actual_error))
+ {
+ idempotent_error= true;
+ thd->wsrep_has_ignored_error= true;
+ }
+#endif /* WITH_WSREP */
if (idempotent_error || ignored_error)
{
if (global_system_variables.log_warnings)
diff --git a/sql/mdl.cc b/sql/mdl.cc
index f03fc89fcc1..cc06d5ef336 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -1073,7 +1073,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout,
thd_wait_begin(NULL, THD_WAIT_META_DATA_LOCK);
while (!m_wait_status && !owner->is_killed() &&
wait_result != ETIMEDOUT && wait_result != ETIME)
- {
+ {
#ifdef WITH_WSREP
// Allow tests to block the applier thread using the DBUG facilities
DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait",
@@ -1084,7 +1084,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout,
DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()),
STRING_WITH_LEN(act)));
};);
- if (wsrep_thd_is_BF(owner->get_thd(), false))
+ if (wsrep_thd_is_BF((void*)owner->get_thd(), false))
{
wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status);
}
@@ -1158,19 +1158,19 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
DBUG_ASSERT(ticket->get_lock());
#ifdef WITH_WSREP
if ((this == &(ticket->get_lock()->m_waiting)) &&
- wsrep_thd_is_BF(ticket->get_ctx()->get_thd(), false))
+ wsrep_thd_is_BF((void*)ticket->get_ctx()->get_thd(), false))
{
Ticket_iterator itw(ticket->get_lock()->m_waiting);
Ticket_iterator itg(ticket->get_lock()->m_granted);
DBUG_ASSERT(WSREP_ON);
- MDL_ticket *waiting, *granted;
+ MDL_ticket *waiting;
MDL_ticket *prev=NULL;
bool added= false;
while ((waiting= itw++) && !added)
{
- if (!wsrep_thd_is_BF(waiting->get_ctx()->get_thd(), true))
+ if (!wsrep_thd_is_BF((void*)waiting->get_ctx()->get_thd(), true))
{
WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
thd_get_thread_id(waiting->get_ctx()->get_thd()),
@@ -1185,18 +1185,6 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
/* Otherwise, insert the ticket at the back of the waiting list. */
if (!added) m_list.push_back(ticket);
- while ((granted= itg++))
- {
- if (granted->get_ctx() != ticket->get_ctx() &&
- granted->is_incompatible_when_granted(ticket->get_type()))
- {
- if (!wsrep_grant_mdl_exception(ticket->get_ctx(), granted,
- &ticket->get_lock()->key))
- {
- WSREP_DEBUG("MDL victim killed at add_ticket");
- }
- }
- }
}
else
#endif /* WITH_WSREP */
@@ -1558,7 +1546,6 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
bool can_grant= FALSE;
bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
- bool wsrep_can_grant= TRUE;
/*
New lock request can be satisfied iff:
@@ -1571,10 +1558,20 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
{
if (! (m_granted.bitmap() & granted_incompat_map))
can_grant= TRUE;
+#ifdef WITH_WSREP
+ else if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()),false) &&
+ key.mdl_namespace() == MDL_key::GLOBAL)
+ {
+ WSREP_DEBUG("global lock granted for BF: %lld %s",
+ wsrep_thd_thread_id(requestor_ctx->get_thd()),
+ wsrep_thd_query(requestor_ctx->get_thd()));
+ can_grant= TRUE;
+ }
else
{
Ticket_iterator it(m_granted);
MDL_ticket *ticket;
+ bool wsrep_can_grant= TRUE;
/* Check that the incompatible lock belongs to some other context. */
while ((ticket= it++))
@@ -1582,16 +1579,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
if (ticket->get_ctx() != requestor_ctx &&
ticket->is_incompatible_when_granted(type_arg))
{
-#ifdef WITH_WSREP
- if (wsrep_thd_is_BF(requestor_ctx->get_thd(),false) &&
- key.mdl_namespace() == MDL_key::GLOBAL)
- {
- WSREP_DEBUG("global lock granted for BF: %lu %s",
- thd_get_thread_id(requestor_ctx->get_thd()),
- wsrep_thd_query(requestor_ctx->get_thd()));
- can_grant = true;
- }
- else if (!wsrep_grant_mdl_exception(requestor_ctx, ticket, &key))
+ if (!wsrep_grant_mdl_exception(requestor_ctx, ticket, &key))
{
wsrep_can_grant= FALSE;
if (wsrep_log_conflicts)
@@ -1603,21 +1591,33 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
"abort" );
}
}
- else
- can_grant= TRUE;
- /* Continue loop */
+ }
+ }
+ if (wsrep_can_grant)
+ can_grant= TRUE;
+ }
#else
+ else
+ {
+ Ticket_iterator it(m_granted);
+ MDL_ticket *ticket;
+
+ /* Check that the incompatible lock belongs to some other context. */
+ while ((ticket= it++))
+ {
+ if (ticket->get_ctx() != requestor_ctx &&
+ ticket->is_incompatible_when_granted(type_arg))
break;
-#endif /* WITH_WSREP */
- }
}
- if ((ticket == NULL) && wsrep_can_grant)
- can_grant= TRUE; /* Incompatible locks are our own. */
+ if (ticket == NULL) /* Incompatible locks are our own. */
+ can_grant= TRUE;
}
+#endif /* WITH_WSREP */
}
+#ifdef WITH_WSREP
else
{
- if (wsrep_thd_is_BF(requestor_ctx->get_thd(), false) &&
+ if (wsrep_thd_is_BF((void*)requestor_ctx->get_thd(), false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s",
@@ -1626,6 +1626,8 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
can_grant = true;
}
}
+#endif /* WITH_WSREP */
+
return can_grant;
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ce14dc678c6..d3b9ab03640 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1604,7 +1604,6 @@ ATTRIBUTE_NORETURN static void mysqld_exit(int exit_code);
static void delete_pid_file(myf flags);
static void end_ssl();
-
#ifndef EMBEDDED_LIBRARY
/****************************************************************************
** Code to end mysqld
@@ -1733,6 +1732,7 @@ static void close_connections(void)
#endif
tmp->set_killed(KILL_SERVER_HARD);
MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
+ if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd);
mysql_mutex_lock(&tmp->LOCK_thd_kill);
if (tmp->mysys_var)
{
@@ -1757,6 +1757,7 @@ static void close_connections(void)
mysql_mutex_unlock(&tmp->mysys_var->mutex);
}
mysql_mutex_unlock(&tmp->LOCK_thd_kill);
+ if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_wsrep_thd);
}
mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
@@ -1842,6 +1843,10 @@ static void close_connections(void)
mysql_mutex_unlock(&LOCK_thread_count);
}
end_slave();
+#ifdef WITH_WSREP
+ if (wsrep_inited == 1)
+ wsrep_deinit(true);
+#endif
/* All threads has now been aborted */
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
mysql_mutex_lock(&LOCK_thread_count);
@@ -2028,7 +2033,7 @@ static void __cdecl kill_server(int sig_ptr)
/* Stop wsrep threads in case they are running. */
if (wsrep_running_threads > 0)
{
- wsrep_stop_replication(NULL);
+ wsrep_shutdown_replication();
}
close_connections();
@@ -2140,10 +2145,14 @@ extern "C" void unireg_abort(int exit_code)
if (wsrep)
{
/*
+ Signal SE init waiters to exit with error status
+ */
+ wsrep_SE_init_failed();
+ /*
This is an abort situation, we cannot expect to gracefully close all
wsrep threads here, we can only diconnect from service
*/
- wsrep_close_client_connections(FALSE);
+ wsrep_close_client_connections(FALSE, NULL);
shutdown_in_progress= 1;
wsrep->disconnect(wsrep);
WSREP_INFO("Service disconnected.");
@@ -2930,6 +2939,14 @@ void signal_thd_deleted()
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
}
+ else
+ {
+ /* Naah, I signal anyways */
+ WSREP_DEBUG("forced signal for COND_thread_count");
+ mysql_mutex_lock(&LOCK_thread_count);
+ mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
+ }
}
@@ -5330,6 +5347,15 @@ static int init_server_components()
}
}
+ if (WSREP_NOT_SPECIFIED)
+ {
+ // enable normal operation in case no provider is specified
+#ifndef EMBEDDED_LIBRARY
+ wsrep_ready_set(TRUE);
+#endif
+ global_system_variables.wsrep_on = 0;
+ }
+
if (opt_bin_log)
{
if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
@@ -6092,10 +6118,7 @@ int mysqld_main(int argc, char **argv)
wsrep_SE_init_grab();
wsrep_SE_init_done();
/*! in case of SST wsrep waits for wsrep->sst_received */
- if (wsrep_sst_continue())
- {
- WSREP_ERROR("Failed to signal the wsrep provider to continue.");
- }
+ wsrep_sst_continue();
}
else
{
@@ -8752,6 +8775,20 @@ SHOW_VAR status_vars[]= {
{"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC},
#endif
#ifdef WITH_WSREP
+ {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL},
+ {"wsrep_ready", (char*) &wsrep_show_ready, SHOW_FUNC},
+ {"wsrep_cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
+ {"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG},
+ {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR},
+ {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH},
+ {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH},
+ {"wsrep_local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC},
+ {"wsrep_provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR},
+ {"wsrep_provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR},
+ {"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
+ {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
+ {"wsrep_thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH},
+ {"wsrep_cluster_capabilities", (char*) &wsrep_cluster_capabilities, SHOW_CHAR_PTR},
{"wsrep", (char*) &wsrep_show_status, SHOW_FUNC},
#endif
{NullS, NullS, SHOW_LONG}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 29004fe24e4..d370ff38e4a 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -551,8 +551,25 @@ static uchar *net_store_length_fast(uchar *packet, size_t length)
void Protocol::end_statement()
{
- /* sanity check*/
- DBUG_ASSERT_IF_WSREP(!(WSREP(thd) && thd->wsrep_conflict_state == REPLAYING));
+ /*
+ Commented out: This sanity check does not hold in general.
+ Thd->LOCK_wsrep_thd() must be unlocked before sending response
+ to client, so BF abort may sneak in here.
+ DBUG_ASSERT(!WSREP(thd) || thd->wsrep_conflict_state() == NO_CONFLICT);
+ */
+
+ /*
+ sanity check, don't send end statement while replaying
+ */
+#ifdef WITH_WSREP
+ DBUG_ASSERT(thd->wsrep_conflict_state_unsafe() != REPLAYING);
+ if (WSREP(thd) && thd->wsrep_conflict_state_unsafe()== REPLAYING)
+ {
+ WSREP_ERROR("attempting net_end_statement while replaying");
+ return;
+ }
+#endif
+
DBUG_ENTER("Protocol::end_statement");
DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
bool error= FALSE;
diff --git a/sql/slave.cc b/sql/slave.cc
index bb1300d36e6..20e9cfb3a32 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3917,14 +3917,19 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi,
exec_res= ev->apply_event(rgi);
#ifdef WITH_WSREP
- if (exec_res && thd->wsrep_conflict_state != NO_CONFLICT)
+ if (WSREP_ON)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (exec_res && thd->wsrep_conflict_state() != NO_CONFLICT)
{
WSREP_DEBUG("SQL apply failed, res %d conflict state: %d",
- exec_res, thd->wsrep_conflict_state);
+ exec_res, thd->wsrep_conflict_state_unsafe());
rli->abort_slave= 1;
rli->report(ERROR_LEVEL, ER_UNKNOWN_COM_ERROR, rgi->gtid_info(),
"Node has dropped from cluster");
}
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
#endif
#ifndef DBUG_OFF
@@ -4217,6 +4222,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
}
if (ev)
{
+#ifdef WITH_WSREP
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
int exec_res;
Log_event_type typ= ev->get_type_code();
@@ -4261,6 +4271,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
rli->abort_slave= 1;
rli->stop_for_until= true;
mysql_mutex_unlock(&rli->data_lock);
+#ifdef WITH_WSREP
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
delete ev;
DBUG_RETURN(1);
}
@@ -4298,7 +4313,16 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
if (res == 0)
rli->event_relay_log_pos= rli->future_event_relay_log_pos;
if (res >= 0)
+#ifdef WITH_WSREP
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(res);
+#ifdef WITH_WSREP
+ }
+#endif /* WITH_WSREP */
/*
Else we proceed to execute the event non-parallel.
This is the case for pre-10.0 events without GTID, and for handling
@@ -4320,6 +4344,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
"aborted because of out-of-memory error");
mysql_mutex_unlock(&rli->data_lock);
delete ev;
+#ifdef WITH_WSREP
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(1);
}
@@ -4334,6 +4363,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
"thread aborted because of out-of-memory error");
mysql_mutex_unlock(&rli->data_lock);
delete ev;
+#ifdef WITH_WSREP
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(1);
}
/*
@@ -4362,13 +4396,19 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
retry.
*/
if (unlikely(exec_res == 2))
+#ifdef WITH_WSREP
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(1);
-
#ifdef WITH_WSREP
- mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state == NO_CONFLICT)
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
{
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
#endif /* WITH_WSREP */
if (slave_trans_retries)
{
@@ -4446,10 +4486,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
#ifdef WITH_WSREP
}
else
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
#endif /* WITH_WSREP */
thread_safe_increment64(&rli->executed_entries);
+#ifdef WITH_WSREP
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#endif /* WITH_WSREP */
DBUG_RETURN(exec_res);
}
mysql_mutex_unlock(&rli->data_lock);
@@ -5515,10 +5560,16 @@ pthread_handler_t handle_slave_sql(void *arg)
if (exec_relay_log_event(thd, rli, serial_rgi))
{
#ifdef WITH_WSREP
- if (thd->wsrep_conflict_state != NO_CONFLICT)
+ if (WSREP_ON)
{
- wsrep_node_dropped= TRUE;
- rli->abort_slave= TRUE;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+
+ if (thd->wsrep_conflict_state() != NO_CONFLICT)
+ {
+ wsrep_node_dropped= TRUE;
+ rli->abort_slave= TRUE;
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
#endif /* WITH_WSREP */
@@ -5550,6 +5601,9 @@ pthread_handler_t handle_slave_sql(void *arg)
sql_print_information("Slave SQL thread exiting, replication stopped in "
"log '%s' at position %llu%s", RPL_LOG_NAME,
rli->group_master_log_pos, tmp.c_ptr_safe());
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ WSREP_DEBUG("SQL thread %lu exec %d query state %d", thd->thread_id, thd->wsrep_exec_mode , thd->wsrep_query_state());
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
err_before_start:
@@ -5662,24 +5716,25 @@ err_during_init:
trigger automatic restart of slave when node joins back to cluster.
*/
if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave)
- {
- if (wsrep_ready_get())
- {
- WSREP_INFO("Slave error due to node temporarily non-primary"
- "SQL slave will continue");
- wsrep_node_dropped= FALSE;
- mysql_mutex_unlock(&rli->run_lock);
- WSREP_DEBUG("wsrep_conflict_state now: %d", thd->wsrep_conflict_state);
- WSREP_INFO("slave restart: %d", thd->wsrep_conflict_state);
- thd->wsrep_conflict_state= NO_CONFLICT;
- goto wsrep_restart_point;
- } else {
- WSREP_INFO("Slave error due to node going non-primary");
- WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
- "automatically restarted when node joins back to cluster.");
- wsrep_restart_slave_activated= TRUE;
- }
- }
+ {
+ if (wsrep_ready_get())
+ {
+ WSREP_INFO("Slave error due to node temporarily non-primary"
+ "SQL slave will continue");
+ wsrep_node_dropped= FALSE;
+ mysql_mutex_unlock(&rli->run_lock);
+ goto wsrep_restart_point;
+ } else {
+ WSREP_INFO("Slave error due to node going non-primary");
+ WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
+ "automatically restarted when node joins back to cluster");
+ wsrep_restart_slave_activated= TRUE;
+ }
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXITING);
+ if (WSREP(thd)) wsrep->free_connection(wsrep, thd->thread_id);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
#endif /* WITH_WSREP */
/*
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c86edc47bf9..c88fe153136 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -44,6 +44,7 @@
#include "transaction.h" // trans_commit_stmt
#include "sql_audit.h"
#include "debug_sync.h"
+#include "wsrep_trans_observer.h"
/*
Sufficient max length of printed destinations and frame offsets (all uints).
@@ -51,7 +52,6 @@
#define SP_INSTR_UINT_MAXLEN 8
#define SP_STMT_PRINT_MAXLEN 40
-
#include <my_user.h>
extern "C" uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first);
@@ -1324,6 +1324,13 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
sql_digest_state *parent_digest= thd->m_digest;
thd->m_digest= NULL;
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ WSREP_DEBUG("assigned new next trx ID for SP, trx id: %lu", thd->wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
err_status= i->execute(thd, &ip);
thd->m_digest= parent_digest;
@@ -3566,6 +3573,24 @@ sp_instr_stmt::exec_core(THD *thd, uint *nextp)
(char *)thd->security_ctx->host_or_ip,
3);
int res= mysql_execute_command(thd);
+#ifdef WITH_WSREP
+ if ((thd->is_fatal_error || thd->killed_errno()) &&
+ (thd->wsrep_conflict_state_unsafe() == NO_CONFLICT))
+ {
+ /*
+ SP was killed, and it is not due to a wsrep conflict.
+ We skip after_command hook at this point because
+ otherwise it clears the error, and cleans up the
+ whole transaction. For now we just return and finish
+ our handling once we are back to mysql_parse.
+ */
+ WSREP_DEBUG("Skipping after_command hook for killed SP");
+ }
+ else
+ {
+ (void) wsrep_after_command(thd, !thd->in_active_multi_stmt_transaction());
+ }
+#endif /* WITH_WSREP */
MYSQL_QUERY_EXEC_DONE(res);
*nextp= m_ip+1;
return res;
@@ -4501,8 +4526,8 @@ int
sp_instr_error::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_error::execute");
-
my_message(m_errcode, ER_THD(thd, m_errcode), MYF(0));
+ WSREP_DEBUG("sp_instr_error: %s %d", ER_THD(thd, m_errcode), thd->is_error());
*nextp= m_ip+1;
DBUG_RETURN(-1);
}
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 700b4699430..fb89e0bc5b2 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -498,7 +498,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
#ifdef WITH_WSREP
error:
- WSREP_WARN("ALTER TABLE isolation failure");
+ // Jump to error may happen from WSREP_TO_ISOLATION_BEGIN
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e46b7675bbe..0587d401461 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -63,6 +63,9 @@
#endif
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
+#ifdef WITH_WSREP
+#include "wsrep_sr.h"
+#endif
bool
No_such_table_error_handler::handle_condition(THD *,
@@ -872,10 +875,19 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
The metadata lock must be released after giving back
the table to the table cache.
*/
- DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+#ifdef WITH_WSREP
+ /* if SR thread was aborted, MDL locks were released early */
+ DBUG_ASSERT(thd->variables.wsrep_trx_fragment_size > 0 ||
+ thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+ table->s->db.str,
+ table->s->table_name.str,
+ MDL_SHARED));
+#else
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
table->s->db.str,
table->s->table_name.str,
MDL_SHARED));
+#endif /* WITH_WSSREP */
table->mdl_ticket= NULL;
if (table->file)
@@ -3988,6 +4000,15 @@ bool open_tables(THD *thd, const DDL_options_st &options,
thd->current_tablenr= 0;
restart:
+#ifdef WITH_WSREP
+ if (WSREP_CLIENT(thd) &&
+ (thd->wsrep_is_streaming() ||
+ thd->variables.wsrep_trx_fragment_size > 0) &&
+ wsrep_may_produce_SR_step(thd))
+ {
+ wsrep_prepare_SR_for_open_tables(thd, start);
+ }
+#endif /* WITH_WSREP */
/*
Close HANDLER tables which are marked for flush or against which there
are pending exclusive metadata locks. This is needed both in order to
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 0bbfdba88c7..9571c785e28 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -771,6 +771,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
*scramble= '\0';
#ifdef WITH_WSREP
+ mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL);
wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID;
wsrep_ws_handle.opaque = NULL;
wsrep_retry_counter = 0;
@@ -779,12 +781,20 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
wsrep_retry_query_len = 0;
wsrep_retry_command = COM_CONNECT;
wsrep_consistency_check = NO_CONSISTENCY_CHECK;
+ wsrep_status_vars = 0;
wsrep_mysql_replicated = 0;
wsrep_TOI_pre_query = NULL;
wsrep_TOI_pre_query_len = 0;
+ wsrep_fragments_sent = 0;
+ wsrep_trx_fragment_size = 0;
+ wsrep_SR_thd = false;
+ wsrep_rbr_buf = NULL;
+ wsrep_nbo_ctx = NULL;
wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */
wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED;
wsrep_affected_rows = 0;
+ wsrep_has_ignored_error = false;
+ m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID;
wsrep_replicate_GTID = false;
wsrep_skip_wsrep_GTID = false;
#endif
@@ -1221,10 +1231,14 @@ void THD::init(bool skip_lock)
first_successful_insert_id_in_cur_stmt= 0;
#ifdef WITH_WSREP
wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE;
- wsrep_conflict_state= NO_CONFLICT;
- wsrep_query_state= QUERY_IDLE;
+ m_wsrep_conflict_state= NO_CONFLICT;
+ m_wsrep_query_state= QUERY_IDLE;
wsrep_last_query_id= 0;
+ wsrep_xid.null();
+ wsrep_skip_locking= FALSE;
wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
+ wsrep_node_uuid(wsrep_trx_meta.stid.node);
+ wsrep_trx_meta.stid.trx= WSREP_UNDEFINED_TRX_ID;
wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED;
wsrep_converted_lock_session= false;
wsrep_retry_counter= 0;
@@ -1234,8 +1248,16 @@ void THD::init(bool skip_lock)
wsrep_mysql_replicated = 0;
wsrep_TOI_pre_query = NULL;
wsrep_TOI_pre_query_len = 0;
+ wsrep_fragments_sent = 0;
+ wsrep_trx_fragment_size = 0;
+ wsrep_SR_thd = false;
+ wsrep_rbr_buf = NULL;
+ wsrep_nbo_ctx = NULL;
wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED;
+ wsrep_last_written_gtid = WSREP_GTID_UNDEFINED;
+ wsrep_SR_rollback_replicated_for_trx = WSREP_UNDEFINED_TRX_ID;
wsrep_affected_rows = 0;
+ m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID;
wsrep_replicate_GTID = false;
wsrep_skip_wsrep_GTID = false;
#endif /* WITH_WSREP */
@@ -1454,6 +1476,70 @@ void THD::cleanup(void)
DBUG_ENTER("THD::cleanup");
DBUG_ASSERT(cleanup_done == 0);
+#ifdef WITH_WSREP
+ if (this->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ WSREP_LOG_THD(this, "THD::cleanup");
+ }
+ /*
+ Before cleanup make sure that all wsrep transactions
+ will be rolled back.
+ */
+ if (WSREP_CLIENT_NNULL(this))
+ {
+ mysql_mutex_lock(&this->LOCK_wsrep_thd);
+ DBUG_ASSERT(this->wsrep_query_state() == QUERY_EXITING);
+ /*
+ Background rollback is in process
+ */
+ if (this->wsrep_is_rolling_back())
+ {
+ /*
+ Rollback thread is rolling back a transaction for this thd,
+ wait until it has finished.
+ */
+ while (this->wsrep_is_rolling_back())
+ {
+ mysql_mutex_unlock(&this->LOCK_wsrep_thd);
+ my_sleep(1000);
+ mysql_mutex_lock(&this->LOCK_wsrep_thd);
+ }
+ DBUG_ASSERT(this->wsrep_conflict_state() == ABORTED);
+ }
+
+ /*
+ BF abort happened while the client was idle.
+ */
+ if (this->wsrep_conflict_state() == ABORTED)
+ {
+ wsrep_cleanup_transaction(this);
+ }
+
+ if (this->wsrep_conflict_state() == MUST_ABORT)
+ {
+ wsrep_client_rollback(this);
+ }
+
+ mysql_mutex_unlock(&this->LOCK_wsrep_thd);
+
+ trans_rollback(this);
+ mysql_mutex_lock(&this->LOCK_wsrep_thd);
+
+ if (this->wsrep_exec_mode == LOCAL_ROLLBACK ||
+ this->wsrep_conflict_state() == ABORTING)
+ {
+ wsrep_post_rollback(this);
+ wsrep_cleanup_transaction(this);
+ }
+
+ DBUG_ASSERT(this->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID &&
+ this->wsrep_conflict_state() == NO_CONFLICT);
+
+ mysql_mutex_unlock(&this->LOCK_wsrep_thd);
+ }
+
+ this->wsrep_client_thread= 0;
+#endif /* WITH_WSREP */
set_killed(KILL_CONNECTION);
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
if (transaction.xid_state.xa_state == XA_PREPARED)
@@ -1603,15 +1689,25 @@ THD::~THD()
THD is not deleted while they access it. The following mutex_lock
ensures that no one else is using this THD and it's now safe to delete
*/
+ if (WSREP(this)) mysql_mutex_lock(&LOCK_wsrep_thd);
mysql_mutex_lock(&LOCK_thd_kill);
mysql_mutex_unlock(&LOCK_thd_kill);
+ if (WSREP(this)) mysql_mutex_unlock(&LOCK_wsrep_thd);
-#ifdef WITH_WSREP
- delete wsrep_rgi;
-#endif
if (!free_connection_done)
free_connection();
+#ifdef WITH_WSREP
+ mysql_mutex_lock(&LOCK_wsrep_thd);
+ mysql_mutex_unlock(&LOCK_wsrep_thd);
+ mysql_mutex_destroy(&LOCK_wsrep_thd);
+ mysql_cond_destroy(&COND_wsrep_thd);
+ if (wsrep_rgi != NULL) {
+ delete wsrep_rgi;
+ wsrep_rgi = NULL;
+ }
+ if (wsrep_status_vars) wsrep->stats_free(wsrep, wsrep_status_vars);
+#endif
mdl_context.destroy();
free_root(&transaction.mem_root,MYF(0));
@@ -1793,6 +1889,7 @@ void THD::awake_no_mutex(killed_state state_to_set)
DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d",
this, current_thd, (int) state_to_set));
THD_CHECK_SENTRY(this);
+ if (WSREP(this)) mysql_mutex_assert_owner(&LOCK_wsrep_thd);
mysql_mutex_assert_owner(&LOCK_thd_kill);
print_aborted_warning(3, "KILLED");
@@ -1977,14 +2074,21 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
*/
if (!thd_table->needs_reopen())
{
+#ifdef WITH_WSREP
signalled|= mysql_lock_abort_for_thread(this, thd_table);
- if (WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ if (WSREP_NNULL(this) && wsrep_thd_is_BF((void*)this, FALSE))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) this->real_id);
wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
}
}
+ else
+ {
+#else
+ signalled|= mysql_lock_abort_for_thread(this, thd_table);
+#endif /* WITH_WSREP */
+ }
}
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
@@ -4968,11 +5072,13 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
extern "C" int thd_binlog_format(const MYSQL_THD thd)
{
+#ifdef WITH_WSREP
if (WSREP(thd))
{
/* for wsrep binlog format is meaningful also when binlogging is off */
- return (int) thd->wsrep_binlog_format();
+ return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format);
}
+#endif /* WITH_WSREP */
if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG))
return (int) thd->variables.binlog_format;
return BINLOG_FORMAT_UNSPEC;
@@ -5455,6 +5561,13 @@ void THD::set_query_and_id(char *query_arg, uint32 query_length_arg,
set_query_inner(query_arg, query_length_arg, cs);
mysql_mutex_unlock(&LOCK_thd_data);
query_id= new_query_id;
+#ifdef WITH_WSREP
+ if (WSREP_NNULL(this) && wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ set_wsrep_next_trx_id(query_id);
+ WSREP_DEBUG("assigned new next trx id: %lu", wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
}
/** Assign a new value to thd->mysys_var. */
@@ -5900,9 +6013,27 @@ int THD::decide_logging_format(TABLE_LIST *tables)
binlogging is off, or if the statement is filtered out from the
binlog by filtering rules.
*/
+#ifdef WITH_WSREP
+ if (WSREP_CLIENT_NNULL(this) && variables.wsrep_trx_fragment_size > 0)
+ {
+ if (!is_current_stmt_binlog_format_row())
+ {
+ my_message(ER_NOT_SUPPORTED_YET,
+ "Streaming replication not supported with "
+ "binlog_format=STATEMENT", MYF(0));
+ DBUG_RETURN(-1);
+ }
+ }
+
+ if ((WSREP_EMULATE_BINLOG_NNULL(this) ||
+ (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG))) &&
+ !(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
+ !binlog_filter->db_ok(db.str)))
+#else
if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) &&
!(wsrep_binlog_format() == BINLOG_FORMAT_STMT &&
!binlog_filter->db_ok(db.str)))
+#endif /* WITH_WSREP */
{
if (is_bulk_op())
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 25e2d736cdc..8e08864abf7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -61,8 +61,27 @@ void set_thd_stage_info(void *thd,
#include "my_apc.h"
#include "rpl_gtid.h"
-#include "wsrep_mysqld.h"
+#ifdef WITH_WSREP
+#include <vector>
+#include "wsrep_mysqld.h"
+#include "wsrep_binlog.h"
+struct wsrep_thd_shadow {
+ ulonglong options;
+ uint server_status;
+ enum wsrep_exec_mode wsrep_exec_mode;
+ Vio *vio;
+ ulong tx_isolation;
+ char *db;
+ size_t db_length;
+ my_hrtime_t user_time;
+ longlong row_count_func;
+};
+#include <map>
+#include <set>
+#include <string>
+typedef std::map<std::string, std::set<std::string> > wsrep_key_set;
+#endif /* WITH_WSREP */
class Reprepare_observer;
class Relay_log_info;
struct rpl_group_info;
@@ -705,10 +724,12 @@ typedef struct system_variables
my_bool wsrep_on;
my_bool wsrep_causal_reads;
+ uint wsrep_sync_wait;
+ ulong wsrep_retry_autocommit;
+ ulong wsrep_trx_fragment_size;
+ ulong wsrep_trx_fragment_unit;
+ ulong wsrep_OSU_method;
my_bool wsrep_dirty_reads;
- uint wsrep_sync_wait;
- ulong wsrep_retry_autocommit;
- ulong wsrep_OSU_method;
double long_query_time_double, max_statement_time_double;
my_bool pseudo_slave_mode;
@@ -3204,7 +3225,6 @@ public:
mysql_bin_log.start_union_events() call.
*/
bool unioned_events_trans;
-
/*
'queries' (actually SP statements) that run under inside this binlog
union have thd->query_id >= first_query_id.
@@ -3212,7 +3232,9 @@ public:
query_id_t first_query_id;
} binlog_evt_union;
+ mysql_mutex_t LOCK_wsrep_thd;
mysql_cond_t COND_wsrep_thd;
+
/**
Internal parser state.
Note that since the parser is not re-entrant, we keep only one parser
@@ -3295,11 +3317,17 @@ public:
void awake_no_mutex(killed_state state_to_set);
void awake(killed_state state_to_set)
{
+ /*
+ mutex locking order (LOCK_wsrep_thd - LOCK_thd_kill)) requires
+ to grab LOCK_wsrep_thd here
+ */
+ mysql_mutex_lock(&LOCK_wsrep_thd);
mysql_mutex_lock(&LOCK_thd_kill);
awake_no_mutex(state_to_set);
mysql_mutex_unlock(&LOCK_thd_kill);
+ mysql_mutex_unlock(&LOCK_wsrep_thd);
}
-
+
/** Disconnect the associated communication endpoint. */
void disconnect();
@@ -4477,6 +4505,13 @@ public:
void set_query_id(query_id_t new_query_id)
{
query_id= new_query_id;
+#ifdef WITH_WSREP
+ if (WSREP(this) && wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ set_wsrep_next_trx_id(query_id);
+ WSREP_DEBUG("assigned new next trx id: %lu", wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
}
void set_open_tables(TABLE *open_tables_arg)
{
@@ -4738,33 +4773,248 @@ public:
const bool wsrep_applier; /* dedicated slave applier thread */
bool wsrep_applier_closing; /* applier marked to close */
bool wsrep_client_thread; /* to identify client threads*/
- bool wsrep_PA_safe;
- bool wsrep_converted_lock_session;
- bool wsrep_apply_toi; /* applier processing in TOI */
enum wsrep_exec_mode wsrep_exec_mode;
query_id_t wsrep_last_query_id;
- enum wsrep_query_state wsrep_query_state;
- enum wsrep_conflict_state wsrep_conflict_state;
+ XID wsrep_xid;
+
+ /** This flag denotes that record locking should be skipped during INSERT
+ and gap locking during SELECT. Only used by the streaming replication thread
+ that only modifies the wsrep_schema.SR table. */
+ my_bool wsrep_skip_locking;
+
+ /*
+ Delegated rollback:
+
+ Wsrep_query_state, wsrep_conflict_state and wsrep_exec_mode define
+ together the state for rollback process. In most of the cases the
+ client thread will handle the rollback, but if the BF abort happens when
+ the client thread is in QUERY_IDLE state, the rollback process
+ is delegated to rollbacker thread. In this case rollbacker thread
+ will do the rollback on behalf of client thread and will leave
+ the states into the following
+ * wsrep_query_state = QUERY_IDLE
+ * wsrep_conflict_state = ABORTED
+ * wsrep_exec_mode = LOCAL_ROLLBACK
+ */
+
+ /*
+ Set wsrep_query_state
+
+ Asserts LOCK_wsrep_thd ownership.
+ */
+ void set_wsrep_query_state(enum wsrep_query_state state)
+ {
+ mysql_mutex_assert_owner(&LOCK_wsrep_thd);
+ /*
+ State machine:
+
+ QI - QUERY_IDLE
+ QX - QUERY_EXEC
+ QC - QUERY_COMMITTING
+ QOC - QUERY_ORDERED_COMMIT
+ QE - QUERY_EXITING
+
+ |---> QE
+ |
+ o--> QI <-> QX -> QC -> QOC
+ ^ | |
+ |-------------
+ */
+ static const bool allowed[QUERY_EXITING + 1][QUERY_EXITING + 1] =
+ {
+ /* QI QX QC QOC, QE To / From */
+ { false, true, false, false, true }, /* QI */
+ { true , false, true, false, false }, /* QX */
+ { false, true, false, true, false }, /* QC */
+ { false, true, false, false, false }, /* QOC */
+ { false, false, false, false, false } /* QE */
+ };
+ if (allowed[m_wsrep_query_state][state] == false)
+ {
+ WSREP_DEBUG("Unallowed query state change %d -> %d",
+ m_wsrep_query_state, state);
+ }
+ DBUG_ASSERT(allowed[m_wsrep_query_state][state] == true);
+ m_wsrep_query_state= state;
+ }
+
+ /*
+ Return current wsrep_query_state
+
+ Asserts LOCK_wsrep_thd ownership
+ */
+ enum wsrep_query_state wsrep_query_state() const
+ {
+ mysql_mutex_assert_owner(&LOCK_wsrep_thd);
+ return m_wsrep_query_state;
+ }
+
+ /*
+ Return current wsrep_query_state
+
+ Does not assert LOCK_wsrep_thd ownership, useful for
+ debugging and logging where strict access is not
+ absolutely required.
+ */
+ enum wsrep_query_state wsrep_query_state_unsafe() const
+ {
+ return m_wsrep_query_state;
+ }
+
+ void set_wsrep_conflict_state(enum wsrep_conflict_state state)
+ {
+ mysql_mutex_assert_owner(&LOCK_wsrep_thd);
+ /*
+ State machine
+
+ NC - NO_CONFLICT
+ MA - MUST_ABORT
+ AB - ABORTING
+ AD - ABORTED
+ MR - MUST_REPLAY
+ RI - REPLAYING
+ RA - RETRY_AUTOCOMMIT
+ CF - CERT_FAILURE
+
+ 1) BF abort
+ 2) Cert failure or rollback
+ 3) Pre commit returns success, so the transaction must be replayed
+ 4) Pre commit return certification failure, cleanup after certification
+ failure
+ 5) Post rollback phase
+ 6) Is autocommit and wsrep_retry_autocommit is set
+ 7) Simultaneous certification failure and BF abort
+
+ 4 5
+ -> NC <-----------------> CF -------------------
+ | ^^ | 7 |
+ | || 1 2 | |
+ | 6||-----------> MA --------> AB ------> AD <-|
+ | | | ^ |
+ | |-> RA | 3 | |
+ | | | |
+ | -> MR -> RI - |
+ | | |
+ |------------------------------------------
+
+ */
+
+ static const bool allowed[CERT_FAILURE + 1][CERT_FAILURE + 1] =
+ {
+ /* NC MA AB AD MR RI RA CF To / From */
+ { false, true, false, false, false, false, true, true }, /* NC */
+ { true, false, true, false, true, false, false, false }, /* MA */
+ { false, false, false, true, false, false, false, false }, /* AB */
+ { true , false, false, false, false, false, false, false }, /* AD */
+ { false, false, false, false, false, true, false, false }, /* MR */
+ { true, false, true, false, false, false, false, false }, /* RI */
+ { true, false, false, false, false, false, false, false }, /* RA */
+ { true, false, true, true, false, false, false, false } /* CF */
+ };
+ if (allowed[m_wsrep_conflict_state][state] == false)
+ {
+ WSREP_DEBUG("Unallowed conflict state change %d -> %d",
+ m_wsrep_conflict_state, state);
+ }
+ DBUG_ASSERT(allowed[m_wsrep_conflict_state][state] == true);
+
+ /*
+ Sanity checks agains query state and thread context
+ */
+ switch (state)
+ {
+ case MUST_ABORT:
+ break;
+ default:
+ /*
+ Only the current thread context may change the state apart from
+ NC -> MA transition.
+ */
+ DBUG_ASSERT(this == current_thd);
+ break;
+ }
+#ifndef DBUG_OFF
+ if (state == NO_CONFLICT)
+ {
+ m_wsrep_conflict_state_history.clear();
+ }
+ else
+ {
+ m_wsrep_conflict_state_history.push_back(m_wsrep_conflict_state);
+ }
+#endif /* DBUG_OFF */
+ m_wsrep_conflict_state= state;
+ }
+
+ /*
+ Return wsrep_conflict_state
+
+ Asserts LOCK_wsrep_thd ownership
+ */
+ enum wsrep_conflict_state wsrep_conflict_state() const
+ {
+ mysql_mutex_assert_owner(&LOCK_wsrep_thd);
+ return m_wsrep_conflict_state;
+ }
+
+ /*
+ Return wsrep_conflict_state
+
+ Does not assert LOCK_wsrep_thd ownership, useful mostly
+ for debugging and logging where strict access is not
+ aboslutely required.
+ */
+ enum wsrep_conflict_state wsrep_conflict_state_unsafe() const
+ {
+ return m_wsrep_conflict_state;
+ }
+
+ /*
+ Check if wsrep rollback process has started
+ */
+ bool wsrep_is_rolling_back() const
+ {
+ return (wsrep_conflict_state() == MUST_ABORT ||
+ wsrep_conflict_state() == ABORTING);
+ }
+
+private:
+ enum wsrep_query_state m_wsrep_query_state;
+ enum wsrep_conflict_state m_wsrep_conflict_state;
+#ifndef DBUG_OFF
+ std::vector<enum wsrep_conflict_state> m_wsrep_conflict_state_history;
+#endif /* DBUG_OFF */
+public:
+
+ // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75
+ // wsrep_seqno_t wsrep_trx_seqno;
wsrep_trx_meta_t wsrep_trx_meta;
uint32 wsrep_rand;
Relay_log_info *wsrep_rli;
rpl_group_info *wsrep_rgi;
+ bool wsrep_converted_lock_session;
wsrep_ws_handle_t wsrep_ws_handle;
+#ifdef WSREP_PROC_INFO
+ // char wsrep_info[128]; /* string for dynamic proc info */
+#endif /* WSREP_PROC_INFO */
ulong wsrep_retry_counter; // of autocommit
- char *wsrep_retry_query;
+ bool wsrep_PA_safe;
+ char* wsrep_retry_query;
size_t wsrep_retry_query_len;
enum enum_server_command wsrep_retry_command;
- enum wsrep_consistency_check_mode
+ enum wsrep_consistency_check_mode
wsrep_consistency_check;
+ wsrep_stats_var* wsrep_status_vars;
int wsrep_mysql_replicated;
- const char *wsrep_TOI_pre_query; /* a query to apply before
- the actual TOI query */
+ const char* wsrep_TOI_pre_query; /* a query to apply before
+ the actual TOI query */
size_t wsrep_TOI_pre_query_len;
wsrep_po_handle_t wsrep_po_handle;
size_t wsrep_po_cnt;
#ifdef GTID_SUPPORT
+ my_bool wsrep_po_in_trans;
rpl_sid wsrep_po_sid;
-#endif /* GTID_SUPPORT */
+#endif /* GTID_SUPPORT */
void *wsrep_apply_format;
char wsrep_info[128]; /* string for dynamic proc info */
/*
@@ -4773,10 +5023,90 @@ public:
table updates from being replicated to other nodes via galera replication.
*/
bool wsrep_ignore_table;
+ bool wsrep_apply_toi; /* applier processing in TOI */
+ ulong wsrep_fragments_sent; // # of fragments replicated
+ // for trx
+ bool wsrep_SR_thd; // is applier THD for streaming
+ // transaction
+ wsrep_trx_id_t wsrep_SR_rollback_replicated_for_trx;
+ wsrep_fragment_set wsrep_SR_fragments;
+ wsrep_key_set wsrep_SR_keys;
+ TABLE_LIST wsrep_SR_table;
+ uchar* wsrep_rbr_buf;
+ Wsrep_nbo_ctx* wsrep_nbo_ctx; // Context for non-blocking operations
wsrep_gtid_t wsrep_sync_wait_gtid;
+ wsrep_gtid_t wsrep_last_written_gtid;
ulong wsrep_affected_rows;
+ bool wsrep_has_ignored_error;
bool wsrep_replicate_GTID;
bool wsrep_skip_wsrep_GTID;
+
+ bool wsrep_is_streaming()
+ {
+ return ((wsrep_fragments_sent > 0) &&
+ (wsrep_exec_mode == LOCAL_STATE ||
+ wsrep_exec_mode == LOCAL_COMMIT ||
+ wsrep_exec_mode == LOCAL_ROLLBACK));
+ }
+
+ /*
+ Return true if the current transaction has been assigned a valid sequence
+ number.
+ */
+ bool wsrep_trx_has_seqno() const
+ {
+ DBUG_ASSERT(wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED ||
+ wsrep_trx_meta.gtid.seqno > 0);
+ return (wsrep_trx_meta.gtid.seqno > 0);
+ }
+
+ /*
+ Return true if current transaction must go through commit ordering.
+ This is the case if the transaction has been assigned valid seqno
+ and has been assigned write set handle.
+ */
+ bool wsrep_trx_must_order_commit() const
+ {
+ return (wsrep_ws_handle.opaque && wsrep_trx_has_seqno());
+ }
+
+ /*
+ Transaction id:
+ * m_wsrep_next_trx_id is assigned on the first query after
+ wsrep_next_trx_id() return WSREP_UNDEFINED_TRX_ID
+ * Each storage engine must assign value of wsrep_next_trx_id()
+ via wsrep_ws_handle_for_trx() when the transaction starts.
+ * Effective transaction id is returned via wsrep_trx_id()
+ */
+
+ /*
+ Return effective transaction id
+ */
+ wsrep_trx_id_t wsrep_trx_id() const
+ {
+ return wsrep_ws_handle.trx_id;
+ }
+
+ /*
+ Set next trx id
+ */
+ void set_wsrep_next_trx_id(query_id_t query_id)
+ {
+ DBUG_ASSERT(wsrep_ws_handle.trx_id == WSREP_UNDEFINED_TRX_ID);
+ //DBUG_ASSERT(query_id != 0);
+ m_wsrep_next_trx_id = (wsrep_trx_id_t) query_id;
+ }
+ /*
+ Return next trx id
+ */
+ wsrep_trx_id_t wsrep_next_trx_id() const
+ {
+ return m_wsrep_next_trx_id;
+ }
+
+private:
+ wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */
+public:
#endif /* WITH_WSREP */
/* Handling of timeouts for commands */
@@ -6255,7 +6585,7 @@ public:
be rolled back or that do not expect any previously metadata
locked tables.
*/
-#define CF_IMPLICT_COMMIT_BEGIN (1U << 6)
+#define CF_IMPLICIT_COMMIT_BEGIN (1U << 6)
/**
Implicitly commit after the SQL statement.
@@ -6273,7 +6603,7 @@ public:
before and after every DDL statement and any statement that
modifies our currently non-transactional system tables.
*/
-#define CF_AUTO_COMMIT_TRANS (CF_IMPLICT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END)
+#define CF_AUTO_COMMIT_TRANS (CF_IMPLICIT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END)
/**
Diagnostic statement.
@@ -6317,6 +6647,13 @@ public:
*/
#define CF_DISALLOW_IN_RO_TRANS (1U << 15)
+#ifdef WITH_WSREP
+/**
+ DDL statement that may be subject to error filtering.
+*/
+#define CF_WSREP_MAY_IGNORE_ERRORS (1U << 24)
+#endif /* WITH_WSREP */
+
/**
Statement that need the binlog format to be unchanged.
*/
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index b48070b9c8f..088dec72313 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -1186,8 +1186,7 @@ void end_connection(THD *thd)
(longlong) thd->thread_id, rcode);
}
}
- thd->wsrep_client_thread= 0;
-#endif
+#endif /* WITH_WSREP */
plugin_thdvar_cleanup(thd);
if (thd->user_connect)
@@ -1408,7 +1407,7 @@ void do_handle_one_connection(CONNECT *connect)
if (WSREP(thd))
{
mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_EXITING;
+ thd->set_wsrep_query_state(QUERY_EXITING);
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
#endif
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 51acf10a98a..a6aa8b999dc 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3902,10 +3902,14 @@ bool select_insert::prepare_eof()
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
trans_table, table->file->table_type()));
- error= (IF_WSREP((thd->wsrep_conflict_state == MUST_ABORT ||
- thd->wsrep_conflict_state == CERT_FAILURE) ? -1 :, )
- (thd->locked_tables_mode <= LTM_LOCK_TABLES ?
- table->file->ha_end_bulk_insert() : 0));
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+
+ error= (IF_WSREP((thd->wsrep_conflict_state() == MUST_ABORT ||
+ thd->wsrep_conflict_state() == CERT_FAILURE) ? -1 :, )
+ (thd->locked_tables_mode <= LTM_LOCK_TABLES ?
+ table->file->ha_end_bulk_insert() : 0));
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
if (likely(!error) && unlikely(thd->is_error()))
error= thd->get_stmt_da()->sql_errno();
@@ -4566,8 +4570,17 @@ bool select_create::send_eof()
#ifdef WITH_WSREP
if (WSREP_ON)
{
+ if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ (void) wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle,
+ thd->wsrep_next_trx_id());
+ }
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ WSREP_DEBUG("CTAS key append for trx: %lu thd %llu query %lld ",
+ thd->wsrep_trx_id(), thd->thread_id, thd->query_id);
+
/*
- append table level exclusive key for CTAS
+ append table level exclusive key for CTAS
*/
wsrep_key_arr_t key_arr= {0, 0};
wsrep_prepare_keys_for_isolation(thd,
@@ -4575,15 +4588,15 @@ bool select_create::send_eof()
create_table->table_name.str,
table_list,
&key_arr);
- int rcode = wsrep->append_key(
- wsrep,
- &thd->wsrep_ws_handle,
- key_arr.keys, //&wkey,
- key_arr.keys_len,
- WSREP_KEY_EXCLUSIVE,
- false);
+ int rcode = wsrep->append_key(wsrep,
+ &thd->wsrep_ws_handle,
+ key_arr.keys, //&wkey,
+ key_arr.keys_len,
+ WSREP_KEY_EXCLUSIVE,
+ false);
wsrep_keys_free(&key_arr);
- if (rcode) {
+ if (rcode)
+ {
DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
WSREP_ERROR("Appending table key for CTAS failed: %s, %d",
(wsrep_thd_query(thd)) ?
@@ -4591,7 +4604,7 @@ bool select_create::send_eof()
return true;
}
/* If commit fails, we should be able to reset the OK status. */
- thd->get_stmt_da()->set_overwrite_status(TRUE);
+ thd->get_stmt_da()->set_overwrite_status(true);
}
#endif /* WITH_WSREP */
trans_commit_stmt(thd);
@@ -4600,13 +4613,13 @@ bool select_create::send_eof()
#ifdef WITH_WSREP
if (WSREP_ON)
{
- thd->get_stmt_da()->set_overwrite_status(FALSE);
- mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state != NO_CONFLICT)
+ thd->get_stmt_da()->set_overwrite_status(false);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() != NO_CONFLICT)
{
- WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s",
- (longlong) thd->thread_id, thd->wsrep_conflict_state,
- thd->query());
+ WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s",
+ thd->thread_id, thd->wsrep_conflict_state(),
+ WSREP_QUERY(thd));
mysql_mutex_unlock(&thd->LOCK_thd_data);
abort_result_set();
DBUG_RETURN(true);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index dd6e723c953..c2d4de0e081 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -42,6 +42,8 @@
#include "sql_derived.h"
#include "sql_show.h"
+#include "wsrep_mysqld.h"
+
extern "C" int _my_b_net_read(IO_CACHE *info, uchar *Buffer, size_t Count);
class XML_TAG {
@@ -106,7 +108,7 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table,
{
DBUG_ENTER("wsrep_load_data_split");
- if (!wsrep_load_data_splitting || !wsrep_on(thd)
+ if (!wsrep_load_data_splitting || !WSREP(thd)
|| !info.records || (info.records % 10000)
|| !thd->transaction.stmt.ha_list
|| thd->transaction.stmt.ha_list->ht() != binlog_hton
@@ -119,10 +121,15 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table,
if (hton->db_type != DB_TYPE_INNODB)
DBUG_RETURN(false);
WSREP_DEBUG("intermediate transaction commit in LOAD DATA");
+#ifdef OUT /* this is old mariadb implementation... */
if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true);
if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true);
wsrep_post_commit(thd, true);
hton->commit(hton, thd, true);
+#else
+ /* ...which is replaced by this */
+ wsrep_tc_log_commit(thd);
+#endif
table->file->extra(HA_EXTRA_FAKE_START_STMT);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1baa26ab465..18cded52a74 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -111,8 +111,9 @@
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
-static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
+static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state,
bool is_com_multi,
bool is_next_command);
@@ -877,6 +878,16 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_REVOKE_ALL]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_INSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
+#ifdef WITH_WSREP
+ /*
+ Statements for which some errors are ignored when
+ wsrep_ignore_apply_errors = WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL
+ */
+ sql_command_flags[SQLCOM_DROP_DB]|= CF_WSREP_MAY_IGNORE_ERRORS;
+ sql_command_flags[SQLCOM_DROP_TABLE]|= CF_WSREP_MAY_IGNORE_ERRORS;
+ sql_command_flags[SQLCOM_DROP_INDEX]|= CF_WSREP_MAY_IGNORE_ERRORS;
+ sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_WSREP_MAY_IGNORE_ERRORS;
+#endif /* WITH_WSREP */
}
bool sqlcom_can_generate_row_events(const THD *thd)
@@ -1174,6 +1185,7 @@ static enum enum_server_command fetch_command(THD *thd, char *packet)
#ifdef WITH_WSREP
static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
{
+ bool accessible_tables = true;
for (const TABLE_LIST *table= tables; table; table= table->next_global)
{
TABLE_CATEGORY c;
@@ -1182,7 +1194,7 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
if (c != TABLE_CATEGORY_INFORMATION && c != TABLE_CATEGORY_PERFORMANCE)
return false;
}
- return true;
+ return accessible_tables;
}
#endif /* WITH_WSREP */
#ifndef EMBEDDED_LIBRARY
@@ -1212,19 +1224,6 @@ bool do_command(THD *thd)
enum enum_server_command command;
DBUG_ENTER("do_command");
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_IDLE;
- if (thd->wsrep_conflict_state==MUST_ABORT)
- {
- wsrep_client_rollback(thd);
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
-
/*
indicator of uninitialized lex => normal flow of errors handling
(see my_message_sql)
@@ -1265,29 +1264,6 @@ bool do_command(THD *thd)
DEBUG_SYNC(thd, "before_do_command_net_read");
packet_length= my_net_read_packet(net, 1);
-#ifdef WITH_WSREP
- if (WSREP(thd)) {
- mysql_mutex_lock(&thd->LOCK_thd_data);
-
- /* these THD's are aborted or are aborting during being idle */
- if (thd->wsrep_conflict_state == ABORTING)
- {
- while (thd->wsrep_conflict_state == ABORTING) {
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- my_sleep(1000);
- mysql_mutex_lock(&thd->LOCK_thd_data);
- }
- thd->store_globals();
- }
- else if (thd->wsrep_conflict_state == ABORTED)
- {
- thd->store_globals();
- }
-
- thd->wsrep_query_state= QUERY_EXEC;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
if (unlikely(packet_length == packet_error))
{
@@ -1295,20 +1271,6 @@ bool do_command(THD *thd)
net->error,
vio_description(net->vio)));
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state == MUST_ABORT)
- {
- DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu",
- (ulong) thd->real_id));
- wsrep_client_rollback(thd);
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-#endif /* WITH_WSREP */
-
/* Instrument this broken statement as "statement/com/error" */
thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
com_statement_info[COM_END].
@@ -1365,7 +1327,7 @@ bool do_command(THD *thd)
Bail out if DB snapshot has not been installed.
*/
if (!thd->wsrep_applier &&
- (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) &&
+ (!wsrep_ready_get() || wsrep_reject_queries != WSREP_REJECT_NONE) &&
(server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0)
{
my_message(ER_UNKNOWN_COM_ERROR,
@@ -1381,7 +1343,7 @@ bool do_command(THD *thd)
goto out;
}
}
-#endif
+#endif /* WITH_WSREP */
/* Restore read timeout value */
my_net_set_read_timeout(net, thd->variables.net_read_timeout);
@@ -1390,37 +1352,6 @@ bool do_command(THD *thd)
DBUG_ASSERT(!thd->apc_target.is_enabled());
return_value= dispatch_command(command, thd, packet+1,
(uint) (packet_length-1), FALSE, FALSE);
-#ifdef WITH_WSREP
- if (WSREP(thd))
- {
- while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
- {
- WSREP_DEBUG("Retry autocommit for: %s\n", thd->wsrep_retry_query);
- CHARSET_INFO *current_charset = thd->variables.character_set_client;
- if (!is_supported_parser_charset(current_charset))
- {
- /* Do not use non-supported parser character sets */
- WSREP_WARN("Current client character set is non-supported parser "
- "character set: %s", current_charset->csname);
- thd->variables.character_set_client = &my_charset_latin1;
- WSREP_WARN("For retry temporally setting character set to : %s",
- my_charset_latin1.csname);
- }
- thd->clear_error();
- return_value= dispatch_command(command, thd, thd->wsrep_retry_query,
- thd->wsrep_retry_query_len, FALSE, FALSE);
- thd->variables.character_set_client = current_charset;
- }
-
- if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING)
- {
- my_free(thd->wsrep_retry_query);
- thd->wsrep_retry_query = NULL;
- thd->wsrep_retry_query_len = 0;
- thd->wsrep_retry_command = COM_CONNECT;
- }
- }
-#endif /* WITH_WSREP */
DBUG_ASSERT(!thd->apc_target.is_enabled());
out:
@@ -1576,36 +1507,75 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
compile_time_assert(COM_END == 255);
#ifdef WITH_WSREP
- if (WSREP(thd))
+ bool wsrep_on= WSREP_ON;
+ if (wsrep_on)
{
- if (!thd->in_multi_stmt_transaction_mode())
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ DBUG_ASSERT(thd->wsrep_query_state() == QUERY_IDLE);
+ if (thd->wsrep_is_rolling_back())
{
- thd->wsrep_PA_safe= true;
+ /*
+ Rollback thread is rolling back a transaction for this thd,
+ wait until it has finished.
+ */
+ while (thd->wsrep_is_rolling_back())
+ {
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ my_sleep(1000);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ }
+ DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED);
}
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_EXEC;
- if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
- {
- thd->wsrep_conflict_state= NO_CONFLICT;
- }
- if (thd->wsrep_conflict_state== MUST_ABORT)
- {
- wsrep_client_rollback(thd);
- }
- /* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */
- if (thd->wsrep_conflict_state == ABORTED &&
- command != COM_STMT_CLOSE && command != COM_QUIT)
+ /*
+ BF aborter should atomically check thd query state and start
+ background rollback process if the thd query state is QUERY_IDLE.
+ Because the wait for the background rollback is done above we should
+ be here either in NO_CONFLICT or in ABORTED state.
+ */
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == ABORTED);
+
+ thd->set_wsrep_query_state(QUERY_EXEC);
+
+ /*
+ Aborted by background rollbacker thread. Jump straight to dispatch_end
+ label where the error handling is performed.
+
+ We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted.
+ (see MDEV-10812).
+ */
+ if (thd->wsrep_conflict_state() == ABORTED)
{
- my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
- MYF(0));
- WSREP_DEBUG("Deadlock error for: %s", thd->query());
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- thd->reset_killed();
- thd->mysys_var->abort = 0;
- thd->wsrep_conflict_state = NO_CONFLICT;
- thd->wsrep_retry_counter = 0;
- goto dispatch_end;
+ thd->store_globals();
+ WSREP_LOG_THD(thd, "enter found BF aborted");
+ DBUG_ASSERT(!thd->get_stmt_da()->is_set());
+
+ if (command == COM_STMT_PREPARE ||
+ command == COM_STMT_FETCH ||
+ command == COM_STMT_SEND_LONG_DATA ||
+ command == COM_STMT_CLOSE ||
+ command == COM_QUIT
+ )
+ {
+ WSREP_DEBUG("Prepared Statement bail out or COM_QUIT");
+ }
+ else
+ {
+ thd->reset_killed();
+ thd->mysys_var->abort = 0;
+ thd->wsrep_retry_counter = 0;
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#ifdef WSREP_TODO
+ /*
+ Increment threads running to compensate dec_thread_running() called
+ after dispatch_end label.
+ */
+ inc_thread_running();
+#endif /* WSREP_TODO */
+ goto dispatch_end;
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
@@ -1656,6 +1626,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
*/
thd->set_query_id(get_query_id());
}
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ WSREP_DEBUG("assigned new next trx id: %lu", thd->wsrep_next_trx_id());
+ }
+#endif /* WITH_WSREP */
if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
statistic_increment(thd->status_var.questions, &LOCK_status);
@@ -1840,8 +1817,29 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
if (WSREP_ON)
- wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state,
- is_com_multi, is_next_command);
+ {
+ if (wsrep_mysql_parse(thd, thd->query(), thd->query_length(),
+ &parser_state,
+ is_com_multi, is_next_command))
+ {
+ WSREP_DEBUG("Deadlock error for: %s", thd->query());
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->killed = NOT_KILLED;
+ thd->mysys_var->abort = 0;
+#ifdef WITH_WSREP
+ thd->wsrep_retry_counter = 0;
+#endif
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#ifdef WSREP_TODO
+ /*
+ Increment threads running to compensate dec_thread_running() called
+ after dispatch_end label.
+ */
+ inc_thread_running();
+#endif /* WSREP_TODO */
+ goto dispatch_end;
+ }
+ }
else
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state,
is_com_multi, is_next_command);
@@ -1930,8 +1928,30 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
parser_state.reset(beginning_of_next_stmt, length);
if (WSREP_ON)
- wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state,
- is_com_multi, is_next_command);
+ {
+ if (wsrep_mysql_parse(thd, beginning_of_next_stmt,
+ length, &parser_state,
+ is_com_multi, is_next_command))
+ {
+ WSREP_DEBUG("Deadlock error for: %s", thd->query());
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->killed = NOT_KILLED;
+ thd->mysys_var->abort = 0;
+#ifdef WITH_WSREP
+ thd->wsrep_retry_counter = 0;
+#endif
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+#ifdef WSREP_TODO
+ /*
+ Increment threads running to compensate dec_thread_running() called
+ after dispatch_end label.
+ */
+ inc_thread_running();
+#endif /* WSREP_TODO */
+
+ goto dispatch_end;
+ }
+ }
else
mysql_parse(thd, beginning_of_next_stmt, length, &parser_state,
is_com_multi, is_next_command);
@@ -2367,10 +2387,10 @@ com_multi_end:
break;
}
-#ifdef WITH_WSREP
dispatch_end:
+#ifdef WITH_WSREP
- if (WSREP(thd))
+ if (wsrep_on)
{
/*
MDEV-10812
@@ -2378,15 +2398,51 @@ com_multi_end:
*/
DBUG_ASSERT((command != COM_QUIT && command != COM_STMT_CLOSE)
|| thd->get_stmt_da()->is_disabled());
- /* wsrep BF abort in query exec phase */
- mysql_mutex_lock(&thd->LOCK_thd_data);
- do_end_of_statement= thd->wsrep_conflict_state != REPLAYING &&
- thd->wsrep_conflict_state != RETRY_AUTOCOMMIT;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
- else
- do_end_of_statement= true;
+ /*
+ BF aborted before sending response back to client
+ */
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ do_end_of_statement= thd->wsrep_conflict_state() != REPLAYING &&
+ thd->wsrep_conflict_state() != RETRY_AUTOCOMMIT;
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ wsrep_client_rollback(thd);
+ wsrep_post_rollback(thd);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED);
+ }
+ if (thd->wsrep_conflict_state() == ABORTED &&
+ !(command == COM_STMT_PREPARE ||
+ command == COM_STMT_FETCH ||
+ command == COM_STMT_SEND_LONG_DATA ||
+ command == COM_STMT_CLOSE ||
+ command == COM_QUIT
+ ))
+ {
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ wsrep_cleanup_transaction(thd);
+ WSREP_LOG_THD(thd, "leave");
+ }
+
+ /*
+ Final check after sending response back to client. Handle possible
+ BF abort and query state change atomically. Don't call
+ wsrep_cleanup_transaction() to leave thd->wsrep_conflict_state()
+ to ABORTED so that the rollback will be detected when the client
+ returns to action.
+ */
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ wsrep_client_rollback(thd);
+ wsrep_post_rollback(thd);
+ WSREP_LOG_THD(thd, "after return to client found BF aborted");
+ }
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ } else { /* if (WSREP(thd))... */
+ do_end_of_statement= true;
+ }
#endif /* WITH_WSREP */
if (do_end_of_statement)
@@ -3414,7 +3470,7 @@ mysql_execute_command(THD *thd)
} /* endif unlikely slave */
#endif
#ifdef WITH_WSREP
- if (wsrep && WSREP(thd))
+ if (WSREP(thd))
{
/*
change LOCK TABLE WRITE to transaction
@@ -3444,8 +3500,8 @@ mysql_execute_command(THD *thd)
* allow SET and SHOW queries and reads from information schema
* and dirty reads (if configured)
*/
- if (!thd->wsrep_applier &&
- !(wsrep_ready && wsrep_reject_queries == WSREP_REJECT_NONE) &&
+ if (!(thd->wsrep_applier || thd->wsrep_SR_thd) &&
+ !(wsrep_ready_get() && wsrep_reject_queries == WSREP_REJECT_NONE) &&
!(thd->variables.wsrep_dirty_reads &&
(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) &&
!wsrep_tables_accessible_when_detached(all_tables) &&
@@ -3610,7 +3666,7 @@ mysql_execute_command(THD *thd)
not run in it's own transaction it may simply never appear on
the slave in case the outside transaction rolls back.
*/
- if (stmt_causes_implicit_commit(thd, CF_IMPLICT_COMMIT_BEGIN))
+ if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN))
{
/*
Note that this should never happen inside of stored functions
@@ -3681,6 +3737,17 @@ mysql_execute_command(THD *thd)
/* Start timeouts */
thd->set_query_timer();
+#ifdef WITH_WSREP
+ /*
+ THD is executing non-blocking operation. Set mark that the
+ execution has made it to actual command execution.
+ */
+ if (thd->wsrep_nbo_ctx) {
+ DBUG_ASSERT(thd->wsrep_nbo_ctx->executing() == false);
+ thd->wsrep_nbo_ctx->set_executing(true);
+ }
+#endif /* WITH_WSREP */
+
switch (lex->sql_command) {
case SQLCOM_SHOW_EVENTS:
@@ -3742,12 +3809,17 @@ mysql_execute_command(THD *thd)
case SQLCOM_SELECT:
{
#ifdef WITH_WSREP
- if (lex->sql_command == SQLCOM_SELECT)
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_READ)
- else
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW)
+ DBUG_ASSERT(thd->wsrep_exec_mode != REPL_RECV);
+ if (lex->sql_command == SQLCOM_SELECT)
+ {
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_READ);
+ }
+ else
+ {
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
+ }
#endif /* WITH_WSREP */
-
+
thd->status_var.last_query_cost= 0.0;
/*
@@ -4550,9 +4622,7 @@ end_with_restore_list:
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
ha_rows found= 0, updated= 0;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if (update_precheck(thd, all_tables))
break;
@@ -4701,9 +4771,7 @@ end_with_restore_list:
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
/*
Since INSERT DELAYED doesn't support temporary tables, we could
@@ -4761,9 +4829,7 @@ end_with_restore_list:
select_insert *sel_result;
bool explain= MY_TEST(lex->describe);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if ((res= insert_precheck(thd, all_tables)))
break;
@@ -4883,9 +4949,7 @@ end_with_restore_list:
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
select_result *sel_result=lex->result;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if ((res= delete_precheck(thd, all_tables)))
break;
@@ -4945,9 +5009,7 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
multi_delete *result;
- if (WSREP_CLIENT(thd) &&
- wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
- goto error;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
if ((res= multi_delete_precheck(thd, all_tables)))
break;
@@ -5121,9 +5183,46 @@ end_with_restore_list:
if (check_one_table_access(thd, privilege, all_tables))
goto error;
+#ifdef WITH_WSREP
+ /*
+ If wsrep_load_data_splitting is configured make LOAD DATA to
+ replicate on each 10K rows.
+
+ If streaming replication is not configured make LOAD DATA to
+ replicate on each 1MB.
+ */
+ ulong wsrep_trx_fragment_size_orig= thd->variables.wsrep_trx_fragment_size;
+ ulong wsrep_trx_fragment_unit_orig= thd->variables.wsrep_trx_fragment_unit;
+ const bool wsrep_on= WSREP(thd);
+ if (wsrep_on)
+ {
+ if (!wsrep_provider_is_SR_capable() ||
+ !thd->is_current_stmt_binlog_format_row())
+ {
+ thd->variables.wsrep_trx_fragment_size= 0;
+ }
+ else if (wsrep_load_data_splitting)
+ {
+ thd->variables.wsrep_trx_fragment_size= 10000;
+ thd->variables.wsrep_trx_fragment_unit= WSREP_FRAG_ROWS;
+ }
+ else if (thd->variables.wsrep_trx_fragment_size == 0)
+ {
+ thd->variables.wsrep_trx_fragment_size= (1 << 20);
+ thd->variables.wsrep_trx_fragment_unit= WSREP_FRAG_BYTES;
+ }
+ }
+#endif /* WITH_WSREP */
res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
lex->update_list, lex->value_list, lex->duplicates,
lex->ignore, (bool) lex->local_file);
+#ifdef WITH_WSREP
+ if (wsrep_on)
+ {
+ thd->variables.wsrep_trx_fragment_size= wsrep_trx_fragment_size_orig;
+ thd->variables.wsrep_trx_fragment_unit= wsrep_trx_fragment_unit_orig;
+ }
+#endif /* WITH_WSREP */
break;
}
@@ -5763,6 +5862,7 @@ end_with_restore_list:
thd->mdl_context.release_transactional_locks();
WSREP_DEBUG("BEGIN failed, MDL released: %lld",
(longlong) thd->thread_id);
+ WSREP_DEBUG("stmt_da, sql_errno: %d", (thd->get_stmt_da()->is_error()) ? thd->get_stmt_da()->sql_errno() : 0);
goto error;
}
my_ok(thd);
@@ -5804,15 +5904,17 @@ end_with_restore_list:
}
#ifdef WITH_WSREP
if (WSREP(thd)) {
-
- if (thd->wsrep_conflict_state == NO_CONFLICT ||
- thd->wsrep_conflict_state == REPLAYING)
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == REPLAYING)
{
my_ok(thd);
}
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
} else {
#endif /* WITH_WSREP */
- my_ok(thd);
+
+ my_ok(thd);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
@@ -5853,12 +5955,17 @@ end_with_restore_list:
thd->set_killed(KILL_CONNECTION);
#ifdef WITH_WSREP
if (WSREP(thd)) {
- if (thd->wsrep_conflict_state == NO_CONFLICT) {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ bool send_ok= (thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == REPLAYING);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ if (send_ok)
+ {
my_ok(thd);
}
} else {
#endif /* WITH_WSREP */
- my_ok(thd);
+ my_ok(thd);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
@@ -6305,6 +6412,17 @@ finish:
DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
thd->in_multi_stmt_transaction_mode());
+#ifdef WITH_WSREP
+ /*
+ Thread was executing non-blocking operation. Total order isolation
+ has been released after locking table names. We need to grab
+ total order isolation section here again to commit/binlog in order.
+ */
+ if (thd->wsrep_nbo_ctx)
+ {
+ wsrep_end_nbo_lock(thd, first_table);
+ }
+#endif /* WITH_WSREP */
lex->unit.cleanup();
@@ -6331,25 +6449,6 @@ finish:
THD_STAGE_INFO(thd, stage_rollback);
trans_rollback_stmt(thd);
}
-#ifdef WITH_WSREP
- if (thd->spcont &&
- (thd->wsrep_conflict_state == MUST_ABORT ||
- thd->wsrep_conflict_state == ABORTED ||
- thd->wsrep_conflict_state == CERT_FAILURE))
- {
- /*
- The error was cleared, but THD was aborted by wsrep and
- wsrep_conflict_state is still set accordingly. This
- situation is expected if we are running a stored procedure
- that declares a handler that catches ER_LOCK_DEADLOCK error.
- In which case the error may have been cleared in method
- sp_rcontext::handle_sql_condition().
- */
- trans_rollback_stmt(thd);
- thd->wsrep_conflict_state= NO_CONFLICT;
- thd->killed= NOT_KILLED;
- }
-#endif /* WITH_WSREP */
else
{
/* If commit fails, we should be able to reset the OK status. */
@@ -6365,9 +6464,6 @@ finish:
/* Free tables. Set stage 'closing tables' */
close_thread_tables(thd);
-#ifdef WITH_WSREP
- thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
-#endif /* WITH_WSREP */
#ifndef DBUG_OFF
@@ -6429,9 +6525,10 @@ finish:
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
- WSREP_TO_ISOLATION_END;
-
#ifdef WITH_WSREP
+ thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
+
+ WSREP_TO_ISOLATION_END;
/*
Force release of transactional locks if not in active MST and wsrep is on.
*/
@@ -6444,11 +6541,18 @@ finish:
(longlong) thd->thread_id);
thd->mdl_context.release_transactional_locks();
}
+
+ /*
+ Non-blocking operation finished execution.
+ */
+ if (thd->wsrep_nbo_ctx) thd->wsrep_nbo_ctx->set_executing(false);
+
+ /* assume PA safety for next transaction */
+ thd->wsrep_PA_safe= true;
#endif /* WITH_WSREP */
DBUG_RETURN(res || thd->is_error());
-}
-
+ }
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
{
@@ -6568,12 +6672,12 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
return res;
}
-
static bool execute_show_status(THD *thd, TABLE_LIST *all_tables)
{
bool res;
system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var;
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
@@ -6592,6 +6696,8 @@ static bool execute_show_status(THD *thd, TABLE_LIST *all_tables)
offsetof(STATUS_VAR, last_cleared_system_status_var));
mysql_mutex_unlock(&LOCK_status);
return res;
+ error:
+ return true;
}
@@ -7833,22 +7939,23 @@ void mysql_init_multi_delete(LEX *lex)
lex->query_tables_last= &lex->query_tables;
}
-static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
+static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state,
bool is_com_multi,
bool is_next_command)
{
#ifdef WITH_WSREP
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
bool is_autocommit=
- !thd->in_multi_stmt_transaction_mode() &&
- thd->wsrep_conflict_state == NO_CONFLICT &&
+ !thd->in_multi_stmt_transaction_mode() &&
+ thd->wsrep_conflict_state() == NO_CONFLICT &&
!thd->wsrep_applier;
do
{
- if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
+ if (thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT)
{
- thd->wsrep_conflict_state= NO_CONFLICT;
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
/* Performance Schema Interface instrumentation, begin */
thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
com_statement_info[thd->get_command()].m_key);
@@ -7864,21 +7971,32 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
});
}
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
mysql_parse(thd, rawbuf, length, parser_state, is_com_multi,
is_next_command);
+ (void) wsrep_after_command(thd, !thd->in_active_multi_stmt_transaction());
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ /*
+ State after after_command hook must be either NO_CONFLICT
+ or MUST_ABORT if the BF abort happened just after leaving
+ after_command hook.
+ */
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == MUST_ABORT ||
+ thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT);
if (WSREP(thd)) {
/* wsrep BF abort in query exec phase */
- mysql_mutex_lock(&thd->LOCK_thd_data);
- if (thd->wsrep_conflict_state == MUST_ABORT) {
+ if (thd->wsrep_conflict_state() == MUST_ABORT) {
wsrep_client_rollback(thd);
WSREP_DEBUG("abort in exec query state, avoiding autocommit");
}
- if (thd->wsrep_conflict_state == MUST_REPLAY)
+ /* note: this is obsolete, comin from 10.3.6 merging */
+ if (thd->wsrep_conflict_state() == MUST_REPLAY)
{
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ WSREP_WARN("EXPLAIN DELETED");
if (thd->lex->explain)
delete_explain_query(thd->lex);
mysql_mutex_lock(&thd->LOCK_thd_data);
@@ -7886,17 +8004,20 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
wsrep_replay_transaction(thd);
}
- /* setting error code for BF aborted trxs */
- if (thd->wsrep_conflict_state == ABORTED ||
- thd->wsrep_conflict_state == CERT_FAILURE)
+ if (thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT)
{
thd->reset_for_next_command();
if (is_autocommit &&
thd->lex->sql_command != SQLCOM_SELECT &&
(thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit))
{
- WSREP_DEBUG("wsrep retrying AC query: %s",
- (thd->query()) ? thd->query() : "void");
+ WSREP_DEBUG("wsrep retrying AC query: %lu %s",
+ thd->wsrep_retry_counter, WSREP_QUERY(thd));
+
+ // close_thread_tables(thd);
+
+ assert(LOCAL_ROLLBACK != thd->wsrep_exec_mode);
+ assert(LOCAL_STATE == thd->wsrep_exec_mode);
/* Performance Schema Interface instrumentation, end */
MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
@@ -7904,53 +8025,99 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
thd->m_digest= NULL;
close_thread_tables(thd);
- thd->wsrep_conflict_state= RETRY_AUTOCOMMIT;
thd->wsrep_retry_counter++; // grow
wsrep_copy_query(thd);
thd->set_time();
parser_state->reset(rawbuf, length);
+#ifdef OUT
+ /* PSI end */
+ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
+ thd->m_statement_psi= NULL;
+ thd->m_digest= NULL;
+
+ /* DTRACE end */
+ if (MYSQL_QUERY_DONE_ENABLED())
+ {
+ WSREP_WARN("DTRACE END");
+ MYSQL_QUERY_DONE(thd->is_error());
+ }
+
+ /* SHOW PROFILE end */
+#if defined(ENABLED_PROFILING)
+ thd->profiling.finish_current_query();
+#endif
+
+ /* SHOW PROFILE begin */
+#if defined(ENABLED_PROFILING)
+ thd->profiling.start_new_query("continuing");
+ thd->profiling.set_query_source(rawbuf, length);
+#endif
+
+ /* DTRACE begin */
+ MYSQL_QUERY_START(rawbuf, thd->thread_id,
+ (char *) (thd->db ? thd->db : ""),
+ &thd->security_ctx->priv_user[0],
+ (char *) thd->security_ctx->host_or_ip);
+
+ /* PSI begin */
+ thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
+ com_statement_info[thd->get_command()].m_key,
+ thd->db.str, thd->db.length,
+ thd->charset());
+ DBUG_ASSERT(thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID);
+#endif
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ WSREP_DEBUG("assigned new next trx id: %lu", thd->wsrep_next_trx_id());
}
else
{
- WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s",
- (thd->wsrep_conflict_state == ABORTED) ?
+ WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s",
+ (thd->wsrep_conflict_state_unsafe() == ABORTED) ?
"BF Aborted" : "cert failure",
(longlong) thd->thread_id, is_autocommit,
thd->wsrep_retry_counter,
thd->variables.wsrep_retry_autocommit, thd->query());
- my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
- MYF(0));
- thd->wsrep_conflict_state= NO_CONFLICT;
- if (thd->wsrep_conflict_state != REPLAYING)
+ /*
+ mariaDB code use here:
+ my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
+ MYF(0));
+ But, this breaks many mtr tests where victim deadlock may be
+ randomly reported by native deadlock error or this mesage.
+ Fixed this, temporarily, to use native ER_LOCK_DEADLOCK
+ error, just to get the tests passing
+ */
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
+ thd->reset_killed();
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ if (thd->wsrep_conflict_state() != REPLAYING)
thd->wsrep_retry_counter= 0; // reset
}
- mysql_mutex_unlock(&thd->LOCK_thd_data);
thd->reset_killed();
}
else
{
set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok
- mysql_mutex_unlock(&thd->LOCK_thd_data);
}
}
/* If retry is requested clean up explain structure */
- if ((thd->wsrep_conflict_state == RETRY_AUTOCOMMIT ||
- thd->wsrep_conflict_state == MUST_REPLAY )
- && thd->lex->explain)
+ if ((thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT ||
+ thd->wsrep_conflict_state() == MUST_REPLAY )
+ && thd->lex->explain)
{
- delete_explain_query(thd->lex);
+ delete_explain_query(thd->lex);
}
- } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT);
+ } while (thd->wsrep_conflict_state()== RETRY_AUTOCOMMIT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
if (thd->wsrep_retry_query)
{
WSREP_DEBUG("releasing retry_query: conf %d sent %d kill %d errno %d SQL %s",
- thd->wsrep_conflict_state,
- thd->get_stmt_da()->is_sent(),
+ thd->wsrep_conflict_state_unsafe(),
+ thd->get_stmt_da()->is_sent(),
thd->killed,
- thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
+ thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
thd->wsrep_retry_query);
my_free(thd->wsrep_retry_query);
thd->wsrep_retry_query = NULL;
@@ -7958,6 +8125,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
thd->wsrep_retry_command = COM_CONNECT;
}
#endif /* WITH_WSREP */
+ return false;
}
/*
@@ -8909,6 +9077,7 @@ THD *find_thread_by_id(longlong id, bool query_id)
continue;
if (id == (query_id ? tmp->query_id : (longlong) tmp->thread_id))
{
+ if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd);
mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
break;
}
@@ -8937,7 +9106,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD);
DBUG_ENTER("kill_one_thread");
DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal));
-
+ WSREP_DEBUG("kill_one_thread %lu", thd->thread_id);
if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY)))
{
/*
@@ -8963,15 +9132,18 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
if (((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) &&
- !wsrep_thd_is_BF(tmp, false))
+ !wsrep_thd_is_BF((void*)tmp, false))
{
+ //if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd);
tmp->awake_no_mutex(kill_signal);
+ //if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_wsrep_thd);
error=0;
}
else
error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR :
ER_KILL_DENIED_ERROR);
mysql_mutex_unlock(&tmp->LOCK_thd_kill);
+ if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_wsrep_thd);
}
DBUG_PRINT("exit", ("%d", error));
DBUG_RETURN(error);
@@ -9029,7 +9201,10 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
DBUG_RETURN(ER_KILL_DENIED_ERROR);
}
if (!threads_to_kill.push_back(tmp, thd->mem_root))
+ {
+ if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd);
mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
+ }
}
}
mysql_mutex_unlock(&LOCK_thread_count);
@@ -9051,6 +9226,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
*/
next_ptr= it2++;
mysql_mutex_unlock(&ptr->LOCK_thd_kill);
+ if (WSREP(ptr)) mysql_mutex_unlock(&ptr->LOCK_wsrep_thd);
(*rows)++;
} while ((ptr= next_ptr));
}
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 1027872898a..e2578b1e363 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -37,6 +37,8 @@ int test_if_data_home_dir(const char *dir);
int error_if_data_home_dir(const char *path, const char *what);
my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags);
+bool stmt_causes_implicit_commit(const THD *thd, uint mask);
+
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
int mysql_multi_update_prepare(THD *thd);
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 8c231d9b8f7..4c72e890e74 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -2281,6 +2281,10 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_CSTRING *name)
}
}
return 0;
+#ifdef WITH_WSREP
+ error:
+#endif /* WITH_WSREP */
+ return 1;
}
@@ -2299,6 +2303,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
if (!opt_noacl && check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index 47decf38973..64c3396c230 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -150,21 +150,17 @@ static struct wsrep_service_st wsrep_handler = {
get_wsrep_load_data_splitting,
get_wsrep_log_conflicts,
get_wsrep_protocol_version,
- wsrep_aborting_thd_contains,
- wsrep_aborting_thd_enqueue,
wsrep_consistency_check,
wsrep_is_wsrep_xid,
wsrep_xid_seqno,
wsrep_xid_uuid,
- wsrep_lock_rollback,
wsrep_on,
- wsrep_post_commit,
- wsrep_prepare_key,
- wsrep_run_wsrep_commit,
+ wsrep_prepare_key_for_innodb,
wsrep_thd_LOCK,
wsrep_thd_UNLOCK,
wsrep_thd_awake,
wsrep_thd_conflict_state,
+ wsrep_thd_thread_id,
wsrep_thd_conflict_state_str,
wsrep_thd_exec_mode,
wsrep_thd_exec_mode_str,
@@ -181,7 +177,6 @@ static struct wsrep_service_st wsrep_handler = {
wsrep_thd_ws_handle,
wsrep_trx_is_aborting,
wsrep_trx_order_before,
- wsrep_unlock_rollback
};
static struct thd_specifics_service_st thd_specifics_handler=
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c615356b354..c9a36b02fe4 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4198,13 +4198,13 @@ reexecute:
if (WSREP_ON)
{
mysql_mutex_lock(&thd->LOCK_thd_data);
- switch (thd->wsrep_conflict_state)
+ switch (thd->wsrep_conflict_state())
{
case CERT_FAILURE:
WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d",
(longlong) thd->thread_id,
thd->get_stmt_da()->sql_errno() );
- thd->wsrep_conflict_state = NO_CONFLICT;
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
break;
case MUST_REPLAY:
@@ -4394,13 +4394,13 @@ reexecute:
if (WSREP_ON)
{
mysql_mutex_lock(&thd->LOCK_thd_data);
- switch (thd->wsrep_conflict_state)
+ switch (thd->wsrep_conflict_state())
{
case CERT_FAILURE:
WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d",
(longlong) thd->thread_id,
thd->get_stmt_da()->sql_errno() );
- thd->wsrep_conflict_state = NO_CONFLICT;
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
break;
case MUST_REPLAY:
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 2ee175293de..1847416368a 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3845,6 +3845,17 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len,
return 1;
}
+#ifdef WITH_WSREP
+ if (WSREP_ON)
+ {
+ /* RESET MASTER will initialize GTID sequence, and that would happen locally
+ in this node, so better reject it
+ */
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ "RESET MASTER not allowed when node is in cluster", MYF(0));
+ return 1;
+ }
+#endif /* WITH_WSREP */
bool ret= 0;
/* Temporarily disable master semisync before reseting master. */
repl_semisync_master.before_reset_master();
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 08e1c1c69d3..3d6d60811af 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2650,7 +2650,7 @@ err:
int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno()
: 0;
#ifdef WITH_WSREP
- thd->wsrep_skip_wsrep_GTID = false;
+ thd->wsrep_skip_wsrep_GTID = true;
#endif /* WITH_WSREP */
error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
built_query.ptr(),
@@ -2701,7 +2701,7 @@ err:
end:
#ifdef WITH_WSREP
- thd->wsrep_skip_wsrep_GTID = false;
+ thd->wsrep_skip_wsrep_GTID = false;
#endif /* WITH_WSREP */
DBUG_RETURN(error);
}
@@ -7560,6 +7560,19 @@ static bool mysql_inplace_alter_table(THD *thd,
}
}
+#ifdef WITH_WSREP
+ if (thd->wsrep_nbo_ctx) {
+ wsrep_begin_nbo_unlock(thd);
+ }
+ DBUG_EXECUTE_IF("sync.alter_locked_tables_inplace",
+ {
+ const char act[]=
+ "now "
+ "wait_for signal.alter_locked_tables_inplace";
+ DBUG_ASSERT(!debug_sync_set_action(thd,
+ STRING_WITH_LEN(act)));
+ };);
+#endif /* WITH_WSREP */
DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade");
THD_STAGE_INFO(thd, stage_alter_inplace);
@@ -9782,6 +9795,21 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
+#ifdef WITH_WSREP
+ if (thd->wsrep_nbo_ctx) {
+ wsrep_begin_nbo_unlock(thd);
+ }
+
+ DBUG_EXECUTE_IF("sync.alter_locked_tables",
+ {
+ const char act[]=
+ "now "
+ "wait_for signal.alter_locked_tables";
+ DBUG_ASSERT(!debug_sync_set_action(thd,
+ STRING_WITH_LEN(act)));
+ };);
+
+#endif /* WITH_WSREP */
/* Open the table since we need to copy the data. */
if (table->s->tmp_table != NO_TMP_TABLE)
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index d515aacd1d0..2239afbb13b 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -416,8 +416,22 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
if (WSREP(thd) &&
wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0))
DBUG_RETURN(TRUE);
- if (lock_table(thd, table_ref, &hton_can_recreate))
- DBUG_RETURN(TRUE);
+
+ /*
+ When using non-blocking operation for TRUNCATE always fall to
+ handler_truncate() in order to avoid calling lock_table_names()
+ twice.
+ */
+#ifdef WITH_WSREP
+ if (WSREP(thd) && thd->wsrep_nbo_ctx) {
+ hton_can_recreate= false;
+ }
+ else
+#endif
+ {
+ if (lock_table(thd, table_ref, &hton_can_recreate))
+ DBUG_RETURN(TRUE);
+ }
if (hton_can_recreate)
{
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 75a962939ae..464ba06ddf9 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5401,7 +5401,7 @@ static Sys_var_ulong Sys_wsrep_max_ws_size (
GLOBAL_VAR(wsrep_max_ws_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1024, WSREP_MAX_WS_SIZE), DEFAULT(WSREP_MAX_WS_SIZE),
BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
- ON_CHECK(wsrep_max_ws_size_check), ON_UPDATE(wsrep_max_ws_size_update));
+ ON_CHECK(0), ON_UPDATE(wsrep_max_ws_size_update));
static Sys_var_ulong Sys_wsrep_max_ws_rows (
"wsrep_max_ws_rows", "Max number of rows in write set",
@@ -5438,7 +5438,7 @@ static Sys_var_uint Sys_wsrep_sync_wait(
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(wsrep_sync_wait_update));
-static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS };
+static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", "NBO", NullS };
static Sys_var_enum Sys_wsrep_OSU_method(
"wsrep_OSU_method", "Method for Online Schema Upgrade",
SESSION_VAR(wsrep_OSU_method), CMD_LINE(OPT_ARG),
@@ -5488,7 +5488,7 @@ static Sys_var_ulong Sys_wsrep_mysql_replication_bundle(
static Sys_var_mybool Sys_wsrep_load_data_splitting(
"wsrep_load_data_splitting", "To commit LOAD DATA "
- "transaction after every 10K rows inserted",
+ "transaction after every 10K rows inserted (deprecating)",
GLOBAL_VAR(wsrep_load_data_splitting),
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
@@ -5508,12 +5508,44 @@ static Sys_var_mybool Sys_wsrep_restart_slave(
"wsrep_restart_slave", "Should MariaDB slave be restarted automatically, when node joins back to cluster",
GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
+static Sys_var_ulong Sys_wsrep_trx_fragment_size(
+ "wsrep_trx_fragment_size",
+ "Size of transaction fragments for streaming replication (measured in "
+ "units of 'wsrep_trx_fragment_unit')",
+ SESSION_VAR(wsrep_trx_fragment_size), CMD_LINE(REQUIRED_ARG),
+ VALID_RANGE(0, WSREP_MAX_WS_SIZE), DEFAULT(0), BLOCK_SIZE(1),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_trx_fragment_size_check));
+
+extern const char *wsrep_fragment_units[];
+
+static Sys_var_enum Sys_wsrep_trx_fragment_unit(
+ "wsrep_trx_fragment_unit",
+ "Unit for streaming replication transaction fragments' size: bytes, "
+ "events, rows, statements",
+ SESSION_VAR(wsrep_trx_fragment_unit), CMD_LINE(REQUIRED_ARG),
+ wsrep_fragment_units,
+ DEFAULT(WSREP_FRAG_BYTES),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0));
+
+extern const char *wsrep_SR_store_types[];
+static Sys_var_enum Sys_wsrep_SR_store(
+ "wsrep_SR_store", "Storage for streaming replication fragments",
+ READ_ONLY GLOBAL_VAR(wsrep_SR_store_type), CMD_LINE(REQUIRED_ARG),
+ wsrep_SR_store_types, DEFAULT(WSREP_SR_STORE_TABLE),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG);
+
static Sys_var_mybool Sys_wsrep_dirty_reads(
"wsrep_dirty_reads",
"Allow reads even when the node is not in the primary component.",
SESSION_VAR(wsrep_dirty_reads), CMD_LINE(OPT_ARG),
DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG);
+static Sys_var_uint Sys_wsrep_ignore_apply_errors (
+ "wsrep_ignore_apply_errors", "Ignore replication errors",
+ GLOBAL_VAR(wsrep_ignore_apply_errors), CMD_LINE(REQUIRED_ARG),
+ VALID_RANGE(WSREP_IGNORE_ERRORS_NONE, WSREP_IGNORE_ERRORS_MAX),
+ DEFAULT(7), BLOCK_SIZE(1));
+
static Sys_var_uint Sys_wsrep_gtid_domain_id(
"wsrep_gtid_domain_id", "When wsrep_gtid_mode is set, this value is "
"used as gtid_domain_id for galera transactions and also copied to the "
diff --git a/sql/table.cc b/sql/table.cc
index e98836cd93c..e82092b1820 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -249,6 +249,13 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
DBUG_ASSERT(db != NULL);
DBUG_ASSERT(name != NULL);
+#ifdef WITH_WSREP
+ if (my_strcasecmp(system_charset_info, db->str, "wsrep_schema") == 0 &&
+ my_strcasecmp(system_charset_info, name->str, "SR") == 0)
+ {
+ return TABLE_CATEGORY_INFORMATION;
+ }
+#endif /* WITH_WSREP */
if (is_infoschema_db(db))
return TABLE_CATEGORY_INFORMATION;
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 1c2820200d1..8978ed18923 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -135,8 +135,6 @@ static bool xa_trans_force_rollback(THD *thd)
by ha_rollback()/THD::transaction::cleanup().
*/
thd->transaction.xid_state.rm_error= 0;
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
if (ha_rollback_trans(thd, true))
{
my_error(ER_XAER_RMERR, MYF(0));
@@ -184,14 +182,10 @@ bool trans_begin(THD *thd, uint flags)
(thd->variables.option_bits & OPTION_TABLE_LOCK))
{
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= MY_TEST(ha_commit_trans(thd, TRUE));
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
}
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
@@ -252,7 +246,6 @@ bool trans_begin(THD *thd, uint flags)
}
#ifdef WITH_WSREP
- thd->wsrep_PA_safe= true;
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
@@ -299,8 +292,6 @@ bool trans_commit(THD *thd)
if (trans_check(thd))
DBUG_RETURN(TRUE);
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
@@ -311,8 +302,6 @@ bool trans_commit(THD *thd)
mysql_mutex_assert_not_owner(&LOCK_after_binlog_sync);
mysql_mutex_assert_not_owner(&LOCK_commit_ordered);
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
/*
if res is non-zero, then ha_commit_trans has rolled back the
transaction, so the hooks for rollback will be called.
@@ -368,14 +357,10 @@ bool trans_commit_implicit(THD *thd)
/* Safety if one did "drop table" on locked tables */
if (!thd->locked_tables_mode)
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= MY_TEST(ha_commit_trans(thd, TRUE));
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
}
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
@@ -409,14 +394,9 @@ bool trans_rollback(THD *thd)
int res;
DBUG_ENTER("trans_rollback");
-#ifdef WITH_WSREP
- thd->wsrep_PA_safe= true;
-#endif /* WITH_WSREP */
if (trans_check(thd))
DBUG_RETURN(TRUE);
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
@@ -424,6 +404,7 @@ bool trans_rollback(THD *thd)
#ifdef HAVE_REPLICATION
repl_semisync_master.wait_after_rollback(thd, FALSE);
#endif
+ //(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
/* Reset the binlog transaction marker */
thd->variables.option_bits&= ~OPTION_GTID_BEGIN;
@@ -515,14 +496,10 @@ bool trans_commit_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
- if (WSREP_ON)
- wsrep_register_hton(thd, FALSE);
res= ha_commit_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
{
trans_reset_one_shot_chistics(thd);
- if (WSREP_ON)
- wsrep_post_commit(thd, FALSE);
}
}
@@ -578,8 +555,6 @@ bool trans_rollback_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
- if (WSREP_ON)
- wsrep_register_hton(thd, FALSE);
ha_rollback_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
trans_reset_one_shot_chistics(thd);
@@ -733,7 +708,8 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name)
logging is off.
*/
bool mdl_can_safely_rollback_to_savepoint=
- (!(mysql_bin_log.is_open() && thd->variables.sql_log_bin) ||
+ (!((WSREP_EMULATE_BINLOG_NNULL(thd) || mysql_bin_log.is_open())
+ && thd->variables.sql_log_bin) ||
ha_rollback_to_savepoint_can_release_mdl(thd));
if (ha_rollback_to_savepoint(thd, sv))
@@ -944,13 +920,9 @@ bool trans_xa_commit(THD *thd)
}
else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
{
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
int r= ha_commit_trans(thd, TRUE);
if ((res= MY_TEST(r)))
my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
- if (WSREP_ON)
- wsrep_post_commit(thd, TRUE);
}
else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
{
@@ -969,8 +941,6 @@ bool trans_xa_commit(THD *thd)
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
{
- if (WSREP_ON)
- wsrep_register_hton(thd, TRUE);
ha_rollback_trans(thd, TRUE);
my_error(ER_XAER_RMERR, MYF(0));
}
diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc
index f2d90def5ef..e3de1e160a4 100644
--- a/sql/wsrep_applier.cc
+++ b/sql/wsrep_applier.cc
@@ -14,10 +14,15 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "mariadb.h"
+#include "my_pthread.h"
#include "wsrep_priv.h"
#include "wsrep_binlog.h" // wsrep_dump_rbr_buf()
#include "wsrep_xid.h"
+#include "wsrep_sr.h"
+#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h"
+#include "slave.h" // opt_log_slave_updates
#include "log_event.h" // class THD, EVENT_LEN_OFFSET, etc.
#include "wsrep_applier.h"
#include "debug_sync.h"
@@ -62,7 +67,7 @@ void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev)
{
if (thd->wsrep_apply_format)
{
- delete (Format_description_log_event*)thd->wsrep_apply_format;
+ delete (Format_description_log_event*)thd->wsrep_apply_format;
}
thd->wsrep_apply_format= ev;
}
@@ -79,9 +84,56 @@ Format_description_log_event* wsrep_get_apply_format(THD* thd)
return thd->wsrep_rgi->rli->relay_log.description_event_for_exec;
}
-static wsrep_cb_status_t wsrep_apply_events(THD* thd,
- const void* events_buf,
- size_t buf_len)
+void wsrep_apply_error::store(const THD* const thd)
+{
+ Diagnostics_area::Sql_condition_iterator it=
+ thd->get_stmt_da()->sql_conditions();
+ const Sql_condition* cond;
+
+ static size_t const max_len= 2*MAX_SLAVE_ERRMSG; // 2x so that we have enough
+
+ if (NULL == str_)
+ {
+ // this must be freeable by standard free()
+ str_= static_cast<char*>(malloc(max_len));
+ if (NULL == str_)
+ {
+ WSREP_ERROR("Failed to allocate %zu bytes for error buffer.", max_len);
+ len_ = 0;
+ return;
+ }
+ }
+ else
+ {
+ /* This is possible when we invoke rollback after failed applying.
+ * In this situation DA should not be reset yet and should contain
+ * all previous errors from applying and new ones from rollbacking,
+ * so we just overwrite is from scratch */
+ }
+
+ char* slider= str_;
+ const char* const buf_end= str_ + max_len - 1; // -1: leave space for \0
+
+ for (cond= it++; cond && slider < buf_end; cond= it++)
+ {
+ uint const err_code= cond->get_sql_errno();
+ const char* const err_str= cond->get_message_text();
+
+ slider+= my_snprintf(slider, buf_end - slider, " %s, Error_code: %d;",
+ err_str, err_code);
+ }
+
+ *slider= '\0';
+ len_= slider - str_ + 1; // +1: add \0
+
+ WSREP_DEBUG("Error buffer for thd %llu seqno %lld, %zu bytes: %s",
+ thd->thread_id, (long long)wsrep_thd_trx_seqno(thd),
+ len_, str_ ? str_ : "(null)");
+}
+
+int wsrep_apply_events(THD* thd,
+ const void* events_buf,
+ size_t buf_len)
{
char *buf= (char *)events_buf;
int rcode= 0;
@@ -91,18 +143,24 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
DBUG_ENTER("wsrep_apply_events");
if (thd->killed == KILL_CONNECTION &&
- thd->wsrep_conflict_state != REPLAYING)
+ thd->wsrep_conflict_state() != REPLAYING)
{
WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld",
(long long) wsrep_thd_trx_seqno(thd));
- DBUG_RETURN(WSREP_CB_FAILURE);
+ DBUG_RETURN(WSREP_ERR_ABORTED);
}
mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_EXEC;
- if (thd->wsrep_conflict_state!= REPLAYING)
- thd->wsrep_conflict_state= NO_CONFLICT;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ // thd->set_wsrep_query_state(QUERY_EXEC);
+ if (thd->wsrep_conflict_state() != REPLAYING)
+ {
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+ if (thd->wsrep_conflict_state() != NO_CONFLICT)
+ {
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ }
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld",
(long long) wsrep_thd_trx_seqno(thd));
@@ -117,7 +175,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
{
WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %zu",
(long long)wsrep_thd_trx_seqno(thd), buf_len);
- rcode= 1;
+ rcode= WSREP_ERR_BAD_EVENT;
goto error;
}
@@ -146,9 +204,6 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
/* Use the original server id for logging. */
thd->set_server_id(ev->server_id);
thd->set_time(); // time the query
- wsrep_xid_init(&thd->transaction.xid_state.xid,
- thd->wsrep_trx_meta.gtid.uuid,
- thd->wsrep_trx_meta.gtid.seqno);
thd->lex->current_select= 0;
if (!ev->when)
{
@@ -167,7 +222,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
if (exec_res)
{
- WSREP_WARN("RBR event %d %s apply warning: %d, %lld",
+ WSREP_WARN("Event %d %s apply failed: %d, seqno %lld",
event, ev->get_type_str(), exec_res,
(long long) wsrep_thd_trx_seqno(thd));
rcode= exec_res;
@@ -177,28 +232,30 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
}
event++;
- if (thd->wsrep_conflict_state!= NO_CONFLICT &&
- thd->wsrep_conflict_state!= REPLAYING)
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() != NO_CONFLICT &&
+ thd->wsrep_conflict_state() != REPLAYING)
WSREP_WARN("conflict state after RBR event applying: %d, %lld",
- thd->wsrep_query_state, (long long)wsrep_thd_trx_seqno(thd));
+ thd->wsrep_query_state(), (long long)wsrep_thd_trx_seqno(thd));
- if (thd->wsrep_conflict_state == MUST_ABORT) {
- WSREP_WARN("RBR event apply failed, rolling back: %lld",
+ if (thd->wsrep_conflict_state() == MUST_ABORT) {
+ WSREP_WARN("Event apply failed, rolling back: %lld",
(long long) wsrep_thd_trx_seqno(thd));
trans_rollback(thd);
thd->locked_tables_list.unlock_locked_tables(thd);
/* Release transactional metadata locks. */
thd->mdl_context.release_transactional_locks();
- thd->wsrep_conflict_state= NO_CONFLICT;
- DBUG_RETURN(WSREP_CB_FAILURE);
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ DBUG_RETURN(rcode ? rcode : WSREP_ERR_ABORTED);
}
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
delete_or_keep_event_post_apply(thd->wsrep_rgi, typ, ev);
}
error:
mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_query_state= QUERY_IDLE;
mysql_mutex_unlock(&thd->LOCK_thd_data);
assert(thd->wsrep_exec_mode== REPL_RECV);
@@ -206,21 +263,208 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd,
if (thd->killed == KILL_CONNECTION)
WSREP_INFO("applier aborted: %lld", (long long)wsrep_thd_trx_seqno(thd));
- if (rcode) DBUG_RETURN(WSREP_CB_FAILURE);
- DBUG_RETURN(WSREP_CB_SUCCESS);
+ DBUG_RETURN(rcode);
+}
+
+static wsrep_SR_trx_info* wsrep_prepare_applier_ctx(
+ uint32_t const flags,
+ const wsrep_trx_meta_t* const meta,
+ THD** thd)
+{
+ DBUG_ENTER("wsrep_prepare_applier_ctx");
+
+ THD* const orig_thd(*thd);
+ wsrep_SR_trx_info* SR_trx(NULL);
+
+ if ((flags & WSREP_FLAG_TRX_START) &&
+ (flags & WSREP_FLAG_TRX_END || flags & WSREP_FLAG_ROLLBACK))
+ {
+ /* non-SR trx */
+ (*thd)->store_globals();
+ }
+ else if (!(flags & WSREP_FLAG_TRX_START))
+ {
+ /* continuation of SR trx */
+ SR_trx = sr_pool->find(meta->stid.node, meta->stid.trx);
+ if (NULL == SR_trx)
+ {
+ WSREP_DEBUG("SR transaction has been aborted already.");
+ goto out;
+ }
+ /* SR trx write sets cannot be applied in parallel */
+ assert(SR_trx->get_applier_thread() == 0);
+
+ /* switch THD contexts */
+ SR_trx->set_applier_thread(orig_thd->thread_id);
+ *thd = SR_trx->get_THD();
+ (*thd)->thread_stack = orig_thd->thread_stack;
+ WSREP_DEBUG("fragment trx found, thread_id: %lld", (*thd)->thread_id);
+ (*thd)->store_globals();
+ }
+ else
+ {
+ assert(flags & WSREP_FLAG_TRX_START);
+ assert(!(flags & WSREP_FLAG_ROLLBACK));
+
+ /* starting new streaming replication trx, prepare a new context */
+ WSREP_DEBUG("WS with begin and not commit flag");
+ *thd = wsrep_start_SR_THD(orig_thd->thread_stack);
+ SR_trx = sr_pool->add(meta->stid.node, meta->stid.trx, *thd);
+
+ (*thd)->store_globals();
+ }
+
+ assert(*thd);
+ (*thd)->wsrep_trx_meta = *meta;
+
+out:
+ DBUG_RETURN(SR_trx);
+}
+
+static inline void wsrep_restore_applier_ctx(wsrep_SR_trx_info* const SR_trx,
+ THD* const orig_thd)
+{
+ DBUG_ENTER("wsrep_restore_applier_ctx");
+ WSREP_DEBUG("resetting default thd for applier, id: %lld, thd: %p",
+ orig_thd->thread_id, orig_thd);
+ SR_trx->set_applier_thread(0);
+ orig_thd->store_globals();
+ DBUG_VOID_RETURN;
+}
+
+
+static wsrep_cb_status_t wsrep_rollback_common(THD* thd, wsrep_apply_error& err)
+{
+ DBUG_ENTER("wsrep_rollback_common");
+ wsrep_cb_status_t rcode(WSREP_CB_SUCCESS);
+
+ WSREP_DEBUG("Slave rolling back %lld", (long long)wsrep_thd_trx_seqno(thd));
+//#ifdef WSREP_PROC_INFO
+ snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
+ "rolling back %lld", (long long)wsrep_thd_trx_seqno(thd));
+ thd_proc_info(thd, thd->wsrep_info);
+//#else
+// thd_proc_info(thd, "rolling back");
+//#endif /* WSREP_PROC_INFO */
+
+ if (thd->wsrep_SR_thd && wsrep_SR_store)
+ {
+ /* prevent rollbacker to abort the same thd */
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ thd->set_wsrep_conflict_state(ABORTING);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ /* rollback SR trx */
+ if (trans_rollback_stmt(thd) || trans_rollback(thd))
+ {
+ rcode = WSREP_CB_FAILURE;
+ err.store(thd);
+ }
+ }
+
+//#ifdef WSREP_PROC_INFO
+ snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
+ "rolled back %lld", (long long)wsrep_thd_trx_seqno(thd));
+ thd_proc_info(thd, thd->wsrep_info);
+//#else
+// thd_proc_info(thd, "rolled back");
+//#endif /* WSREP_PROC_INFO */
+ thd->wsrep_rgi->cleanup_context(thd, 0);
+#ifdef GTID_SUPPORT
+ thd->variables.gtid_next.set_automatic();
+#endif
+ DBUG_RETURN(rcode);
+}
+
+
+static wsrep_cb_status_t wsrep_rollback_trx(THD* thd,
+ const void* const buf,
+ size_t const buf_len,
+ uint32_t const flags,
+ const wsrep_trx_meta_t* const meta,
+ wsrep_apply_error& err)
+{
+ DBUG_ENTER("wsrep_rollback_trx");
+
+ assert(flags & WSREP_FLAG_ROLLBACK);
+
+ THD* const orig_thd(thd);
+
+ wsrep_SR_trx_info* const SR_trx(wsrep_prepare_applier_ctx(flags, meta, &thd));
+
+ WSREP_DEBUG("Rollback for: %ld", meta->stid.trx);
+
+ // Preempted by rollbacker
+ if (!SR_trx && !(flags & WSREP_FLAG_TRX_START))
+ {
+ WSREP_DEBUG("Pre-empted by rollbacker: %ld",
+ meta->stid.trx);
+ DBUG_RETURN(WSREP_CB_SUCCESS);
+ }
+
+ if (SR_trx)
+ {
+ /*
+ TODO: Must be done atomically with writing dummy event, should be
+ moved into wsrep_rollback_comman().
+ */
+ wsrep_rollback_SR_trx(thd);
+ }
+
+ wsrep_cb_status_t const rcode(wsrep_rollback_common(thd, err));
+
+ if (SR_trx)
+ {
+ wsrep_restore_applier_ctx(SR_trx, orig_thd);
+ }
+
+ DBUG_RETURN(rcode);
}
-wsrep_cb_status_t wsrep_apply_cb(void* const ctx,
- const void* const buf,
- size_t const buf_len,
- uint32_t const flags,
- const wsrep_trx_meta_t* meta)
+static int wsrep_apply_trx(THD* orig_thd,
+ const void* const buf,
+ size_t const buf_len,
+ uint32_t const flags,
+ const wsrep_trx_meta_t* meta,
+ wsrep_apply_error& err)
{
- THD* const thd((THD*)ctx);
+ THD* thd= orig_thd;
+ DBUG_ENTER("wsrep_apply_trx");
- assert(thd->wsrep_apply_toi == false);
+ DBUG_ASSERT(thd->wsrep_apply_toi == false);
+ DBUG_ASSERT(!(flags & WSREP_FLAG_ROLLBACK));
+ DBUG_ASSERT(!(flags & WSREP_FLAG_ISOLATION));
+ DBUG_ASSERT(err.is_null());
- // Allow tests to block the applier thread using the DBUG facilities.
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() == REPLAYING &&
+ (flags & WSREP_FLAG_TRX_END) && !(flags & WSREP_FLAG_TRX_START))
+ {
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ /*
+ Replaying, must add final frag to SR storage for actual replay
+ */
+ if (wsrep_SR_store)
+ {
+ wsrep_SR_store->append_frag_commit(thd,
+ flags,
+ (const uchar*)buf,
+ buf_len);
+ DBUG_RETURN(wsrep_replay_from_SR_store(thd, *meta));
+ }
+ DBUG_RETURN(0);
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ wsrep_SR_trx_info* const SR_trx(wsrep_prepare_applier_ctx(flags, meta, &thd));
+
+ assert(thd);
+
+ /* moved dbug sync point here, after possible THD switch for SR transactions
+ has ben done
+ */
+ // Allow tests to block the applier thread using the DBUG facilities
DBUG_EXECUTE_IF("sync.wsrep_apply_cb",
{
const char act[]=
@@ -231,66 +475,325 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx,
STRING_WITH_LEN(act)));
};);
- thd->wsrep_trx_meta = *meta;
-
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Applying write set %lld: %p, %zu",
- (long long)wsrep_thd_trx_seqno(thd), buf, buf_len);
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Applying write set");
-#endif /* WSREP_PROC_INFO */
-
/* tune FK and UK checking policy */
- if (wsrep_slave_UK_checks == FALSE)
+ if (wsrep_slave_UK_checks == FALSE)
thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS;
else
thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS;
- if (wsrep_slave_FK_checks == FALSE)
+ if (wsrep_slave_FK_checks == FALSE)
thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
else
thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
- /* With galera we assume that the master has done the constraint checks */
- thd->variables.option_bits|= OPTION_NO_CHECK_CONSTRAINT_CHECKS;
+ /*
+ Actual applying is done in wsrep_apply_events()
+ */
+ int rcode(wsrep_apply_events(thd, buf, buf_len));
- if (flags & WSREP_FLAG_ISOLATION)
+ if (0 != rcode || thd->wsrep_has_ignored_error)
{
- thd->wsrep_apply_toi= true;
- /*
- Don't run in transaction mode with TOI actions.
- */
- thd->variables.option_bits&= ~OPTION_BEGIN;
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ wsrep_dump_rbr_buf_with_header(thd, buf, buf_len);
}
- wsrep_cb_status_t rcode(wsrep_apply_events(thd, buf, buf_len));
+
+ if (0 != rcode)
+ {
+ err.store(thd);
+ wsrep_rollback_common(thd, err);
+ }
+ else if (thd->wsrep_SR_thd && wsrep_SR_store)
+ {
+ /* remove trx from persistent storage on last fragment */
+ if ((flags & WSREP_FLAG_TRX_END))
+ {
+ WSREP_DEBUG("last fragment, cleanup SR table ");
+ DBUG_EXECUTE_IF("crash_apply_cb_before_fragment_removal",
+ DBUG_SUICIDE(););
+ SR_trx->cleanup();
+ DBUG_EXECUTE_IF("crash_apply_cb_after_fragment_removal",
+ DBUG_SUICIDE(););
+ }
+ else
+ {
+ DBUG_EXECUTE_IF("crash_apply_cb_before_append_frag",
+ DBUG_SUICIDE(););
+ SR_trx->append_fragment(meta);
+ /* store the fragment in persistent storage */
+ WSREP_DEBUG("append fragment to SR table");
+ orig_thd->store_globals();
+ wsrep_SR_store->append_frag_apply(orig_thd,
+ flags,
+ (const uchar*)buf,
+ buf_len);
+ thd->store_globals();
+ DBUG_EXECUTE_IF("crash_apply_cb_after_append_frag",
+ DBUG_SUICIDE(););
+ }
+ }
+
+ thd->close_temporary_tables();
+
+ if (SR_trx)
+ {
+ if (rcode)
+ {
+ WSREP_DEBUG("fragment trx destruction");
+//gcf487 trans_rollback(thd); - done in wsrep_rollback_common()
+// close_thread_tables(thd);
+// sr_pool->remove(orig_thd, thd, true);
+ }
+ wsrep_restore_applier_ctx(SR_trx, orig_thd);
+ }
+ DBUG_RETURN(rcode);
+}
+
+
+static int wsrep_apply_toi(THD* const thd,
+ const void* const buf,
+ size_t const buf_len,
+ uint32_t const flags,
+ const wsrep_trx_meta_t* const meta,
+ wsrep_apply_error& err)
+{
+ DBUG_ENTER("wsrep_apply_toi");
+
+ DBUG_ASSERT(flags & WSREP_FLAG_ISOLATION);
+
+
+ thd->wsrep_trx_meta = *meta;
+
+ thd->wsrep_apply_toi= true;
+
+ /*
+ Don't run in transaction mode with TOI actions. These will be
+ reset to defaults in commit callback.
+ */
+ thd->variables.option_bits&= ~OPTION_BEGIN;
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+
+ thd->store_globals();
+
+ int const rcode(wsrep_apply_events(thd, buf, buf_len));
+
+ if (0 != rcode || thd->wsrep_has_ignored_error)
+ {
+ wsrep_dump_rbr_buf_with_header(thd, buf, buf_len);
+ thd->wsrep_has_ignored_error= false;
+
+ if (0 != rcode) err.store(thd);
+ }
+
+ thd->close_temporary_tables();
+
+ DBUG_RETURN(rcode);
+}
+
+
+static void wsrep_apply_non_blocking(THD* thd, void* args)
+{
+ /* Go to BF mode */
+ wsrep_thd_shadow shadow;
+ wsrep_prepare_bf_thd(thd, &shadow);
+
+ Wsrep_nbo_ctx* nbo_ctx= (Wsrep_nbo_ctx*) args;
+
+ DBUG_ASSERT(nbo_ctx);
+
+ /*
+ Record context for synchronizing with applier thread once
+ MDL locks have been aquired.
+ */
+ thd->wsrep_nbo_ctx= nbo_ctx;
+
+ /* Must be applier thread */
+ assert(thd->wsrep_exec_mode == REPL_RECV);
+
+ /* Set OSU method for non blocking */
+ thd->variables.wsrep_OSU_method= WSREP_OSU_NBO;
+
+ /*
+ First apply TOI action as usual, wsrep->to_execute_start() will
+ be called at stmt commit. Applying is always assumed to succeed here.
+ Non-blocking operation end is supposed to sync the end result with
+ group and abort if the result does not match.
+ */
+ wsrep_apply_error err;
+ if (wsrep_apply_toi(thd, nbo_ctx->buf(), nbo_ctx->buf_len(), nbo_ctx->flags(),
+ &nbo_ctx->meta(), err) != WSREP_CB_SUCCESS)
+ {
+ WSREP_DEBUG("Applying NBO failed");
+ }
+
+ /*
+ Applying did not cause action to signal slave thread. Wake up
+ the slave before exit.
+ */
+ if (!thd->wsrep_nbo_ctx->ready()) thd->wsrep_nbo_ctx->signal();
+
+ /* Non-blocking operation end. No need to take action on error here,
+ it is handled by provider. */
+ wsrep_buf_t const err_buf= err.get_buf();
+ if (thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED &&
+ wsrep->to_execute_end(wsrep, thd->thread_id, &err_buf) != WSREP_OK)
+ {
+ WSREP_WARN("Non-blocking operation end failed");
+ }
+
+ if (wsrep->free_connection(wsrep, thd->thread_id) != WSREP_OK)
+ {
+ WSREP_WARN("Failed to free connection: %llu",
+ (long long unsigned)thd->thread_id);
+ }
+
+ thd->wsrep_nbo_ctx= NULL;
+ delete nbo_ctx;
+
+ /* Return from BF mode before syncing with group */
+ wsrep_return_from_bf_mode(thd, &shadow);
+}
+
+static int start_nbo_thd(const void* const buf,
+ size_t const buf_len,
+ uint32_t const flags,
+ const wsrep_trx_meta_t* const meta)
+{
+ int rcode= WSREP_RET_SUCCESS;
+
+ // Non-blocking operation start
+ Wsrep_nbo_ctx* nbo_ctx= 0;
+ Wsrep_thd_args* args= 0;
+ try
+ {
+ nbo_ctx= new Wsrep_nbo_ctx(buf, buf_len, flags, *meta);
+ args= new Wsrep_thd_args(wsrep_apply_non_blocking, nbo_ctx);
+ pthread_t th;
+ int err;
+ int max_tries= 1000;
+ while ((err= pthread_create(&th, &connection_attrib, start_wsrep_THD,
+ args)) == EAGAIN)
+ {
+ --max_tries;
+ if (max_tries == 0)
+ {
+ delete nbo_ctx;
+ delete args;
+ WSREP_ERROR("Failed to create thread for non-blocking operation: %d",
+ err);
+ return WSREP_ERR_FAILED;
+ }
+ else
+ {
+ usleep(1000);
+ }
+ }
+
+ // Detach thread and wait until worker signals that it has locked
+ // required resources.
+ pthread_detach(th);
+ nbo_ctx->wait_sync();
+ // nbo_ctx will be deleted by worker thread
+ }
+ catch (...)
+ {
+ delete nbo_ctx;
+ delete args;
+ WSREP_ERROR("Caught exception while trying to create thread for "
+ "non-blocking operation");
+ rcode= WSREP_ERR_FAILED;
+ }
+
+ return rcode;
+}
+
+int wsrep_apply(void* const ctx,
+ uint32_t const flags,
+ const wsrep_buf_t* const buf,
+ const wsrep_trx_meta_t* meta,
+ wsrep_apply_error& err)
+{
+ THD* thd= (THD*)ctx;
+
+ DBUG_ENTER("wsrep_apply");
+
+ DBUG_ASSERT(!WSREP_NBO_END(flags) || WSREP_FLAG_ROLLBACK & flags);
+
+ thd->wsrep_trx_meta = *meta;
#ifdef WSREP_PROC_INFO
snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Applied write set %lld", (long long)wsrep_thd_trx_seqno(thd));
+ "applying write set %lld: %p, %zu",
+ (long long)wsrep_thd_trx_seqno(thd), buf->ptr, buf->len);
thd_proc_info(thd, thd->wsrep_info);
#else
- thd_proc_info(thd, "Applied write set");
+ thd_proc_info(thd, "Applying write set");
#endif /* WSREP_PROC_INFO */
- if (WSREP_CB_SUCCESS != rcode)
+ WSREP_DEBUG("apply_cb with flags: %u seqno: %ld, srctrx: %ld",
+ flags, meta->gtid.seqno, meta->stid.trx);
+
+ bool const rollback(WSREP_FLAG_ROLLBACK & flags);
+ int rcode= 0;
+
+ if (!(flags & WSREP_FLAG_ISOLATION))
{
- wsrep_dump_rbr_buf_with_header(thd, buf, buf_len);
+ // Transaction
+ if (!rollback)
+ {
+ DBUG_ASSERT(meta->stid.trx != uint64_t(-1));
+ rcode= wsrep_apply_trx(thd, buf->ptr, buf->len, flags, meta, err);
+ }
+ else
+ {
+ DBUG_ASSERT(meta->stid.trx != uint64_t(-1) ||
+ (NULL == buf->ptr && 0 == buf->len));
+ rcode= wsrep_rollback_trx(thd, buf->ptr, buf->len, flags, meta, err);
+ }
+ DBUG_ASSERT(rcode == 0 || !err.is_null());
+ DBUG_ASSERT(err.is_null() || rcode != 0);
}
-
- if (thd->has_thd_temporary_tables())
+ else if (WSREP_NBO_START(flags))
+ {
+ // NBO-start
+ if (!rollback)
+ rcode = start_nbo_thd(buf->ptr, buf->len, flags, meta);
+ else
+ {
+ WSREP_DEBUG("Failed NBO start, seqno: %lld",
+ (long long)wsrep_thd_trx_seqno(thd));
+ rcode= wsrep_rollback_common(thd, err);
+ }
+ }
+ else if (WSREP_NBO_END(flags))
{
- WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..",
- thd->thread_id);
- thd->close_temporary_tables();
+ // ineffective NBO-end - binlog something for it
+ assert(rollback);
+ rcode= wsrep_rollback_common(thd, err);
+ }
+ else
+ {
+ // Regular TOI
+ if (!rollback)
+ rcode= wsrep_apply_toi(thd, buf->ptr, buf->len, flags, meta, err);
+ else
+ rcode= wsrep_rollback_common(thd, err);
}
- return rcode;
+
+#ifdef WSREP_PROC_INFO
+ snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
+ "Applied write set %lld", (long long)wsrep_thd_trx_seqno(thd));
+ thd_proc_info(thd, thd->wsrep_info);
+#else
+ thd_proc_info(thd, "Applied write set");
+#endif /* WSREP_PROC_INFO */
+ WSREP_DEBUG("apply_cb done with rcode: %d", rcode);
+
+ DBUG_RETURN(rcode != 0 ? rcode : err.length());
}
-static wsrep_cb_status_t wsrep_commit(THD* const thd)
+static wsrep_cb_status_t wsrep_commit_thd(THD* const thd,
+ bool fragment_not_trx_end,
+ const wsrep_apply_error& err)
{
#ifdef WSREP_PROC_INFO
snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
@@ -299,9 +802,36 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd)
#else
thd_proc_info(thd, "Committing");
#endif /* WSREP_PROC_INFO */
+ DBUG_ENTER("wsrep_commit_thd");
+
+ wsrep_cb_status_t rcode= WSREP_CB_SUCCESS;
+ if (!opt_log_slave_updates && wsrep_before_commit(thd, true))
+ rcode= WSREP_CB_FAILURE;
+ WSREP_DEBUG("applier commit_thd ");
+
+ /*
+ This is needed because the applying of DDL, does not call for binlog log_and_order
+ MySQL version is different, where at the end of DDL applyin, trans_commit_stmt has
+ a call for tc_log:commit(), and DDL binlogging happens there.
+ */
+ if (opt_log_slave_updates && thd->wsrep_apply_toi && wsrep_before_commit(thd, true))
+ {
+ rcode= WSREP_CB_FAILURE;
+ }
+ /*
+ We can ignore the storage engine durability setting for fragments
+ here: Committing a fragment does not cause actual transaction to
+ be committed, so it will be enough that the fragment is
+ committed in order to be able to recover to consistent state.
+ */
+
+ enum durability_properties dur_save= thd->durability_property;
+ if (fragment_not_trx_end)
+ thd->durability_property= HA_IGNORE_DURABILITY;
- wsrep_cb_status_t const rcode(trans_commit(thd) ?
- WSREP_CB_FAILURE : WSREP_CB_SUCCESS);
+ if (rcode == WSREP_CB_SUCCESS && trans_commit(thd))
+ rcode= WSREP_CB_FAILURE;
+ thd->durability_property= dur_save;
if (WSREP_CB_SUCCESS == rcode)
{
@@ -314,6 +844,30 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd)
wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid,
thd->wsrep_trx_meta.gtid.seqno);
}
+ if ((!opt_log_slave_updates || thd->wsrep_apply_toi)
+ && wsrep_ordered_commit(thd, true, err))
+ rcode= WSREP_CB_FAILURE;
+
+ if (rcode == WSREP_CB_SUCCESS)
+ {
+ DBUG_ASSERT(fragment_not_trx_end ||
+ thd->wsrep_query_state_unsafe() == QUERY_ORDERED_COMMIT);
+ /*
+ FIXME: For some reason fragment commits don't go through
+ binlog commit group commit if log slave updates is on. This
+ effectively disables binlog group commit for dummy events
+ which are logged into binlog.
+ */
+ if (fragment_not_trx_end && opt_log_slave_updates && !wsrep_gtid_mode)
+ {
+ if (wsrep_before_commit(thd, true) ||
+ wsrep_ordered_commit(thd, true, err))
+ {
+ WSREP_DEBUG("Binlog commit failed (WCT)");
+ rcode= WSREP_CB_FAILURE;
+ }
+ }
+ }
}
#ifdef WSREP_PROC_INFO
@@ -324,59 +878,117 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd)
thd_proc_info(thd, "Committed");
#endif /* WSREP_PROC_INFO */
- return rcode;
+ DBUG_RETURN(rcode);
}
-static wsrep_cb_status_t wsrep_rollback(THD* const thd)
+static
+wsrep_cb_status_t wsrep_commit(void* const ctx,
+ uint32_t const flags,
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* const exit,
+ const wsrep_apply_error& err)
{
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Rolling back %lld", (long long)wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Rolling back");
-#endif /* WSREP_PROC_INFO */
+ DBUG_ENTER("wsrep_commit");
+ WSREP_DEBUG("applier commit with flags: %u seqno: %ld, srctrx: %ld",
+ flags, meta->gtid.seqno, meta->stid.trx);
- wsrep_cb_status_t const rcode(trans_rollback(thd) ?
- WSREP_CB_FAILURE : WSREP_CB_SUCCESS);
+ THD* thd((THD*)ctx);
+ wsrep_cb_status_t rcode= WSREP_CB_SUCCESS;
+ bool const trx_end(flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK));
-#ifdef WSREP_PROC_INFO
- snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Rolled back %lld", (long long)wsrep_thd_trx_seqno(thd));
- thd_proc_info(thd, thd->wsrep_info);
-#else
- thd_proc_info(thd, "Rolled back");
-#endif /* WSREP_PROC_INFO */
+ if (WSREP_NBO_START(flags))
+ {
+ WSREP_DEBUG("NBO");
+ wsrep_cb_status_t ret= WSREP_CB_SUCCESS;
+ if (wsrep_before_commit(thd, true) ||
+ wsrep_ordered_commit(thd, true, err))
+ {
+ ret= WSREP_CB_FAILURE;
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ DBUG_RETURN(ret);
+ }
- return rcode;
-}
+ bool const toi(flags & WSREP_FLAG_ISOLATION); // ineffective NBO end
+ bool const fragment(!((flags & WSREP_FLAG_TRX_START) && trx_end) && !toi);
+ wsrep_SR_trx_info* const SR_trx
+ (fragment ? sr_pool->find(meta->stid.node, meta->stid.trx) : NULL);
-wsrep_cb_status_t wsrep_commit_cb(void* const ctx,
- uint32_t const flags,
- const wsrep_trx_meta_t* meta,
- wsrep_bool_t* const exit,
- bool const commit)
-{
- THD* const thd((THD*)ctx);
+ if (!SR_trx && trx_end && fragment)
+ {
+ WSREP_DEBUG("SR trxid %ld seqno %lld has been aborted already, skipping "
+ "commit_cb", meta->stid.trx, (long long)meta->gtid.seqno);
+ }
+ else
+ {
+ assert(0 == SR_trx || fragment);
+ assert(!fragment || 0 != SR_trx);
+ }
- assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd));
+ if (SR_trx && trx_end)
+ {
+ void* opaque= thd->wsrep_ws_handle.opaque;
+ thd = SR_trx->get_THD();
+ WSREP_DEBUG("last trx fragment, switching context from %p to %p", ctx, thd);
+ thd->wsrep_ws_handle.opaque= opaque;
+ thd->store_globals();
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ DBUG_EXECUTE_IF("crash_commit_cb_before_last_fragment_commit",
+ DBUG_SUICIDE(););
+ }
- wsrep_cb_status_t rcode;
+ thd->wsrep_trx_meta = *meta;
+ wsrep_xid_init(&thd->wsrep_xid, meta->gtid.uuid, meta->gtid.seqno);
+ assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd));
- if (commit)
- rcode = wsrep_commit(thd);
+ /*
+ Failed certification, write a dummy binlog event in wsrep_gtid_mode
+ to keep GTID sequence continuous. If wsrep_gtid_mode is off, release
+ commit critical section.
+ */
+ if (!fragment && (flags & WSREP_FLAG_ROLLBACK))
+ {
+ if (wsrep_gtid_mode)
+ {
+ wsrep_write_dummy_event(thd, "rollback");
+ }
+ else
+ {
+ if (wsrep_before_commit(thd, true) ||
+ wsrep_ordered_commit(thd, true, err))
+ {
+ WSREP_DEBUG("Binlog commit failed (WC)");
+ rcode= WSREP_CB_FAILURE;
+ }
+ }
+ }
else
- rcode = wsrep_rollback(thd);
+ {
+ /* here if thd == SR_trx->get_thd() we are committing in SR context -
+ * that is SR transaction.
+ * otherwise we are committing in the usual applier context -
+ * that is regular transaction or SR fragment. */
+ rcode = wsrep_commit_thd(thd, fragment && !trx_end, err);
+ }
+
+ thd->wsrep_ws_handle.opaque= NULL;
+ thd->wsrep_xid.null();
- /* Cleanup */
wsrep_set_apply_format(thd, NULL);
thd->mdl_context.release_transactional_locks();
thd->reset_query(); /* Mutex protected */
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
- if (wsrep_slave_count_change < 0 && commit && WSREP_CB_SUCCESS == rcode)
+ if (wsrep_slave_count_change < 0 && trx_end && WSREP_CB_SUCCESS == rcode)
{
+ WSREP_DEBUG("applier commit, locking LOCK_wsrep_slave_threads %lu", thd->thread_id);
+ mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool);
mysql_mutex_lock(&LOCK_wsrep_slave_threads);
if (wsrep_slave_count_change < 0)
{
@@ -394,13 +1006,85 @@ wsrep_cb_status_t wsrep_commit_cb(void* const ctx,
thd->wsrep_apply_toi= false;
}
- return rcode;
+ /* Cleanup for streaming replication */
+ if (SR_trx && trx_end)
+ {
+ SR_trx->release();
+
+ /* Cleanup for streaming replication */
+ if (trx_end)
+ {
+ sr_pool->remove((THD*)ctx, meta->stid.node, meta->stid.trx, false);
+ DBUG_EXECUTE_IF("crash_commit_cb_last_fragment_commit_success",
+ DBUG_SUICIDE(););
+ /* Set thd to null as it is deleted in sr_pool->remove() */
+ thd= NULL;
+ }
+ }
+
+ if (thd)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ if (thd->wsrep_conflict_state() != REPLAYING)
+ {
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+ if (ctx != thd)
+ {
+ thd= (THD*)ctx;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() != REPLAYING)
+ {
+ thd->set_wsrep_query_state(QUERY_IDLE);
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+
+ DBUG_RETURN(rcode);
}
+wsrep_cb_status_t wsrep_apply_cb(void* const ctx,
+ const wsrep_ws_handle_t* ws_handle,
+ uint32_t flags,
+ const wsrep_buf_t* const buf,
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* exit_loop)
+{
+ assert(meta->gtid.seqno > 0);
+ DBUG_ENTER("wsrep_apply_cb");
+
+ THD *thd= (THD*)ctx;
+ void* opaque_save= thd->wsrep_ws_handle.opaque;
+ thd->wsrep_ws_handle.opaque= ws_handle->opaque;
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() != REPLAYING)
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ wsrep_apply_error err;
+ int const apply_err= wsrep_apply(ctx, flags, buf, meta, err);
+ DBUG_ASSERT(0 == apply_err || !err.is_null());
+ DBUG_ASSERT(0 != apply_err || err.is_null());
+
+ if (0 != apply_err) flags |= WSREP_FLAG_ROLLBACK;
+
+ wsrep_cb_status_t rcode= wsrep_commit(ctx, flags, meta, exit_loop, err);
+
+ thd->wsrep_ws_handle.opaque= opaque_save;
+
+ DBUG_ASSERT(thd->wsrep_conflict_state_unsafe() == REPLAYING ||
+ thd->wsrep_query_state_unsafe() == QUERY_IDLE);
+
+ DBUG_RETURN(rcode);
+}
-wsrep_cb_status_t wsrep_unordered_cb(void* const ctx,
- const void* const data,
- size_t const size)
+wsrep_cb_status_t wsrep_unordered_cb(void* const ctx,
+ const wsrep_buf_t* const data)
{
return WSREP_CB_SUCCESS;
}
+
diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h
index f19d2d46d0c..a64c0e5eb12 100644
--- a/sql/wsrep_applier.h
+++ b/sql/wsrep_applier.h
@@ -1,4 +1,4 @@
-/* Copyright 2013 Codership Oy <http://www.codership.com>
+/* Copyright 2013-2015 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,26 +19,63 @@
#include <my_config.h>
#include "../wsrep/wsrep_api.h"
+#include "sql_class.h" // THD class
+
void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev);
Format_description_log_event* wsrep_get_apply_format(THD* thd);
+int wsrep_apply_events(THD* thd,
+ const void* events_buf,
+ size_t buf_len);
+
/* wsrep callback prototypes */
-extern "C" {
-wsrep_cb_status_t wsrep_apply_cb(void *ctx,
- const void* buf, size_t buf_len,
- uint32_t flags,
- const wsrep_trx_meta_t* meta);
+wsrep_cb_status_t wsrep_apply_cb(void* ctx,
+ const wsrep_ws_handle_t* ws_handle,
+ uint32_t flags,
+ const wsrep_buf_t* buf,
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* exit_loop);
+
+/* Applier error codes, when nothing better is available. */
+#define WSREP_RET_SUCCESS 0 // Success
+#define WSREP_ERR_GENERIC 1 // When in doubt (MySQL default error code)
+#define WSREP_ERR_BAD_EVENT 2 // Can't parse event
+#define WSREP_ERR_NOT_FOUND 3 // Key. table, schema not found
+#define WSREP_ERR_EXISTS 4 // Key, table, schema already exists
+#define WSREP_ERR_WRONG_TYPE 5 // Incompatible data type
+#define WSREP_ERR_FAILED 6 // Operation failed for some internal reason
+#define WSREP_ERR_ABORTED 7 // Operation was aborted externally
+
+class wsrep_apply_error
+{
+public:
+ wsrep_apply_error() : str_(NULL), len_(0) {};
+ ~wsrep_apply_error() { ::free(str_); }
+ /* stores the current THD error info from the diagnostic area. Works only
+ * once, subsequent invocations are ignored in order to preserve the original
+ * condition. */
+ void store(const THD* thd);
+ const char* c_str() const { return str_; }
+ size_t length() const { return len_; }
+ bool is_null() const { return (c_str() == NULL && length() == 0); }
+ wsrep_buf_t get_buf() const
+ {
+ wsrep_buf_t ret= { c_str(), length() };
+ return ret;
+ }
+private:
+ char* str_;
+ size_t len_;
+};
-wsrep_cb_status_t wsrep_commit_cb(void *ctx,
- uint32_t flags,
- const wsrep_trx_meta_t* meta,
- wsrep_bool_t* exit,
- bool commit);
+int wsrep_apply(void* ctx,
+ uint32_t flags,
+ const wsrep_buf_t* buf,
+ const wsrep_trx_meta_t* meta,
+ wsrep_apply_error& err);
-wsrep_cb_status_t wsrep_unordered_cb(void* ctx,
- const void* data,
- size_t size);
+wsrep_cb_status_t wsrep_unordered_cb(void* ctx,
+ const wsrep_buf_t* data);
-} /* extern "C" */
#endif /* WSREP_APPLIER_H */
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index cafd41b2653..66e743d6472 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -20,6 +20,12 @@
#include "log_event.h"
#include "wsrep_applier.h"
+#include "transaction.h"
+
+const char *wsrep_fragment_units[] = { "bytes", "events", "rows", "statements", NullS };
+const char *wsrep_SR_store_types[] = { "none", "file", "table", NullS };
+
+
extern handlerton *binlog_hton;
/*
Write the contents of a cache to a memory buffer.
@@ -112,7 +118,7 @@ heap_size(size_t length)
}
/* append data to writeset */
-static inline wsrep_status_t
+static inline wsrep_trx_status
wsrep_append_data(wsrep_t* const wsrep,
wsrep_ws_handle_t* const ws,
const void* const data,
@@ -125,9 +131,13 @@ wsrep_append_data(wsrep_t* const wsrep,
if (rc != WSREP_OK)
{
WSREP_WARN("append_data() returned %d", rc);
+ if (WSREP_SIZE_EXCEEDED == rc)
+ return WSREP_TRX_SIZE_EXCEEDED;
+ else
+ return WSREP_TRX_ERROR;
}
- return rc;
+ return WSREP_TRX_OK;
}
/*
@@ -139,29 +149,33 @@ wsrep_append_data(wsrep_t* const wsrep,
This version reads all of cache into single buffer and then appends to a
writeset at once.
*/
-static int wsrep_write_cache_once(wsrep_t* const wsrep,
- THD* const thd,
- IO_CACHE* const cache,
- size_t* const len)
+static wsrep_trx_status wsrep_write_cache_once(wsrep_t* const wsrep,
+ THD* const thd,
+ IO_CACHE* const cache,
+ size_t* const len)
{
my_off_t const saved_pos(my_b_tell(cache));
DBUG_ENTER("wsrep_write_cache_once");
- if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
+ if (reinit_io_cache(cache, READ_CACHE, wsrep_get_fragment_base(thd), 0, 0))
{
WSREP_ERROR("failed to initialize io-cache");
- DBUG_RETURN(ER_ERROR_ON_WRITE);
+ DBUG_RETURN(WSREP_TRX_ERROR);
}
- int err(WSREP_OK);
+ wsrep_trx_status ret(WSREP_TRX_OK);
size_t total_length(0);
uchar stack_buf[STACK_SIZE]; /* to avoid dynamic allocations for few data*/
- uchar* heap_buf(NULL);
uchar* buf(stack_buf);
size_t allocated(sizeof(stack_buf));
size_t used(0);
+ if (thd->wsrep_fragments_sent > 0)
+ {
+ allocated = 0;
+ }
+
uint length(my_b_bytes_in_cache(cache));
if (unlikely(0 == length)) length = my_b_fill(cache);
@@ -178,31 +192,31 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep,
{
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
wsrep_max_ws_size, total_length);
- err = WSREP_TRX_SIZE_EXCEEDED;
+ ret = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup;
}
if (total_length > allocated)
{
size_t const new_size(heap_size(total_length));
- uchar* tmp = (uchar *)my_realloc(heap_buf, new_size,
- MYF(MY_ALLOW_ZERO_PTR));
+ uchar* tmp = (uchar *)my_realloc(thd->wsrep_rbr_buf,
+ new_size, MYF(MY_ALLOW_ZERO_PTR));
if (!tmp)
{
WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
allocated, length);
- err = WSREP_TRX_SIZE_EXCEEDED;
+ ret = WSREP_TRX_ERROR;
goto cleanup;
}
- heap_buf = tmp;
- buf = heap_buf;
+ thd->wsrep_rbr_buf = tmp;
+ buf = thd->wsrep_rbr_buf;
allocated = new_size;
if (used <= STACK_SIZE && used > 0) // there's data in stack_buf
{
DBUG_ASSERT(buf == stack_buf);
- memcpy(heap_buf, stack_buf, used);
+ memcpy(thd->wsrep_rbr_buf, stack_buf, used);
}
}
@@ -216,23 +230,34 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep,
} while ((length = my_b_fill(cache)));
if (used > 0)
- err = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used);
+ ret = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used);
- if (WSREP_OK == err) *len = total_length;
+ if (WSREP_TRX_OK == ret)
+ {
+#ifndef NDEBUG
+ ulong fb= wsrep_get_fragment_base(thd);
+ assert(total_length + fb == saved_pos);
+#endif
+ }
cleanup:
+ *len = total_length;
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
{
WSREP_ERROR("failed to reinitialize io-cache");
}
- if (unlikely(WSREP_OK != err))
+ if (unlikely(WSREP_TRX_OK != ret))
{
wsrep_dump_rbr_buf_with_header(thd, buf, used);
}
+ if (thd->wsrep_fragments_sent == 0)
+ {
+ my_free(thd->wsrep_rbr_buf);
+ thd->wsrep_rbr_buf = NULL;
+ }
- my_free(heap_buf);
- DBUG_RETURN(err);
+ DBUG_RETURN(ret);
}
/*
@@ -243,21 +268,21 @@ cleanup:
This version uses incremental data appending as it reads it from cache.
*/
-static int wsrep_write_cache_inc(wsrep_t* const wsrep,
- THD* const thd,
- IO_CACHE* const cache,
- size_t* const len)
+static wsrep_trx_status wsrep_write_cache_inc(wsrep_t* const wsrep,
+ THD* const thd,
+ IO_CACHE* const cache,
+ size_t* const len)
{
my_off_t const saved_pos(my_b_tell(cache));
DBUG_ENTER("wsrep_write_cache_inc");
- if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
+ if (reinit_io_cache(cache, READ_CACHE, wsrep_get_fragment_base(thd), 0, 0))
{
WSREP_ERROR("failed to initialize io-cache");
DBUG_RETURN(WSREP_TRX_ERROR);
}
- int err(WSREP_OK);
+ wsrep_trx_status ret(WSREP_TRX_OK);
size_t total_length(0);
@@ -275,12 +300,12 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
{
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
wsrep_max_ws_size, total_length);
- err = WSREP_TRX_SIZE_EXCEEDED;
+ ret = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup;
}
- if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle,
- cache->read_pos, length)))
+ if(WSREP_TRX_OK != (ret=wsrep_append_data(wsrep, &thd->wsrep_ws_handle,
+ cache->read_pos, length)))
goto cleanup;
if (cache->file < 0)
@@ -290,15 +315,19 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
}
} while ((length = my_b_fill(cache)));
- if (WSREP_OK == err) *len = total_length;
+ if (WSREP_TRX_OK == ret)
+ {
+ assert(total_length + wsrep_get_fragment_base(thd) == saved_pos);
+ }
cleanup:
+ *len = total_length;
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
{
WSREP_ERROR("failed to reinitialize io-cache");
}
- DBUG_RETURN(err);
+ DBUG_RETURN(ret);
}
/*
@@ -307,12 +336,12 @@ cleanup:
This function quite the same as MYSQL_BIN_LOG::write_cache(),
with the exception that here we write in buffer instead of log file.
*/
-int wsrep_write_cache(wsrep_t* const wsrep,
- THD* const thd,
- IO_CACHE* const cache,
- size_t* const len)
+wsrep_trx_status wsrep_write_cache(wsrep_t* const wsrep,
+ THD* const thd,
+ IO_CACHE* const cache,
+ size_t* const len)
{
- if (wsrep_incremental_data_collection) {
+ if (wsrep_incremental_data_collection && thd->wsrep_fragments_sent == 0) {
return wsrep_write_cache_inc(wsrep, thd, cache, len);
}
else {
@@ -512,3 +541,99 @@ cleanup1:
DBUG_VOID_RETURN;
}
+#include "wsrep_thd_pool.h"
+extern Wsrep_thd_pool *wsrep_thd_pool;
+
+#include "log_event.h"
+// #include "binlog.h"
+
+int wsrep_write_dummy_event_low(THD *thd, const char *msg)
+{
+ int ret= 0;
+ if (mysql_bin_log.is_open() && wsrep_gtid_mode)
+ {
+ DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
+
+ /* For restoring orig thd state before returing it back to pool */
+ int wsrep_on= thd->variables.wsrep_on;
+ int sql_log_bin= thd->variables.sql_log_bin;
+ int option_bits= thd->variables.option_bits;
+ enum wsrep_exec_mode exec_mode= thd->wsrep_exec_mode;
+
+ /*
+ Fake that the connection is local client connection for the duration
+ of mysql_bin_log.write_event(), otherwise the write will fail.
+ */
+ thd->wsrep_exec_mode= LOCAL_STATE;
+ thd->variables.wsrep_on= 1;
+ thd->variables.sql_log_bin= 1;
+ thd->variables.option_bits |= OPTION_BIN_LOG;
+
+ Ignorable_log_event skip_event(thd);
+ ret= mysql_bin_log.write_event(&skip_event);
+
+ /* Restore original thd state */
+ thd->wsrep_exec_mode= exec_mode;
+ thd->variables.wsrep_on= wsrep_on;
+ thd->variables.sql_log_bin= sql_log_bin;
+ thd->variables.option_bits= option_bits;
+
+ if (ret)
+ {
+ WSREP_ERROR("Write to binlog failed: %d", ret);
+ abort();
+ unireg_abort(1);
+ }
+ ret= trans_commit_stmt(thd);
+ if (ret)
+ {
+ WSREP_ERROR("STMT commit failed: %d", ret);
+ abort();
+ }
+ }
+
+ return ret;
+}
+
+int wsrep_write_dummy_event(THD *orig_thd, const char *msg)
+{
+ if (WSREP_EMULATE_BINLOG(orig_thd))
+ {
+ return 0;
+ }
+
+ /* Use tmp thd for the transaction to avoid messing up orig_thd
+ transaction state */
+ THD* thd= wsrep_thd_pool->get_thd(0);
+
+ if (!thd)
+ {
+ return 1;
+ }
+
+ /*
+ Use original THD wsrep TRX meta data and WS handle to make
+ commit generate GTID and go through commit ordering hooks.
+ */
+ wsrep_trx_meta_t meta_save= thd->wsrep_trx_meta;
+ thd->wsrep_trx_meta= orig_thd->wsrep_trx_meta;
+ wsrep_ws_handle_t handle_save= thd->wsrep_ws_handle;
+ thd->wsrep_ws_handle= orig_thd->wsrep_ws_handle;
+
+ int ret= wsrep_write_dummy_event_low(thd, msg);
+
+ if (ret || (ret= trans_commit(thd)))
+ {
+ WSREP_ERROR("Failed to write skip event into binlog");
+ abort();
+ unireg_abort(1);
+ }
+
+ thd->wsrep_trx_meta= meta_save;
+ thd->wsrep_ws_handle= handle_save;
+
+ wsrep_thd_pool->release_thd(thd);
+
+ orig_thd->store_globals();
+ return ret;
+}
diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h
index 864813d5c98..8c7f124fcbd 100644
--- a/sql/wsrep_binlog.h
+++ b/sql/wsrep_binlog.h
@@ -16,11 +16,38 @@
#ifndef WSREP_BINLOG_H
#define WSREP_BINLOG_H
+#include "my_global.h"
+
+#define WSREP_FRAG_BYTES 0
+#define WSREP_FRAG_EVENTS 1
+#define WSREP_FRAG_ROWS 2
+#define WSREP_FRAG_STATEMENTS 3
+
+#define WSREP_SR_STORE_NONE 0
+#define WSREP_SR_STORE_FILE 1
+#define WSREP_SR_STORE_TABLE 2
+
+extern ulong wsrep_SR_store_type;
+extern const char *wsrep_fragment_units[];
+extern const char *wsrep_SR_store_types[];
+
+class wsrep_SR_trx;
#include "sql_class.h" // THD, IO_CACHE
#define HEAP_PAGE_SIZE 65536 /* 64K */
#define WSREP_MAX_WS_SIZE 2147483647 /* 2GB */
+bool wsrep_fragment_full(THD *thd);
+void wsrep_reset_SR_trans(THD *thd);
+void wsrep_reset_SR_fill(THD *thd);
+int wsrep_append_SR_trans(THD *thd, ulong unit, ulong size, bool replicate);
+bool wsrep_fragmented(THD *thd);
+void wsrep_step_fragment_base(THD *thd, ulong size);
+ulong wsrep_get_fragment_base(THD *thd);
+void wsrep_append_fill_rate(THD*, ulong);
+void wsrep_reset_fragment_fill(THD*, ulong);
+ulong wsrep_get_fragment_fill(THD*);
+
/*
Write the contents of a cache to a memory buffer.
@@ -38,23 +65,33 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len);
@param len total amount of data written
@return wsrep error status
*/
-int wsrep_write_cache (wsrep_t* const wsrep,
- THD* const thd,
- IO_CACHE* const cache,
- size_t* const len);
+wsrep_trx_status wsrep_write_cache(wsrep_t* wsrep,
+ THD* thd,
+ IO_CACHE* cache,
+ size_t* len);
/* Dump replication buffer to disk */
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len);
-/* Dump replication buffer to disk without intermediate buffer */
-void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache);
-
/* Dump replication buffer along with header to a file */
void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf,
size_t buf_len);
int wsrep_binlog_close_connection(THD* thd);
-int wsrep_binlog_savepoint_set(THD *thd, void *sv);
-int wsrep_binlog_savepoint_rollback(THD *thd, void *sv);
+uint wsrep_get_trans_cache_position(THD *thd);
+
+/*
+ Write dummy event into binlog in place of unused GTID.
+ The binlog write is done in thd context.
+*/
+int wsrep_write_dummy_event_low(THD *thd, const char *msg);
+/*
+ Write dummy event to binlog in place of unused GTID and
+ commit. The binlog write and commit are done in temporary
+ thd context, the original thd state is not altered.
+*/
+int wsrep_write_dummy_event(THD* thd, const char *msg);
+
+void wsrep_register_binlog_handler(THD *thd, bool trx);
#endif /* WSREP_BINLOG_H */
diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc
index 0b6e7e0d5bb..57cc0d51997 100644
--- a/sql/wsrep_dummy.cc
+++ b/sql/wsrep_dummy.cc
@@ -17,7 +17,13 @@
#include <sql_class.h>
#include <mysql/service_wsrep.h>
-my_bool wsrep_thd_is_BF(THD *, my_bool)
+int64_t wsrep_thd_trx_seqno(const THD *)
+{ return 0;}
+
+my_thread_id wsrep_thd_thread_id(THD *thd)
+{ return (my_thread_id)0; }
+
+my_bool wsrep_thd_is_BF(void *, my_bool)
{ return 0; }
int wsrep_trx_order_before(THD *, THD *)
@@ -26,7 +32,8 @@ int wsrep_trx_order_before(THD *, THD *)
enum wsrep_conflict_state wsrep_thd_conflict_state(THD *, my_bool)
{ return NO_CONFLICT; }
-int wsrep_is_wsrep_xid(const XID*)
+//int wsrep_is_wsrep_xid(const XID*)
+int wsrep_is_wsrep_xid(const void* xid)
{ return 0; }
long long wsrep_xid_seqno(const XID* x)
@@ -38,10 +45,13 @@ const unsigned char* wsrep_xid_uuid(const XID*)
return uuid;
}
+bool wsrep_prepare_key_for_innodb(THD* thd, const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*)
+{ return 0; }
+
bool wsrep_prepare_key(const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*)
{ return 0; }
-struct wsrep *get_wsrep()
+struct wsrep_st *get_wsrep()
{ return 0; }
my_bool get_wsrep_certify_nonPK()
@@ -77,6 +87,9 @@ bool wsrep_consistency_check(THD *)
void wsrep_lock_rollback()
{ }
+int wsrep_on(void *)
+{ return 0;}
+
int wsrep_on(THD *thd)
{ return 0; }
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index d4d35d752be..79072bb1916 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -340,6 +340,7 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
}
+ DBUG_ENTER("wsrep_run_wsrep_commit");
DEBUG_SYNC(thd, "wsrep_before_replication");
if (thd->slave_thread && !opt_log_slave_updates) DBUG_RETURN(WSREP_TRX_OK);
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0a2735fe0b7..951497e100f 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -13,8 +13,10 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
-#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
+#include <sql_plugin.h> // SHOW_MY_BOOL
+#include "mariadb.h"
#include <mysqld.h>
+#include <transaction.h>
#include <sql_class.h>
#include <sql_parse.h>
#include <sql_base.h> /* find_temporary_table() */
@@ -33,9 +35,16 @@
#include "wsrep_var.h"
#include "wsrep_binlog.h"
#include "wsrep_applier.h"
+#include "wsrep_sr.h"
+#include "wsrep_sr_file.h"
+#include "wsrep_sr_table.h"
+#include "wsrep_schema.h"
+#include "wsrep_thd_pool.h"
#include "wsrep_xid.h"
+#include "wsrep_trans_observer.h"
#include <cstdio>
#include <cstdlib>
+#include <string>
#include "log_event.h"
#include <slave.h>
@@ -85,7 +94,7 @@ my_bool wsrep_certify_nonPK; // Certify, even when no primary
my_bool wsrep_recovery; // Recovery
my_bool wsrep_replicate_myisam; // Enable MyISAM replication
my_bool wsrep_log_conflicts;
-my_bool wsrep_load_data_splitting; // Commit load data every 10K intervals
+my_bool wsrep_load_data_splitting= 0; // Commit load data every 10K intervals
my_bool wsrep_slave_UK_checks; // Slave thread does UK checks
my_bool wsrep_slave_FK_checks; // Slave thread does FK checks
my_bool wsrep_sst_donor_rejects_queries;
@@ -111,7 +120,15 @@ my_bool wsrep_restart_slave_activated= 0; // Node has dropped, and slave
bool wsrep_new_cluster= false; // Bootstrap the cluster?
int wsrep_slave_count_change= 0; // No. of appliers to stop/start
int wsrep_to_isolation= 0; // No. of active TO isolation threads
-long wsrep_max_protocol_version= 3; // Maximum protocol version to use
+long wsrep_max_protocol_version= 4; // Maximum protocol version to use
+long int wsrep_protocol_version= wsrep_max_protocol_version;
+ulong wsrep_trx_fragment_size= 0; // size limit for fragmenting
+ // 0 = no fragmenting
+ulong wsrep_trx_fragment_unit= WSREP_FRAG_BYTES;
+ // unit for fragment size
+ulong wsrep_SR_store_type= WSREP_SR_STORE_TABLE;
+uint wsrep_ignore_apply_errors= 0;
+
/*
* End configuration options
@@ -127,29 +144,36 @@ mysql_mutex_t LOCK_wsrep_sst;
mysql_cond_t COND_wsrep_sst;
mysql_mutex_t LOCK_wsrep_sst_init;
mysql_cond_t COND_wsrep_sst_init;
-mysql_mutex_t LOCK_wsrep_rollback;
-mysql_cond_t COND_wsrep_rollback;
-wsrep_aborting_thd_t wsrep_aborting_thd= NULL;
mysql_mutex_t LOCK_wsrep_replaying;
mysql_cond_t COND_wsrep_replaying;
mysql_mutex_t LOCK_wsrep_slave_threads;
mysql_mutex_t LOCK_wsrep_desync;
mysql_mutex_t LOCK_wsrep_config_state;
+mysql_mutex_t LOCK_wsrep_SR_pool;
+mysql_mutex_t LOCK_wsrep_SR_store;
+mysql_mutex_t LOCK_wsrep_thd_pool; /* locking policy:
+ 1. LOCK_wsrep_slave_threads
+ 2. LOCK_wsrep_thd_pool
+ */
int wsrep_replaying= 0;
ulong wsrep_running_threads = 0; // # of currently running wsrep threads
ulong my_bind_addr;
#ifdef HAVE_PSI_INTERFACE
-PSI_mutex_key key_LOCK_wsrep_rollback,
+PSI_mutex_key key_LOCK_wsrep_thd,
key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst,
key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init,
key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync,
- key_LOCK_wsrep_config_state;
+ key_LOCK_wsrep_config_state,
+ key_LOCK_wsrep_SR_pool,
+ key_LOCK_wsrep_SR_store, key_LOCK_wsrep_thd_pool, key_LOCK_wsrep_nbo,
+ key_LOCK_wsrep_thd_queue;
-PSI_cond_key key_COND_wsrep_rollback,
+PSI_cond_key key_COND_wsrep_thd,
key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst,
- key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread;
+ key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread,
+ key_COND_wsrep_nbo, key_COND_wsrep_thd_queue;
PSI_file_key key_file_wsrep_gra_log;
@@ -160,20 +184,23 @@ static PSI_mutex_info wsrep_mutexes[]=
{ &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0},
{ &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
- { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0},
{ &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL},
{ &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL},
- { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL}
+ { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_SR_pool, "LOCK_wsrep_SR_pool", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_SR_store, "LOCK_wsrep_SR_store", PSI_FLAG_GLOBAL},
+ { &key_LOCK_wsrep_thd_pool, "LOCK_wsrep_thd_pool", PSI_FLAG_GLOBAL}
};
static PSI_cond_info wsrep_conds[]=
{
+ { &key_COND_wsrep_thd, "COND_wsrep_thd", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_ready, "COND_wsrep_ready", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0},
- { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL},
{ &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL}
};
@@ -185,6 +212,7 @@ static PSI_file_info wsrep_files[]=
my_bool wsrep_inited = 0; // initialized ?
+static wsrep_uuid_t node_uuid= WSREP_UUID_UNDEFINED;
static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED;
static char cluster_uuid_str[40]= { 0, };
static const char* cluster_status_str[WSREP_VIEW_MAX] =
@@ -212,11 +240,25 @@ long long wsrep_local_bf_aborts = 0;
const char* wsrep_provider_name = provider_name;
const char* wsrep_provider_version = provider_version;
const char* wsrep_provider_vendor = provider_vendor;
+char* wsrep_provider_capabilities = NULL;
+char* wsrep_cluster_capabilities = NULL;
/* End wsrep status variables */
-wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED;
-wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED;
-long wsrep_protocol_version = 3;
+wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED;
+wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED;
+wsp::node_status local_status;
+static wsrep_view_status_t local_view_status = WSREP_VIEW_NON_PRIMARY;
+
+class SR_storage_file *wsrep_SR_store_file = NULL;
+class SR_storage_table *wsrep_SR_store_table = NULL;
+class SR_storage *wsrep_SR_store = NULL;
+
+/*
+ */
+#define WSREP_THD_POOL_SIZE 16
+Wsrep_thd_pool* wsrep_thd_pool= 0;
+Wsrep_schema *wsrep_schema= 0;
+static bool wsrep_schema_inited= false;
wsp::Config_state *wsrep_config_state;
@@ -259,8 +301,8 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...)
static void wsrep_log_states (wsrep_log_level_t const level,
const wsrep_uuid_t* const group_uuid,
wsrep_seqno_t const group_seqno,
- const wsrep_uuid_t* const node_uuid,
- wsrep_seqno_t const node_seqno)
+ const wsrep_uuid_t* const loc_uuid,
+ wsrep_seqno_t const loc_seqno)
{
char uuid_str[37];
char msg[256];
@@ -270,9 +312,9 @@ static void wsrep_log_states (wsrep_log_level_t const level,
uuid_str, (long long)group_seqno);
wsrep_log_cb (level, msg);
- wsrep_uuid_print (node_uuid, uuid_str, sizeof(uuid_str));
+ wsrep_uuid_print (loc_uuid, uuid_str, sizeof(uuid_str));
snprintf (msg, 255, "WSREP: Local state: %s:%lld",
- uuid_str, (long long)node_seqno);
+ uuid_str, (long long)loc_seqno);
wsrep_log_cb (level, msg);
}
@@ -281,14 +323,19 @@ void wsrep_init_sidno(const wsrep_uuid_t& wsrep_uuid)
{
/* generate new Sid map entry from inverted uuid */
rpl_sid sid;
- wsrep_uuid_t ltid_uuid;
-
- for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i)
+ if (wsrep_protocol_version >= 4)
{
+ sid.copy_from(wsrep_uuid.data);
+ }
+ else
+ {
+ wsrep_uuid_t ltid_uuid;
+ for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i)
+ {
ltid_uuid.data[i] = ~wsrep_uuid.data[i];
+ }
+ sid.copy_from(ltid_uuid.data);
}
-
- sid.copy_from(ltid_uuid.data);
global_sid_lock->wrlock();
wsrep_sidno= global_sid_map->add_sid(sid);
WSREP_INFO("Initialized wsrep sidno %d", wsrep_sidno);
@@ -296,19 +343,187 @@ void wsrep_init_sidno(const wsrep_uuid_t& wsrep_uuid)
}
#endif /* GTID_SUPPORT */
-static wsrep_cb_status_t
-wsrep_view_handler_cb (void* app_ctx,
- void* recv_ctx,
- const wsrep_view_info_t* view,
- const char* state,
- size_t state_len,
- void** sst_req,
- size_t* sst_req_len)
+void wsrep_init_schema()
{
- *sst_req = NULL;
- *sst_req_len = 0;
+ WSREP_INFO("wsrep_init_schema_and_SR %p %p", wsrep_schema, wsrep_SR_store);
+ if (!wsrep_schema)
+ {
+ if (wsrep_before_SE()) {
+ delete wsrep_thd_pool;
+ wsrep_thd_pool=0;
+ }
+
+ if (!wsrep_thd_pool) {
+ wsrep_thd_pool= new Wsrep_thd_pool(WSREP_THD_POOL_SIZE);
+ }
+
+ wsrep_schema= new Wsrep_schema(wsrep_thd_pool);
+
+ if (strcmp (wsrep_provider, WSREP_NONE))
+ {
+ if (wsrep_schema->init())
+ {
+ WSREP_ERROR("Failed to init wsrep schema");
+ delete wsrep_schema;
+ delete wsrep_thd_pool;
+ unireg_abort(1);
+ }
+ }
+ }
+}
+
+void wsrep_init_SR()
+{
+ /* initialize SR pools, now that innodb has initialized */
+ if (wsrep_SR_store && wsrep_SR_store->init(wsrep_cluster_state_uuid,
+ wsrep_schema)) {
+ WSREP_ERROR("wsrep SR persistency store initialization failed");
+ unireg_abort(1);
+ }
+ else {
+ if (wsrep_SR_store && wsrep_SR_store->restore(0)) {
+ WSREP_ERROR("wsrep SR persistency restore failed");
+ unireg_abort(1);
+ }
+ }
+}
+
+int wsrep_replay_from_SR_store(THD* thd, const wsrep_trx_meta_t& meta)
+{
+ DBUG_ENTER("wsrep_replay_from_SR_store");
+ if (!wsrep_SR_store) {
+ WSREP_ERROR("no SR persistency store defined, can't replay");
+ DBUG_RETURN(1);
+ }
+
+ int ret= wsrep_SR_store->replay_trx(thd, meta);
+ DBUG_RETURN(ret);
+}
+
+static void wsrep_rollback_SR_connections()
+{
+ THD *tmp;
+ mysql_mutex_lock(&LOCK_thread_count);
+
+ I_List_iterator<THD> it(threads);
+ while ((tmp=it++))
+ {
+ mysql_mutex_lock(&tmp->LOCK_wsrep_thd);
+ if (tmp->wsrep_client_thread && tmp->wsrep_is_streaming())
+ {
+ tmp->set_wsrep_conflict_state(MUST_ABORT);
+ if (tmp->wsrep_query_state() == QUERY_IDLE)
+ {
+ wsrep_fire_rollbacker(tmp);
+ }
+ /*
+ No need to send rollback fragment for this trx: slaves rollback
+ all SR transactions whose master goes non-Primary.
+ */
+ tmp->wsrep_SR_rollback_replicated_for_trx= tmp->wsrep_trx_id();
+ }
+ mysql_mutex_unlock(&tmp->LOCK_wsrep_thd);
+ }
+
+ mysql_mutex_unlock(&LOCK_thread_count);
+}
+
+/** Export the WSREP provider's capabilities as a human readable string.
+ * The result is saved in a dynamically allocated string of the form:
+ * :cap1:cap2:cap3:
+ */
+static void wsrep_capabilities_export(wsrep_cap_t const cap, char** str)
+{
+ static const char* names[] =
+ {
+ /* Keep in sync with wsrep/wsrep_api.h WSREP_CAP_* macros. */
+ "MULTI_MASTER",
+ "CERTIFICATION",
+ "PARALLEL_APPLYING",
+ "TRX_REPLAY",
+ "ISOLATION",
+ "PAUSE",
+ "CAUSAL_READS",
+ "CAUSAL_TRX",
+ "INCREMENTAL_WRITESET",
+ "SESSION_LOCKS",
+ "DISTRIBUTED_LOCKS",
+ "CONSISTENCY_CHECK",
+ "UNORDERED",
+ "ANNOTATION",
+ "PREORDERED",
+ "STREAMING",
+ "SNAPSHOT",
+ "NBO",
+ };
+
+ std::string s;
+ for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i)
+ {
+ if (cap & (1ULL << i))
+ {
+ if (s.empty())
+ {
+ s = ":";
+ }
+ s += names[i];
+ s += ":";
+ }
+ }
+
+ /* A read from the string pointed to by *str may be started at any time,
+ * so it must never point to free(3)d memory or non '\0' terminated string. */
+
+ char* const previous = *str;
+
+ *str = strdup(s.c_str());
- wsrep_member_status_t memb_status= wsrep_config_state->get_status();
+ if (previous != NULL)
+ {
+ free(previous);
+ }
+}
+
+wsrep_cb_status_t
+wsrep_connected_handler_cb(void* app_ctx,
+ const wsrep_view_info_t* initial_view)
+{
+ if (initial_view->my_idx < 0) {
+ WSREP_ERROR("Invalid index %d in initial view", initial_view->my_idx);
+ return WSREP_CB_FAILURE;
+ }
+
+ node_uuid= initial_view->members[initial_view->my_idx].id;
+ cluster_uuid= initial_view->state_id.uuid;
+ wsrep_cluster_status= cluster_status_str[initial_view->status];
+
+ char node_uuid_str[WSREP_UUID_STR_LEN + 1];
+ (void)wsrep_uuid_print(&node_uuid, node_uuid_str, sizeof(node_uuid_str));
+ (void)wsrep_uuid_print(&cluster_uuid, cluster_uuid_str,
+ sizeof(cluster_uuid_str));
+
+ WSREP_INFO("Connected to cluster %s with id: %s",
+ cluster_uuid_str, node_uuid_str);
+ return WSREP_CB_SUCCESS;
+}
+
+static wsrep_cb_status_t
+wsrep_view_handler_cb(void* app_ctx,
+ void* recv_ctx,
+ const wsrep_view_info_t* view,
+ /* TODO: These are unused, should be removed?*/
+ const char* state,
+ size_t state_len)
+{
+ /* Allow calling view handler from non-applier threads */
+ struct st_my_thread_var* tmp_thread_var= 0;
+ if (!my_thread_var) {
+ my_thread_init();
+ tmp_thread_var= my_thread_var;
+ }
+
+ wsrep_cb_status_t ret= WSREP_CB_SUCCESS;
+ wsrep_member_status_t new_status= local_status.get();
if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t)))
{
@@ -323,11 +538,16 @@ wsrep_view_handler_cb (void* app_ctx,
wsrep_cluster_size= view->memb_num;
wsrep_local_index= view->my_idx;
- WSREP_INFO("New cluster view: global state: %s:%lld, view# %lld: %s, "
- "number of nodes: %ld, my index: %ld, protocol version %d",
- wsrep_cluster_state_uuid, (long long)view->state_id.seqno,
- (long long)wsrep_cluster_conf_id, wsrep_cluster_status,
- wsrep_cluster_size, wsrep_local_index, view->proto_ver);
+ if (wsrep_cluster_size > 0) {
+ WSREP_INFO("New cluster view: global state: %s:%lld, view# %lld: %s, "
+ "number of nodes: %ld, my index: %ld, protocol version %d",
+ wsrep_cluster_state_uuid, (long long)view->state_id.seqno,
+ (long long)wsrep_cluster_conf_id, wsrep_cluster_status,
+ wsrep_cluster_size, wsrep_local_index, view->proto_ver);
+ }
+ else {
+ WSREP_INFO("Provider closed.");
+ }
/* Proceed further only if view is PRIMARY */
if (WSREP_VIEW_PRIMARY != view->status)
@@ -338,7 +558,7 @@ wsrep_view_handler_cb (void* app_ctx,
#endif /* HAVE_QUERY_CACHE */
wsrep_ready_set(FALSE);
- memb_status= WSREP_MEMBER_UNDEFINED;
+ new_status= WSREP_MEMBER_UNDEFINED;
/* Always record local_uuid and local_seqno in non-prim since this
* may lead to re-initializing provider and start position is
* determined according to these variables */
@@ -355,6 +575,7 @@ wsrep_view_handler_cb (void* app_ctx,
case 1:
case 2:
case 3:
+ case 4: // SR and view callback change
// version change
if (view->proto_ver != wsrep_protocol_version)
{
@@ -374,101 +595,200 @@ wsrep_view_handler_cb (void* app_ctx,
unireg_abort(1);
}
- if (view->state_gap)
+ if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t)))
{
- WSREP_WARN("Gap in state sequence. Need state transfer.");
-
- /* After that wsrep will call wsrep_sst_prepare. */
- /* keep ready flag 0 until we receive the snapshot */
- wsrep_ready_set(FALSE);
-
- /* Close client connections to ensure that they don't interfere
- * with SST. Necessary only if storage engines are initialized
- * before SST.
- * TODO: Just killing all ongoing transactions should be enough
- * since wsrep_ready is OFF and no new transactions can start.
- */
- if (!wsrep_before_SE())
- {
- WSREP_DEBUG("[debug]: closing client connections for PRIM");
- wsrep_close_client_connections(FALSE);
- }
+ memcpy((wsrep_uuid_t*)&cluster_uuid, &view->state_id.uuid,
+ sizeof(cluster_uuid));
- ssize_t const req_len= wsrep_sst_prepare (sst_req);
-
- if (req_len < 0)
- {
- WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len,
- strerror(-req_len));
- memb_status= WSREP_MEMBER_UNDEFINED;
- }
- else
- {
- assert(sst_req != NULL);
- *sst_req_len= req_len;
- memb_status= WSREP_MEMBER_JOINER;
- }
+ wsrep_uuid_print (&cluster_uuid, cluster_uuid_str,
+ sizeof(cluster_uuid_str));
}
- else
+
+ /*
+ * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized
+ * before - OR - it was reinitilized on startup (lp:992840)
+ */
+ if (wsrep_startup)
{
- /*
- * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized
- * before - OR - it was reinitilized on startup (lp:992840)
- */
- if (wsrep_startup)
- {
if (wsrep_before_SE())
{
wsrep_SE_init_grab();
// Signal mysqld init thread to continue
wsrep_sst_complete (&cluster_uuid, view->state_id.seqno, false);
// and wait for SE initialization
- wsrep_SE_init_wait();
+ if (wsrep_SE_init_wait())
+ {
+ ret= WSREP_CB_FAILURE;
+ goto out;
+ }
+ }
+
+ wsrep_seqno_t seqno;
+
+ /* Init storage engine XIDs from first view */
+ if (view->memb_num == 1)
+ {
+ seqno= view->state_id.seqno;
+ wsrep_set_SE_checkpoint(WSREP_UUID_UNDEFINED, WSREP_SEQNO_UNDEFINED);
+ wsrep_set_SE_checkpoint(cluster_uuid, seqno);
}
else
{
- local_uuid= cluster_uuid;
- local_seqno= view->state_id.seqno;
+ // must get from state transfer
+ wsrep_uuid_t unused;
+ wsrep_get_SE_checkpoint(unused, seqno);
}
- /* Init storage engine XIDs from first view */
- wsrep_set_SE_checkpoint(local_uuid, local_seqno);
+
+ wsrep_verify_SE_checkpoint(cluster_uuid, seqno);
+ new_status= WSREP_MEMBER_JOINED;
#ifdef GTID_SUPPORT
wsrep_init_sidno(local_uuid);
#endif /* GTID_SUPPORT */
- memb_status= WSREP_MEMBER_JOINED;
- }
+ }
+ else
+ {
+ wsrep_get_SE_checkpoint(local_uuid, local_seqno);
- // just some sanity check
- if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t)))
- {
- WSREP_ERROR("Undetected state gap. Can't continue.");
- wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->state_id.seqno,
- &local_uuid, -1);
- unireg_abort(1);
- }
+ // just a sanity check
+ if (wsrep_uuid_compare(&local_uuid, &cluster_uuid) != 0)
+ {
+ WSREP_ERROR("Undetected state gap. Can't continue.");
+ wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->state_id.seqno,
+ &local_uuid, local_seqno);
+ unireg_abort(1);
+ }
}
- if (wsrep_auto_increment_control)
+ if (wsrep_auto_increment_control && view->my_idx >= 0)
{
- global_system_variables.auto_increment_offset= view->my_idx + 1;
- global_system_variables.auto_increment_increment= view->memb_num;
+ global_system_variables.auto_increment_offset= view->my_idx + 1;
+ global_system_variables.auto_increment_increment= view->memb_num;
}
{ /* capabilities may be updated on new configuration */
- uint64_t const caps(wsrep->capabilities (wsrep));
+ wsrep_cap_t const caps(view->capabilities);
- my_bool const idc((caps & WSREP_CAP_INCREMENTAL_WRITESET) != 0);
- if (TRUE == wsrep_incremental_data_collection && FALSE == idc)
- {
- WSREP_WARN("Unsupported protocol downgrade: "
- "incremental data collection disabled. Expect abort.");
- }
- wsrep_incremental_data_collection = idc;
+ my_bool const idc((caps & WSREP_CAP_INCREMENTAL_WRITESET) != 0);
+ if (TRUE == wsrep_incremental_data_collection && FALSE == idc)
+ {
+ WSREP_WARN("Unsupported protocol downgrade: "
+ "incremental data collection disabled. Expect abort.");
+ }
+ wsrep_incremental_data_collection = idc;
+
+ wsrep_capabilities_export(caps, &wsrep_cluster_capabilities);
+ }
+
+ /*
+ Initialize wsrep schema and SR
+ */
+ if (!wsrep_schema) {
+ wsrep_init_schema();
+ }
+
+ if (wsrep_schema->store_view(view)) {
+ WSREP_ERROR("Storing view failed");
+ unireg_abort(1);
+ }
+
+ /*
+ If the recv_ctx is a pointer to thd object we need to store globals
+ here as wsrep_schema->store_view() uses temporary thd object and
+ writes over thread locals.
+ */
+ if (recv_ctx) ((THD*) recv_ctx)->store_globals();
+
+ if (wsrep_startup == TRUE) {
+ wsrep_init_SR();
+ }
+
+ trim_SR_pool((THD*)recv_ctx, view->members, view->memb_num);
+
+ /*
+ Transitioning from non-primary to primary view
+ */
+ if (local_view_status != WSREP_VIEW_PRIMARY) {
+ wsrep_rollback_SR_connections();
}
out:
if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE;
- wsrep_config_state->set(memb_status, view);
+ local_status.set(new_status, view);
+ local_view_status = view->status;
+
+ if (tmp_thread_var) {
+ my_thread_end();
+ }
+
+ return ret;
+}
+
+/* Verifies that SE position is consistent with the group position
+ * and initializes other variables */
+void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid,
+ wsrep_seqno_t const seqno)
+{
+ wsrep_get_SE_checkpoint(local_uuid, local_seqno);
+
+ if (memcmp(&local_uuid, &uuid, sizeof (wsrep_uuid_t)) ||
+ local_seqno > seqno)
+ {
+ WSREP_ERROR("Failed to update SE checkpoint. Can't continue.");
+ wsrep_log_states(WSREP_LOG_FATAL, &uuid, seqno,
+ &local_uuid, local_seqno);
+ assert(0);
+ unireg_abort(1);
+ }
+
+#ifdef GTID_SUPPORT
+ wsrep_init_sidno(local_uuid);
+#endif
+}
+
+static wsrep_cb_status_t
+wsrep_sst_request_cb (void* app_ctx,
+ void** sst_req,
+ size_t* sst_req_len)
+{
+ *sst_req = NULL;
+ *sst_req_len = 0;
+
+ wsrep_member_status_t new_status= local_status.get();
+
+ WSREP_INFO("Preparing to receive SST.");
+
+ /* After that wsrep will call wsrep_sst_prepare. */
+ /* keep ready flag 0 until we receive the snapshot */
+ wsrep_ready_set(FALSE);
+
+ /* Close client connections to ensure that they don't interfere
+ * with SST. Necessary only if storage engines are initialized
+ * before SST.
+ * TODO: Just killing all ongoing transactions should be enough
+ * since wsrep_ready is OFF and no new transactions can start.
+ */
+ if (!wsrep_before_SE())
+ {
+ WSREP_DEBUG("[debug]: closing client connections for SST");
+ wsrep_close_client_connections(TRUE);
+ }
+
+ ssize_t const req_len = wsrep_sst_prepare (sst_req);
+
+ if (req_len < 0)
+ {
+ WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len,
+ strerror(-req_len));
+ new_status= WSREP_MEMBER_UNDEFINED;
+ }
+ else
+ {
+ assert(*sst_req != NULL || 0 == req_len);
+ *sst_req_len= req_len;
+ new_status= WSREP_MEMBER_JOINER;
+ }
+
+ local_status.set(new_status);
return WSREP_CB_SUCCESS;
}
@@ -516,11 +836,12 @@ void wsrep_ready_wait ()
mysql_mutex_unlock (&LOCK_wsrep_ready);
}
-static void wsrep_synced_cb(void* app_ctx)
+static wsrep_cb_status_t wsrep_synced_cb(void* app_ctx)
{
WSREP_INFO("Synchronized with group, ready for connections");
- my_bool signal_main= wsrep_ready_set(TRUE);
wsrep_config_state->set(WSREP_MEMBER_SYNCED);
+ my_bool signal_main= wsrep_ready_set(TRUE);
+ local_status.set(WSREP_MEMBER_SYNCED);
if (signal_main)
{
@@ -528,7 +849,10 @@ static void wsrep_synced_cb(void* app_ctx)
// Signal mysqld init thread to continue
wsrep_sst_complete (&local_uuid, local_seqno, false);
// and wait for SE initialization
- wsrep_SE_init_wait();
+ if (wsrep_SE_init_wait())
+ {
+ return WSREP_CB_FAILURE;
+ }
}
if (wsrep_restart_slave_activated)
{
@@ -550,6 +874,7 @@ static void wsrep_synced_cb(void* app_ctx)
mysql_mutex_unlock(&LOCK_active_mi);
}
+ return WSREP_CB_SUCCESS;
}
static void wsrep_init_position()
@@ -559,7 +884,7 @@ static void wsrep_init_position()
wsrep_seqno_t seqno;
wsrep_get_SE_checkpoint(uuid, seqno);
- if (!memcmp(&uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)))
+ if (wsrep_uuid_compare(&uuid, &WSREP_UUID_UNDEFINED) == 0)
{
WSREP_INFO("Read nil XID from storage engines, skipping position init");
return;
@@ -567,9 +892,10 @@ static void wsrep_init_position()
char uuid_str[40] = {0, };
wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
- WSREP_INFO("Initial position: %s:%lld", uuid_str, (long long)seqno);
+ WSREP_INFO("Storage engines initial position: %s:%lld",
+ uuid_str, (long long)seqno);
- if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(local_uuid)) &&
+ if (wsrep_uuid_compare(&local_uuid, &WSREP_UUID_UNDEFINED) == 0 &&
local_seqno == WSREP_SEQNO_UNDEFINED)
{
// Initial state
@@ -594,6 +920,7 @@ int wsrep_init()
if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO) &&
wsrep_start_position_init(wsrep_start_position))
{
+ assert(0);
return 1;
}
@@ -653,6 +980,17 @@ int wsrep_init()
wsrep->provider_vendor, sizeof(provider_vendor) - 1);
}
+ if (wsrep_gtid_mode && opt_bin_log && !opt_log_slave_updates)
+ {
+ WSREP_ERROR("Option --log-slave-updates is required if "
+ "binlog is enabled, GTID mode is on and wsrep provider "
+ "is specified");
+ return -1;
+ }
+
+ if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0)
+ wsrep_data_home_dir = mysql_real_data_home;
+
/* Initialize node address */
char node_addr[512]= { 0, };
size_t const node_addr_max= sizeof(node_addr) - 1;
@@ -747,9 +1085,11 @@ int wsrep_init()
done:
struct wsrep_init_args wsrep_args;
+ memset(&wsrep_args, 0, sizeof(wsrep_args));
struct wsrep_gtid const state_id = { local_uuid, local_seqno };
+ wsrep_args.app_ctx = 0;
wsrep_args.data_dir = wsrep_data_home_dir;
wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : "";
wsrep_args.node_address = node_addr;
@@ -761,9 +1101,10 @@ done:
wsrep_args.state_id = &state_id;
wsrep_args.logger_cb = wsrep_log_cb;
- wsrep_args.view_handler_cb = wsrep_view_handler_cb;
+ wsrep_args.connected_cb = wsrep_connected_handler_cb;
+ wsrep_args.view_cb = wsrep_view_handler_cb;
+ wsrep_args.sst_request_cb = wsrep_sst_request_cb;
wsrep_args.apply_cb = wsrep_apply_cb;
- wsrep_args.commit_cb = wsrep_commit_cb;
wsrep_args.unordered_cb = wsrep_unordered_cb;
wsrep_args.sst_donate_cb = wsrep_sst_donate_cb;
wsrep_args.synced_cb = wsrep_synced_cb;
@@ -777,8 +1118,44 @@ done:
wsrep->free(wsrep);
free(wsrep);
wsrep = NULL;
- } else {
- wsrep_inited= 1;
+ return rcode;
+ }
+
+ if (!wsrep_provider_is_SR_capable() &&
+ global_system_variables.wsrep_trx_fragment_size > 0)
+ {
+ WSREP_ERROR("The WSREP provider (%s) does not support streaming "
+ "replication but wsrep_trx_fragment_size is set to a "
+ "value other than 0 (%lu). Cannot continue. Either set "
+ "wsrep_trx_fragment_size to 0 or use wsrep_provider that "
+ "supports streaming replication.",
+ wsrep_provider, global_system_variables.wsrep_trx_fragment_size);
+ wsrep->free(wsrep);
+ free(wsrep);
+ wsrep = NULL;
+ return -1;
+ }
+ wsrep_inited= 1;
+
+ wsrep_capabilities_export(wsrep->capabilities(wsrep),
+ &wsrep_provider_capabilities);
+
+ WSREP_DEBUG("SR storage init for: %s",
+ (wsrep_SR_store_type == WSREP_SR_STORE_TABLE) ? "table" :
+ (wsrep_SR_store_type == WSREP_SR_STORE_FILE) ? "file" : "void");
+
+ switch (wsrep_SR_store_type)
+ {
+ case WSREP_SR_STORE_FILE:
+ wsrep_SR_store = wsrep_SR_store_file =
+ new SR_storage_file(mysql_real_data_home_ptr,
+ 1024,
+ wsrep_cluster_state_uuid);
+ break;
+ case WSREP_SR_STORE_TABLE:
+ wsrep_SR_store = wsrep_SR_store_table = new SR_storage_table();
+ break;
+ case WSREP_SR_STORE_NONE: break;
}
return rcode;
@@ -802,25 +1179,35 @@ void wsrep_thr_init()
mysql_cond_init(key_COND_wsrep_sst, &COND_wsrep_sst, NULL);
mysql_mutex_init(key_LOCK_wsrep_sst_init, &LOCK_wsrep_sst_init, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_wsrep_sst_init, &COND_wsrep_sst_init, NULL);
- mysql_mutex_init(key_LOCK_wsrep_rollback, &LOCK_wsrep_rollback, MY_MUTEX_INIT_FAST);
- mysql_cond_init(key_COND_wsrep_rollback, &COND_wsrep_rollback, NULL);
mysql_mutex_init(key_LOCK_wsrep_replaying, &LOCK_wsrep_replaying, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying, NULL);
mysql_mutex_init(key_LOCK_wsrep_slave_threads, &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_config_state, &LOCK_wsrep_config_state, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_wsrep_SR_pool,
+ &LOCK_wsrep_SR_pool, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_wsrep_SR_store,
+ &LOCK_wsrep_SR_store, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_wsrep_thd_pool,
+ &LOCK_wsrep_thd_pool, MY_MUTEX_INIT_FAST);
DBUG_VOID_RETURN;
}
+extern int wsrep_on(void *);
+
void wsrep_init_startup (bool first)
{
if (wsrep_init()) unireg_abort(1);
+#ifdef OLD_MARIADB
wsrep_thr_lock_init(
(wsrep_thd_is_brute_force_fun)wsrep_thd_is_BF,
(wsrep_abort_thd_fun)wsrep_abort_thd,
wsrep_debug, wsrep_convert_LOCK_to_trx,
(wsrep_on_fun)wsrep_on);
+#endif
+ wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_abort_thd,
+ wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on);
/*
Pre-initialize global_system_variables.table_plugin with a dummy engine
@@ -853,6 +1240,14 @@ void wsrep_init_startup (bool first)
void wsrep_deinit(bool free_options)
{
DBUG_ASSERT(wsrep_inited == 1);
+ if (wsrep_schema)
+ delete wsrep_schema;
+ wsrep_schema= 0;
+ WSREP_DEBUG("wsrep_deinit, free %d", free_options);
+ if (wsrep_thd_pool)
+ delete wsrep_thd_pool;
+ wsrep_thd_pool= 0;
+
wsrep_unload(wsrep);
wsrep= 0;
provider_name[0]= '\0';
@@ -861,9 +1256,16 @@ void wsrep_deinit(bool free_options)
wsrep_inited= 0;
- if (free_options)
+ if (wsrep_provider_capabilities != NULL)
{
- wsrep_sst_auth_free();
+ char* p = wsrep_provider_capabilities;
+ wsrep_provider_capabilities = NULL;
+ free(p);
+
+ if (free_options)
+ {
+ wsrep_sst_auth_free();
+ }
}
}
@@ -872,28 +1274,42 @@ void wsrep_thr_deinit()
{
if (!wsrep_config_state)
return; // Never initialized
+ WSREP_DEBUG("wsrep_thr_deinit");
mysql_mutex_destroy(&LOCK_wsrep_ready);
mysql_cond_destroy(&COND_wsrep_ready);
mysql_mutex_destroy(&LOCK_wsrep_sst);
mysql_cond_destroy(&COND_wsrep_sst);
mysql_mutex_destroy(&LOCK_wsrep_sst_init);
mysql_cond_destroy(&COND_wsrep_sst_init);
- mysql_mutex_destroy(&LOCK_wsrep_rollback);
- mysql_cond_destroy(&COND_wsrep_rollback);
mysql_mutex_destroy(&LOCK_wsrep_replaying);
mysql_cond_destroy(&COND_wsrep_replaying);
mysql_mutex_destroy(&LOCK_wsrep_slave_threads);
mysql_mutex_destroy(&LOCK_wsrep_desync);
mysql_mutex_destroy(&LOCK_wsrep_config_state);
+ mysql_mutex_destroy(&LOCK_wsrep_SR_pool);
+ mysql_mutex_destroy(&LOCK_wsrep_SR_store);
+ mysql_mutex_destroy(&LOCK_wsrep_thd_pool);
+
delete wsrep_config_state;
wsrep_config_state= 0; // Safety
+
+ if (wsrep_cluster_capabilities != NULL)
+ {
+ char* p = wsrep_cluster_capabilities;
+ wsrep_cluster_capabilities = NULL;
+ free(p);
+ }
}
void wsrep_recover()
{
- char uuid_str[40];
+ wsrep_uuid_t uuid;
+ wsrep_seqno_t seqno;
+ wsrep_get_SE_checkpoint(uuid, seqno);
+ char uuid_str[40] = {0, };;
+ wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
- if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) &&
+ if (wsrep_uuid_compare(&local_uuid, &WSREP_UUID_UNDEFINED) == 0 &&
local_seqno == -2)
{
wsrep_uuid_print(&local_uuid, uuid_str, sizeof(uuid_str));
@@ -901,10 +1317,6 @@ void wsrep_recover()
uuid_str, (long long)local_seqno);
return;
}
- wsrep_uuid_t uuid;
- wsrep_seqno_t seqno;
- wsrep_get_SE_checkpoint(uuid, seqno);
- wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
WSREP_INFO("Recovered position: %s:%lld", uuid_str, (long long)seqno);
}
@@ -924,17 +1336,56 @@ void wsrep_stop_replication(THD *thd)
wsrep_connected= FALSE;
- wsrep_close_client_connections(TRUE);
-
+ /* my connection, should not terminate with wsrep_close_client_connection(),
+ make transaction to rollback
+ */
+ if (thd && !thd->wsrep_applier) trans_rollback(thd);
+ wsrep_close_client_connections(TRUE, thd);
+
/* wait until appliers have stopped */
wsrep_wait_appliers_close(thd);
+ node_uuid= WSREP_UUID_UNDEFINED;
+
+ delete wsrep_schema;
+ wsrep_schema= 0;
+
return;
}
+void wsrep_shutdown_replication()
+{
+ WSREP_INFO("Shutdown replication");
+ if (!wsrep)
+ {
+ WSREP_INFO("Provider was not loaded, in shutdown replication");
+ return;
+ }
+
+ /* disconnect from group first to get wsrep_ready == FALSE */
+ WSREP_DEBUG("Provider disconnect");
+ wsrep->disconnect(wsrep);
+ wsrep_connected= FALSE;
+
+ wsrep_close_client_connections(TRUE);
+ wsrep_close_SR_transactions(NULL);
+
+ /* wait until appliers have stopped */
+ wsrep_wait_appliers_close(NULL);
+ node_uuid= WSREP_UUID_UNDEFINED;
+
+ if (current_thd)
+ {
+ /* Undocking the thread specific data. */
+ my_pthread_setspecific_ptr(THR_THD, NULL);
+ //my_pthread_setspecific_ptr(THR_MALLOC, NULL);
+ }
+}
+
bool wsrep_start_replication()
{
wsrep_status_t rcode;
+ WSREP_DEBUG("wsrep_start_replication");
/* wsrep provider must be loaded. */
DBUG_ASSERT(wsrep);
@@ -957,7 +1408,27 @@ bool wsrep_start_replication()
return true;
}
- bool const bootstrap= wsrep_new_cluster;
+ /*
+ With mysqldump etc SST THD pool must be initialized before starting
+ replication in order to avoid deadlock between THD pool initialization
+ and possible causal read of status variables.
+
+ On the other hand, with SST methods that require starting wsrep first
+ plugins are not necessarily initialized at this point, so THD pool
+ initialization must be postponed until plugin init has been done and
+ before wsrep schema is initialized.
+ */
+ if (!wsrep_before_SE())
+ {
+ WSREP_DEBUG("thd pool init for mysqldump SST");
+ if (wsrep_thd_pool) delete wsrep_thd_pool;
+ wsrep_thd_pool= new Wsrep_thd_pool(WSREP_THD_POOL_SIZE);
+ }
+ wsrep_init_SR_pool();
+ wsrep_startup= TRUE;
+
+ bool const bootstrap(TRUE == wsrep_new_cluster);
+ wsrep_new_cluster= FALSE;
WSREP_INFO("Start replication");
@@ -1000,13 +1471,17 @@ bool wsrep_start_replication()
bool wsrep_must_sync_wait (THD* thd, uint mask)
{
- return (thd->variables.wsrep_sync_wait & mask) &&
+ bool ret;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ ret= (thd->variables.wsrep_sync_wait & mask) &&
thd->variables.wsrep_on &&
!(thd->variables.wsrep_dirty_reads &&
!is_update_query(thd->lex->sql_command)) &&
!thd->in_active_multi_stmt_transaction() &&
- thd->wsrep_conflict_state != REPLAYING &&
+ thd->wsrep_conflict_state() != REPLAYING &&
thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ return ret;
}
bool wsrep_sync_wait (THD* thd, uint mask)
@@ -1017,7 +1492,7 @@ bool wsrep_sync_wait (THD* thd, uint mask)
thd->variables.wsrep_sync_wait, mask);
// This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0
// TODO: modify to check if thd has locked any rows.
- wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid);
+ wsrep_status_t ret = wsrep_sync_wait_upto(thd, NULL, -1);
if (unlikely(WSREP_OK != ret))
{
@@ -1051,6 +1526,16 @@ bool wsrep_sync_wait (THD* thd, uint mask)
return false;
}
+wsrep_status_t wsrep_sync_wait_upto (THD* thd,
+ wsrep_gtid_t* upto,
+ int timeout)
+{
+ return wsrep->sync_wait(wsrep,
+ upto,
+ timeout,
+ &thd->wsrep_sync_wait_gtid);
+}
+
void wsrep_keys_free(wsrep_key_arr_t* key_arr)
{
for (size_t i= 0; i < key_arr->keys_len; ++i)
@@ -1074,9 +1559,9 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr)
*/
static bool wsrep_prepare_key_for_isolation(const char* db,
- const char* table,
- wsrep_buf_t* key,
- size_t* key_len)
+ const char* table,
+ wsrep_buf_t* key,
+ size_t* key_len)
{
if (*key_len < 2) return false;
@@ -1088,6 +1573,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
case 1:
case 2:
case 3:
+ case 4:
{
*key_len= 0;
if (db)
@@ -1109,13 +1595,20 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
break;
}
default:
+ assert(0);
+ WSREP_ERROR("Unsupported protocol version: %ld", wsrep_protocol_version);
+ unireg_abort(1);
return false;
}
return true;
}
-/* Prepare key list from db/table and table_list */
+/*
+ * Prepare key list from db/table and table_list
+ *
+ * Return zero in case of success, 1 in case of failure.
+ */
bool wsrep_prepare_keys_for_isolation(THD* thd,
const char* db,
const char* table,
@@ -1138,7 +1631,7 @@ bool wsrep_prepare_keys_for_isolation(THD* thd,
{
WSREP_ERROR("Can't allocate memory for key_parts");
goto err;
- }
+ }
ka->keys[0].key_parts_num= 2;
if (!wsrep_prepare_key_for_isolation(
db, table,
@@ -1153,13 +1646,9 @@ bool wsrep_prepare_keys_for_isolation(THD* thd,
for (const TABLE_LIST* table= table_list; table; table= table->next_global)
{
wsrep_key_t* tmp;
- if (ka->keys)
- tmp= (wsrep_key_t*)my_realloc(ka->keys,
+ tmp= (wsrep_key_t*)my_realloc(ka->keys,
(ka->keys_len + 1) * sizeof(wsrep_key_t),
- MYF(0));
- else
- tmp= (wsrep_key_t*)my_malloc((ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0));
-
+ MY_ALLOW_ZERO_PTR);
if (!tmp)
{
WSREP_ERROR("Can't allocate memory for key_array");
@@ -1182,13 +1671,13 @@ bool wsrep_prepare_keys_for_isolation(THD* thd,
goto err;
}
}
- return 0;
+ return false;
err:
wsrep_keys_free(ka);
- return 1;
+ return true;
}
-
+#ifdef OUT
bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len,
const uchar* row_id, size_t row_id_len,
wsrep_buf_t* key, size_t* key_len)
@@ -1209,6 +1698,7 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len,
case 1:
case 2:
case 3:
+ case 4:
{
key[0].ptr = cache_key;
key[0].len = strlen( (char*)cache_key );
@@ -1229,7 +1719,101 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len,
return true;
}
+#endif
+bool wsrep_prepare_key_for_innodb(THD* thd,
+ const uchar* cache_key,
+ size_t cache_key_len,
+ const uchar* row_id,
+ size_t row_id_len,
+ wsrep_buf_t* key,
+ size_t* key_len)
+{
+
+ if (*key_len < 3) return false;
+
+ *key_len= 0;
+ switch (wsrep_protocol_version)
+ {
+ case 0:
+ {
+ key[0].ptr = cache_key;
+ key[0].len = cache_key_len;
+
+ *key_len = 1;
+ break;
+ }
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ {
+ key[0].ptr = cache_key;
+ key[0].len = strlen( (char*)cache_key );
+
+ key[1].ptr = cache_key + strlen( (char*)cache_key ) + 1;
+ key[1].len = strlen( (char*)(key[1].ptr) );
+
+ *key_len = 2;
+ break;
+ }
+ default:
+ assert(0);
+ WSREP_ERROR("Unsupported protocol version: %ld", wsrep_protocol_version);
+ unireg_abort(1);
+ return false;
+ }
+
+ key[*key_len].ptr = row_id;
+ key[*key_len].len = row_id_len;
+ ++(*key_len);
+
+ return true;
+}
+
+bool wsrep_append_SR_keys(THD* thd)
+{
+ wsrep_key_set::iterator db_it;
+ for (db_it = thd->wsrep_SR_keys.begin();
+ db_it != thd->wsrep_SR_keys.end();
+ ++db_it)
+ {
+ const std::string& db(db_it->first);
+ wsrep_key_set::mapped_type& table_names(db_it->second);
+ wsrep_key_set::mapped_type::iterator table_it;
+ for (table_it = table_names.begin();
+ table_it != table_names.end();
+ ++table_it)
+ {
+ size_t parts_len(2);
+ wsrep_buf_t parts[2];
+ if (!wsrep_prepare_key_for_isolation(db.c_str(),
+ (*table_it).c_str(),
+ parts,
+ &parts_len))
+ {
+ WSREP_ERROR("Failed to prepare key for streaming transaction, %s",
+ thd->query());
+ return false;
+ }
+
+ wsrep_key_t key = {parts, parts_len};
+ if (wsrep->append_key(wsrep,
+ &thd->wsrep_ws_handle,
+ &key,
+ 1,
+ WSREP_KEY_SHARED,
+ true))
+ {
+ WSREP_ERROR("Failed to append key for streaming transaction, %s",
+ thd->query());
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
/*
* Construct Query_log_Event from thd query and serialize it
@@ -1241,7 +1825,7 @@ int wsrep_to_buf_helper(
THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len)
{
IO_CACHE tmp_io_cache;
- Log_event_writer writer(&tmp_io_cache,0);
+ Log_event_writer writer(&tmp_io_cache, 0);
if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX,
65536, MYF(MY_WME)))
return 1;
@@ -1399,8 +1983,97 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
}
/* Forward declarations. */
-static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
-static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
+int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
+int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
+/*
+ Rewrite DROP TABLE for TOI. Temporary tables are eliminated from
+ the query as they are visible only to client connection.
+
+ TODO: See comments for sql_base.cc:drop_temporary_table() and refine
+ the function to deal with transactional locked tables.
+ */
+static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len)
+{
+
+ LEX* lex= thd->lex;
+ SELECT_LEX* select_lex= lex->first_select_lex();
+ TABLE_LIST* first_table= select_lex->table_list.first;
+ String buff;
+
+ bool found_temp_table= false;
+ for (TABLE_LIST* table= first_table; table; table= table->next_global)
+ {
+ if (thd->find_temporary_table(table->db.str, table->table_name.str))
+ {
+ found_temp_table= true;
+ break;
+ }
+ }
+
+ if (found_temp_table)
+ {
+ buff.append("DROP TABLE ");
+ if (lex->create_info.if_exists())
+ buff.append("IF EXISTS ");
+
+ for (TABLE_LIST* table= first_table; table; table= table->next_global)
+ {
+ if (!thd->find_temporary_table(table->db.str, table->table_name.str))
+ {
+ append_identifier(thd, &buff, table->db.str, table->db.length);
+ buff.append(".");
+ append_identifier(thd, &buff, table->table_name.str, table->table_name.length);
+ buff.append(",");
+ }
+ }
+
+ /* Chop the last comma */
+ buff.chop();
+ buff.append(" /* generated by wsrep */");
+
+ WSREP_DEBUG("Rewrote '%s' as '%s'", thd->query(), buff.ptr());
+
+ return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len);
+ }
+ else
+ {
+ return wsrep_to_buf_helper(thd, thd->query(), thd->query_length(),
+ buf, buf_len);
+ }
+}
+
+static int wsrep_TOI_event_buf(THD* thd, uchar** buf, size_t* buf_len)
+{
+ int err;
+ switch (thd->lex->sql_command)
+ {
+ case SQLCOM_CREATE_VIEW:
+ err= create_view_query(thd, buf, buf_len);
+ break;
+ case SQLCOM_CREATE_PROCEDURE:
+ case SQLCOM_CREATE_SPFUNCTION:
+ err= wsrep_create_sp(thd, buf, buf_len);
+ break;
+ case SQLCOM_CREATE_TRIGGER:
+ err= wsrep_create_trigger_query(thd, buf, buf_len);
+ break;
+ case SQLCOM_CREATE_EVENT:
+ err= wsrep_create_event_query(thd, buf, buf_len);
+ break;
+ case SQLCOM_ALTER_EVENT:
+ err= wsrep_alter_event_query(thd, buf, buf_len);
+ break;
+ case SQLCOM_DROP_TABLE:
+ err= wsrep_drop_table_query(thd, buf, buf_len);
+ break;
+ default:
+ err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), buf,
+ buf_len);
+ break;
+ }
+
+ return err;
+}
/*
Decide if statement should run in TOI.
@@ -1480,20 +2153,80 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
}
+static bool wsrep_can_run_in_nbo(THD *thd)
+{
+ switch (thd->lex->sql_command)
+ {
+ case SQLCOM_ALTER_TABLE:
+ /*
+ CREATE INDEX and DROP INDEX are mapped to ALTER TABLE internally
+ */
+ case SQLCOM_CREATE_INDEX:
+ case SQLCOM_DROP_INDEX:
+ switch (thd->lex->alter_info.requested_lock)
+ {
+ case Alter_info::ALTER_TABLE_LOCK_SHARED:
+ case Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE:
+ return true;
+ default:
+ return false;
+ }
+ case SQLCOM_OPTIMIZE:
+ return true;
+ default:
+ break; /* Keep compiler happy */
+ }
+ return false;
+}
+
+static void wsrep_TOI_begin_failed(THD* thd, const wsrep_buf_t* const err)
+{
+ if (wsrep_thd_trx_seqno(thd) > 0)
+ {
+ /* GTID was granted and TO acquired - need to log event and release TO */
+ if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd);
+ if (wsrep_write_dummy_event(thd, "TOI begin failed")) { goto fail; }
+ wsrep_xid_init(&thd->wsrep_xid,
+ thd->wsrep_trx_meta.gtid.uuid,
+ thd->wsrep_trx_meta.gtid.seqno);
+ //if (tc_log) tc_log->commit(thd, true);
+ if (tc_log)
+ {
+ tc_log->log_and_order(thd, thd->transaction.xid_state.xid.get_my_xid(),
+ true, false, false);
+ }
+ wsrep_status_t const rcode=
+ wsrep->to_execute_end(wsrep, thd->thread_id, err);
+ if (WSREP_OK != rcode)
+ {
+ WSREP_ERROR("Leaving critical section for failed TOI failed: thd: %llu, "
+ "schema: %s, SQL: %s, rcode: %d",
+ (long long)thd->real_id, (thd->db.str ? thd->db.str : "(null)"),
+ thd->query(), rcode);
+ goto fail;
+ }
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ wsrep_cleanup_transaction(thd);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ return;
+fail:
+ WSREP_ERROR("Failed to release TOI resources. Need to abort.");
+ unireg_abort(1);
+}
+
/*
- returns:
+ returns:
0: statement was replicated as TOI
1: TOI replication was skipped
- -1: TOI replication failed
+ -1: TOI replication failed
+ -2: NBO begin failed
*/
static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list)
{
- wsrep_status_t ret(WSREP_WARNING);
- uchar* buf(0);
- size_t buf_len(0);
- int buf_err;
- int rc= 0;
+ DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI ||
+ thd->variables.wsrep_OSU_method == WSREP_OSU_NBO);
if (wsrep_can_run_in_toi(thd, db_, table_, table_list) == false)
{
@@ -1501,74 +2234,178 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
return 1;
}
- WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, thd->query() );
- switch (thd->lex->sql_command)
+ if (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO &&
+ (wsrep->capabilities(wsrep) & WSREP_CAP_NBO) == 0)
{
- case SQLCOM_CREATE_VIEW:
- buf_err= create_view_query(thd, &buf, &buf_len);
- break;
- case SQLCOM_CREATE_PROCEDURE:
- case SQLCOM_CREATE_SPFUNCTION:
- buf_err= wsrep_create_sp(thd, &buf, &buf_len);
- break;
- case SQLCOM_CREATE_TRIGGER:
- buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len);
- break;
- case SQLCOM_CREATE_EVENT:
- buf_err= wsrep_create_event_query(thd, &buf, &buf_len);
- break;
- case SQLCOM_ALTER_EVENT:
- buf_err= wsrep_alter_event_query(thd, &buf, &buf_len);
- break;
- case SQLCOM_CREATE_ROLE:
- if (sp_process_definer(thd))
- {
- WSREP_WARN("Failed to set CREATE ROLE definer for TOI.");
- }
- /* fallthrough */
- default:
- buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(),
- &buf, &buf_len);
- break;
+ const char* const msg=
+ "wsrep_OSU_method NBO is not supported by wsrep provider";
+ WSREP_DEBUG("%s", msg);
+ my_message(ER_NOT_SUPPORTED_YET, msg, MYF(0));
+ return -1;
+ }
+
+ bool can_run_in_nbo(wsrep_can_run_in_nbo(thd));
+ if (can_run_in_nbo == false &&
+ thd->variables.wsrep_OSU_method == WSREP_OSU_NBO)
+ {
+ WSREP_DEBUG("wsrep_OSU_method NBO not supported for %s",
+ WSREP_QUERY(thd));
+ my_message(ER_NOT_SUPPORTED_YET,
+ "wsrep_OSU_method NBO not supported for query",
+ MYF(0));
+ return -1;
}
+ bool run_in_nbo= (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO &&
+ can_run_in_nbo);
+
+ uint32_t flags= (run_in_nbo ? WSREP_FLAG_TRX_START :
+ WSREP_FLAG_TRX_START | WSREP_FLAG_TRX_END);
+ wsrep_status_t ret;
+ uchar* buf= 0;
+ size_t buf_len(0);
+ int buf_err;
+ int rc;
+ time_t wait_start;
+
+ buf_err= wsrep_TOI_event_buf(thd, &buf, &buf_len);
+ if (buf_err) {
+ WSREP_ERROR("Failed to create TOI event buf: %d", buf_err);
+ my_message(ER_UNKNOWN_ERROR,
+ "WSREP replication failed to prepare TOI event buffer. "
+ "Check your query.",
+ MYF(0));
+ return -1;
+ }
+ struct wsrep_buf buff= { buf, buf_len };
+
wsrep_key_arr_t key_arr= {0, 0};
- struct wsrep_buf buff = { buf, buf_len };
- if (!buf_err &&
- !wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr) &&
- key_arr.keys_len > 0 &&
- WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id,
- key_arr.keys, key_arr.keys_len,
- &buff, 1,
- &thd->wsrep_trx_meta)))
- {
- thd->wsrep_exec_mode= TOTAL_ORDER;
- wsrep_to_isolation++;
- wsrep_keys_free(&key_arr);
- WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode);
- }
- else if (key_arr.keys_len > 0) {
- /* jump to error handler in mysql_execute_command() */
- WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. Check wsrep "
- "connection state and retry the query.",
- ret,
- thd->get_db(),
- (thd->query()) ? thd->query() : "void");
- my_message(ER_LOCK_DEADLOCK, "WSREP replication failed. Check "
- "your wsrep connection state and retry the query.", MYF(0));
- wsrep_keys_free(&key_arr);
+ if (wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)) {
+ WSREP_ERROR("Failed to prepare keys for isolation");
+ my_message(ER_UNKNOWN_ERROR,
+ "WSREP replication failed to prepare keys. Check your query.",
+ MYF(0));
rc= -1;
+ goto out;
}
- else {
+
+ /* wsrep_can_run_in_toi() should take care of checking that
+ DDLs with only temp tables should not be TOId at all */
+ DBUG_ASSERT(key_arr.keys_len > 0);
+ if (key_arr.keys_len == 0)
+ {
/* non replicated DDL, affecting temporary tables only */
- WSREP_DEBUG("TO isolation skipped for: %d, sql: %s."
- "Only temporary tables affected.",
- ret, (thd->query()) ? thd->query() : "void");
+ WSREP_DEBUG("TO isolation skipped, sql: %s."
+ "Only temporary tables affected.", WSREP_QUERY(thd));
rc= 1;
+ goto out;
+ }
+
+ thd_proc_info(thd, "acquiring total order isolation");
+ wait_start= time(NULL);
+ do
+ {
+ ret= wsrep->to_execute_start(wsrep,
+ thd->thread_id,
+ key_arr.keys,
+ key_arr.keys_len,
+ &buff,
+ 1,
+ flags,
+ &thd->wsrep_trx_meta);
+
+ if (thd->killed != NOT_KILLED) break;
+
+ if (ret == WSREP_TRX_FAIL)
+ {
+ WSREP_DEBUG("to_execute_start() failed for %lld: %s, NBO: %s, seqno: %lld",
+ thd->thread_id, WSREP_QUERY(thd), run_in_nbo ? "yes" : "no",
+ (long long)wsrep_thd_trx_seqno(thd));
+ if (ulong(time(NULL) - wait_start) < thd->variables.lock_wait_timeout)
+ {
+ usleep(100000);
+ }
+ else
+ {
+ my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
+ break;
+ }
+ if (run_in_nbo) /* will loop */
+ {
+ wsrep_TOI_begin_failed(thd, NULL /* failed repl/certification doesn't mean error in execution */);
+ }
+ }
+ } while (ret == WSREP_TRX_FAIL && run_in_nbo);
+
+ if (ret != WSREP_OK) {
+ /* jump to error handler in mysql_execute_command() */
+ switch (ret)
+ {
+ case WSREP_SIZE_EXCEEDED:
+ WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. "
+ "Maximum size exceeded.",
+ ret,
+ (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
+ break;
+ default:
+ WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. "
+ "Check wsrep connection state and retry the query.",
+ ret,
+ (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ if (!thd->is_error())
+ {
+ my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check "
+ "your wsrep connection state and retry the query.");
+ }
+ }
+ rc= -1;
}
+ else {
+
+ try {
+ /*
+ Allocate dummy thd->wsrep_nbo_ctx to track execution state
+ in mysql_execute_command().
+ */
+ if (run_in_nbo) {
+ thd->wsrep_nbo_ctx= new Wsrep_nbo_ctx(0, 0, 0, wsrep_trx_meta_t());
+ }
+ thd->wsrep_exec_mode= TOTAL_ORDER;
+ ++wsrep_to_isolation;
+ WSREP_DEBUG("TO BEGIN(%lld): %lld, %d, %s",
+ thd->thread_id,
+ (long long)wsrep_thd_trx_seqno(thd),
+ thd->wsrep_exec_mode, WSREP_QUERY(thd));
+ rc= 0;
+
+ }
+ catch (std::bad_alloc& e) {
+ rc= -2;
+ }
+ }
+
+ out:
if (buf) my_free(buf);
+ if (key_arr.keys_len) wsrep_keys_free(&key_arr);
+
+ switch(rc)
+ {
+ case 0:
+ break;
+ case -2:
+ {
+ const char* const err_str= "Failed to allocate NBO context object.";
+ wsrep_buf_t const err= { err_str, strlen(err_str) };
+ wsrep_TOI_begin_failed(thd, &err);
+ break;
+ }
+ default:
+ wsrep_TOI_begin_failed(thd, NULL);
+ }
+
return rc;
}
@@ -1577,21 +2414,43 @@ static void wsrep_TOI_end(THD *thd) {
wsrep_to_isolation--;
WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void");
+ thd->wsrep_exec_mode, WSREP_QUERY(thd));
- wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid,
- thd->wsrep_trx_meta.gtid.seqno);
- WSREP_DEBUG("TO END: %lld, update seqno",
- (long long)wsrep_thd_trx_seqno(thd));
-
- if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) {
- WSREP_DEBUG("TO END: %lld", (long long)wsrep_thd_trx_seqno(thd));
+ if (wsrep_thd_trx_seqno(thd) != WSREP_SEQNO_UNDEFINED)
+ {
+ wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid,
+ thd->wsrep_trx_meta.gtid.seqno);
+ WSREP_DEBUG("TO END: %lld, update seqno",
+ (long long)wsrep_thd_trx_seqno(thd));
+
+ if (thd->is_error() && !wsrep_must_ignore_error(thd))
+ {
+ wsrep_apply_error err;
+ err.store(thd);
+
+ wsrep_buf_t const tmp= err.get_buf();
+ ret= wsrep->to_execute_end(wsrep, thd->thread_id, &tmp);
+ }
+ else
+ {
+ ret= wsrep->to_execute_end(wsrep, thd->thread_id, NULL);
+ }
+
+ if (WSREP_OK == ret)
+ {
+ WSREP_DEBUG("TO END: %lld", (long long)wsrep_thd_trx_seqno(thd));
+ }
+ else
+ {
+ WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s",
+ ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd));
+ }
}
- else {
- WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s",
- ret,
- thd->get_db(),
- (thd->query()) ? thd->query() : "void");
+
+ if (thd->wsrep_nbo_ctx)
+ {
+ delete thd->wsrep_nbo_ctx;
+ thd->wsrep_nbo_ctx= NULL;
}
}
@@ -1599,7 +2458,7 @@ static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
{
wsrep_status_t ret(WSREP_WARNING);
WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, thd->query() );
+ thd->wsrep_exec_mode, WSREP_QUERY(thd));
ret = wsrep->desync(wsrep);
if (ret != WSREP_OK)
@@ -1678,17 +2537,15 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list)
{
- int ret= 0;
-
/*
No isolation for applier or replaying threads.
*/
- if (thd->wsrep_exec_mode == REPL_RECV)
- return 0;
+ if (thd->wsrep_exec_mode == REPL_RECV) return 0;
- mysql_mutex_lock(&thd->LOCK_thd_data);
+ int ret= 0;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
- if (thd->wsrep_conflict_state == MUST_ABORT)
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
{
WSREP_INFO("thread: %lld schema: %s query: %s has been aborted due to multi-master conflict",
(longlong) thd->thread_id, thd->get_db(), thd->query());
@@ -1703,14 +2560,14 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
if (thd->global_read_lock.can_acquire_protection())
{
WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld",
- thd->query(), (longlong) thd->thread_id);
+ WSREP_QUERY(thd), thd->thread_id);
return -1;
}
if (wsrep_debug && thd->mdl_context.has_locks())
{
WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lld",
- thd->query(), (longlong) thd->thread_id);
+ WSREP_QUERY(thd), thd->thread_id);
}
/*
@@ -1730,10 +2587,11 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
{
switch (thd->variables.wsrep_OSU_method) {
case WSREP_OSU_TOI:
- ret = wsrep_TOI_begin(thd, db_, table_, table_list);
+ case WSREP_OSU_NBO:
+ ret= wsrep_TOI_begin(thd, db_, table_, table_list);
break;
case WSREP_OSU_RSU:
- ret = wsrep_RSU_begin(thd, db_, table_);
+ ret= wsrep_RSU_begin(thd, db_, table_);
break;
default:
WSREP_ERROR("Unsupported OSU method: %lu",
@@ -1761,29 +2619,126 @@ void wsrep_to_isolation_end(THD *thd)
{
switch(thd->variables.wsrep_OSU_method)
{
- case WSREP_OSU_TOI: wsrep_TOI_end(thd); break;
- case WSREP_OSU_RSU: wsrep_RSU_end(thd); break;
+ case WSREP_OSU_TOI:
+ case WSREP_OSU_NBO:
+ wsrep_TOI_end(thd);
+ break;
+ case WSREP_OSU_RSU:
+ wsrep_RSU_end(thd);
+ break;
default:
WSREP_WARN("Unsupported wsrep OSU method at isolation end: %lu",
thd->variables.wsrep_OSU_method);
break;
}
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
wsrep_cleanup_transaction(thd);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+}
+
+void wsrep_begin_nbo_unlock(THD* thd)
+{
+ DBUG_ASSERT(thd->wsrep_nbo_ctx);
+ if (thd->wsrep_exec_mode == TOTAL_ORDER)
+ {
+ if (wsrep->to_execute_end(wsrep, thd->thread_id, NULL) != WSREP_OK) {
+ WSREP_ERROR("Non-blocking operation failed to release provider "
+ "resources, cannot continue");
+ unireg_abort(1);
+ }
+ }
+ else if (thd->wsrep_exec_mode == REPL_RECV) {
+ thd->wsrep_nbo_ctx->signal();
}
+ thd->wsrep_nbo_ctx->set_toi_released(true);
+}
+
+void wsrep_end_nbo_lock(THD* thd, const TABLE_LIST *table_list)
+{
+ DBUG_ASSERT(thd->wsrep_nbo_ctx);
+
+ // Release TOI critical section if not released yet. This
+ // may happen if operation fails in early phase.
+ if (thd->wsrep_nbo_ctx->toi_released() == false) {
+ wsrep_begin_nbo_unlock(thd);
+ }
+
+ DBUG_ASSERT(thd->wsrep_exec_mode == TOTAL_ORDER ||
+ thd->wsrep_exec_mode == REPL_RECV);
+ wsrep_status_t ret;
+ uint32_t flags= WSREP_FLAG_TRX_END;
+
+ wsrep_key_arr_t key_arr= {0, 0};
+
+ if (wsrep_prepare_keys_for_isolation(thd, NULL, NULL, table_list, &key_arr))
+ {
+ WSREP_ERROR("Failed to prepare keys for NBO end. This is fatal, must abort");
+ unireg_abort(1);
+
+ }
+ thd_proc_info(thd, "acquiring total order isolation for NBO end");
+
+ DBUG_ASSERT(key_arr.keys_len > 0);
+
+ time_t wait_start= time(NULL);
+ while ((ret= wsrep->to_execute_start(wsrep, thd->thread_id,
+ key_arr.keys, key_arr.keys_len, 0, 0,
+ flags,
+ &thd->wsrep_trx_meta))
+ == WSREP_CONN_FAIL) {
+ if (thd->killed != NOT_KILLED) {
+ WSREP_ERROR("Non-blocking operation end failed to sync with group, "
+ "thd killed %d", thd->killed);
+ /* Error handling happens outside of while() */
+ break;
+ }
+ usleep(100000);
+ if (ulong(time(NULL) - wait_start) >= thd->variables.lock_wait_timeout)
+ {
+ WSREP_ERROR("Lock wait timeout while waiting NBO end to replicate.");
+ break;
+ }
+ }
+
+ if (ret != WSREP_OK)
+ {
+ WSREP_ERROR("Failed to acquire total order isolation for non-blocking DDL "
+ "end event, provider returned error code %d: "
+ "(schema: %s, query: %s)",
+ ret, (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ thd->get_stmt_da()->set_overwrite_status(true);
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), ret);
+ thd->get_stmt_da()->set_overwrite_status(false);
+ WSREP_ERROR("This will leave database in inconsistent state since DDL "
+ "execution cannot be terminated in order. Node must rejoin "
+ "the cluster via SST");
+ wsrep->free_connection(wsrep, thd->thread_id);
+ wsrep->disconnect(wsrep);
+ // We let the operation to finish out of order in order to release
+ // all resources properly. However GTID is cleared so that the
+ // event won't be binlogged with incorrect GTID.
+ thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
+ }
+
+ thd->wsrep_nbo_ctx->set_toi_released(false);
}
#define WSREP_MDL_LOG(severity, msg, schema, schema_len, req, gra) \
WSREP_##severity( \
"%s\n" \
"schema: %.*s\n" \
- "request: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \
- "granted: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \
+ "request: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \
+ "granted: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \
msg, schema_len, schema, \
- (longlong) req->thread_id, (long long)wsrep_thd_trx_seqno(req), \
- req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \
+ (longlong) req->thread_id, (long long)wsrep_thd_trx_seqno(req), \
+ req->wsrep_exec_mode, req->wsrep_query_state_unsafe(), \
+ req->wsrep_conflict_state_unsafe(), \
req->get_command(), req->lex->sql_command, req->query(), \
- (longlong) gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \
- gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \
+ (longlong) gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \
+ gra->wsrep_exec_mode, gra->wsrep_query_state_unsafe(), \
+ gra->wsrep_conflict_state_unsafe(), \
gra->get_command(), gra->lex->sql_command, gra->query());
/**
@@ -1810,8 +2765,6 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
const char* schema= key->db_name();
int schema_len= key->db_name_length();
- mysql_mutex_lock(&request_thd->LOCK_thd_data);
-
/*
We consider granting MDL exceptions only for appliers (BF THD) and ones
executing under TOI mode.
@@ -1831,9 +2784,10 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
lock is not granted to the requester THD, thus it has to wait.
@return false
*/
+ mysql_mutex_lock(&request_thd->LOCK_wsrep_thd);
if (request_thd->wsrep_exec_mode == TOTAL_ORDER ||
- request_thd->wsrep_exec_mode == REPL_RECV)
- {
+ request_thd->wsrep_exec_mode == REPL_RECV) {
+
mysql_mutex_unlock(&request_thd->LOCK_thd_data);
WSREP_MDL_LOG(DEBUG, "MDL conflict ", schema, schema_len,
request_thd, granted_thd);
@@ -1843,11 +2797,23 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
if (granted_thd->wsrep_exec_mode == TOTAL_ORDER ||
granted_thd->wsrep_exec_mode == REPL_RECV)
{
- WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", schema, schema_len,
- request_thd, granted_thd);
- ticket->wsrep_report(true);
- mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
- ret= true;
+ if (wsrep_thd_is_SR((void*)granted_thd) &&
+ !wsrep_thd_is_SR((void*)request_thd))
+ {
+ WSREP_MDL_LOG(INFO, "MDL conflict, DDL vs SR",
+ schema, schema_len, request_thd, granted_thd);
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
+ ret = FALSE;
+ }
+ else
+ {
+ WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", schema, schema_len,
+ request_thd, granted_thd);
+ ticket->wsrep_report(true);
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ ret = TRUE;
+ }
}
else if (granted_thd->lex->sql_command == SQLCOM_FLUSH ||
granted_thd->mdl_context.has_explicit_locks())
@@ -1855,52 +2821,173 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
WSREP_DEBUG("BF thread waiting for FLUSH");
ticket->wsrep_report(wsrep_debug);
mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
- ret= false;
+ ret = FALSE;
+ }
+ else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE)
+ {
+ WSREP_DEBUG("DROP caused BF abort");
+ ticket->wsrep_report(wsrep_debug);
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
+ ret = FALSE;
+ }
+ else if (granted_thd->wsrep_query_state() == QUERY_COMMITTING)
+ {
+ WSREP_DEBUG("mdl granted, but commiting thd abort scheduled");
+ ticket->wsrep_report(wsrep_debug);
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
+ ret = FALSE;
}
else
{
- /* Print some debug information. */
- if (wsrep_debug)
+ WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len,
+ request_thd, granted_thd);
+ ticket->wsrep_report(wsrep_debug);
+ //if (granted_thd->wsrep_conflict_state == CERT_FAILURE)
+ switch (granted_thd->wsrep_conflict_state())
{
- if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE ||
- request_thd->lex->sql_command == SQLCOM_DROP_SEQUENCE)
- {
- WSREP_DEBUG("DROP caused BF abort, conf %d", granted_thd->wsrep_conflict_state);
- }
- else if (granted_thd->wsrep_query_state == QUERY_COMMITTING)
- {
- WSREP_DEBUG("MDL granted, but committing thd abort scheduled");
- }
- else
- {
- WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len,
- request_thd, granted_thd);
- }
- ticket->wsrep_report(true);
+ case CERT_FAILURE:
+ {
+ WSREP_DEBUG("MDL granted is aborting because of cert failure");
+ sleep(20);
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ ret = TRUE;
+ break;
+ }
+ case ABORTING:
+ {
+ WSREP_DEBUG("MDL granted is aborting %d",
+ granted_thd->wsrep_conflict_state());
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ ret = TRUE;
+ break;
+ }
+ case MUST_ABORT:
+ case ABORTED:
+ case MUST_REPLAY:
+ case REPLAYING:
+ case RETRY_AUTOCOMMIT:
+ WSREP_DEBUG("MDL granted is in %d state",
+ granted_thd->wsrep_conflict_state());
+ // fall through
+ case NO_CONFLICT:
+ {
+ mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd);
+ wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1);
+ ret = FALSE;
+ break;
+ }
}
-
- mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
- wsrep_abort_thd((void *) request_thd, (void *) granted_thd, 1);
- ret= false;
}
}
else
{
mysql_mutex_unlock(&request_thd->LOCK_thd_data);
}
-
return ret;
}
+void
+wsrep_last_committed_id(wsrep_gtid_t* gtid)
+{
+ wsrep->last_committed_id(wsrep, gtid);
+}
+
+void
+wsrep_node_uuid(wsrep_uuid_t& uuid)
+{
+ uuid = node_uuid;
+}
+
+bool wsrep_node_is_donor()
+{
+ return (WSREP_ON) ? (local_status.get() == 2) : false;
+}
+
+bool wsrep_node_is_synced()
+{
+ return (WSREP_ON) ? (local_status.get() == 4) : false;
+}
+
+int wsrep_must_ignore_error(THD* thd)
+{
+ const int error= thd->get_stmt_da()->sql_errno();
+ const uint flags= sql_command_flags[thd->lex->sql_command];
+
+ DBUG_ASSERT(error);
+ DBUG_ASSERT((thd->wsrep_exec_mode == TOTAL_ORDER) ||
+ (thd->wsrep_exec_mode == REPL_RECV && thd->wsrep_apply_toi));
+
+ if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_DDL))
+ goto ignore_error;
+
+ if ((flags & CF_WSREP_MAY_IGNORE_ERRORS) &&
+ (wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL))
+ {
+ switch (error)
+ {
+ case ER_DB_DROP_EXISTS:
+ case ER_BAD_TABLE_ERROR:
+ case ER_CANT_DROP_FIELD_OR_KEY:
+ goto ignore_error;
+ }
+ }
+
+ return 0;
+
+ignore_error:
+ WSREP_WARN("Ignoring error '%s' on query. "
+ "Default database: '%s'. Query: '%s', Error_code: %d",
+ thd->get_stmt_da()->message(),
+ print_slave_db_safe(thd->db.str),
+ thd->query(),
+ error);
+ return 1;
+}
+
+int wsrep_ignored_error_code(Log_event* ev, int error)
+{
+ const THD* thd= ev->thd;
+
+ DBUG_ASSERT(error);
+ DBUG_ASSERT(thd->wsrep_exec_mode == REPL_RECV && !thd->wsrep_apply_toi);
+
+ if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DML))
+ {
+ const int ev_type= ev->get_type_code();
+ if (ev_type == DELETE_ROWS_EVENT && error == ER_KEY_NOT_FOUND)
+ goto ignore_error;
+ }
-pthread_handler_t start_wsrep_THD(void *arg)
+ return 0;
+
+ignore_error:
+ WSREP_WARN("Ignoring error '%s' on %s event. Error_code: %d",
+ thd->get_stmt_da()->message(),
+ ev->get_type_str(),
+ error);
+ return 1;
+}
+
+void *start_wsrep_THD(void *arg)
{
THD *thd;
- wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
+ // wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
- if (my_thread_init() || (!(thd= new THD(next_thread_id(), true))))
+ Wsrep_thd_args* thd_args= (Wsrep_thd_args*) arg;
+
+ if (my_thread_init())
{
- goto error;
+ WSREP_ERROR("Could not initialize thread");
+ delete thd_args;
+ return(NULL);
+ }
+
+ if (!(thd= new THD(next_thread_id(), true)))
+ {
+ delete thd_args;
+ return(NULL);
}
mysql_mutex_lock(&LOCK_thread_count);
@@ -1918,6 +3005,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0));
DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id));
+ WSREP_DEBUG("Creating wsrep system thread: %lld", thd->thread_id);
thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
(void) mysql_mutex_unlock(&LOCK_thread_count);
@@ -1936,6 +3024,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
+ delete thd_args;
goto error;
}
@@ -1958,6 +3047,8 @@ pthread_handler_t start_wsrep_THD(void *arg)
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
+ delete thd;
+ delete thd_args;
goto error;
}
@@ -1975,10 +3066,14 @@ pthread_handler_t start_wsrep_THD(void *arg)
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
- processor(thd);
+ thd_args->fun()(thd, thd_args->args());
+ thd->store_globals();
+
+ WSREP_DEBUG("wsrep system thread: %lld closing", thd->thread_id);
close_connection(thd, 0);
-
+ delete thd_args;
+
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads--;
WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
@@ -2021,13 +3116,19 @@ error:
static bool abort_replicated(THD *thd)
{
bool ret_code= false;
- if (thd->wsrep_query_state== QUERY_COMMITTING)
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_query_state()== QUERY_COMMITTING)
{
WSREP_DEBUG("aborting replicated trx: %llu", (ulonglong)(thd->real_id));
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
(void)wsrep_abort_thd(thd, thd, TRUE);
ret_code= true;
}
+ else
+ {
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
return ret_code;
}
@@ -2044,7 +3145,7 @@ static inline bool is_replaying_connection(THD *thd)
bool ret;
mysql_mutex_lock(&thd->LOCK_thd_data);
- ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false;
+ ret= (thd->wsrep_conflict_state() == REPLAYING) ? true : false;
mysql_mutex_unlock(&thd->LOCK_thd_data);
return ret;
@@ -2056,20 +3157,23 @@ static inline bool is_committing_connection(THD *thd)
bool ret;
mysql_mutex_lock(&thd->LOCK_thd_data);
- ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false;
+ ret= (thd->wsrep_query_state() == QUERY_COMMITTING) ? true : false;
mysql_mutex_unlock(&thd->LOCK_thd_data);
return ret;
}
-static bool have_client_connections()
+static bool have_client_connections(THD *except_thd)
{
THD *tmp;
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
+ if (tmp == except_thd)
+ continue;
+
DBUG_PRINT("quit",("Informing thread %lld that it's time to die",
(longlong) tmp->thread_id));
if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION)
@@ -2085,18 +3189,30 @@ static void wsrep_close_thread(THD *thd)
{
thd->set_killed(KILL_CONNECTION);
MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd));
+ mysql_mutex_lock(&thd->LOCK_thd_kill);
if (thd->mysys_var)
{
thd->mysys_var->abort=1;
mysql_mutex_lock(&thd->mysys_var->mutex);
if (thd->mysys_var->current_cond)
{
- mysql_mutex_lock(thd->mysys_var->current_mutex);
- mysql_cond_broadcast(thd->mysys_var->current_cond);
- mysql_mutex_unlock(thd->mysys_var->current_mutex);
+ uint i;
+ for (i=0; i < 2; i++)
+ {
+ int ret= mysql_mutex_trylock(thd->mysys_var->current_mutex);
+ mysql_cond_broadcast(thd->mysys_var->current_cond);
+ if (!ret)
+ {
+ /* Thread has surely got the signal, unlock and abort */
+ mysql_mutex_unlock(thd->mysys_var->current_mutex);
+ break;
+ }
+ sleep(1);
+ }
}
mysql_mutex_unlock(&thd->mysys_var->mutex);
}
+ mysql_mutex_unlock(&thd->LOCK_thd_kill);
}
@@ -2138,46 +3254,64 @@ int wsrep_wait_committing_connections_close(int wait_time)
return 0;
}
-
-void wsrep_close_client_connections(my_bool wait_to_end)
+void wsrep_close_client_connections(my_bool wait_to_end, THD* except_caller_thd)
{
- /*
- First signal all threads that it's time to die
- */
+ kill_cached_threads++;
+ flush_thread_cache();
+
+ /* OLD ... */
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
-
- bool kill_cached_threads_saved= kill_cached_threads;
- kill_cached_threads= true; // prevent future threads caching
- mysql_cond_broadcast(&COND_thread_cache); // tell cached threads to die
+ /*
+ First signal all threads that it's time to die
+ */
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %lld that it's time to die",
(longlong) tmp->thread_id));
- /* We skip slave threads & scheduler on this first loop through. */
+ /* We skip slave threads, scheduler & caller on this first loop through. */
if (!is_client_connection(tmp))
continue;
+ if (tmp == except_caller_thd)
+ {
+ DBUG_ASSERT(is_client_connection(tmp));
+ /* Even though we don't kill the caller we must release resources
+ * it might have allocated with the provider */
+ wsrep_status_t rcode= wsrep->free_connection(wsrep, tmp->thread_id);
+ if (rcode) {
+ WSREP_WARN("wsrep failed to free connection context: %lld, code: %d",
+ tmp->thread_id, rcode);
+ }
+ continue;
+ }
+
if (is_replaying_connection(tmp))
{
+ WSREP_DEBUG("killed client was replaying");
tmp->set_killed(KILL_CONNECTION);
continue;
}
/* replicated transactions must be skipped */
if (abort_replicated(tmp))
+ {
+ WSREP_DEBUG("killed client has replicated");
continue;
-
+ }
WSREP_DEBUG("closing connection %lld", (longlong) tmp->thread_id);
wsrep_close_thread(tmp);
}
mysql_mutex_unlock(&LOCK_thread_count);
- if (thread_count)
- sleep(2); // Give threads time to die
+ /*
+ Sleep for couple of seconds to give threads time to die.
+ */
+ for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++)
+ my_sleep(20000);
mysql_mutex_lock(&LOCK_thread_count);
/*
@@ -2190,7 +3324,8 @@ void wsrep_close_client_connections(my_bool wait_to_end)
#ifndef __bsdi__ // Bug in BSDI kernel
if (is_client_connection(tmp) &&
!abort_replicated(tmp) &&
- !is_replaying_connection(tmp))
+ !is_replaying_connection(tmp) &&
+ tmp != except_caller_thd)
{
WSREP_INFO("killing local connection: %lld", (longlong) tmp->thread_id);
close_connection(tmp,0);
@@ -2201,14 +3336,14 @@ void wsrep_close_client_connections(my_bool wait_to_end)
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
WSREP_DEBUG("waiting for client connections to close: %u", thread_count);
- while (wait_to_end && have_client_connections())
+ while (wait_to_end && have_client_connections(except_caller_thd))
{
- mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
+ struct timespec abstime;
+ set_timespec(abstime, 5);
+ mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count, &abstime);
DBUG_PRINT("quit",("One thread died (count=%u)", thread_count));
}
- kill_cached_threads= kill_cached_threads_saved;
-
mysql_mutex_unlock(&LOCK_thread_count);
/* All client connection threads have now been aborted */
@@ -2247,7 +3382,9 @@ void wsrep_wait_appliers_close(THD *thd)
{
/* Wait for wsrep appliers to gracefully exit */
mysql_mutex_lock(&LOCK_thread_count);
- while (wsrep_running_threads > 1)
+ while (wsrep_running_threads > 2)
+ // Rollbacker and post rollbacker threads need to be killed explicitly.
+
// 1 is for rollbacker thread which needs to be killed explicitly.
// This gotta be fixed in a more elegant manner if we gonna have arbitrary
// number of non-applier wsrep threads.
@@ -2304,7 +3441,7 @@ void wsrep_kill_mysql(THD *thd)
}
-static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
+int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
sp_head *sp = thd->lex->sphead;
@@ -2338,13 +3475,15 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
}
-extern int wsrep_on(THD *thd)
+//extern int wsrep_on(THD *thd)
+extern int wsrep_on(void *thd_ptr)
{
+ THD* thd = (THD*)thd_ptr;
return (int)(WSREP(thd));
}
-extern "C" bool wsrep_thd_is_wsrep_on(THD *thd)
+bool wsrep_thd_is_wsrep_on(THD *thd)
{
return thd->variables.wsrep_on;
}
@@ -2356,22 +3495,15 @@ bool wsrep_consistency_check(THD *thd)
}
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode)
+void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode)
{
thd->wsrep_exec_mode= mode;
}
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state)
-{
- thd->wsrep_query_state= state;
-}
-
-
void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state)
{
- if (WSREP(thd)) thd->wsrep_conflict_state= state;
+ if (WSREP(thd)) thd->set_wsrep_conflict_state(state);
}
@@ -2383,50 +3515,59 @@ enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd)
const char *wsrep_thd_exec_mode_str(THD *thd)
{
- return
- (!thd) ? "void" :
- (thd->wsrep_exec_mode == LOCAL_STATE) ? "local" :
- (thd->wsrep_exec_mode == REPL_RECV) ? "applier" :
- (thd->wsrep_exec_mode == TOTAL_ORDER) ? "total order" :
- (thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void";
+ switch (thd->wsrep_exec_mode)
+ {
+ case LOCAL_STATE: return "local";
+ case REPL_RECV: return "applier";
+ case TOTAL_ORDER: return "total order";
+ case LOCAL_COMMIT: return "local commit";
+ case LOCAL_ROLLBACK: return "local rollback";
+ }
+ return "void";
+
}
enum wsrep_query_state wsrep_thd_query_state(THD *thd)
{
- return thd->wsrep_query_state;
+ return thd->wsrep_query_state();
}
const char *wsrep_thd_query_state_str(THD *thd)
{
- return
- (!thd) ? "void" :
- (thd->wsrep_query_state == QUERY_IDLE) ? "idle" :
- (thd->wsrep_query_state == QUERY_EXEC) ? "executing" :
- (thd->wsrep_query_state == QUERY_COMMITTING) ? "committing" :
- (thd->wsrep_query_state == QUERY_EXITING) ? "exiting" :
- (thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back" : "void";
-}
+ switch (thd->wsrep_query_state_unsafe())
+ {
+ case QUERY_IDLE: return "idle";
+ case QUERY_EXEC: return "executing";
+ case QUERY_COMMITTING: return "committing";
+ case QUERY_ORDERED_COMMIT: return "ordered_commit";
+ case QUERY_EXITING: return "exiting";
+ }
+ return "void";
+}
enum wsrep_conflict_state wsrep_thd_get_conflict_state(THD *thd)
{
- return thd->wsrep_conflict_state;
+ return thd->wsrep_conflict_state();
}
const char *wsrep_thd_conflict_state_str(THD *thd)
{
- return
- (!thd) ? "void" :
- (thd->wsrep_conflict_state == NO_CONFLICT) ? "no conflict" :
- (thd->wsrep_conflict_state == MUST_ABORT) ? "must abort" :
- (thd->wsrep_conflict_state == ABORTING) ? "aborting" :
- (thd->wsrep_conflict_state == MUST_REPLAY) ? "must replay" :
- (thd->wsrep_conflict_state == REPLAYING) ? "replaying" :
- (thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying" :
- (thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void";
+ switch (thd->wsrep_conflict_state_unsafe())
+ {
+ case NO_CONFLICT: return "no conflict";
+ case MUST_ABORT: return "must abort";
+ case ABORTING: return "aborting";
+ case ABORTED: return "aborted";
+ case MUST_REPLAY: return "must replay";
+ case REPLAYING: return "replaying";
+ case RETRY_AUTOCOMMIT: return "retrying";
+ case CERT_FAILURE: return "cert failure";
+ }
+ return "void";
}
@@ -2448,28 +3589,41 @@ void wsrep_thd_UNLOCK(THD *thd)
}
-extern "C" time_t wsrep_thd_query_start(THD *thd)
+time_t wsrep_thd_query_start(THD *thd)
{
return thd->query_start();
}
-extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd)
+uint32 wsrep_thd_wsrep_rand(THD *thd)
{
return thd->wsrep_rand;
}
-longlong wsrep_thd_trx_seqno(THD *thd)
+my_thread_id wsrep_thd_thread_id(THD *thd)
+{
+ return thd->thread_id;
+}
+
+int64_t wsrep_thd_trx_seqno(const THD *thd)
{
return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED;
}
-extern "C" query_id_t wsrep_thd_query_id(THD *thd)
+query_id_t wsrep_thd_query_id(THD *thd)
{
return thd->query_id;
}
+wsrep_trx_id_t wsrep_thd_next_trx_id(THD *thd)
+{
+ return thd->wsrep_next_trx_id();
+}
+wsrep_trx_id_t wsrep_thd_trx_id(THD *thd)
+{
+ return thd->wsrep_trx_id();
+}
char *wsrep_thd_query(THD *thd)
{
@@ -2477,20 +3631,21 @@ char *wsrep_thd_query(THD *thd)
}
-extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd)
+query_id_t wsrep_thd_wsrep_last_query_id(THD *thd)
{
return thd->wsrep_last_query_id;
}
-extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id)
+void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id)
{
thd->wsrep_last_query_id= id;
}
-extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
+void wsrep_thd_awake(THD *thd, my_bool signal)
{
+ WSREP_DEBUG("wsrep_thd_awake %lu %d", thd->thread_id, signal);
if (signal)
{
thd->awake(KILL_QUERY);
@@ -2510,39 +3665,70 @@ int wsrep_thd_retry_counter(THD *thd)
}
-extern "C" bool wsrep_thd_ignore_table(THD *thd)
+bool wsrep_thd_ignore_table(THD *thd)
{
return thd->wsrep_ignore_table;
}
extern int
+//wsrep_trx_order_before(void *thd1, void *thd2)
wsrep_trx_order_before(THD *thd1, THD *thd2)
{
- if (wsrep_thd_trx_seqno(thd1) < wsrep_thd_trx_seqno(thd2)) {
+ if (wsrep_thd_trx_seqno((THD*)thd1) < wsrep_thd_trx_seqno((THD*)thd2)) {
WSREP_DEBUG("BF conflict, order: %lld %lld\n",
- (long long)wsrep_thd_trx_seqno(thd1),
- (long long)wsrep_thd_trx_seqno(thd2));
+ (long long)wsrep_thd_trx_seqno((THD*)thd1),
+ (long long)wsrep_thd_trx_seqno((THD*)thd2));
return 1;
}
WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
- (long long)wsrep_thd_trx_seqno(thd1),
- (long long)wsrep_thd_trx_seqno(thd2));
+ (long long)wsrep_thd_trx_seqno((THD*)thd1),
+ (long long)wsrep_thd_trx_seqno((THD*)thd2));
return 0;
}
+int
+wsrep_trx_is_aborting(THD *thd_ptr)
+{
+ if (thd_ptr) {
+ if ((((THD *)thd_ptr)->wsrep_conflict_state() == MUST_ABORT) ||
+ (((THD *)thd_ptr)->wsrep_conflict_state() == ABORTING)) {
+ return 1;
+ }
+ }
+ return 0;
+}
-int wsrep_trx_is_aborting(THD *thd_ptr)
+void
+wsrep_thd_last_written_gtid(THD *thd, wsrep_gtid_t* gtid)
{
- if (thd_ptr) {
- if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) ||
- (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) {
- return 1;
- }
- }
- return 0;
+ *gtid = WSREP_GTID_UNDEFINED;
+ if (thd)
+ {
+ *gtid = thd->wsrep_last_written_gtid;
+ }
}
+ulong
+wsrep_thd_trx_fragment_size(THD *thd)
+{
+ if (thd)
+ return thd->variables.wsrep_trx_fragment_size;
+ return 0;
+}
+
+bool
+wsrep_thd_is_streaming(THD* thd)
+{
+ return thd && thd->wsrep_is_streaming();
+}
+
+#if 0
+my_bool wsrep_thd_no_gaps(const void *thd_ptr)
+{
+ return ((THD*)thd_ptr)->wsrep_no_gaps;
+}
+#endif // 0
void wsrep_copy_query(THD *thd)
{
@@ -2614,7 +3800,7 @@ error:
}
-static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
+int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
{
LEX *lex= thd->lex;
String stmt_query;
@@ -2711,46 +3897,88 @@ my_bool get_wsrep_certify_nonPK()
return wsrep_certify_nonPK;
}
-void wsrep_lock_rollback()
+bool wsrep_provider_is_SR_capable()
{
- mysql_mutex_lock(&LOCK_wsrep_rollback);
+ return wsrep->capabilities(wsrep) & WSREP_CAP_STREAMING;
}
-void wsrep_unlock_rollback()
-{
- mysql_cond_signal(&COND_wsrep_rollback);
- mysql_mutex_unlock(&LOCK_wsrep_rollback);
-}
-my_bool wsrep_aborting_thd_contains(THD *thd)
+int wsrep_ordered_commit_if_no_binlog(THD* thd)
{
- mysql_mutex_assert_owner(&LOCK_wsrep_rollback);
- wsrep_aborting_thd_t abortees = wsrep_aborting_thd;
- while (abortees)
+ return 0;
+ if (!(wsrep_emulate_bin_log && thd->wsrep_trx_must_order_commit()))
{
- if (abortees->aborting_thd == thd)
- return true;
- abortees = abortees->next;
+ return 0;
}
- return false;
+ int ret= 0;
+ switch (thd->wsrep_exec_mode)
+ {
+ case LOCAL_STATE:
+ case TOTAL_ORDER:
+ /* Statement commit may get us here */
+ break;
+ case LOCAL_COMMIT:
+ ret= wsrep_ordered_commit(thd, true, wsrep_apply_error());
+ break;
+ case REPL_RECV:
+ {
+ wsrep_buf_t const err= { NULL, 0 };
+ wsrep_status_t rcode=
+ wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, &err);
+ if (rcode != WSREP_OK)
+ {
+ DBUG_ASSERT(rcode == WSREP_NODE_FAIL);
+ WSREP_ERROR("Failed to leave commit order critical section (WOKINB), "
+ "rcode: %d", rcode);
+ ret= 1;
+ }
+ if (!ret)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+ break;
+ }
+ default:
+ DBUG_ASSERT(0);
+ WSREP_WARN("Call to wsrep_commit_order_leave_if_no_binlog called in %s",
+ wsrep_thd_exec_mode_str(thd));
+ break;
+ }
+ return ret;
}
-void wsrep_aborting_thd_enqueue(THD *thd)
+wsrep_status_t wsrep_tc_log_commit(THD* thd)
{
- mysql_mutex_assert_owner(&LOCK_wsrep_rollback);
- wsrep_aborting_thd_t aborting = (wsrep_aborting_thd_t)
- my_malloc(sizeof(struct wsrep_aborting_thd), MYF(0));
- aborting->aborting_thd = thd;
- aborting->next = wsrep_aborting_thd;
- wsrep_aborting_thd = aborting;
-}
+ if (wsrep_before_commit(thd, true))
+ {
+ return WSREP_TRX_FAIL;
+ }
+ if (binlog_hton->commit(binlog_hton, thd, true))
+ {
+ WSREP_ERROR("Binlog hton commit fail");
+ return WSREP_TRX_FAIL;
+ }
-bool wsrep_node_is_donor()
-{
- return (WSREP_ON) ? (wsrep_config_state->get_status() == 2) : false;
-}
+ if (wsrep_after_commit(thd, true))
+ {
+ return WSREP_TRX_FAIL;
+ }
-bool wsrep_node_is_synced()
-{
- return (WSREP_ON) ? (wsrep_config_state->get_status() == 4) : false;
+ /* Set wsrep transaction id if not set. */
+ if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ }
+ DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID);
+
+ wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, thd->wsrep_next_trx_id());
+ }
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+
+ return WSREP_OK;
}
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 699a4daf27a..5145fe86a19 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2015 Codership Oy <http://www.codership.com>
+/* Copyright 2008-2017 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,36 +24,28 @@
#ifdef WITH_WSREP
typedef struct st_mysql_show_var SHOW_VAR;
+
#include <sql_priv.h>
-//#include "rpl_gtid.h"
#include "../wsrep/wsrep_api.h"
#include "mdl.h"
#include "mysqld.h"
#include "sql_table.h"
+#include <vector>
+
#define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX
class set_var;
class THD;
+typedef std::vector<wsrep_trx_meta_t> wsrep_fragment_set;
+
enum wsrep_consistency_check_mode {
NO_CONSISTENCY_CHECK,
CONSISTENCY_CHECK_DECLARED,
CONSISTENCY_CHECK_RUNNING,
};
-struct wsrep_thd_shadow {
- ulonglong options;
- uint server_status;
- enum wsrep_exec_mode wsrep_exec_mode;
- Vio *vio;
- ulong tx_isolation;
- const char *db;
- size_t db_length;
- my_hrtime_t user_time;
- longlong row_count_func;
-};
-
// Global wsrep parameters
extern wsrep_t* wsrep;
@@ -77,7 +69,6 @@ extern const char* wsrep_start_position;
extern ulong wsrep_max_ws_size;
extern ulong wsrep_max_ws_rows;
extern const char* wsrep_notify_cmd;
-extern long wsrep_max_protocol_version;
extern ulong wsrep_forced_binlog_format;
extern my_bool wsrep_desync;
extern ulong wsrep_reject_queries;
@@ -87,6 +78,10 @@ extern my_bool wsrep_restart_slave;
extern my_bool wsrep_restart_slave_activated;
extern my_bool wsrep_slave_FK_checks;
extern my_bool wsrep_slave_UK_checks;
+extern ulong wsrep_trx_fragment_size;
+extern ulong wsrep_trx_fragment_unit;
+extern ulong wsrep_SR_store_type;
+extern uint wsrep_ignore_apply_errors;
extern ulong wsrep_running_threads;
extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
@@ -101,6 +96,7 @@ enum enum_wsrep_reject_types {
enum enum_wsrep_OSU_method {
WSREP_OSU_TOI,
WSREP_OSU_RSU,
+ WSREP_OSU_NBO,
WSREP_OSU_NONE,
};
@@ -114,6 +110,14 @@ enum enum_wsrep_sync_wait {
WSREP_SYNC_WAIT_MAX = 0xF
};
+enum enum_wsrep_ignore_apply_error {
+ WSREP_IGNORE_ERRORS_NONE = 0x0,
+ WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL = 0x1,
+ WSREP_IGNORE_ERRORS_ON_RECONCILING_DML = 0x2,
+ WSREP_IGNORE_ERRORS_ON_DDL = 0x4,
+ WSREP_IGNORE_ERRORS_MAX = 0x7
+};
+
// MySQL status variables
extern my_bool wsrep_connected;
extern my_bool wsrep_ready;
@@ -126,9 +130,12 @@ extern long long wsrep_local_bf_aborts;
extern const char* wsrep_provider_name;
extern const char* wsrep_provider_version;
extern const char* wsrep_provider_vendor;
+extern char* wsrep_provider_capabilities;
+extern char* wsrep_cluster_capabilities;
-int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff,
- enum enum_var_type scope);
+int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff);
+int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff);
+void wsrep_free_status(THD *thd);
int wsrep_init();
void wsrep_deinit(bool free_options);
@@ -147,37 +154,47 @@ void wsrep_init_startup(bool before);
// Other wsrep global variables
extern my_bool wsrep_inited; // whether wsrep is initialized ?
-
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state);
-
extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
-
+extern "C" void wsrep_fire_rollbacker(THD *thd);
extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
extern "C" time_t wsrep_thd_query_start(THD *thd);
extern "C" query_id_t wsrep_thd_query_id(THD *thd);
+extern "C" wsrep_trx_id_t wsrep_thd_next_trx_id(THD *thd);
+extern "C" wsrep_trx_id_t wsrep_thd_trx_id(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
-extern void wsrep_close_client_connections(my_bool wait_to_end);
+extern "C" void wsrep_thd_last_written_gtid(THD *thd, wsrep_gtid_t *t);
+extern "C" ulong wsrep_thd_trx_fragment_size(THD *thd);
+
extern int wsrep_wait_committing_connections_close(int wait_time);
extern void wsrep_close_applier(THD *thd);
extern void wsrep_wait_appliers_close(THD *thd);
extern void wsrep_close_applier_threads(int count);
extern void wsrep_kill_mysql(THD *thd);
+
/* new defines */
extern void wsrep_stop_replication(THD *thd);
extern bool wsrep_start_replication();
+extern void wsrep_shutdown_replication();
extern bool wsrep_must_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
extern bool wsrep_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
+extern wsrep_status_t wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
+extern void wsrep_last_committed_id (wsrep_gtid_t* gtid);
extern int wsrep_check_opts();
extern void wsrep_prepend_PATH (const char* path);
+
+
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;
+/* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to
+ * avoid compiler warnings (GCC 6 and later) */
+#define WSREP_NNULL(thd) \
+ (WSREP_ON && wsrep && thd->variables.wsrep_on)
+
#define WSREP_ON \
(global_system_variables.wsrep_on)
@@ -186,12 +203,22 @@ extern wsrep_seqno_t wsrep_locked_seqno;
wsrep_provider && \
strcmp(wsrep_provider, WSREP_NONE))
+#define WSREP_NOT_SPECIFIED \
+ (strlen(wsrep_provider)== 0 || \
+ !strcmp(wsrep_provider, WSREP_NONE))
+
#define WSREP(thd) \
- (WSREP_ON && thd->variables.wsrep_on)
+ (thd && WSREP_NNULL(thd))
+
+#define WSREP_CLIENT_NNULL(thd) \
+ (WSREP_NNULL(thd) && thd->wsrep_client_thread)
#define WSREP_CLIENT(thd) \
(WSREP(thd) && thd->wsrep_client_thread)
+#define WSREP_EMULATE_BINLOG_NNULL(thd) \
+ (WSREP_NNULL(thd) && wsrep_emulate_bin_log)
+
#define WSREP_EMULATE_BINLOG(thd) \
(WSREP(thd) && wsrep_emulate_bin_log)
@@ -205,9 +232,9 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
#define WSREP_LOG_CONFLICT_THD(thd, role) \
WSREP_LOG(sql_print_information, \
"%s: \n " \
- " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \
+ " THD: %lld, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \
" SQL: %s", \
- role, thd_get_thread_id(thd), wsrep_thd_exec_mode_str(thd), \
+ role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \
wsrep_thd_query_state_str(thd), \
wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \
wsrep_thd_query(thd) \
@@ -221,6 +248,7 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
); \
if (bf_thd != NULL) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \
if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \
+ WSREP_LOG(sql_print_information, "context: %s:%d", __FILE__, __LINE__); \
}
#define WSREP_PROVIDER_EXISTS \
@@ -231,33 +259,45 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
extern my_bool wsrep_ready_get();
extern void wsrep_ready_wait();
+static inline
+wsrep_status_t wsrep_trx_status_to_wsrep_status(wsrep_trx_status status)
+{
+ switch (status)
+ {
+ case WSREP_TRX_OK:
+ return WSREP_OK;
+ case WSREP_TRX_CERT_FAIL:
+ case WSREP_TRX_ERROR:
+ return WSREP_TRX_FAIL;
+ case WSREP_TRX_SIZE_EXCEEDED:
+ return WSREP_SIZE_EXCEEDED;
+ }
+ return WSREP_NOT_IMPLEMENTED;
+}
+
class Ha_trx_info;
struct THD_TRANS;
void wsrep_register_hton(THD* thd, bool all);
+void wsrep_register_hton(THD* thd, bool all, bool force);
+void wsrep_post_rollback(THD* thd);
void wsrep_brute_force_killer(THD *thd);
int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id);
-/* this is visible for client build so that innodb plugin gets this */
-typedef struct wsrep_aborting_thd {
- struct wsrep_aborting_thd *next;
- THD *aborting_thd;
-} *wsrep_aborting_thd_t;
-
extern mysql_mutex_t LOCK_wsrep_ready;
extern mysql_cond_t COND_wsrep_ready;
extern mysql_mutex_t LOCK_wsrep_sst;
extern mysql_cond_t COND_wsrep_sst;
extern mysql_mutex_t LOCK_wsrep_sst_init;
extern mysql_cond_t COND_wsrep_sst_init;
-extern mysql_mutex_t LOCK_wsrep_rollback;
-extern mysql_cond_t COND_wsrep_rollback;
extern int wsrep_replaying;
extern mysql_mutex_t LOCK_wsrep_replaying;
extern mysql_cond_t COND_wsrep_replaying;
extern mysql_mutex_t LOCK_wsrep_slave_threads;
extern mysql_mutex_t LOCK_wsrep_desync;
+extern mysql_mutex_t LOCK_wsrep_SR_pool;
+extern mysql_mutex_t LOCK_wsrep_SR_store;
+extern mysql_mutex_t LOCK_wsrep_thd_pool;
extern mysql_mutex_t LOCK_wsrep_config_state;
-extern wsrep_aborting_thd_t wsrep_aborting_thd;
extern my_bool wsrep_emulate_bin_log;
extern int wsrep_to_isolation;
#ifdef GTID_SUPPORT
@@ -267,6 +307,9 @@ extern my_bool wsrep_preordered_opt;
extern handlerton *wsrep_hton;
#ifdef HAVE_PSI_INTERFACE
+
+extern PSI_mutex_key key_LOCK_wsrep_thd;
+extern PSI_cond_key key_COND_wsrep_thd;
extern PSI_mutex_key key_LOCK_wsrep_ready;
extern PSI_mutex_key key_COND_wsrep_ready;
extern PSI_mutex_key key_LOCK_wsrep_sst;
@@ -275,24 +318,161 @@ extern PSI_mutex_key key_LOCK_wsrep_sst_init;
extern PSI_cond_key key_COND_wsrep_sst_init;
extern PSI_mutex_key key_LOCK_wsrep_sst_thread;
extern PSI_cond_key key_COND_wsrep_sst_thread;
-extern PSI_mutex_key key_LOCK_wsrep_rollback;
-extern PSI_cond_key key_COND_wsrep_rollback;
extern PSI_mutex_key key_LOCK_wsrep_replaying;
extern PSI_cond_key key_COND_wsrep_replaying;
extern PSI_mutex_key key_LOCK_wsrep_slave_threads;
extern PSI_mutex_key key_LOCK_wsrep_desync;
+extern PSI_mutex_key key_LOCK_wsrep_SR_pool;
+extern PSI_mutex_key key_LOCK_wsrep_SR_store;
+extern PSI_mutex_key key_LOCK_wsrep_thd_pool;
+extern PSI_mutex_key key_LOCK_wsrep_nbo;
+extern PSI_cond_key key_COND_wsrep_nbo;
+extern PSI_mutex_key key_LOCK_wsrep_global_seqno;
+extern PSI_mutex_key key_LOCK_wsrep_thd_queue;
+extern PSI_cond_key key_COND_wsrep_thd_queue;
extern PSI_file_key key_file_wsrep_gra_log;
#endif /* HAVE_PSI_INTERFACE */
struct TABLE_LIST;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list);
+
+void wsrep_begin_nbo_unlock(THD*);
+void wsrep_end_nbo_lock(THD*, const TABLE_LIST *table_list);
+
void wsrep_to_isolation_end(THD *thd);
+
void wsrep_cleanup_transaction(THD *thd);
+bool wsrep_append_SR_keys(THD *thd);
int wsrep_to_buf_helper(
THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len);
+int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
+int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len);
+bool wsrep_stmt_rollback_is_safe(THD* thd);
+
+void wsrep_init_sidno(const wsrep_uuid_t&);
+bool wsrep_node_is_donor();
+bool wsrep_node_is_synced();
+
+void wsrep_init_schema();
+void wsrep_init_SR();
+void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno);
+int wsrep_replay_from_SR_store(THD*, const wsrep_trx_meta_t&);
+void wsrep_node_uuid(wsrep_uuid_t&);
+
+class Log_event;
+int wsrep_ignored_error_code(Log_event* ev, int error);
+int wsrep_must_ignore_error(THD* thd);
+
+bool wsrep_replicate_GTID(THD* thd);
+
+/*
+ * Helper class for non-blocking operations.
+ */
+class Wsrep_nbo_ctx
+{
+ public:
+ Wsrep_nbo_ctx(const void* buf, size_t buf_len,
+ uint32_t flags, const wsrep_trx_meta_t& meta) :
+ buf_ (0),
+ buf_len_(buf_len),
+ flags_ (flags),
+ meta_ (meta),
+ mutex_ (),
+ cond_ (),
+ ready_ (false),
+ executing_(false),
+ toi_released_(false)
+ {
+ mysql_mutex_init(key_LOCK_wsrep_nbo, &mutex_, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_nbo, &cond_, NULL);
+
+ if ((buf_ = malloc(buf_len_)) == 0) {
+ throw std::exception();
+ }
+ memcpy(buf_, buf, buf_len);
+ }
+
+
+ ~Wsrep_nbo_ctx() {
+ free(buf_);
+ }
+
+ const void* buf() { return buf_; }
+ size_t buf_len() { return buf_len_; }
+ uint32_t flags() { return flags_; }
+ const wsrep_trx_meta_t& meta() { return meta_; }
+
+ void wait_sync()
+ {
+ mysql_mutex_lock(&mutex_);
+ while (ready_ == false)
+ {
+ mysql_cond_wait(&cond_, &mutex_);
+ }
+ mysql_mutex_unlock(&mutex_);
+ }
+
+ void signal()
+ {
+ mysql_mutex_lock(&mutex_);
+ ready_ = true;
+ mysql_cond_signal(&cond_);
+ mysql_mutex_unlock(&mutex_);
+ }
+
+ bool ready() const { return ready_; }
+
+ void set_executing(bool val) { executing_ = val; }
+
+ bool executing() const { return executing_; }
+
+ void set_toi_released(bool val) { toi_released_ = true; }
+
+ bool toi_released() const { return toi_released_; }
+
+ private:
+ void* buf_;
+ size_t buf_len_;
+ uint32_t flags_;
+ wsrep_trx_meta_t meta_;
+ mysql_mutex_t mutex_;
+ mysql_cond_t cond_;
+ bool ready_;
+ bool executing_;
+ bool toi_released_;
+};
+
+/*
+ Convenience macros for determining NBO start and END
+*/
+#define WSREP_NBO_START(flags_) \
+((flags_ & WSREP_FLAG_ISOLATION) && (flags_ & WSREP_FLAG_TRX_START) && \
+ !(flags_ & WSREP_FLAG_TRX_END))
+
+#define WSREP_NBO_END(flags_) \
+ ((flags_ & WSREP_FLAG_ISOLATION) && !(flags_ & WSREP_FLAG_TRX_START) && \
+ (flags_ & WSREP_FLAG_TRX_END))
+
+#define WSREP_TOI(flags_) \
+ ((flags_ & WSREP_FLAG_ISOLATION) && (flags_ & WSREP_FLAG_TRX_START) && \
+ (flags_ & WSREP_FLAG_TRX_END))
+
+typedef struct wsrep_key_arr
+{
+ wsrep_key_t* keys;
+ size_t keys_len;
+} wsrep_key_arr_t;
+
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka);
+void wsrep_keys_free(wsrep_key_arr_t* key_arr);
+
extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
MDL_ticket *ticket,
@@ -303,10 +483,34 @@ void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end);
void thd_binlog_rollback_stmt(THD * thd);
void thd_binlog_trx_reset(THD * thd);
-typedef void (*wsrep_thd_processor_fun)(THD *);
-pthread_handler_t start_wsrep_THD(void *arg);
+typedef void (*wsrep_thd_processor_fun)(THD*, void *);
+class Wsrep_thd_args
+{
+ public:
+ Wsrep_thd_args(wsrep_thd_processor_fun fun, void* args)
+ :
+ fun_ (fun),
+ args_(args)
+ { }
+
+ wsrep_thd_processor_fun fun() { return fun_; }
+
+ void* args() { return args_; }
+
+ private:
+
+ Wsrep_thd_args(const Wsrep_thd_args&);
+ Wsrep_thd_args& operator=(const Wsrep_thd_args&);
+
+ wsrep_thd_processor_fun fun_;
+ void* args_;
+};
+
+void* start_wsrep_THD(void*);
+
+extern void wsrep_close_client_connections(my_bool wait_to_end,
+ THD *except_caller_thd = NULL);
int wsrep_wait_committing_connections_close(int wait_time);
-void wsrep_close_client_connections(my_bool wait_to_end);
void wsrep_close_applier(THD *thd);
void wsrep_close_applier_threads(int count);
void wsrep_wait_appliers_close(THD *thd);
@@ -321,18 +525,6 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
bool wsrep_node_is_donor();
bool wsrep_node_is_synced();
-typedef struct wsrep_key_arr
-{
- wsrep_key_t* keys;
- size_t keys_len;
-} wsrep_key_arr_t;
-bool wsrep_prepare_keys_for_isolation(THD* thd,
- const char* db,
- const char* table,
- const TABLE_LIST* table_list,
- wsrep_key_arr_t* ka);
-void wsrep_keys_free(wsrep_key_arr_t* key_arr);
-
#define WSREP_BINLOG_FORMAT(my_format) \
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
@@ -342,9 +534,11 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr);
#define WSREP(T) (0)
#define WSREP_ON (0)
#define WSREP_EMULATE_BINLOG(thd) (0)
+#define WSREP_EMULATE_BINLOG_NNULL(thd) (0)
#define WSREP_CLIENT(thd) (0)
#define WSREP_FORMAT(my_format) ((ulong)my_format)
#define WSREP_PROVIDER_EXISTS (0)
+#define WSREP_NOT_SPECIFIED (1)
#define wsrep_emulate_bin_log (0)
#define wsrep_to_isolation (0)
#define wsrep_init() (1)
@@ -367,4 +561,37 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr);
#define wsrep_running_threads (0)
#define WSREP_BINLOG_FORMAT(my_format) my_format
#endif /* WITH_WSREP */
+
+#ifdef WITH_WSREP
+/**
+ * Check if the wsrep provider (ie the Galera library) is capable of
+ * doing streaming replication.
+ * @return true if SR capable
+ */
+bool wsrep_provider_is_SR_capable();
+
+/**
+ * Mark current commit ordered if binlogging is not enabled.
+ *
+ * The purpose of this function is to leave commit order critical
+ * section if binlog is not enabled.
+ *
+ * The function can be called from inside storage engine during commit.
+ * Binlog options are checked inside the function.
+ *
+ * @return Zero in case of success, non-zero in case of failure.
+ */
+
+int wsrep_ordered_commit_if_no_binlog(THD*);
+
+/**
+ * Commit the current transaction with the
+ * MySQL "Transaction Coordinator Log" (see `class TC_LOG` in sql/log.h).
+ * Calling this function will generate and assign a new wsrep transaction id
+ * for `thd`.
+ * @return WSREP_OK on success or other WSREP_* error code on failure
+ */
+wsrep_status_t wsrep_tc_log_commit(THD* thd);
+
+#endif /* WITH_WSREP */
#endif /* WSREP_MYSQLD_H */
diff --git a/sql/wsrep_plugin.cc b/sql/wsrep_plugin.cc
new file mode 100644
index 00000000000..44421075dd4
--- /dev/null
+++ b/sql/wsrep_plugin.cc
@@ -0,0 +1,53 @@
+/* Copyright 2016 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "wsrep_trans_observer.h"
+#include "wsrep_mysqld.h"
+
+#include <mysql/plugin.h>
+
+static int wsrep_plugin_init(void *p)
+{
+ WSREP_INFO("wsrep_plugin_init()");
+ return wsrep_register_trans_observer(p);
+}
+
+static int wsrep_plugin_deinit(void *p)
+{
+ WSREP_INFO("wsrep_plugin_deinit()");
+ return wsrep_unregister_trans_observer(p);
+}
+
+struct Mysql_replication wsrep_plugin= {
+ MYSQL_REPLICATION_INTERFACE_VERSION
+};
+
+mysql_declare_plugin(wsrep)
+{
+ MYSQL_REPLICATION_PLUGIN,
+ &wsrep_plugin,
+ "wsrep",
+ "Codership Oy",
+ "Wsrep replication plugin",
+ PLUGIN_LICENSE_GPL,
+ wsrep_plugin_init,
+ wsrep_plugin_deinit,
+ 0x0100,
+ NULL, /* Status variables */
+ NULL, /* System variables */
+ NULL, /* Config options */
+ 0 /* Flags */
+}
+mysql_declare_plugin_end;
diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h
index 222a49cc2ab..e0206e9377a 100644
--- a/sql/wsrep_priv.h
+++ b/sql/wsrep_priv.h
@@ -19,6 +19,7 @@
#ifndef WSREP_PRIV_H
#define WSREP_PRIV_H
+#include <my_global.h>
#include "wsrep_mysqld.h"
#include "../wsrep/wsrep_api.h"
@@ -31,21 +32,23 @@ my_bool wsrep_ready_set (my_bool x);
ssize_t wsrep_sst_prepare (void** msg);
wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx,
void* recv_ctx,
- const void* msg, size_t msg_len,
+ const wsrep_buf_t* msg,
const wsrep_gtid_t* state_id,
- const char* state, size_t state_len,
+ const wsrep_buf_t* state,
bool bypass);
extern wsrep_uuid_t local_uuid;
extern wsrep_seqno_t local_seqno;
// a helper function
-bool wsrep_sst_received (wsrep_t* const wsrep,
+void wsrep_sst_received (THD* thd,
+ wsrep_t* const wsrep,
const wsrep_uuid_t& uuid,
const wsrep_seqno_t seqno,
const void* const state,
const size_t state_len,
const bool implicit);
+
/*! SST thread signals init thread about sst completion */
void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool);
diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc
new file mode 100644
index 00000000000..dd4e13d00ec
--- /dev/null
+++ b/sql/wsrep_schema.cc
@@ -0,0 +1,1481 @@
+/* Copyright (C) 2015-2017 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "mariadb.h"
+
+#include "table.h"
+#include "key.h"
+#include "sql_base.h"
+#include "sql_parse.h"
+#include "sql_update.h"
+#include "transaction.h"
+
+#include "wsrep_thd_pool.h"
+#include "wsrep_schema.h"
+#include "wsrep_applier.h"
+#include "wsrep_xid.h"
+
+#include <string>
+#include <sstream>
+
+const std::string wsrep_schema_str= "wsrep_schema";
+static const std::string create_wsrep_schema_str=
+ "CREATE DATABASE IF NOT EXISTS wsrep_schema";
+
+static const std::string create_cluster_table_str=
+ "CREATE TABLE IF NOT EXISTS wsrep_schema.cluster"
+ "("
+ "cluster_uuid CHAR(36) PRIMARY KEY,"
+ "view_id BIGINT NOT NULL,"
+ "view_seqno BIGINT NOT NULL,"
+ "protocol_version INT NOT NULL"
+ ") ENGINE=InnoDB";
+
+static const std::string create_members_table_str=
+ "CREATE TABLE IF NOT EXISTS wsrep_schema.members"
+ "("
+ "node_uuid CHAR(36) PRIMARY KEY,"
+ "cluster_uuid CHAR(36) NOT NULL,"
+ "node_name CHAR(32) NOT NULL,"
+ "node_incoming_address VARCHAR(256) NOT NULL"
+ ") ENGINE=InnoDB";
+
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+static const std::string create_members_history_table_str=
+ "CREATE TABLE IF NOT EXISTS wsrep_schema.members_history"
+ "("
+ "node_uuid CHAR(36) PRIMARY KEY,"
+ "cluster_uuid CHAR(36) NOT NULL,"
+ "last_view_id BIGINT NOT NULL,"
+ "last_view_seqno BIGINT NOT NULL,"
+ "node_name CHAR(32) NOT NULL,"
+ "node_incoming_address VARCHAR(256) NOT NULL"
+ ") ENGINE=InnoDB";
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+
+static const std::string sr_table_str= "SR";
+const std::string sr_table_name_full_str= wsrep_schema_str + "/" + sr_table_str;
+static const std::string create_frag_table_str=
+ "CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + sr_table_str +
+ "("
+ "node_uuid CHAR(36), "
+ "trx_id BIGINT, "
+ "seqno BIGINT, "
+ "flags INT NOT NULL, "
+ "frag LONGBLOB NOT NULL, "
+ "PRIMARY KEY (node_uuid, trx_id, seqno)"
+ ") ENGINE=InnoDB";
+
+static const std::string delete_from_cluster_table=
+ "DELETE FROM wsrep_schema.cluster";
+
+static const std::string delete_from_members_table=
+ "DELETE FROM wsrep_schema.members";
+
+
+namespace Wsrep_schema_impl
+{
+
+static int execute_SQL(THD* thd, const char* sql, uint length) {
+ DBUG_ENTER("Wsrep_schema::execute_SQL()");
+ int err= 0;
+
+ PSI_statement_locker *parent_locker= thd->m_statement_psi;
+ Parser_state parser_state;
+
+ WSREP_DEBUG("SQL: %d %s thd: %lld", length, sql, (long long)thd->thread_id);
+
+ if (parser_state.init(thd, (char*)sql, length) == 0) {
+ thd->reset_for_next_command();
+ lex_start(thd);
+
+ thd->m_statement_psi= NULL;
+
+ thd->set_query((char*)sql, length);
+ thd->set_query_id(next_query_id());
+
+ mysql_parse(thd, (char*)sql, length, & parser_state, FALSE, FALSE);
+
+ if (thd->is_error()) {
+ WSREP_WARN("Wsrep_schema::execute_sql() failed, %d %s\nSQL: %s",
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->message(),
+ sql);
+ err= 1;
+ }
+ thd->m_statement_psi= parent_locker;
+ thd->end_statement();
+ thd->reset_query();
+ close_thread_tables(thd);
+ delete_explain_query(thd->lex);
+ }
+ else {
+ WSREP_WARN("SR init failure");
+ }
+ thd->cleanup_after_query();
+ DBUG_RETURN(err);
+}
+
+/*
+ Initialize thd for next "statement"
+ */
+static void init_stmt(THD* thd) {
+ lex_start(thd);
+ thd->reset_for_next_command();
+}
+
+static void finish_stmt(THD* thd) {
+ trans_commit_stmt(thd);
+ thd->lex->unit.cleanup();
+ close_thread_tables(thd);
+}
+
+static int open_table(THD* thd,
+ const LEX_CSTRING *schema_name,
+ const LEX_CSTRING *table_name,
+ enum thr_lock_type const lock_type,
+ TABLE** table) {
+ assert(table);
+ *table= NULL;
+
+ DBUG_ENTER("Wsrep_schema::open_table()");
+
+ TABLE_LIST tables;
+ uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |
+ MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |
+ MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_LOCK_IGNORE_TIMEOUT);
+#ifdef OUT
+ tables.init_one_table(schema_name.str, schema_name.length,
+ table_name.str, table_name.length,
+ table_name.str, lock_type);
+#endif
+ tables.init_one_table(schema_name,
+ table_name,
+ NULL, lock_type);
+
+ if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) {
+ close_thread_tables(thd);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), schema_name->str, table_name->str);
+ DBUG_RETURN(1);
+ }
+
+ *table= tables.table;
+ (*table)->use_all_columns();
+
+ DBUG_RETURN(0);
+}
+
+
+static int open_for_write(THD* thd, const char* table_name, TABLE** table) {
+ // LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) };
+ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() };
+ LEX_CSTRING table_str= { table_name, strlen(table_name) };
+ if (Wsrep_schema_impl::open_table(thd, &schema_str, &table_str, TL_WRITE,
+ table)) {
+ WSREP_ERROR("Failed to open table %s.%s for writing",
+ schema_str.str, table_name);
+ return 1;
+ }
+ empty_record(*table);
+ (*table)->use_all_columns();
+ restore_record(*table, s->default_values);
+ return 0;
+}
+
+
+static void store(TABLE* table, uint field, const wsrep_uuid_t& uuid) {
+ assert(field < table->s->fields);
+ char uuid_str[37]= {'\0', };
+ wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
+ table->field[field]->store(uuid_str,
+ strlen(uuid_str),
+ &my_charset_bin);
+}
+
+template <typename INTTYPE>
+static void store(TABLE* table, uint field, const INTTYPE val) {
+ assert(field < table->s->fields);
+ table->field[field]->store(val);
+}
+
+template <typename CHARTYPE>
+static void store(TABLE* table, uint field, const CHARTYPE* str, size_t str_len) {
+ assert(field < table->s->fields);
+ table->field[field]->store((const char*)str,
+ str_len,
+ &my_charset_bin);
+}
+
+static int update_or_insert(TABLE* table) {
+ DBUG_ENTER("Wsrep_schema::update_or_insert()");
+ int ret= 0;
+ char* key;
+ int error;
+
+ /*
+ Verify that the table has primary key defined.
+ */
+ if (table->s->primary_key >= MAX_KEY ||
+ !table->s->keys_in_use.is_set(table->s->primary_key)) {
+ WSREP_ERROR("No primary key for %s.%s",
+ table->s->db.str, table->s->table_name.str);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ Find the record and update or insert a new one if not found.
+ */
+ if (!(key= (char*) my_safe_alloca(table->s->max_unique_length))) {
+ WSREP_ERROR("Error allocating %ud bytes for key",
+ table->s->max_unique_length);
+ DBUG_RETURN(1);
+ }
+
+ key_copy((uchar*) key, table->record[0],
+ table->key_info + table->s->primary_key, 0);
+
+ if ((error= table->file->ha_index_read_idx_map(table->record[1],
+ table->s->primary_key,
+ (uchar*) key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))) {
+ /*
+ Row not found, insert a new one.
+ */
+ if ((error= table->file->ha_write_row(table->record[0]))) {
+ WSREP_ERROR("Error writing into %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ ret= 1;
+ }
+ }
+ else if (!records_are_comparable(table) || compare_record(table)) {
+ /*
+ Record has changed
+ */
+ if ((error= table->file->ha_update_row(table->record[1],
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME) {
+ WSREP_ERROR("Error updating record in %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ ret= 1;
+ }
+ }
+
+ my_safe_afree(key, table->s->max_unique_length);
+
+ DBUG_RETURN(ret);
+}
+
+static int insert(TABLE* table) {
+ DBUG_ENTER("Wsrep_schema::insert()");
+ int ret= 0;
+ int error;
+
+ /*
+ Verify that the table has primary key defined.
+ */
+ if (table->s->primary_key >= MAX_KEY ||
+ !table->s->keys_in_use.is_set(table->s->primary_key)) {
+ WSREP_ERROR("No primary key for %s.%s",
+ table->s->db.str, table->s->table_name.str);
+ DBUG_RETURN(1);
+ }
+
+ if ((error= table->file->ha_write_row(table->record[0]))) {
+ WSREP_ERROR("Error writing into %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ ret= 1;
+ }
+
+ DBUG_RETURN(ret);
+}
+
+static int delete_row(TABLE* table) {
+ int error;
+ int retry= 3;
+
+ do {
+ error= table->file->ha_delete_row(table->record[0]);
+ retry--;
+ } while (error && retry);
+
+ if (error) {
+ WSREP_ERROR("Error deleting row from %s.%s: %d",
+ table->s->db.str,
+ table->s->table_name.str,
+ error);
+ table->file->print_error(error, MYF(0));
+ return 1;
+ }
+ return 0;
+}
+
+static int open_for_read(THD* thd, const char* table_name, TABLE** table) {
+ // LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) };
+
+ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() };
+ LEX_CSTRING table_str= { table_name, strlen(table_name) };
+ if (Wsrep_schema_impl::open_table(thd, &schema_str, &table_str, TL_READ,
+ table)) {
+ WSREP_ERROR("Failed to open table %s.%s for reading",
+ schema_str.str, table_name);
+ return 1;
+ }
+ empty_record(*table);
+ (*table)->use_all_columns();
+ restore_record(*table, s->default_values);
+ return 0;
+}
+
+/*
+ Init table for sequential scan.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int init_for_scan(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_rnd_init(TRUE))) {
+ WSREP_ERROR("Failed to init table for scan: %d", error);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ Scan next record. For return codes see handler::ha_rnd_next()
+
+ @return 0 in case of success, error code in case of error
+ */
+static int next_record(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_rnd_next(table->record[0])) &&
+ error != HA_ERR_END_OF_FILE) {
+ WSREP_ERROR("Failed to read next record: %d", error);
+ }
+ return error;
+}
+
+/*
+ End scan.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int end_scan(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_rnd_end())) {
+ WSREP_ERROR("Failed to end scan: %d", error);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ Scan wsrep uuid from given field.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int scan(TABLE* table, uint field, wsrep_uuid_t& uuid)
+{
+ assert(field < table->s->fields);
+ int error;
+ String uuid_str;
+ (void)table->field[field]->val_str(&uuid_str);
+ if ((error= wsrep_uuid_scan((const char*)uuid_str.c_ptr(),
+ uuid_str.length(),
+ &uuid) < 0)) {
+ WSREP_ERROR("Failed to scan uuid: %d", -error);
+ return 1;
+ }
+ return 0;
+}
+
+template <typename INTTYPE>
+static int scan(TABLE* table, uint field, INTTYPE& val)
+{
+ assert(field < table->s->fields);
+ val= table->field[field]->val_int();
+ return 0;
+}
+
+static int scan(TABLE* table, uint field, char* strbuf, uint strbuf_len)
+{
+ String str;
+ (void)table->field[field]->val_str(&str);
+ strncpy(strbuf, str.c_ptr(), std::min(str.length(), strbuf_len));
+ strbuf[strbuf_len - 1] = '\0';
+ return 0;
+}
+
+/*
+ Scan member
+ TODO: filter members by cluster UUID
+ */
+static int scan_member(TABLE* table,
+ wsrep_uuid_t const cluster_uuid,
+ std::vector<wsrep_member_info_t>& members)
+{
+ wsrep_member_info_t member;
+
+ memset(&member, 0, sizeof(member));
+
+ if (scan(table, 0, member.id) ||
+ scan(table, 2, member.name, sizeof(member.name)) ||
+ scan(table, 3, member.incoming, sizeof(member.incoming))) {
+ return 1;
+ }
+
+ if (members.empty() == false) {
+ assert(memcmp(&members.rbegin()->id, &member.id, sizeof(member.id)) < 0);
+ }
+
+ try {
+ members.push_back(member);
+ }
+ catch (...) {
+ WSREP_ERROR("Caught exception while scanning members table");
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ Init table for index scan and retrieve first record
+
+ @return 0 in case of success, error code in case of error.
+ */
+static int init_for_index_scan(TABLE* table, const uchar* key,
+ key_part_map map) {
+ int error;
+ if ((error= table->file->ha_index_init(table->s->primary_key, true))) {
+ WSREP_ERROR("Failed to init table for index scan: %d", error);
+ return error;
+ }
+
+ error= table->file->ha_index_read_map(table->record[0],
+ key, map, HA_READ_KEY_EXACT);
+ switch(error) {
+ case 0:
+ case HA_ERR_END_OF_FILE:
+ case HA_ERR_KEY_NOT_FOUND:
+ break;
+ case -1:
+ WSREP_DEBUG("init_for_index_scan interrupted");
+ break;
+ default:
+ WSREP_ERROR("init_for_index_scan failed to read first record, error %d", error);
+ }
+ return error;
+}
+
+/*
+ Scan next index record. For return codes see handler::ha_index_next()
+
+ @return 0 in case of success, error code in case of error
+ */
+/*
+static int next_index_record(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_index_next(table->record[0])) &&
+ error != HA_ERR_END_OF_FILE) {
+ WSREP_ERROR("Failed to read next record: %d", error);
+ }
+ return error;
+}
+*/
+
+/*
+ End index scan.
+
+ @return 0 in case of success, 1 in case of error.
+ */
+static int end_index_scan(TABLE* table) {
+ int error;
+ if ((error= table->file->ha_index_end())) {
+ WSREP_ERROR("Failed to end scan: %d", error);
+ return 1;
+ }
+ return 0;
+}
+
+static void make_key(TABLE* table, uchar* key, key_part_map* map, int parts) {
+ uint prefix_length= 0;
+ KEY_PART_INFO* key_part= table->key_info->key_part;
+ for (int i=0; i < parts; i++)
+ prefix_length += key_part[i].store_length;
+ *map = make_prev_keypart_map(parts);
+ key_copy(key, table->record[0], table->key_info, prefix_length);
+}
+
+
+static int apply_frag(THD* thd, TABLE* table, wsrep_uuid_t cluster_uuid)
+{
+ int ret= 0;
+ wsrep_trx_meta_t meta;
+ String buf;
+ int32_t flags;
+
+ Wsrep_schema_impl::scan(table, 0, meta.stid.node);
+ Wsrep_schema_impl::scan(table, 1, meta.stid.trx);
+ Wsrep_schema_impl::scan(table, 2, meta.gtid.seqno);
+ Wsrep_schema_impl::scan(table, 3, flags);
+ meta.gtid.uuid= cluster_uuid;
+
+ WSREP_INFO("apply frag %llu %lld", (unsigned long long)meta.stid.trx, (long long)meta.gtid.seqno);
+ (void)table->field[4]->val_str(&buf);
+
+ wsrep_buf_t const ws = { buf.c_ptr(), buf.length() };
+ wsrep_apply_error err;
+ if ((ret = wsrep_apply(thd, flags, &ws, &meta, err))
+ != WSREP_RET_SUCCESS) {
+ WSREP_WARN("Failed to apply frag: %d, %s",
+ ret, err.c_str() ? err.c_str() : "(null)");
+ }
+
+ thd->store_globals(); /* Restore orig thd context */
+ return ret;
+}
+
+} /* namespace Wsrep_schema_impl */
+
+
+Wsrep_schema::Wsrep_schema(Wsrep_thd_pool* thd_pool)
+ :
+ thd_pool_(thd_pool)
+{
+ assert(thd_pool_);
+}
+
+Wsrep_schema::~Wsrep_schema()
+{ }
+
+int Wsrep_schema::init()
+{
+ DBUG_ENTER("Wsrep_schema::init()");
+ int ret;
+ THD* thd= thd_pool_->get_thd(0);
+ if (!thd) {
+ WSREP_ERROR("Unable to get thd");
+ DBUG_RETURN(1);
+ }
+
+ if (Wsrep_schema_impl::execute_SQL(thd, create_wsrep_schema_str.c_str(),
+ create_wsrep_schema_str.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd, create_cluster_table_str.c_str(),
+ create_cluster_table_str.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd, create_members_table_str.c_str(),
+ create_members_table_str.size()) ||
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+ Wsrep_schema_impl::execute_SQL(thd,
+ create_members_history_table_str.c_str(),
+ create_members_history_table_str.size()) ||
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+ Wsrep_schema_impl::execute_SQL(thd,
+ create_frag_table_str.c_str(),
+ create_frag_table_str.size())) {
+ ret= 1;
+ }
+ else {
+ ret= 0;
+ }
+ thd_pool_->release_thd(thd);
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::store_view(const wsrep_view_info_t* view)
+{
+ DBUG_ENTER("Wsrep_schema::store_view()");
+ assert(view->status == WSREP_VIEW_PRIMARY);
+ int ret= 1;
+ int error;
+
+ TABLE* cluster_table= 0;
+ TABLE* members_table= 0;
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+ TABLE* members_history_table= 0;
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+ wsrep_gtid_t last_committed= WSREP_GTID_UNDEFINED;
+
+ THD* thd= thd_pool_->get_thd(0);
+ if (!thd) {
+ WSREP_ERROR("Could not allocate thd");
+ DBUG_RETURN(1);
+ }
+
+ int wsrep_on= thd->variables.wsrep_on;
+ int sql_log_bin= thd->variables.sql_log_bin;
+ ulonglong option_bits= thd->variables.option_bits;
+
+ /*
+ Disable binlogging.
+ */
+ thd->variables.wsrep_on= 0;
+ thd->variables.sql_log_bin= 0;
+ thd->variables.option_bits&= ~OPTION_BIN_LOG;
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) {
+ WSREP_ERROR("failed to start transaction");
+ goto out;
+ }
+
+ /*
+ Clean up cluster table and members table.
+ */
+ if (Wsrep_schema_impl::execute_SQL(thd,
+ delete_from_cluster_table.c_str(),
+ delete_from_cluster_table.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd,
+ delete_from_members_table.c_str(),
+ delete_from_members_table.size())) {
+ goto out;
+ }
+
+ /*
+ Store cluster view info
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "cluster", &cluster_table)) {
+ goto out;
+ }
+
+ Wsrep_schema_impl::store(cluster_table, 0, view->state_id.uuid);
+ Wsrep_schema_impl::store(cluster_table, 1, view->view);
+ Wsrep_schema_impl::store(cluster_table, 2, view->state_id.seqno);
+ Wsrep_schema_impl::store(cluster_table, 3, view->proto_ver);
+ if ((error= Wsrep_schema_impl::update_or_insert(cluster_table))) {
+ WSREP_ERROR("failed to write to cluster table: %d", error);
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ /*
+ Store info about current members
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "members", &members_table)) {
+ WSREP_ERROR("failed to open wsrep.members table");
+ goto out;
+ }
+
+ for (int i= 0; i < view->memb_num; ++i) {
+ Wsrep_schema_impl::store(members_table, 0, view->members[i].id);
+ Wsrep_schema_impl::store(members_table, 1, view->state_id.uuid);
+ Wsrep_schema_impl::store(members_table, 2,
+ view->members[i].name,
+ strlen(view->members[i].name));
+ Wsrep_schema_impl::store(members_table, 3,
+ view->members[i].incoming,
+ strlen(view->members[i].incoming));
+ if ((error= Wsrep_schema_impl::update_or_insert(members_table))) {
+ WSREP_ERROR("failed to write wsrep.members table: %d", error);
+ goto out;
+ }
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+ /*
+ Store members history
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "members_history",
+ &members_history_table)) {
+ WSREP_ERROR("failed to open wsrep.members table");
+ goto out;
+ }
+
+ for (int i= 0; i < view->memb_num; ++i) {
+ Wsrep_schema_impl::store(members_history_table, 0, view->members[i].id);
+ Wsrep_schema_impl::store(members_history_table, 1, view->state_id.uuid);
+ Wsrep_schema_impl::store(members_history_table, 2, view->view);
+ Wsrep_schema_impl::store(members_history_table, 3,
+ view->state_id.seqno);
+ Wsrep_schema_impl::store(members_history_table, 4,
+ view->members[i].name,
+ strlen(view->members[i].name));
+ Wsrep_schema_impl::store(members_history_table, 5,
+ view->members[i].incoming,
+ strlen(view->members[i].incoming));
+ if ((error= Wsrep_schema_impl::update_or_insert(members_history_table))) {
+ WSREP_ERROR("failed to write wsrep.members table: %d", error);
+ goto out;
+ }
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
+
+ /*
+ Assign wsrep GTID before commit if view state_id contains unique
+ seqno.
+ */
+ wsrep_last_committed_id(&last_committed);
+ if (last_committed.seqno < view->state_id.seqno)
+ {
+ WSREP_DEBUG("Assigning unique seqno for view %lld",
+ (long long)view->state_id.seqno);
+ thd->wsrep_trx_meta.gtid= view->state_id;
+ if (wsrep_write_dummy_event_low(thd, "view event"))
+ {
+ WSREP_ERROR("Dummy event write failed");
+ goto out;
+ }
+ }
+ else
+ {
+ WSREP_DEBUG("View does not have unique seqno or the view event was "
+ "contained in SST");
+ }
+
+ if (!trans_commit(thd)) {
+ /* Success */
+ ret= 0;
+ }
+
+ out:
+
+ if (ret) {
+ WSREP_ERROR("Failed to write view event into wsrep_schema");
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+
+ /* Restore original thd state */
+ thd->variables.wsrep_on= wsrep_on;
+ thd->variables.sql_log_bin= sql_log_bin;
+ thd->variables.option_bits= option_bits;
+ thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
+
+ thd_pool_->release_thd(thd);
+
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::restore_view(const wsrep_uuid_t& node_uuid,
+ wsrep_view_info_t** view_info) const {
+ DBUG_ENTER("Wsrep_schema::restore_view()");
+ assert(view_info);
+ int ret= 1;
+ int error;
+ THD* thd= thd_pool_->get_thd(0);
+
+ TABLE* cluster_table= 0;
+ TABLE* members_table=0;
+
+ wsrep_uuid_t cluster_uuid;
+ wsrep_seqno_t view_id;
+ wsrep_seqno_t view_seqno;
+ int my_idx= -1;
+ int proto_ver;
+ std::vector<wsrep_member_info_t> members;
+
+ if (!thd) {
+ WSREP_ERROR("Failed to allocate THD for restore view");
+ DBUG_RETURN(1);
+ }
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) {
+ WSREP_ERROR("Failed to start transaction");
+ goto out;
+ }
+
+ /*
+ Read cluster info from cluster table
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "cluster", &cluster_table) ||
+ Wsrep_schema_impl::init_for_scan(cluster_table) ||
+ Wsrep_schema_impl::next_record(cluster_table) ||
+ Wsrep_schema_impl::scan(cluster_table, 0, cluster_uuid) ||
+ Wsrep_schema_impl::scan(cluster_table, 1, view_id) ||
+ Wsrep_schema_impl::scan(cluster_table, 2, view_seqno) ||
+ Wsrep_schema_impl::scan(cluster_table, 3, proto_ver) ||
+ Wsrep_schema_impl::end_scan(cluster_table)) {
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ /*
+ Read members from members table
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "members", &members_table) ||
+ Wsrep_schema_impl::init_for_scan(members_table)) {
+ goto out;
+ }
+
+ while (true) {
+ if ((error= Wsrep_schema_impl::next_record(members_table)) == 0) {
+ if (Wsrep_schema_impl::scan_member(members_table,
+ cluster_uuid,
+ members)) {
+ goto out;
+ }
+ }
+ else if (error == HA_ERR_END_OF_FILE) {
+ break;
+ }
+ else {
+ goto out;
+ }
+ }
+
+ if (Wsrep_schema_impl::end_scan(members_table)) {
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ for (uint i= 0; i < members.size(); ++i) {
+ if (memcmp(&members[i].id, &node_uuid, sizeof(node_uuid)) == 0) {
+ my_idx= i;
+ }
+ }
+
+ *view_info= (wsrep_view_info_t*)
+ malloc(sizeof(wsrep_view_info_t)
+ + members.size() * sizeof(wsrep_member_info_t));
+ if (!view_info) {
+ WSREP_ERROR("Failed to allocate memory for view info");
+ goto out;
+ }
+
+ (*view_info)->state_id.uuid= cluster_uuid;
+ (*view_info)->state_id.seqno= view_seqno;
+ (*view_info)->view= view_id;
+ (*view_info)->status= WSREP_VIEW_PRIMARY;
+ (*view_info)->my_idx= my_idx;
+ (*view_info)->proto_ver= proto_ver;
+ (*view_info)->memb_num= members.size();
+ std::copy(members.begin(), members.end(), (*view_info)->members);
+
+ (void)trans_commit(thd);
+ ret= 0; /* Success*/
+ out:
+
+ if (ret) {
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+
+ thd_pool_->release_thd(thd);
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::append_frag_apply(THD* thd,
+ const wsrep_trx_meta_t& meta,
+ const uint32_t flags,
+ const unsigned char* frag,
+ size_t frag_len)
+{
+ DBUG_ENTER("Wsrep_schema::append_frag_apply");
+ int error, ret= 1;
+ TABLE* frag_table= 0;
+ int wsrep_on= thd->variables.wsrep_on;
+ int sql_log_bin= thd->variables.sql_log_bin;
+ ulonglong log_bin_option= (thd->variables.option_bits & OPTION_BIN_LOG);
+ my_bool skip_locking= thd->wsrep_skip_locking;
+
+ thd->variables.wsrep_on= 0;
+ thd->variables.sql_log_bin= 0;
+ thd->variables.option_bits&= ~OPTION_BIN_LOG;
+ thd->wsrep_skip_locking= TRUE;
+
+ assert(meta.stid.trx != WSREP_UNDEFINED_TRX_ID);
+ assert(wsrep_uuid_compare(&meta.stid.node, &WSREP_UUID_UNDEFINED) != 0);
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) {
+ WSREP_ERROR("Failed to start transaction");
+ goto out;
+ }
+
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)) {
+ goto out;
+ }
+
+ Wsrep_schema_impl::store(frag_table, 0, meta.stid.node);
+ Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx);
+ Wsrep_schema_impl::store(frag_table, 2, meta.gtid.seqno);
+ Wsrep_schema_impl::store(frag_table, 3, flags);
+ Wsrep_schema_impl::store(frag_table, 4, frag, frag_len);
+
+ /* TODO: make this insert only */
+ if ((error= Wsrep_schema_impl::insert(frag_table))) {
+ WSREP_ERROR("Failed to write to frag table: %d", error);
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ if (!(flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK)) &&
+ meta.gtid.seqno != WSREP_SEQNO_UNDEFINED)
+ {
+ thd->wsrep_trx_meta= meta;
+ if (wsrep_write_dummy_event_low(thd, "fragment"))
+ {
+ goto out;
+ }
+ }
+ ret= 0;
+
+out:
+ thd->variables.wsrep_on= wsrep_on;
+ thd->variables.sql_log_bin= sql_log_bin;
+ thd->variables.option_bits|= log_bin_option;
+ thd->wsrep_skip_locking= skip_locking;
+ DBUG_RETURN(ret);
+}
+
+THD* Wsrep_schema::append_frag(const wsrep_trx_meta_t& meta,
+ const uint32_t flags,
+ const unsigned char* frag,
+ size_t frag_len)
+{
+ DBUG_ENTER("Wsrep_schema::append_frag");
+
+ THD* thd= thd_pool_->get_thd(0);
+
+ if (!thd) {
+ WSREP_ERROR("Could not allocate thd");
+ goto out;
+ }
+
+ if (append_frag_apply(thd, meta, flags, frag, frag_len)) {
+ goto out;
+ }
+
+ DBUG_RETURN(thd);
+
+out:
+ if (thd) release_SR_thd(thd);
+ DBUG_RETURN(NULL);
+}
+
+int Wsrep_schema::append_frag_commit(const wsrep_trx_meta_t& meta,
+ const uint32_t flags,
+ const unsigned char* frag,
+ size_t frag_len)
+{
+ DBUG_ENTER("Wsrep_schema::append_frag_commit");
+
+ THD* thd;
+ int ret= 1;
+ enum durability_properties dur_save;
+
+
+ if ((thd= append_frag(meta, flags, frag, frag_len)) == NULL)
+ goto out;
+
+ /*
+ We can ignore the storage engine durability setting here:
+ Committing a fragment does not cause actual transaction to
+ be committed, so it will be enough that the fragment is
+ committed in order to be able to recover to consistent state.
+ */
+ dur_save= thd->durability_property;
+ thd->durability_property= HA_IGNORE_DURABILITY;
+
+ if (!trans_commit(thd)) {
+ /* Success */
+ ret= 0;
+ }
+
+ thd->durability_property= dur_save;
+
+out:
+ if (thd) {
+ thd->mdl_context.release_transactional_locks();
+ thd_pool_->release_thd(thd);
+ }
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::update_frag_seqno(THD* thd, const wsrep_trx_meta_t& meta)
+{
+ DBUG_ENTER("Wsrep_schema::update_frag_seqno");
+ WSREP_DEBUG("update_frag_seqno(%lld) trx %ld, seqno %lld",
+ thd->thread_id, meta.stid.trx, (long long)meta.gtid.seqno);
+ int error, ret= 1;
+ uchar key[MAX_KEY_LENGTH];
+ key_part_map key_map= 0;
+ TABLE* frag_table= 0;
+ my_bool skip_locking= thd->wsrep_skip_locking;
+ thd->wsrep_skip_locking= TRUE;
+
+ assert(meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
+
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)) {
+ goto out;
+ }
+
+ /* Find record with the given uuid, trx id, and seqno -1 */
+ Wsrep_schema_impl::store(frag_table, 0, meta.stid.node);
+ Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx);
+ Wsrep_schema_impl::store(frag_table, 2, -1);
+ Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3);
+
+ if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, key_map))) {
+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) {
+ WSREP_ERROR("Record not found in %s.%s: %d",
+ frag_table->s->db.str,
+ frag_table->s->table_name.str,
+ error);
+ }
+ frag_table->file->print_error(error, MYF(0));
+ goto out;
+ }
+
+ /* Copy the original record to frag_table->record[1] */
+ store_record(frag_table, record[1]);
+
+ /* Store seqno in frag_table->record[0] and update the row */
+ Wsrep_schema_impl::store(frag_table, 2, meta.gtid.seqno);
+ if ((error= frag_table->file->ha_update_row(frag_table->record[1],
+ frag_table->record[0]))) {
+ WSREP_ERROR("Error updating record in %s.%s: %d",
+ frag_table->s->db.str,
+ frag_table->s->table_name.str,
+ error);
+ frag_table->file->print_error(error, MYF(0));
+ ret= error;
+ goto out;
+ }
+
+ if (Wsrep_schema_impl::end_index_scan(frag_table)) {
+ goto out;
+ }
+
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ thd->wsrep_trx_meta= meta;
+ if (wsrep_write_dummy_event_low(thd, "fragment"))
+ {
+ goto out;
+ }
+
+ if (!trans_commit(thd)) {
+ /* Success */
+ ret= 0;
+ }
+
+out:
+ thd->wsrep_skip_locking= skip_locking;
+ if (ret) {
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+ thd_pool_->release_thd(thd);
+ DBUG_RETURN(ret);
+}
+
+void Wsrep_schema::release_SR_thd(THD* thd)
+{
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ thd->mdl_context.release_transactional_locks();
+ thd_pool_->release_thd(thd);
+}
+
+static int remove_fragment(THD* thd, TABLE* frag_table,
+ const wsrep_trx_meta& meta)
+{
+ WSREP_DEBUG("remove_fragment(%lld) trx %ld, seqno %lld",
+ thd->thread_id, meta.stid.trx, (long long)meta.gtid.seqno);
+ int error, ret= 1;
+ uchar key[MAX_KEY_LENGTH];
+ key_part_map key_map= 0;
+
+ assert(meta.stid.trx != WSREP_UNDEFINED_TRX_ID);
+ assert(wsrep_uuid_compare(&meta.stid.node, &WSREP_UUID_UNDEFINED) != 0);
+
+ /*
+ Remove record with the given uuid, trx id, and seqno.
+ Using a complete key here avoids gap locks.
+ */
+ Wsrep_schema_impl::store(frag_table, 0, meta.stid.node);
+ Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx);
+ Wsrep_schema_impl::store(frag_table, 2, meta.gtid.seqno);
+ Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3);
+
+ if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, key_map))) {
+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) {
+ WSREP_WARN("Record not found in %s.%s:trx %ld, seqno %lld, error %d",
+ frag_table->s->db.str,
+ frag_table->s->table_name.str,
+ meta.stid.trx,
+ (long long)meta.gtid.seqno,
+ error);
+ }
+ frag_table->file->print_error(error, MYF(0));
+ ret= error;
+ goto out;
+ }
+
+ if (Wsrep_schema_impl::delete_row(frag_table)) {
+ goto out;
+ }
+
+ ret= 0;
+
+ out:
+ Wsrep_schema_impl::end_index_scan(frag_table);
+ return ret;
+}
+
+int Wsrep_schema::remove_trx(THD* thd, wsrep_fragment_set* fragments)
+{
+ DBUG_ENTER("Wsrep_schema::remove_trx()");
+ WSREP_DEBUG("Wsrep_schema::remove_trx(%lld)", thd->thread_id);
+ int wsrep_on= thd->variables.wsrep_on;
+ int sql_log_bin= thd->variables.sql_log_bin;
+ ulonglong log_bin_option= (thd->variables.option_bits & OPTION_BIN_LOG);
+ my_bool skip_locking= thd->wsrep_skip_locking;
+
+ thd->variables.wsrep_on= 0;
+ thd->variables.sql_log_bin= 0;
+ thd->variables.option_bits&= ~OPTION_BIN_LOG;
+ thd->wsrep_skip_locking= TRUE;
+
+ TABLE* frag_table= 0;
+ bool was_opened= false;
+ if (thd->open_tables) {
+ for (TABLE* t= thd->open_tables; t != NULL; t= t->next) {
+ if (!strcmp(t->s->db.str, "wsrep_schema") &&
+ !strcmp(t->s->table_name.str, "SR")) {
+ frag_table= t;
+ empty_record(frag_table);
+ frag_table->use_all_columns();
+ restore_record(frag_table, s->default_values);
+ break;
+ }
+ }
+ }
+ else {
+ (void)Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table);
+ was_opened= true;
+ }
+ DBUG_ASSERT(frag_table);
+
+ int ret= 1;
+ if (frag_table) {
+ wsrep_fragment_set::const_iterator it= fragments->begin();
+ for (; it!= fragments->end(); it++) {
+ if (int error= remove_fragment(thd, frag_table, *it)) {
+ ret= error;
+ break;
+ }
+ }
+ if (it == fragments->end()) {
+ ret= 0;
+ }
+ }
+ else {
+ WSREP_WARN("SR table not open in remove_trx()");
+ }
+
+ if (was_opened) {
+ trans_commit_stmt(thd);
+ close_thread_tables(thd);
+ }
+
+ thd->variables.wsrep_on= wsrep_on;
+ thd->variables.sql_log_bin= sql_log_bin;
+ thd->variables.option_bits|= log_bin_option;
+ thd->wsrep_skip_locking= skip_locking;
+
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::rollback_trx(THD* caller)
+{
+ DBUG_ENTER("Wsrep_schema::rollback_trx");
+ WSREP_DEBUG("Wsrep_schema::rollback_trx(%lld)", caller->thread_id);
+
+ /*
+ There are cases where rollback_trx is called unnecessarily from
+ wsrep_client_rollback().
+ For instance, after_command() -> wsrep_client_rollback() -> rollback_trx()
+ is not necessary.
+ However, wsrep_client_rollback() is also called when a server transitions
+ from non-primary back to primary, in which case we want to clean up the
+ SR table. We should fix this eventually, and replace the following if
+ statement with assert.
+ */
+ if (caller->wsrep_SR_fragments.empty()) {
+ WSREP_DEBUG("Wsrep_schema::rollback_trx(%lld) no fragments to remove",
+ caller->thread_id);
+ DBUG_RETURN(0);
+ }
+
+ THD* thd= thd_pool_->get_thd(0);
+
+ if (!thd) {
+ WSREP_ERROR("Could not allocate thd");
+ DBUG_RETURN(1);
+ }
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) {
+ WSREP_ERROR("Failed to start transaction");
+ DBUG_RETURN(1);
+ }
+
+ Wsrep_schema_impl::init_stmt(thd);
+ int ret= remove_trx(thd, &caller->wsrep_SR_fragments);
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ if (!ret && !trans_commit(thd)) {
+ /* Success */
+ ret= 0;
+ }
+
+ if (ret) {
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+
+ thd_pool_->release_thd(thd);
+
+ DBUG_RETURN(ret);
+}
+
+int Wsrep_schema::restore_frags()
+{
+ DBUG_ENTER("Wsrep_schema::restore_frags()");
+ int ret= 1;
+ int error;
+ wsrep_uuid_t cluster_uuid;
+ TABLE* frag_table= 0;
+ TABLE* cluster_table= 0;
+
+
+ THD* thd= thd_pool_->get_thd(0);
+
+ WSREP_INFO("Restoring SR fragments from table storage");
+
+ if (!thd) {
+ WSREP_ERROR("Failed to allocate THD for restore view");
+ DBUG_RETURN(1);
+ }
+
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) {
+ WSREP_ERROR("Failed to start transaction");
+ goto out;
+ }
+
+ /*
+ Scan cluster uuid first
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "cluster", &cluster_table) ||
+ Wsrep_schema_impl::init_for_scan(cluster_table)) {
+ goto out;
+ }
+ if ((error= Wsrep_schema_impl::next_record(cluster_table)) == 0) {
+ if (Wsrep_schema_impl::scan(cluster_table, 0, cluster_uuid)) {
+ goto out;
+ }
+ }
+ else if (error == HA_ERR_END_OF_FILE) {
+ WSREP_ERROR("Cluster table is empty!");
+ goto out;
+ }
+ else {
+ WSREP_ERROR("Cluster table scan returned error: %d", errno);
+ goto out;
+ }
+ if (Wsrep_schema_impl::end_scan(cluster_table)) {
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ /*
+ Scan all fragments and apply them
+ */
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "SR", &frag_table) ||
+ Wsrep_schema_impl::init_for_scan(frag_table)) {
+ goto out;
+ }
+ while (true) {
+ if ((error= Wsrep_schema_impl::next_record(frag_table)) == 0) {
+ if (Wsrep_schema_impl::apply_frag(thd, frag_table, cluster_uuid)) {
+ goto out;
+ }
+ }
+ else if (error == HA_ERR_END_OF_FILE) {
+ break;
+ }
+ else {
+ WSREP_ERROR("Frag table scan returned error: %d", error);
+ goto out;
+ }
+ }
+ if (Wsrep_schema_impl::end_scan(frag_table)) {
+ goto out;
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ (void)trans_commit(thd);
+ ret= 0; /* Success*/
+
+ WSREP_INFO("SR fragments restored");
+ out:
+
+ if (ret) {
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+
+ thd_pool_->release_thd(thd);
+ DBUG_RETURN(ret);
+
+}
+
+
+int Wsrep_schema::replay_trx(THD* real_thd, const wsrep_trx_meta_t& meta)
+{
+ int ret= 1;
+ int error;
+ TABLE* frag_table= 0;
+ uchar key[MAX_KEY_LENGTH];
+ key_part_map key_map= 0;
+
+ THD* thd= thd_pool_->get_thd(0);
+ wsrep_fragment_set* fragments= &real_thd->wsrep_SR_fragments;
+ wsrep_fragment_set::const_iterator it= fragments->begin();
+
+ assert(!fragments->empty());
+
+ if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) {
+ WSREP_ERROR("Failed to start transaction");
+ goto out;
+ }
+
+ Wsrep_schema_impl::init_stmt(thd);
+ if (Wsrep_schema_impl::open_for_read(thd, "SR", &frag_table)) {
+ goto out;
+ }
+
+ for (; it!= fragments->end(); it++) {
+ Wsrep_schema_impl::store(frag_table, 0, meta.stid.node);
+ Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx);
+ Wsrep_schema_impl::store(frag_table, 2, (*it).gtid.seqno);
+ Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3);
+
+ error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, key_map);
+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) {
+ break;
+ } else if (error > 0) {
+ WSREP_ERROR("Frag table scan returned error: %d", error);
+ ret= error;
+ goto out;
+ }
+
+ wsrep_trx_meta_t meta;
+ int32_t flags;
+ Wsrep_schema_impl::scan(frag_table, 0, meta.stid.node);
+ Wsrep_schema_impl::scan(frag_table, 1, meta.stid.trx);
+ Wsrep_schema_impl::scan(frag_table, 2, meta.gtid.seqno);
+ Wsrep_schema_impl::scan(frag_table, 3, flags);
+
+ WSREP_INFO("replay frag trx_id: %llu seqno: %lld flags: %x",
+ (unsigned long long)meta.stid.trx,
+ (long long)meta.gtid.seqno, flags);
+
+ String buf;
+ (void)frag_table->field[4]->val_str(&buf);
+ /*
+ Call wsrep_apply_events() directly to bypass SR processing in
+ wsrep_apply_cb().
+ */
+ real_thd->store_globals();
+ error= wsrep_apply_events(real_thd, buf.c_ptr_safe(), buf.length());
+ if (error != WSREP_CB_SUCCESS) {
+ ret= error;
+ WSREP_ERROR("Failed to apply events during replay, error: %d", error);
+ goto out;
+ }
+ thd->store_globals();
+ if (Wsrep_schema_impl::end_index_scan(frag_table)) {
+ goto out;
+ }
+ }
+ Wsrep_schema_impl::finish_stmt(thd);
+
+ thd->store_globals();
+ (void)trans_commit(thd);
+ real_thd->store_globals();
+ remove_trx(real_thd, &real_thd->wsrep_SR_fragments);
+ (void)trans_commit(real_thd);
+ ret= 0; /* Success*/
+
+ WSREP_INFO("SR transaction replayed");
+ out:
+
+ if (ret) {
+ trans_rollback_stmt(thd);
+ if (!trans_rollback(thd)) {
+ close_thread_tables(thd);
+ }
+ }
+ thd->mdl_context.release_transactional_locks();
+
+ thd_pool_->release_thd(thd);
+
+ real_thd->store_globals();
+ real_thd->mdl_context.release_transactional_locks();
+
+ return ret;
+}
+
+void Wsrep_schema::init_SR_table(TABLE_LIST *table)
+{
+#ifdef OUT
+ table->init_one_table(wsrep_schema_str.c_str(),
+ wsrep_schema_str.size(),
+ "SR", 2, "SR", TL_WRITE);
+#endif
+ //LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) };
+ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() };
+ LEX_CSTRING table_str= { "SR", 2 };
+ table->init_one_table(&schema_str, &table_str, NULL, TL_WRITE);
+}
diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h
new file mode 100644
index 00000000000..f8ab70d0cd1
--- /dev/null
+++ b/sql/wsrep_schema.h
@@ -0,0 +1,141 @@
+/* Copyright (C) 2015-2017 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#ifndef WSREP_SCHEMA_H
+#define WSREP_SCHEMA_H
+
+#include "mysqld.h"
+#include "thr_lock.h" /* enum thr_lock_type */
+#include "../wsrep/wsrep_api.h"
+#include "wsrep_mysqld.h"
+
+#include <string>
+
+/*
+ Forward decls
+*/
+class THD;
+struct TABLE;
+struct TABLE_LIST;
+struct st_mysql_lex_string;
+typedef struct st_mysql_lex_string LEX_STRING;
+
+class Wsrep_thd_pool;
+
+/** Name of the system database (schema) used for WSREP related data. */
+extern const std::string wsrep_schema_str;
+
+/** Name of the table in `wsrep_schema_str` used for storing streaming
+replication data. In an InnoDB full format, e.g. "database/tablename". */
+extern const std::string sr_table_name_full_str;
+
+class Wsrep_schema
+{
+ public:
+
+ Wsrep_schema(Wsrep_thd_pool*);
+ ~Wsrep_schema();
+
+ /*
+ Initialize wsrep schema. Storage engines must be running before
+ calling this function.
+ */
+ int init();
+
+ /*
+ Store wsrep view info into wsrep schema.
+ */
+ int store_view(const wsrep_view_info_t*);
+
+ /*
+ Restore view info from stable storage.
+ */
+ int restore_view(const wsrep_uuid_t& node_uuid, wsrep_view_info_t**) const;
+
+ /*
+ Append transaction fragment to fragment storage.
+ Starts a trx using a THD from thd_pool, does not commit.
+ Should be followed by a call to update_frag_seqno(), or
+ release_SR_thd() if wsrep->certify() fails.
+ */
+ THD* append_frag(const wsrep_trx_meta_t&, uint32_t,
+ const unsigned char*, size_t);
+
+ /*
+ Update fragment sequence number and commits.
+ Use in combination with append_frag().
+ */
+ int update_frag_seqno(THD* thd, const wsrep_trx_meta_t&);
+
+ /*
+ Rollback and release thd returned from append_frag().
+ */
+ void release_SR_thd(THD* thd);
+
+ /*
+ Append transaction fragment to fragment storage.
+ Starts a trx using the given THD, does not commit.
+ */
+ int append_frag_apply(THD* thd, const wsrep_trx_meta_t&,
+ uint32_t, const unsigned char*, size_t);
+
+ /*
+ Append transaction fragment to fragment storage.
+ Starts a trx using a THD from thd_pool and commits.
+ */
+ int append_frag_commit(const wsrep_trx_meta_t&, uint32_t,
+ const unsigned char*, size_t);
+
+ /*
+ Remove transaction from fragment storage in thd's transaction context
+ */
+ int remove_trx(THD* thd, wsrep_fragment_set* fragments);
+
+ /*
+ Remove transaction from fragment storage
+ */
+ int rollback_trx(THD* thd);
+
+ /*
+ Restore and apply all transaction fragments from fragment storage
+ */
+ int restore_frags();
+
+ /*
+ Replay a transaction from fragments stored in wsrep schema
+ */
+ int replay_trx(THD*, const wsrep_trx_meta_t&);
+
+ /*
+ Init TABLE_LIST entry for SR table
+ */
+ void init_SR_table(TABLE_LIST *table);
+
+ /*
+ Close wsrep schema.
+ */
+ void close();
+
+ private:
+ /* Non-copyable */
+ Wsrep_schema(const Wsrep_schema&);
+ Wsrep_schema& operator=(const Wsrep_schema&);
+
+ Wsrep_thd_pool* thd_pool_;
+};
+
+
+#endif /* !WSREP_SCHEMA_H */
diff --git a/sql/wsrep_sr.cc b/sql/wsrep_sr.cc
new file mode 100644
index 00000000000..c007aacb991
--- /dev/null
+++ b/sql/wsrep_sr.cc
@@ -0,0 +1,428 @@
+/* Copyright (C) 2013-2016 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include <my_global.h>
+#include "wsrep_applier.h"
+
+#include "wsrep_priv.h"
+#include "wsrep_sr.h"
+#include "wsrep_thd.h"
+#include "wsrep_trans_observer.h"
+
+#include "transaction.h" // trans_rollback()
+#include "debug_sync.h" // DEBUG_SYNC()
+
+void wsrep_SR_trx_info::remove(THD* caller, bool persistent)
+{
+ WSREP_DEBUG("wsrep_SR_trx_info::remove for thd: %lld trx: %lu",
+ (thd_) ? thd_->thread_id : -1,
+ (thd_) ? thd_->wsrep_trx_id() : -1);
+
+ if (thd_) {
+ if (caller) thd_->thread_stack = caller->thread_stack;
+ thd_->store_globals();
+ /* rollback */
+ wsrep_cb_status_t const rcode(trans_rollback_stmt(thd_) ||
+ trans_rollback(thd_) ?
+ WSREP_CB_FAILURE : WSREP_CB_SUCCESS);
+
+ if (rcode != WSREP_CB_SUCCESS)
+ WSREP_INFO("SR rollback failed, ret: %d, thd: %lld", rcode,thd_->thread_id);
+
+ /* remove persistency records */
+ if (wsrep_SR_store && persistent) wsrep_SR_store->rollback_trx(this);
+
+ /* end and delete thd_ */
+ wsrep_end_SR_THD(thd_);
+
+ /* retain working THD */
+ if (caller) caller->store_globals();
+ thd_ = NULL;
+ }
+}
+
+void wsrep_SR_trx_info::cleanup()
+{
+ if (wsrep_SR_store) wsrep_SR_store->remove_trx(this);
+ get_THD()->store_globals();
+}
+
+/* to prepare wsrep_uuid_t usable in std::map */
+inline bool operator==(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) {
+ return(memcmp(lhs.data, rhs.data, 16) == 0);
+}
+inline bool operator!=(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) {
+ return !operator==(lhs,rhs);
+}
+inline bool operator< (const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) {
+ return(memcmp(lhs.data, rhs.data, 16) < 0);
+}
+inline bool operator> (const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) {
+ return operator< (rhs,lhs);
+}
+inline bool operator<=(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) {
+ return !operator> (lhs,rhs);
+}
+inline bool operator>=(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) {
+ return !operator< (lhs,rhs);
+}
+
+wsrep_SR_trx_info* SR_pool::find(const wsrep_uuid_t& nodeID,
+ const uint64_t& trxID) const
+{
+ wsrep_SR_trx_info* ret(NULL);
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+
+ src_pool_t::const_iterator const si(pool_.find(nodeID));
+ if (si != pool_.end())
+ {
+ trx_pool_t::const_iterator const ti(si->second.find(trxID));
+ if (ti != si->second.end())
+ {
+ wsrep_SR_trx_info* trx = ti->second;
+ if (!trx->preempted())
+ {
+ ret = trx;
+ trx->acquire();
+ }
+ }
+ }
+
+ return ret;
+}
+
+wsrep_SR_trx_info* SR_pool::add(const wsrep_uuid_t& nodeID,
+ const uint64_t& trxID,
+ THD *thd)
+{
+ wsrep_SR_trx_info *trx = new wsrep_SR_trx_info(thd);
+
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+ assert(NULL == pool_[nodeID][trxID]);
+ pool_[nodeID][trxID] = trx;
+ trx->acquire();
+
+ return trx;
+}
+
+void SR_pool::remove(THD* caller, const wsrep_uuid_t& nodeID,
+ const uint64_t& trxID, bool persistent)
+{
+ WSREP_DEBUG("SR_pool::remove, trx: %lu, persistent: %d", trxID, persistent);
+
+ wsrep_SR_trx_info *trx(NULL);
+
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+
+ src_pool_t::iterator const si(pool_.find(nodeID));
+ if (si != pool_.end())
+ {
+ trx_pool_t& trx_pool(si->second);
+ trx_pool_t::iterator ti(trx_pool.find(trxID));
+ if (ti != trx_pool.end())
+ {
+ if (!ti->second->preempted())
+ {
+ trx = ti->second;
+ trx_pool.erase(ti);
+ }
+ }
+
+ if (trx_pool.empty()) pool_.erase(si);
+ }
+ }
+
+ if (trx)
+ {
+ WSREP_DEBUG("trx->remove for trx: %lu", trxID);
+ trx->remove(caller, persistent);
+ delete trx;
+ }
+}
+
+void SR_pool::removeAll(THD* caller, bool persistent)
+{
+ WSREP_DEBUG("SR_pool::removeAll, persistent: %d", persistent);
+
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+
+ src_pool_t::iterator si;
+ for (si = pool_.begin(); si != pool_.end();)
+ {
+ trx_pool_t& trx_pool(si->second);
+ trx_pool_t::iterator ti(trx_pool.begin());
+
+ while (ti != trx_pool.end())
+ {
+ wsrep_SR_trx_info *trx = ti->second;
+ trx->remove(caller, persistent);
+ delete trx;
+ ++ti;
+ }
+
+ pool_.erase(si++);
+ }
+}
+
+void SR_pool::trimToNodes(THD* caller,
+ const wsrep_member_info_t nodes[],
+ int nodeCount)
+{
+ WSREP_DEBUG("SR_pool::trimToNodes");
+
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+
+ src_pool_t::iterator si = pool_.begin();
+ while (si != pool_.end())
+ {
+ bool do_remove(true);
+ for (int i = 0; i< nodeCount; i++)
+ {
+ if (si->first == nodes[i].id)
+ {
+ do_remove = false;
+ break;
+ }
+ }
+
+ if (do_remove)
+ {
+ WSREP_DEBUG("SR_pool::trimToNodes do_remove");
+
+ /* trx_pool erase will not desctruct individual wsrep_SR_trx_info
+ objects, must remove them manually here
+ */
+ trx_pool_t& trx_pool(si->second);
+ trx_pool_t::iterator ti(trx_pool.begin());
+
+ while (ti != trx_pool.end())
+ {
+ wsrep_SR_trx_info *trx = ti->second;
+
+ WSREP_DEBUG("SR transaction to remove: %lld", trx->get_THD()->thread_id);
+
+ trx->remove(caller, true);
+ delete trx;
+ ++ti;
+ }
+
+ /* now removing full trx_pool map */
+ pool_.erase(si++);
+ }
+ else
+ {
+ ++si;
+ }
+ }
+}
+
+bool SR_pool::preempt(THD* thd)
+{
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+
+ src_pool_t::iterator si;
+ for (si = pool_.begin(); si != pool_.end(); ++si)
+ {
+ trx_pool_t& trx_pool(si->second);
+ trx_pool_t::iterator ti(trx_pool.begin());
+ while (ti != trx_pool.end())
+ {
+ wsrep_SR_trx_info *trx = ti->second;
+ if (trx->get_THD() == thd)
+ {
+ trx->mark_preempted();
+ return true;
+ }
+ ++ti;
+ }
+ }
+
+ return false;
+}
+
+bool SR_pool::wait_release_and_remove(THD* caller, THD *victim)
+{
+ wsrep_SR_trx_info *trx(NULL);
+
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_SR_pool);
+
+ src_pool_t::iterator si;
+ for (si = pool_.begin(); si != pool_.end();)
+ {
+ trx_pool_t& trx_pool(si->second);
+
+ for (trx_pool_t::iterator ti = trx_pool.begin();
+ ti != trx_pool.end();
+ ++ti)
+ {
+ if (ti->second->get_THD() == victim)
+ {
+ trx = ti->second;
+ trx_pool.erase(ti);
+ break;
+ }
+ }
+
+ if (trx_pool.empty())
+ {
+ pool_.erase(si++);
+ }
+ else
+ {
+ ++si;
+ }
+
+ }
+ }
+
+ DBUG_ASSERT(trx);
+ DBUG_ASSERT(trx->preempted());
+
+ if (trx)
+ {
+ trx->wait_release();
+ trx->remove(caller, true);
+ delete trx;
+ return true;
+ }
+
+ return false;
+}
+
+
+SR_pool *sr_pool;
+
+void wsrep_close_SR_transactions(THD *thd)
+{
+
+ if (sr_pool)
+ {
+ WSREP_DEBUG("deleting streaming replication transaction pool");
+ sr_pool->removeAll(thd, false);
+ }
+ else
+ {
+ WSREP_DEBUG("empty streaming replication transaction pool");
+ }
+
+ if (wsrep_SR_store) wsrep_SR_store->close();
+
+ delete sr_pool;
+ sr_pool = NULL;
+}
+
+void trim_SR_pool(THD* thd, const wsrep_member_info_t nodes[], int nodeCount)
+{
+ sr_pool->trimToNodes(thd, nodes, nodeCount);
+}
+
+void wsrep_init_SR_pool()
+{
+ WSREP_DEBUG("wsrep_init_SR_pool");
+
+ /* for time being initialize SR pool here */
+ if (!sr_pool) sr_pool = new SR_pool();
+}
+
+void wsrep_restore_SR_trxs(THD *thd)
+{
+ if (wsrep_SR_store) wsrep_SR_store->restore(thd);
+}
+
+bool wsrep_preempt_SR_THD(THD *victim_thd)
+{
+ return sr_pool->preempt(victim_thd);
+}
+
+bool wsrep_abort_SR_THD(THD *thd, THD *victim_thd)
+{
+ return sr_pool->wait_release_and_remove(thd, victim_thd);
+}
+
+void wsrep_prepare_SR_trx_info_for_rollback(THD *thd)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ wsrep_uuid_t node_uuid;
+ wsrep_node_uuid(node_uuid);
+
+ DBUG_ASSERT(thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID);
+
+ int error= 1;
+ THD *sr_thd= wsrep_start_SR_THD(thd->thread_stack);
+ if (sr_thd)
+ {
+ wsrep_SR_trx_info *SR_trx= sr_pool->add(node_uuid,
+ thd->wsrep_ws_handle.trx_id,
+ sr_thd);
+ if (SR_trx)
+ {
+ for (wsrep_fragment_set::const_iterator i=
+ thd->wsrep_SR_fragments.begin();
+ i != thd->wsrep_SR_fragments.end(); ++i)
+ {
+ SR_trx->append_fragment(&(*i));
+ }
+ SR_trx->release();
+ error= 0;
+ }
+ }
+ if (error)
+ {
+ WSREP_WARN("Could not create SR trx info for rollback, wsrep_schema.SR "
+ "table may not be cleaned up for transaction %lu",
+ thd->wsrep_ws_handle.trx_id);
+ }
+ else
+ {
+ thd->wsrep_SR_fragments.clear();
+ }
+}
+
+
+void wsrep_remove_SR_fragments(THD *thd)
+{
+ if (wsrep_SR_store) wsrep_SR_store->remove_trx(thd);
+}
+
+void wsrep_rollback_SR_trx(THD *thd)
+{
+ if (wsrep_SR_store) wsrep_SR_store->rollback_trx(thd);
+ thd->wsrep_SR_fragments.clear();
+}
+
+void wsrep_prepare_SR_for_open_tables(THD *thd, TABLE_LIST **table_list)
+{
+ if (wsrep_SR_store)
+ {
+ wsrep_SR_store->prepare_for_open_tables(thd, table_list);
+ }
+}
+
+void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr)
+{
+ DBUG_ASSERT(victim_thd_ptr);
+ if (!victim_thd_ptr) return;
+
+ THD *victim_thd = (THD*) victim_thd_ptr;
+ WSREP_DEBUG("handle SR rollback, for deadlock: thd %lld trx_id %lu frags %lu conf %d",
+ victim_thd->thread_id,
+ victim_thd->wsrep_trx_id(),
+ victim_thd->wsrep_fragments_sent,
+ victim_thd->wsrep_conflict_state_unsafe());
+ (void)wsrep_before_rollback(victim_thd, true);
+ if (BF_thd_ptr) ((THD*) BF_thd_ptr)->store_globals();
+}
diff --git a/sql/wsrep_sr.h b/sql/wsrep_sr.h
new file mode 100644
index 00000000000..4b2009ef12d
--- /dev/null
+++ b/sql/wsrep_sr.h
@@ -0,0 +1,275 @@
+/* Copyright 2013-2016 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef WSREP_SR_H
+#define WSREP_SR_H
+
+#include "wsrep_mysqld.h"
+#include <sys/types.h>
+#include <map>
+#include "sql_class.h"
+#include "wsrep_utils.h" // wsp::auto_lock
+
+extern class SR_storage_file *wsrep_SR_store_file;
+extern class SR_storage_table *wsrep_SR_store_table;
+extern class SR_storage *wsrep_SR_store;
+
+class wsrep_SR_trx_info
+{
+private:
+ THD *thd_; /* THD processing SR transaction */
+ my_thread_id applier_thread_; /* thread currently applying, 0 if idle */
+
+public:
+ wsrep_SR_trx_info(THD *thd)
+ {
+ WSREP_DEBUG("wsrep_SR_trx_info construtor: %lld", (thd) ? thd->thread_id : -1);
+ thd_ = thd;
+ applier_thread_ = 0;
+ thd_in_use_ = false;
+ preempted_ = false;
+ mysql_mutex_init(key_LOCK_wsrep_thd_queue,
+ &LOCK_wsrep_trx_info_,
+ MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_thd_queue, &COND_wsrep_trx_info_, NULL);
+ }
+
+ ~wsrep_SR_trx_info()
+ {
+ WSREP_DEBUG("wsrep_SR_trx_info destructor: %lld",
+ (thd_) ? thd_->thread_id : -1);
+ remove(NULL, true);
+ mysql_mutex_destroy(&LOCK_wsrep_trx_info_);
+ mysql_cond_destroy(&COND_wsrep_trx_info_);
+ }
+
+ my_thread_id get_applier_thread() { return applier_thread_; }
+ void set_applier_thread(my_thread_id thread_id) { applier_thread_= thread_id; }
+
+ void remove(THD* caller, bool persistent);
+ void cleanup();
+
+ THD* get_THD() const { return thd_; }
+
+ void append_fragment(const wsrep_trx_meta_t *trx)
+ {
+ assert(thd_);
+ thd_->wsrep_SR_fragments.push_back(*trx);
+ }
+
+private:
+ bool thd_in_use_;
+ mysql_mutex_t LOCK_wsrep_trx_info_;
+ mysql_cond_t COND_wsrep_trx_info_;
+
+public:
+ void acquire()
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_trx_info_);
+ assert(!thd_in_use_);
+ thd_in_use_ = true;
+ }
+
+ void release()
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_trx_info_);
+ assert(thd_in_use_);
+ thd_in_use_ = false;
+ mysql_cond_signal(&COND_wsrep_trx_info_);
+ }
+
+ void wait_release()
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_trx_info_);
+ while (thd_in_use_)
+ {
+ mysql_cond_wait(&COND_wsrep_trx_info_,
+ &LOCK_wsrep_trx_info_);
+ }
+ }
+
+private:
+ bool preempted_;
+
+public:
+ /*
+ * These methods should be accessed only through SR_pool,
+ * concurrent access is prevented by LOCK_wsrep_SR_pool.
+ */
+ void mark_preempted()
+ {
+ preempted_ = true;
+ }
+
+ bool preempted() const
+ {
+ return preempted_;
+ }
+};
+
+class SR_pool
+{
+ /* protected by LOCK_wsrep_SR_pool mutex */
+ // ideally we want to change std::map to std::unordered_map here
+ typedef std::map<uint64_t, wsrep_SR_trx_info*> trx_pool_t;
+ typedef std::map<wsrep_uuid_t, trx_pool_t> src_pool_t;
+ private:
+ src_pool_t pool_;
+ public:
+ SR_pool() { }
+
+ ~SR_pool () {
+ WSREP_DEBUG("SR_pool destructor");
+ }
+
+ wsrep_SR_trx_info* find(const wsrep_uuid_t& nodeID,
+ const uint64_t& trxID) const;
+ wsrep_SR_trx_info* add(const wsrep_uuid_t& nodeID, const uint64_t& trxID,
+ THD *thd);
+ void remove(THD* caller, const wsrep_uuid_t& nodeID, const uint64_t& trxID,
+ bool persistent);
+ void removeAll(THD* caller, bool persistent);
+ void trimToNodes (THD* caller, const wsrep_member_info_t nodes[], int nodeCount);
+
+ /*
+ * Mark the corresponding SR trx in the pool as preempted.
+ * Once preempted appliers are no longer able to find the
+ * trx through SR_pool::find(), and can no longer remove
+ * it using SR_pool::remove().
+ * The caller takes responsibility of removing the trx from
+ * the pool by using SR_pool::wait_release_and_remove().
+ */
+ bool preempt(THD* thd);
+
+ /*
+ * Waits until the corresponding trx is released by applier
+ * and removes it from the pool. Caller must first call
+ * SR_pool::preempt() on the same thd.
+ */
+ bool wait_release_and_remove(THD* caller, THD *thd);
+};
+
+class Wsrep_schema;
+
+class SR_storage
+{
+public:
+ SR_storage()
+ :
+ cluster_uuid_(),
+ restored_(false)
+ { }
+ virtual ~SR_storage() {}
+
+ virtual int init(const char* cluster_uuid_str, Wsrep_schema*) = 0;
+
+ virtual THD* append_frag (THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len) = 0;
+
+ virtual void update_frag_seqno (THD* thd, THD* orig_THD) = 0;
+
+ virtual void release_SR_thd(THD* thd) = 0;
+
+ virtual void append_frag_apply (THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len) = 0;
+
+ virtual void append_frag_commit (THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len) = 0;
+
+ virtual void remove_trx ( THD* thd ) = 0;
+
+ virtual void remove_trx ( wsrep_SR_trx_info* trx ) = 0;
+
+ virtual void rollback_trx ( THD* thd ) = 0;
+
+ virtual void rollback_trx ( wsrep_SR_trx_info* trx ) = 0;
+
+ virtual void trx_done ( THD* thd ) = 0;
+
+ virtual int replay_trx(THD* thd, const wsrep_trx_meta_t& meta) = 0;
+
+ virtual int restore( THD *thd ) = 0;
+
+ virtual void prepare_for_open_tables(THD *thd, TABLE_LIST **table_list) = 0;
+
+ virtual void close() = 0;
+
+protected:
+ wsrep_uuid_t cluster_uuid_;
+ bool restored_;
+};
+
+/* functions for appliers */
+extern SR_pool *sr_pool;
+
+void wsrep_close_SR_transactions(THD *thd);
+void wsrep_init_SR_pool();
+void wsrep_restore_SR_trxs(THD *thd);
+void trim_SR_pool(THD* thd, const wsrep_member_info_t nodes[], int nodeCount);
+
+/* functions for rollbacker */
+bool wsrep_preempt_SR_THD(THD* victim_thd);
+bool wsrep_abort_SR_THD(THD* thd, THD* victim_thd);
+
+/*
+ Remove SR fragments from SR storage. This happens in the thd
+ transaction context, fragment removal will be committed
+ at the same time as THD transaction is committed.
+ */
+void wsrep_remove_SR_fragments(THD *thd);
+
+/*
+ Rollback SR trx. Removes fragments from SR storage non-transactionally,
+ so it can be used outside of THD transaction context.
+ */
+void wsrep_rollback_SR_trx(THD *thd);
+
+/*
+ Prepare SR trx info for local transaction. Transfers SR ownership
+ to SR trx info handle.
+ */
+void wsrep_prepare_SR_trx_info_for_rollback(THD *thd);
+
+static inline bool wsrep_may_produce_SR_step(const THD *thd)
+{
+ switch (thd->lex->sql_command)
+ {
+ case SQLCOM_INSERT:
+ case SQLCOM_INSERT_SELECT:
+ case SQLCOM_REPLACE:
+ case SQLCOM_REPLACE_SELECT:
+ case SQLCOM_UPDATE:
+ case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_DELETE:
+ case SQLCOM_LOAD:
+ case SQLCOM_COMMIT:
+ case SQLCOM_ROLLBACK_TO_SAVEPOINT:
+ case SQLCOM_SAVEPOINT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void wsrep_prepare_SR_for_open_tables(THD *thd, TABLE_LIST **table_list);
+void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr);
+
+#endif /* WSREP_SR_H */
diff --git a/sql/wsrep_sr_file.cc b/sql/wsrep_sr_file.cc
new file mode 100644
index 00000000000..7745b759349
--- /dev/null
+++ b/sql/wsrep_sr_file.cc
@@ -0,0 +1,563 @@
+/* Copyright (C) 2013 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include <my_global.h>
+#include "my_pthread.h"
+#include "wsrep_priv.h"
+#include "wsrep_api.h"
+#include "wsrep_sr_file.h"
+#include "wsrep_applier.h" // wsrep_apply()
+#include "wsrep_thd.h"
+#include "wsrep_utils.h"
+#include <map>
+#include <string>
+#include <ostream>
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <dirent.h>
+#include <sstream>
+#include <iomanip>
+
+/* to prepare wsrep_uuid_t usable in std::map */
+inline bool operator==(const node_trx_t& lhs, const node_trx_t& rhs) {
+ return(memcmp(lhs.data, rhs.data, 24) == 0);
+}
+inline bool operator!=(const node_trx_t& lhs, const node_trx_t& rhs) {
+ return !operator==(lhs,rhs);
+}
+inline bool operator< (const node_trx_t& lhs, const node_trx_t& rhs) {
+ return(memcmp(lhs.data, rhs.data, 24) < 0);
+}
+inline bool operator> (const node_trx_t& lhs, const node_trx_t& rhs) {
+ return operator< (rhs,lhs);
+}
+inline bool operator<=(const node_trx_t& lhs, const node_trx_t& rhs) {
+ return !operator> (lhs,rhs);
+}
+inline bool operator>=(const node_trx_t& lhs, const node_trx_t& rhs) {
+ return !operator< (lhs,rhs);
+}
+
+typedef std::map<uint64_t, std::vector<unsigned char> > frag_list_t;
+typedef std::map<node_trx_t, frag_list_t> db_t;
+
+class SR_file {
+ std::string const name_;
+ std::ofstream outfile_;
+
+ size_t size_;
+ long frags_;
+ int const order_;
+
+ typedef std::map<node_trx_t, bool> trxs_t;
+ trxs_t trxs_;
+
+ /* will go in file header */
+ signed long long min_seqno_;
+ signed long long max_seqno_;
+
+public:
+ SR_file(std::string name, int order) :
+ name_(name),
+ order_(order)
+ {
+ outfile_.open(name.c_str(), std::ios::out | std::ios::app | std::ios::binary );
+ size_ = 0;
+ min_seqno_ = 0;
+ max_seqno_ = 0;
+ }
+ SR_file() : order_(0)
+ {
+ }
+ int get_order() { return order_; }
+ std::string get_name() { return name_; }
+
+ void write_file_header();
+ void read_file_header();
+ void write_frag_header(
+ wsrep_uuid_t *node_uuid,
+ wsrep_trx_id_t trx,
+ wsrep_seqno_t seqno,
+ uint32_t flags)
+ {
+ char uuid_str[37] = {'\0',};
+ wsrep_uuid_print(node_uuid, uuid_str, 37);
+
+ outfile_ << uuid_str;
+ outfile_ << ' ' << trx << ' ' << seqno;
+
+ if (flags & WSREP_FLAG_TRX_START) {
+ outfile_ << 'B';
+ } else {
+ outfile_ << ' ';
+ }
+ if (flags & WSREP_FLAG_TRX_END) {
+ outfile_ << 'C';
+ } else {
+ outfile_ << ' ';
+ }
+ if (flags & WSREP_FLAG_ROLLBACK) {
+ outfile_ << 'R';
+ } else {
+ outfile_ << ' ';
+ }
+ }
+ void append(wsrep_uuid_t *node_uuid,
+ wsrep_trx_id_t trx,
+ wsrep_seqno_t seqno,
+ uint32_t flags,
+ const uchar *buf,
+ size_t buf_len)
+ {
+ if (seqno < min_seqno_ || min_seqno_ == 0) min_seqno_ = seqno;
+ if (seqno > max_seqno_ || max_seqno_ == 0) max_seqno_ = seqno;
+
+ write_frag_header(node_uuid, trx, seqno, flags);
+ outfile_ << buf_len << '#';
+ outfile_.write((char*)(buf), buf_len);
+ size_ += buf_len;
+ size_ += 35; /* for header */
+
+ node_trx_t trxid = { {'\0',} };
+ memcpy(trxid.data, node_uuid->data, 16);
+ sprintf((char*)&(trxid.data[16]), "%ld", trx);
+ trxs_[trxid] = true;
+ };
+
+ bool remove(const wsrep_uuid_t *node_uuid,
+ const wsrep_seqno_t seqno)
+ {
+ node_trx_t trxid = { {'\0',} };
+ memcpy(trxid.data, node_uuid->data, 16);
+ sprintf((char*)&(trxid.data[16]), "%ld", seqno);
+
+ //std::string trxid = node_uuid + std::to_string(seqno);
+ trxs_[trxid] = false;
+
+ /* check if all transactions are over in this file */
+ bool all_gone(true);
+
+ trxs_t::iterator iterator;
+ for(iterator = trxs_.begin(); iterator != trxs_.end(); iterator++) {
+ if (iterator->second == true)
+ {
+ all_gone = false;
+ continue;
+ }
+ }
+
+ return all_gone;
+ }
+
+ size_t size()
+ {
+ return size_;
+ }
+
+ class File_hdr {
+ };
+
+ class Frag_hdr {
+ };
+
+ void close()
+ {
+ outfile_.close();
+ }
+};
+
+int SR_storage_file::max_file_order()
+{
+ int max = 0;
+ std::list<SR_file*>::iterator iterator;
+ for (iterator = files_.begin(); iterator != files_.end(); ++iterator) {
+ if ((*iterator)->get_order() > max) max = (*iterator)->get_order();
+ }
+ return max;
+}
+
+std::string *SR_storage_file::new_name(int order)
+{
+ std::string *name = new std::string(dir_);
+ *name += "/wsrep_SR_";
+ *name += order;
+ *name += ".dat";
+ return name;
+}
+
+SR_file *SR_storage_file::append_file() {
+
+ int order = max_file_order() + 1;
+ std::stringstream ss;
+ ss << dir_ << "/wsrep_SR_store." << order;
+ SR_file *file = new SR_file(ss.str(), order);
+ files_.push_back(file);
+ return file;
+}
+
+void SR_storage_file::remove_file(SR_file *file) {
+ remove(file->get_name().c_str());
+ delete file;
+}
+
+SR_storage_file::SR_storage_file(
+ const char *dir,
+ size_t limit,
+ const char * cluster_uuid_str)
+{
+ dir_ = std::string(dir);
+ size_limit_ = limit;
+ wsrep_uuid_scan(cluster_uuid_str, 37, &cluster_uuid_);
+ restored_ = false;
+
+ curr_file_ = NULL;
+
+ WSREP_DEBUG("SR pool initialized, group: %s", cluster_uuid_str);
+}
+
+int SR_storage_file::init(const char* cluster_uuid_str, Wsrep_schema* unused)
+{
+ int rcode = 0;
+
+ WSREP_DEBUG("SR pool initialized,");
+ WSREP_DEBUG("cluster_uuid:str: %s", cluster_uuid_str);
+ wsrep_uuid_scan(cluster_uuid_str, 37, &cluster_uuid_);
+
+ return rcode;
+}
+
+THD* SR_storage_file::append_frag(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len)
+{
+ wsrep_uuid_t *node_uuid = &(thd->wsrep_trx_meta.stid.node);
+ wsrep_trx_id_t trx = thd->wsrep_trx_meta.stid.trx;
+ wsrep_seqno_t seqno = thd->wsrep_trx_meta.gtid.seqno;
+
+ if (!restored_) return NULL;
+
+ wsp::auto_lock lock(&LOCK_wsrep_SR_store);
+
+ if (!curr_file_) curr_file_ = append_file();
+
+ assert(curr_file_);
+
+ curr_file_->append(node_uuid, trx, seqno, flags, buf, buf_len);
+
+ if (curr_file_->size() > size_limit_)
+ {
+ curr_file_->close();
+ curr_file_ = NULL;
+ }
+
+ return NULL;
+}
+
+void SR_storage_file::remove_trx( THD *thd )
+{
+ assert (thd);
+ const wsrep_uuid_t *node_uuid = &(thd->wsrep_trx_meta.stid.node);
+ const wsrep_trx_id_t trxid = thd->wsrep_trx_meta.stid.trx;
+
+ /* remove from all SR files */
+ wsp::auto_lock lock(&LOCK_wsrep_SR_store);
+
+ std::list<SR_file*>::iterator iterator;
+ for (iterator = files_.begin(); iterator != files_.end();) {
+ if ((*iterator)->remove(node_uuid, trxid))
+ {
+ if (curr_file_ == *iterator) curr_file_ = NULL;
+
+ remove_file(*iterator);
+
+ std::list<SR_file*>::iterator prev = iterator++;
+ files_.erase(prev);
+ }
+ else
+ {
+ ++iterator;
+ }
+ }
+}
+
+void SR_storage_file::rollback_trx( THD* thd )
+
+{
+ WSREP_DEBUG("SR_storage_file::commit_trx");
+ remove_trx(thd);
+}
+
+int SR_storage_file::replay_trx(THD* thd, const wsrep_trx_meta_t& meta)
+{
+ WSREP_ERROR("SR_storage_file::replay_trx not implemented");
+ return 1;
+}
+
+
+void SR_storage_file::read_trxs_from_file(
+ std::string file, trxs_t *trxs, THD *thd, enum read_mode mode)
+{
+ std::ifstream infile;
+
+ WSREP_DEBUG("read_trxs_from_file");
+
+ if (!strcmp(file.c_str(), "---"))
+ {
+ WSREP_DEBUG("SR file comment line skipped");
+ return;
+ }
+ infile.open(file.c_str(), std::ios::in | std::ios::binary);
+ infile.exceptions (
+ std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit);
+
+ try {
+
+ while (infile.good())
+ {
+ char uuid[37] = {'\0',};
+ wsrep_uuid_t node_uuid;
+ wsrep_trx_id_t trxid;
+ wsrep_seqno_t seqno;
+ char begin = '#';
+ char commit = '#';
+ char rollback = '#';
+ int len;
+ char *buf;
+
+ /* 1 source node UUID */
+ if (infile.get(uuid, 37))
+ {
+ wsrep_uuid_scan(uuid, 37, &node_uuid);
+ }
+ else
+ break;
+
+ /* 2 source node trx ID */
+ infile >> trxid;
+
+ /* 3 trx seqno */
+ infile >> seqno;
+
+ /* 4 flags: Begin-Commit-Rollback */
+ begin = (char)infile.get();
+ commit = (char)infile.get();
+ rollback = (char)infile.get();
+
+ /* 5 rbr buffer length */
+ infile >> len;
+
+ /* # after header part */
+ if ( (char)infile.get() != '#')
+ {
+ WSREP_WARN("SR frament file bad line: %s %ld %ld %c %c %c",
+ uuid, trxid, seqno, begin, commit, rollback);
+ return;
+ }
+
+ /* 6 the buffer */
+ buf = new char [len];
+ infile.read(buf, len);
+
+ /* */
+ node_trx_t nodetrx;
+ memcpy(nodetrx.data, node_uuid.data, 16);
+ sprintf((char*)&(nodetrx.data[16]), "%ld", trxid);
+
+ int flags = 0;
+ wsrep_trx_meta_t meta;
+ meta.gtid.uuid = cluster_uuid_;
+ meta.gtid.seqno = seqno;
+ meta.stid.node = node_uuid;
+ meta.stid.trx = trxid;
+
+ if (begin == 'B')
+ {
+ if (mode == FILTER)
+ {
+ WSREP_DEBUG("new trx in SR file: trx %ld seqno %ld", trxid, seqno);
+ (*trxs)[nodetrx] = true;
+ }
+ else
+ {
+ flags |= WSREP_FLAG_TRX_START;
+ }
+ }
+ else if (!(*trxs)[nodetrx])
+ {
+ WSREP_WARN("unfinished trx in SR file: trx %ld seqno %ld",
+ trxid, seqno);
+ }
+
+ if (mode == FILTER && (commit == 'C' || rollback == 'R'))
+ {
+ WSREP_DEBUG("trx commit in SR file: trx %ld seqno %ld", trxid, seqno);
+ (*trxs)[nodetrx] = false;
+ }
+
+ if (mode == POPULATE && (*trxs)[nodetrx])
+ {
+ /* pending transaction to launch in sr_pool */
+ WSREP_DEBUG("launching SR trx: %ld", trxid);
+
+ wsrep_buf_t const ws= { buf, size_t(len) };
+ wsrep_apply_error err;
+ if (wsrep_apply(thd, flags, &ws, &meta, err) !=
+ WSREP_CB_SUCCESS)
+ {
+ WSREP_WARN("Streaming Replication fragment restore failed: %s",
+ err.c_str() ? err.c_str() : "(null)");
+ return;
+ }
+ DBUG_ASSERT(err.is_null());
+ }
+ else if (mode == POPULATE)
+ WSREP_DEBUG("not populating trx %ld seqno %ld", trxid, seqno);
+
+ delete[] buf;
+ }
+ }
+ catch(std::exception e)
+ {
+ if(infile.eof())
+ {
+ WSREP_DEBUG("infile EOF");
+ }
+ else
+ WSREP_DEBUG("infile exception");
+ }
+}
+
+int SR_storage_file::restore( THD *thd )
+{
+ std::ifstream infile;
+ std::string file(dir_ + '/' + "wsrep_SR_info");
+ THD * SRthd = NULL;
+
+ char cluster_uuid_str[37] = {'\0',};
+
+ wsp::auto_lock lock(&LOCK_wsrep_SR_store);
+
+ if (restored_)
+ {
+ return 0;
+ }
+ wsrep_uuid_print(&cluster_uuid_, cluster_uuid_str, 37);
+
+ WSREP_DEBUG("SR pool restore, group %s", cluster_uuid_str);
+
+ /* read SR store info */
+ infile.open(file.c_str(), std::ios::in);
+ if (infile.is_open())
+ {
+ std::string line;
+ getline (infile, line);
+
+ /* this should be cluster uuid */
+ if (line.length() != 36)
+ {
+ WSREP_WARN("Streaming Replication info file is corrupted");
+ restored_ = true;
+ return -1;
+ }
+
+ if (strncmp(cluster_uuid_str, line.c_str(), 36)) {
+ WSREP_WARN("Streaming Replication cluster uuid has changed, \n"
+ "cluster in SR file: %s\n"
+ "current cluster: %s",
+ line.c_str(), cluster_uuid_str);
+ restored_ = true;
+ return -2;
+ }
+
+ trxs_t trxs;
+
+ bool thd_started = false;
+ if (!thd)
+ {
+ SRthd = wsrep_start_SR_THD((char*)&infile);
+ SRthd->wsrep_SR_thd = false;
+ thd_started = true;
+ SRthd->store_globals();
+ }
+ else
+ {
+ SRthd = thd;
+ }
+
+ /* read all fragment files, and filter out committed trxs */
+ while ( getline (infile, line) && strcmp(line.c_str(), "---"))
+ {
+ WSREP_DEBUG("SR file filtering line: %s", line.c_str());
+ read_trxs_from_file(line, &trxs, SRthd, FILTER);
+ }
+ /* read again, and populate pending trxs */
+ infile.seekg(infile.beg);
+ getline (infile, line);
+
+ while ( getline (infile, line) )
+ {
+ WSREP_DEBUG("SR file populating line: %s", line.c_str());
+ read_trxs_from_file(line, &trxs, SRthd, POPULATE);
+ }
+ infile.close();
+ if (thd_started)
+ {
+ wsrep_end_SR_THD(SRthd);
+ }
+ else
+ {
+ thd->store_globals();
+ }
+ }
+
+ restored_ = true;
+ remove(file.c_str());
+ return 0;
+}
+
+void SR_storage_file::close()
+{
+ WSREP_DEBUG("SR_storage_file::close()");
+ wsp::auto_lock lock(&LOCK_wsrep_SR_store);
+
+ /* write store info */
+ std::string file(dir_ + '/' + "wsrep_SR_info");
+ std::ofstream srinfo;
+ char cluster_uuid_str[37] = {'\0',};
+
+ wsrep_uuid_print(&cluster_uuid_, cluster_uuid_str, 37);
+
+ srinfo.open(file.c_str());
+ srinfo << cluster_uuid_str << '\n';
+
+ /* close transactions */
+ std::list<SR_file*>::iterator iterator;
+ for (iterator = files_.begin(); iterator != files_.end();)
+ {
+ std::list<SR_file*>::iterator prev = iterator++;
+ WSREP_DEBUG("Closing streaming replication file: %s",
+ (*prev)->get_name().c_str());
+
+ srinfo << (*prev)->get_name() << '\n';
+ (*prev)->close();
+ }
+ srinfo << "---" << '\n';
+
+ srinfo.close();
+
+ restored_ = false;
+}
diff --git a/sql/wsrep_sr_file.h b/sql/wsrep_sr_file.h
new file mode 100644
index 00000000000..123499cb5a2
--- /dev/null
+++ b/sql/wsrep_sr_file.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2013 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "wsrep_priv.h"
+
+#include "wsrep_sr.h"
+#include "wsrep_thd.h"
+#include <map>
+#include <string>
+#include <list>
+
+class SR_storage;
+class SR_file;
+class Wsrep_schema;
+
+typedef struct node_trx {
+ uint8_t data[24];
+} node_trx_t;
+typedef std::map<node_trx_t, bool> trxs_t;
+
+class SR_storage_file: public SR_storage {
+ enum read_mode {
+ FILTER,
+ POPULATE
+ };
+
+ private:
+
+ //wsrep_uuid_t cluster_uuid_;
+ std::string dir_;
+ size_t size_limit_;
+
+ std::list<SR_file*> files_;
+
+ SR_file *curr_file_;
+
+ int max_file_order();
+ std::string *new_name(int order);
+ SR_file *append_file();
+ void remove_file(SR_file *file);
+
+ void read_trxs_from_file(
+ std::string file,
+ trxs_t *trxs,
+ THD *thd,
+ enum read_mode mode);
+
+ public:
+ SR_storage_file(const char *dir, size_t limit, const char* cluster_uuid_str);
+
+ int init(const char *cluster_uuid_str, Wsrep_schema*);
+
+ THD* append_frag(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len);
+
+ void append_frag_apply(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len)
+ {
+ append_frag(thd, flags, buf, buf_len);
+ }
+
+ void append_frag_commit(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len)
+ {
+ append_frag(thd, flags, buf, buf_len);
+ }
+
+ void update_frag_seqno (THD* thd, THD* orig_THD) {};
+
+ void release_SR_thd(THD* thd) {}
+
+ void remove_trx( THD *thd );
+
+ void remove_trx( wsrep_SR_trx_info *trx ) {
+ remove_trx(trx->get_THD());
+ }
+
+ void rollback_trx( THD *thd );
+
+ void rollback_trx( wsrep_SR_trx_info *trx ) {
+ rollback_trx(trx->get_THD());
+ }
+
+ void trx_done( THD *thd ) { }
+
+ int replay_trx(THD* thd, const wsrep_trx_meta_t&);
+
+ int restore( THD *thd );
+
+ void prepare_for_open_tables(THD *, TABLE_LIST **) { }
+
+ void close();
+};
diff --git a/sql/wsrep_sr_table.cc b/sql/wsrep_sr_table.cc
new file mode 100644
index 00000000000..bbde72fc30c
--- /dev/null
+++ b/sql/wsrep_sr_table.cc
@@ -0,0 +1,223 @@
+/* Copyright (C) 2013 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include <my_global.h>
+#include "my_pthread.h"
+#include "wsrep_priv.h"
+#include "wsrep_sr_table.h"
+#include "wsrep_schema.h"
+
+#include "sql_class.h"
+
+
+SR_storage_table::SR_storage_table()
+ :
+ wsrep_schema_(0)
+{
+}
+
+SR_storage_table::~SR_storage_table()
+{
+}
+
+int SR_storage_table::init(const char* cluster_uuid_str,
+ Wsrep_schema* wsrep_schema)
+{
+ /* Storage tables have been created by Wsrep_schema */
+ wsrep_schema_= wsrep_schema;
+ return 0;
+}
+
+
+THD* SR_storage_table::append_frag(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len)
+{
+ /*
+ During restore phase fragments are read from storage, don't
+ append back.
+ */
+ if (restored_ == false) {
+ return NULL;
+ }
+
+ thd->wsrep_trx_meta.stid.trx = thd->wsrep_ws_handle.trx_id;
+
+ THD* ret = wsrep_schema_->append_frag(thd->wsrep_trx_meta, flags,
+ buf, buf_len);
+ if (!ret) {
+ WSREP_ERROR("Failed to append frag to persistent storage");
+ }
+ else {
+ WSREP_DEBUG("SR_storage_table::append_frag(): thd %lld, seqno %lld, "
+ "trx_id: %ld, thd_ret: %p",
+ thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx, ret);
+ }
+
+ thd->store_globals(); /* Restore original thread context */
+ return ret;
+}
+
+void SR_storage_table::update_frag_seqno(THD* thd, THD* orig_THD)
+{
+ thd->store_globals();
+
+ if (wsrep_schema_->update_frag_seqno(thd, orig_THD->wsrep_trx_meta)) {
+ WSREP_ERROR("Failed to update seqno, must abort");
+ unireg_abort(1);
+ }
+
+ orig_THD->wsrep_SR_fragments.push_back(orig_THD->wsrep_trx_meta);
+ orig_THD->store_globals(); /* Restore original thread context */
+}
+
+void SR_storage_table::release_SR_thd(THD* thd)
+{
+ thd->store_globals();
+ wsrep_schema_->release_SR_thd(thd);
+}
+
+void SR_storage_table::append_frag_apply(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len)
+{
+ /*
+ During restore phase fragments are read from storage, don't
+ append back.
+ */
+ if (restored_ == false) {
+ return;
+ }
+
+ if (wsrep_schema_->append_frag_apply(thd, thd->wsrep_trx_meta, flags,
+ buf, buf_len)) {
+ WSREP_ERROR("Failed to append frag to persistent storage, must abort");
+ unireg_abort(1);
+ }
+
+ thd->store_globals(); /* Restore original thread context */
+}
+
+void SR_storage_table::append_frag_commit(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len)
+{
+ /*
+ During restore phase fragments are read from storage, don't
+ append back.
+ */
+ if (restored_ == false) {
+ return;
+ }
+
+ if (wsrep_schema_->append_frag_commit(thd->wsrep_trx_meta, flags,
+ buf, buf_len)) {
+ WSREP_ERROR("Failed to append frag to persistent storage, must abort");
+ unireg_abort(1);
+ }
+
+ thd->wsrep_SR_fragments.push_back(thd->wsrep_trx_meta);
+ thd->store_globals(); /* Restore original thread context */
+}
+
+void SR_storage_table::remove_trx(THD* thd)
+{
+ WSREP_DEBUG("SR_storage_table::remove_trx(%lld) seqno %lld, trx %ld",
+ thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx);
+ int err= wsrep_schema_->remove_trx(thd, &thd->wsrep_SR_fragments);
+ if (err == -1) {
+ WSREP_DEBUG("SR_storage_table::remove_trx() interrupted");
+ } else if (err) {
+ WSREP_WARN("Failed to delete fragments from persistent storage");
+ }
+}
+
+void SR_storage_table::remove_trx(wsrep_SR_trx_info* trx)
+{
+ remove_trx(trx->get_THD());
+}
+
+void SR_storage_table::rollback_trx(THD* thd)
+{
+ WSREP_DEBUG("SR_storage_table::rollback_trx(%lld) seqno %lld, trx %ld",
+ thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx);
+ int err= wsrep_schema_->rollback_trx(thd);
+ if (err == -1) {
+ WSREP_DEBUG("SR_storage_table::rollback_trx() interrupted");
+ } else if (err) {
+ WSREP_WARN("Failed to delete fragments from persistent storage");
+ }
+ thd->store_globals(); /* Restore original thread context */
+}
+
+void SR_storage_table::rollback_trx(wsrep_SR_trx_info* trx)
+{
+ rollback_trx(trx->get_THD());
+}
+
+void SR_storage_table::trx_done(THD* thd)
+{
+ if (thd->wsrep_conflict_state() != MUST_REPLAY)
+ thd->wsrep_SR_fragments.clear();
+}
+
+int SR_storage_table::replay_trx(THD* thd, const wsrep_trx_meta_t& meta)
+{
+ return wsrep_schema_->replay_trx(thd, meta);
+}
+
+int SR_storage_table::restore(THD* thd)
+{
+ if (restored_ == true) {
+ WSREP_DEBUG("SR_storage_table::restore: Already restored");
+ return 0;
+ }
+
+ WSREP_INFO("SR_storage_table::restore");
+ int ret= wsrep_schema_->restore_frags();
+ if (thd) {
+ thd->store_globals();
+ }
+ else {
+ my_pthread_setspecific_ptr(THR_THD, NULL);
+ }
+ restored_= true;
+ return ret;
+}
+
+void SR_storage_table::prepare_for_open_tables(THD *thd, TABLE_LIST **table_list)
+{
+ wsrep_schema_->init_SR_table(&thd->wsrep_SR_table);
+ TABLE_LIST *ptr= *table_list;
+ if (!ptr)
+ {
+ *table_list= &thd->wsrep_SR_table;
+ }
+ else
+ {
+ while (ptr->next_global) ptr = ptr->next_global;
+ ptr->next_global = &thd->wsrep_SR_table;
+ }
+}
+
+void SR_storage_table::close()
+{
+}
diff --git a/sql/wsrep_sr_table.h b/sql/wsrep_sr_table.h
new file mode 100644
index 00000000000..9cc36f21854
--- /dev/null
+++ b/sql/wsrep_sr_table.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 2013 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#include "wsrep_sr.h"
+
+class Wsrep_schema;
+
+class SR_storage_table : public SR_storage
+{
+ public:
+ SR_storage_table();
+ ~SR_storage_table();
+ int init(const char *cluster_uuid_str, Wsrep_schema*);
+
+ THD* append_frag(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len);
+
+ void update_frag_seqno(THD* thd, THD* orig_THD);
+
+ void release_SR_thd(THD* thd);
+
+ void append_frag_apply(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len);
+
+ void append_frag_commit(THD* thd,
+ uint32_t flags,
+ const uchar* buf,
+ size_t buf_len);
+
+ void remove_trx( THD *thd );
+
+ void remove_trx( wsrep_SR_trx_info *trx );
+
+ void rollback_trx( THD *thd );
+
+ void rollback_trx( wsrep_SR_trx_info *trx );
+
+ void trx_done( THD *thd );
+
+ int replay_trx(THD* thd, const wsrep_trx_meta_t& meta);
+
+ int restore( THD *thd );
+
+ void prepare_for_open_tables(THD *thd, TABLE_LIST **table_list);
+
+ void close();
+
+ private:
+ Wsrep_schema* wsrep_schema_;
+};
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index d5b0344c456..fff7e747f9b 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -1,4 +1,4 @@
-/* Copyright 2008-2015 Codership Oy <http://www.codership.com>
+/* Copyright 2008-2017 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,9 +28,10 @@
#include "wsrep_xid.h"
#include <cstdio>
#include <cstdlib>
-
#include <my_service_manager.h>
+const char wsrep_defaults_group_suffix[256] = {0};
+
static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 +
sizeof(WSREP_SST_OPT_CONF) +
sizeof(WSREP_SST_OPT_CONF_SUFFIX) +
@@ -271,7 +272,8 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid,
true Error
*/
-bool wsrep_sst_received (wsrep_t* const wsrep,
+void wsrep_sst_received (THD* thd,
+ wsrep_t* const wsrep,
const wsrep_uuid_t& uuid,
const wsrep_seqno_t seqno,
const void* const state,
@@ -284,81 +286,68 @@ bool wsrep_sst_received (wsrep_t* const wsrep,
OK from wsrep provider. By doing so, the values remain consistent across
the server & wsrep provider.
*/
- bool do_update= false;
-
- // Get the locally stored uuid:seqno.
- if (wsrep_get_SE_checkpoint(local_uuid, local_seqno))
- {
- return true;
- }
+ /*
+ TODO: Handle backwards compatibility. WSREP API v25 does not have
+ wsrep schema.
+ */
+ /*
+ If thd is non-NULL, this thread is holding LOCK_global_system_variables.
+ It needs to be released temporarily since wsrep_init_schema()
+ does THD pool initialization, which will lock this lock in
+ THD allocation.
+ */
+ //if (thd) mysql_mutex_unlock(&LOCK_global_system_variables);
+ wsrep_init_schema();
+ /*
+ Logical SST methods (mysqldump etc) don't update InnoDB sys header.
+ Reset the SE checkpoint before recovering view in order to avoid
+ sanity check failure.
+ */
+ if (!wsrep_before_SE()) {
+ wsrep_seqno_t se_seqno= -1;
+ wsrep_uuid_t se_uuid= WSREP_UUID_UNDEFINED;
+ wsrep_set_SE_checkpoint(se_uuid, se_seqno);
+ wsrep_set_SE_checkpoint(uuid, seqno);
+ }
+ wsrep_verify_SE_checkpoint(uuid, seqno);
+ wsrep_init_SR();
+ //if (thd) mysql_mutex_lock(&LOCK_global_system_variables);
- if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) ||
- local_seqno < seqno)
- {
- do_update= true;
- }
- else if (local_seqno > seqno)
- {
- WSREP_WARN("SST position can't be set in past. Requested: %lld, Current: "
- " %lld.", (long long)seqno, (long long)local_seqno);
/*
- If we are here because of SET command, simply return true (error) instead of
- aborting.
+ Both wsrep_init_SR() and wsrep_recover_view() may use
+ wsrep thread pool. Restore original thd context before returning.
*/
- if (implicit)
- {
- WSREP_WARN("Can't continue.");
- unireg_abort(1);
+ if (thd) {
+ thd->store_globals();
}
- else
- {
- return true;
+ else {
+ my_pthread_setspecific_ptr(THR_THD, NULL);
}
- }
#ifdef GTID_SUPPORT
wsrep_init_sidno(uuid);
#endif /* GTID_SUPPORT */
- if (wsrep)
- {
- int const rcode(seqno < 0 ? seqno : 0);
- wsrep_gtid_t const state_id= {uuid,
- (rcode ? WSREP_SEQNO_UNDEFINED : seqno)};
-
- wsrep_status_t ret= wsrep->sst_received(wsrep, &state_id, state,
- state_len, rcode);
-
- if (ret != WSREP_OK)
+ if (wsrep)
{
- return true;
- }
- }
+ int const rcode(seqno < 0 ? seqno : 0);
+ wsrep_gtid_t const state_id = {
+ uuid, (rcode ? WSREP_SEQNO_UNDEFINED : seqno)
+ };
- // Now is the good time to update the local state and checkpoint.
- if (do_update)
- {
- if (wsrep_set_SE_checkpoint(uuid, seqno))
- {
- return true;
+ wsrep_buf_t const st= { state, state_len };
+ wsrep->sst_received(wsrep, &state_id, &st, rcode);
}
-
- local_uuid= uuid;
- local_seqno= seqno;
- }
-
- return false;
}
// Let applier threads to continue
-bool wsrep_sst_continue ()
+void wsrep_sst_continue ()
{
if (sst_needed)
{
WSREP_INFO("Signalling provider to continue.");
- return wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0, true);
+ wsrep_sst_received (0, wsrep, local_uuid, local_seqno, NULL, 0, true);
}
- return false;
}
struct sst_thread_arg
@@ -719,7 +708,12 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in,
return ret;
}
-static bool SE_initialized = false;
+static enum
+{
+ WSREP_SE_UNINITIALIZED,
+ WSREP_SE_INITIALIZED,
+ WSREP_SE_INIT_ERROR
+} SE_init_status;
ssize_t wsrep_sst_prepare (void** msg)
{
@@ -733,7 +727,7 @@ ssize_t wsrep_sst_prepare (void** msg)
if (!msg)
{
WSREP_ERROR("Could not allocate %zd bytes for state request", ret);
- unireg_abort(1);
+ ret= -ENOMEM;
}
return ret;
}
@@ -760,7 +754,7 @@ ssize_t wsrep_sst_prepare (void** msg)
{
WSREP_ERROR("Could not parse wsrep_node_address : %s",
wsrep_node_address);
- unireg_abort(1);
+ return -ENXIO; /* No such device or address */
}
memcpy(ip_buf, addr.get_address(), addr.get_address_len());
addr_in= ip_buf;
@@ -786,12 +780,17 @@ ssize_t wsrep_sst_prepare (void** msg)
if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP))
{
addr_len= sst_prepare_mysqldump (addr_in, &addr_out);
- if (addr_len < 0) unireg_abort(1);
+ if (addr_len < 0)
+ {
+ WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.",
+ wsrep_sst_method);
+ return addr_len;
+ }
}
else
{
/*! A heuristic workaround until we learn how to stop and start engines */
- if (SE_initialized)
+ if (SE_init_status == WSREP_SE_INITIALIZED)
{
// we already did SST at initializaiton, now engines are running
// sql_print_information() is here because the message is too long
@@ -813,12 +812,12 @@ ssize_t wsrep_sst_prepare (void** msg)
{
WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.",
wsrep_sst_method);
- unireg_abort(1);
+ return addr_len;
}
}
size_t const method_len(strlen(wsrep_sst_method));
- size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/);
+ size_t msg_len (method_len + addr_len + 2 /* + auth_len + 1*/);
*msg = malloc (msg_len);
if (NULL != *msg) {
@@ -832,7 +831,8 @@ ssize_t wsrep_sst_prepare (void** msg)
else {
WSREP_ERROR("Failed to allocate SST request of size %zu. Can't continue.",
msg_len);
- unireg_abort(1);
+ msg_len= -ENOMEM;
+
}
if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out);
@@ -903,6 +903,11 @@ static int sst_donate_mysqldump (const char* addr,
return -ENOMEM;
}
+ /*
+ we enable new client connections so that mysqldump donation can connect in,
+ but we reject local connections from modifyingcdata during SST, to keep
+ data intact
+ */
if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE);
make_wsrep_defaults_file();
@@ -935,7 +940,6 @@ static int sst_donate_mysqldump (const char* addr,
wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)};
wsrep->sst_sent (wsrep, &state_id, ret);
-
return ret;
}
@@ -1312,18 +1316,20 @@ static int sst_donate_other (const char* method,
return arg.err;
}
-wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
- const void* msg, size_t msg_len,
- const wsrep_gtid_t* current_gtid,
- const char* state, size_t state_len,
- bool bypass)
+wsrep_cb_status_t wsrep_sst_donate_cb (void* const app_ctx,
+ void* const recv_ctx,
+ const wsrep_buf_t* const msg,
+ const wsrep_gtid_t* const current_gtid,
+ const wsrep_buf_t* const state,
+ bool const bypass)
{
/* This will be reset when sync callback is called.
* Should we set wsrep_ready to FALSE here too? */
wsrep_config_state->set(WSREP_MEMBER_DONOR);
+ local_status.set(WSREP_MEMBER_DONOR);
- const char* method = (char*)msg;
+ const char* method = (char*)msg->ptr;
size_t method_len = strlen (method);
const char* data = method + method_len + 1;
@@ -1363,16 +1369,16 @@ void wsrep_SE_init_grab()
if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort();
}
-void wsrep_SE_init_wait()
+int wsrep_SE_init_wait()
{
struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
uint32 total_wtime=0;
- while (SE_initialized == false)
+ while (SE_init_status == WSREP_SE_UNINITIALIZED)
{
mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime);
- if (!SE_initialized)
+ if (SE_init_status == WSREP_SE_UNINITIALIZED)
{
total_wtime += wtime.tv_sec;
WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
@@ -1382,6 +1388,7 @@ void wsrep_SE_init_wait()
}
mysql_mutex_unlock (&LOCK_wsrep_sst_init);
+ return !(SE_init_status == WSREP_SE_INITIALIZED);
}
void wsrep_SE_init_done()
@@ -1392,5 +1399,15 @@ void wsrep_SE_init_done()
void wsrep_SE_initialized()
{
- SE_initialized = true;
+ SE_init_status= WSREP_SE_INITIALIZED;
}
+
+void wsrep_SE_init_failed()
+{
+ mysql_mutex_lock(&LOCK_wsrep_sst_init);
+ SE_init_status= WSREP_SE_INIT_ERROR;
+ mysql_cond_signal(&COND_wsrep_sst_init);
+ mysql_mutex_unlock(&LOCK_wsrep_sst_init);
+}
+
+
diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h
index 8bf6dc31464..aa3bcb65545 100644
--- a/sql/wsrep_sst.h
+++ b/sql/wsrep_sst.h
@@ -64,14 +64,20 @@ extern void wsrep_sst_grab();
/*! Init thread waits for SST completion */
extern bool wsrep_sst_wait();
/*! Signals wsrep that initialization is complete, writesets can be applied */
-extern bool wsrep_sst_continue();
+extern void wsrep_sst_continue();
extern void wsrep_sst_auth_init();
extern void wsrep_sst_auth_free();
extern void wsrep_SE_init_grab(); /*! grab init critical section */
-extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */
+/*!
+ wait for SE init to complete
+
+ Return zero on success, non-zero on error
+*/
+extern int wsrep_SE_init_wait();
extern void wsrep_SE_init_done(); /*! signal that SE init is complte */
extern void wsrep_SE_initialized(); /*! mark SE initialization complete */
+extern void wsrep_SE_init_failed(); /*! mark SE initialization failed */
#else
#define wsrep_SE_initialized() do { } while(0)
diff --git a/sql/wsrep_tc.h b/sql/wsrep_tc.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sql/wsrep_tc.h
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index ce6d9688cb3..489613d0c6c 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -22,12 +22,19 @@
//#include "global_threads.h" // LOCK_thread_count, etc.
#include "sql_base.h" // close_thread_tables()
#include "mysqld.h" // start_wsrep_THD();
-
+#include "wsrep_applier.h" // start_wsrep_THD();
+#include "wsrep_sr.h" // wsrep_abort_SR_THD();
+#include "mysql/service_wsrep.h" // wsrep_thd_awake();
#include "slave.h" // opt_log_slave_updates
#include "rpl_filter.h"
#include "rpl_rli.h"
#include "rpl_mi.h"
+#include "debug_sync.h"
+
+static Wsrep_thd_queue* wsrep_rollback_queue = 0;
+static Wsrep_thd_queue* wsrep_post_rollback_queue = 0;
+
#if (__LP64__)
static volatile int64 wsrep_bf_aborts_counter(0);
#define WSREP_ATOMIC_LOAD_LONG my_atomic_load64
@@ -46,31 +53,164 @@ int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff,
var->value = (char*)&wsrep_local_bf_aborts;
return 0;
}
+void wsrep_cleanup_transaction(THD *thd)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ DBUG_ENTER("wsrep_cleanup_transaction");
+ if (thd->wsrep_exec_mode == REPL_RECV) return;
+
+ DBUG_ASSERT(thd->wsrep_conflict_state() != MUST_REPLAY);
+ DBUG_ASSERT(thd->wsrep_SR_fragments.empty());
+
+ if (wsrep_SR_store) wsrep_SR_store->trx_done(thd);
+ if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd);
+
+ wsrep_reset_SR_trans(thd);
+ thd->wsrep_exec_mode= LOCAL_STATE;
+ if (thd->wsrep_conflict_state() != NO_CONFLICT)
+ {
+ /*
+ Catch half finished rollbacks.
+ */
+ DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED ||
+ thd->wsrep_conflict_state() == CERT_FAILURE);
+
+ thd->killed= NOT_KILLED;
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ }
+
+ if (MUST_REPLAY != thd->wsrep_conflict_state())
+ {
+ thd->wsrep_PA_safe= true;
+ thd->wsrep_ws_handle.trx_id= WSREP_UNDEFINED_TRX_ID;
+ thd->set_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID);
+
+ if (thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED)
+ {
+ thd->wsrep_last_written_gtid= thd->wsrep_trx_meta.gtid;
+ }
+ thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
+ thd->wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED;
+ thd->wsrep_affected_rows= 0;
+ thd->wsrep_skip_wsrep_GTID= false;
+ thd->wsrep_xid.null();
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Run post rollback actions.
-/* must have (&thd->LOCK_thd_data) */
-void wsrep_client_rollback(THD *thd)
+ Assert thd->LOCK_wsrep_thd ownership
+ */
+void wsrep_post_rollback(THD *thd)
{
- WSREP_DEBUG("client rollback due to BF abort for (%lld), query: %s",
- (longlong) thd->thread_id, thd->query());
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
- WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1);
+ WSREP_LOG_THD(thd, NULL);
+
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || /* voluntary */
+ thd->wsrep_conflict_state() == ABORTING); /* BF abort or cert failure */
- thd->wsrep_conflict_state= ABORTING;
mysql_mutex_unlock(&thd->LOCK_thd_data);
- trans_rollback(thd);
+
+ if (thd->wsrep_trx_has_seqno())
+ {
+ if (!wsrep_gtid_mode)
+ {
+ void* ptr= NULL;
+ size_t len= 0;
+ wsrep_buf_t err= {ptr, len};
+ if (wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta))
+ {
+ WSREP_WARN("wsrep_post_rollback: failed to enter commit order");
+ }
+ if (wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, &err))
+ {
+ WSREP_WARN("wsrep_post_rollback: failed to leave commit order");
+ }
+ }
+ /*
+ If binlogging is on commit ordering is done when dummy
+ event is written into binlog
+ */
+ else if (wsrep_write_dummy_event(thd, "rollback"))
+ {
+ WSREP_WARN("wsrep_post_rollback: failed to write dummy event");
+ }
+ }
+
+ if (wsrep->release(wsrep, &thd->wsrep_ws_handle))
+ {
+ WSREP_WARN("wsrep::release fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == ABORTING);
+
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
+ {
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ thd->set_wsrep_conflict_state(ABORTING);
+ thd->set_wsrep_conflict_state(ABORTED);
+ }
+ else
+ {
+ thd->set_wsrep_conflict_state(ABORTED);
+ }
+}
+
+/*
+ must have (&thd->LOCK_wsrep_thd)
+ thd->wsrep_conflict_state must be MUST_ABORT
+*/
+void wsrep_client_rollback(THD *thd, bool rollbacker)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT ||
+ thd->wsrep_conflict_state() == CERT_FAILURE);
+ WSREP_DEBUG("client rollback due to BF abort for (%lld %lld), query: %s",
+ thd->thread_id, thd->query_id, WSREP_QUERY(thd));
+
+ my_atomic_add64(&wsrep_bf_aborts_counter, 1);
+
+ /*
+ Rollback proccess should be fired only for threads which are not
+ in the process of committing.
+ */
+ DBUG_ASSERT(thd->wsrep_query_state() != QUERY_COMMITTING);
+ if (rollbacker)
+ {
+ DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED);
+ }
+
+ thd->set_wsrep_conflict_state(ABORTING);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ if (thd->wsrep_is_streaming())
+ {
+ WSREP_DEBUG("wsrep_client_rollback: thd: %lld fragments %zu",
+ thd->thread_id, thd->wsrep_SR_fragments.size());
+ wsrep_SR_store->rollback_trx(thd);
+ thd->wsrep_SR_fragments.clear();
+ }
if (thd->locked_tables_mode && thd->lock)
{
- WSREP_DEBUG("unlocking tables for BF abort (%lld)",
- (longlong) thd->thread_id);
+ WSREP_DEBUG("unlocking tables for BF abort (%lld)", thd->thread_id);
thd->locked_tables_list.unlock_locked_tables(thd);
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
}
if (thd->global_read_lock.is_acquired())
{
- WSREP_DEBUG("unlocking GRL for BF abort (%lld)",
- (longlong) thd->thread_id);
+ WSREP_DEBUG("unlocking GRL for BF abort (%lld)", thd->thread_id);
thd->global_read_lock.unlock_global_read_lock(thd);
}
@@ -82,16 +222,50 @@ void wsrep_client_rollback(THD *thd)
if (thd->get_binlog_table_maps())
{
- WSREP_DEBUG("clearing binlog table map for BF abort (%lld)",
- (longlong) thd->thread_id);
+ WSREP_DEBUG("clearing binlog table map for BF abort (%lld)", thd->thread_id);
thd->clear_binlog_table_maps();
}
- mysql_mutex_lock(&thd->LOCK_thd_data);
- thd->wsrep_conflict_state= ABORTED;
+
+ /*
+ trans_rolback() must be called after all locks are released since it
+ calls ha_rollback_trans() which acquires TO
+ */
+ if (trans_rollback(thd))
+ {
+ WSREP_WARN("client rollback failed for: %lld %lld, conf: %d",
+ thd->thread_id, thd->query_id,
+ thd->wsrep_conflict_state_unsafe());
+ }
+
+ if (rollbacker && thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED)
+ {
+ /*
+ Thd has been assigned seqno and it needs to release provider
+ resoureces. Do it in separate thread to avoid deadlocks.
+ */
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_ROLLBACK);
+ if (wsrep_post_rollback_queue->push_back(thd))
+ {
+ WSREP_WARN("duplicate thd %llu for post-rollbacker",
+ wsrep_thd_thread_id(thd));
+ }
+ }
+
+ /*
+ If the seqno is not set there is no need for post rollback
+ actions.
+ */
+ if (rollbacker /* && wsrep_thd_trx_seqno(thd) == WSREP_SEQNO_UNDEFINED */)
+ {
+ wsrep_post_rollback(thd);
+ }
+
+ return;
}
#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1
#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2
+//#include "rpl_info_factory.h"
static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
{
@@ -135,7 +309,7 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
return rgi;
}
-static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow)
+void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow)
{
shadow->options = thd->variables.option_bits;
shadow->server_status = thd->server_status;
@@ -164,14 +338,16 @@ static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow)
thd->variables.tx_isolation = ISO_READ_COMMITTED;
thd->tx_isolation = ISO_READ_COMMITTED;
- shadow->db = thd->db.str;
+ shadow->db = (char*)thd->db.str;
shadow->db_length = thd->db.length;
shadow->user_time = thd->user_time;
shadow->row_count_func= thd->get_row_count_func();
+ shadow->user_time = thd->user_time;
+
thd->reset_db(&null_clex_str);
}
-static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow)
+void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow)
{
LEX_CSTRING db= {shadow->db, shadow->db_length };
thd->variables.option_bits = shadow->options;
@@ -179,6 +355,7 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow)
thd->wsrep_exec_mode = shadow->wsrep_exec_mode;
thd->net.vio = shadow->vio;
thd->variables.tx_isolation = shadow->tx_isolation;
+ thd->set_row_count_func(shadow->row_count_func);
thd->user_time = shadow->user_time;
thd->reset_db(&db);
@@ -195,9 +372,10 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow)
void wsrep_replay_transaction(THD *thd)
{
DBUG_ENTER("wsrep_replay_transaction");
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
/* checking if BF trx must be replayed */
- if (thd->wsrep_conflict_state== MUST_REPLAY) {
- DBUG_ASSERT(wsrep_thd_trx_seqno(thd));
+ if (thd->wsrep_conflict_state() == MUST_REPLAY) {
+ DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
if (thd->wsrep_exec_mode!= REPL_RECV) {
if (thd->get_stmt_da()->is_sent())
{
@@ -231,7 +409,7 @@ void wsrep_replay_transaction(THD *thd)
thd->get_stmt_da()->reset_diagnostics_area();
- thd->wsrep_conflict_state= REPLAYING;
+ thd->set_wsrep_conflict_state(REPLAYING);
mysql_mutex_unlock(&thd->LOCK_thd_data);
thd->reset_for_next_command();
@@ -269,16 +447,22 @@ void wsrep_replay_transaction(THD *thd)
(void *)thd);
wsrep_return_from_bf_mode(thd, &shadow);
- if (thd->wsrep_conflict_state!= REPLAYING)
- WSREP_WARN("lost replaying mode: %d", thd->wsrep_conflict_state );
+
+ WSREP_DEBUG("replayed %lld, seqno %lld, rcode %d",
+ thd->thread_id, (long long)wsrep_thd_trx_seqno(thd), rcode);
+ DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
mysql_mutex_lock(&thd->LOCK_thd_data);
+ if (thd->wsrep_conflict_state() != REPLAYING)
+ WSREP_WARN("lost replaying mode: %d", thd->wsrep_conflict_state());
+
switch (rcode)
{
case WSREP_OK:
- thd->wsrep_conflict_state= NO_CONFLICT;
- wsrep->post_commit(wsrep, &thd->wsrep_ws_handle);
+ thd->killed= NOT_KILLED;
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ wsrep->release(wsrep, &thd->wsrep_ws_handle);
WSREP_DEBUG("trx_replay successful for: %lld %lld",
(longlong) thd->thread_id, (longlong) thd->real_id);
if (thd->get_stmt_da()->is_sent())
@@ -317,19 +501,32 @@ void wsrep_replay_transaction(THD *thd)
else
{
WSREP_DEBUG("replay failed, rolling back");
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
}
- thd->wsrep_conflict_state= ABORTED;
- wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle);
+ WSREP_DEBUG("Setting thd to ABORTING, thd %lld conf %d",
+ thd->thread_id, thd->wsrep_conflict_state());
+ if (thd->wsrep_conflict_state() != CERT_FAILURE)
+ thd->set_wsrep_conflict_state(ABORTING);
+ /* We returned out ouf order, trx is rolled back,
+ * no locks should remain. Need to do the total order part */
+ DBUG_ASSERT(LOCAL_ROLLBACK != thd->wsrep_exec_mode);
+ thd->wsrep_exec_mode= LOCAL_ROLLBACK;
+ WSREP_DEBUG("replay_transaction(%lld) assigned LOCAL_ROLLBACK to "
+ "seqno %lld, conf %d",
+ thd->thread_id, (long long)wsrep_thd_trx_seqno(thd),
+ thd->wsrep_conflict_state());
+ wsrep_post_rollback(thd);
+
break;
default:
WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s",
rcode, thd->get_db(),
thd->query() ? thd->query() : "void");
+ DBUG_ASSERT(0);
/* we're now in inconsistent state, must abort */
/* http://bazaar.launchpad.net/~codership/codership-mysql/5.6/revision/3962#sql/wsrep_thd.cc */
mysql_mutex_unlock(&thd->LOCK_thd_data);
-
unireg_abort(1);
break;
}
@@ -347,7 +544,8 @@ void wsrep_replay_transaction(THD *thd)
DBUG_VOID_RETURN;
}
-static void wsrep_replication_process(THD *thd)
+static void wsrep_replication_process(THD *thd,
+ void* arg __attribute__((unused)))
{
int rcode;
DBUG_ENTER("wsrep_replication_process");
@@ -362,7 +560,8 @@ static void wsrep_replication_process(THD *thd)
rcode = wsrep->recv(wsrep, (void *)thd);
DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode));
- WSREP_INFO("applier thread exiting (code:%d)", rcode);
+ WSREP_INFO("applier thread %lld exiting (code:%d)",
+ thd->thread_id, rcode);
switch (rcode) {
case WSREP_OK:
@@ -414,13 +613,14 @@ static void wsrep_replication_process(THD *thd)
DBUG_VOID_RETURN;
}
-static bool create_wsrep_THD(wsrep_thd_processor_fun processor)
+static bool create_wsrep_THD(Wsrep_thd_args* args)
{
ulong old_wsrep_running_threads= wsrep_running_threads;
pthread_t unused;
mysql_mutex_lock(&LOCK_thread_count);
+
bool res= pthread_create(&unused, &connection_attrib, start_wsrep_THD,
- (void*)processor);
+ args);
/*
if starting a thread on server startup, wait until the this thread's THD
is fully initialized (otherwise a THD initialization code might
@@ -449,21 +649,30 @@ void wsrep_create_appliers(long threads)
}
long wsrep_threads=0;
- while (wsrep_threads++ < threads) {
- if (create_wsrep_THD(wsrep_replication_process))
+
+ while (wsrep_threads++ < threads)
+ {
+ Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_replication_process, 0));
+ if (create_wsrep_THD(args))
+ {
WSREP_WARN("Can't create thread to manage wsrep replication");
+ }
}
}
-static void wsrep_rollback_process(THD *thd)
+static void wsrep_rollback_process(THD *rollbacker,
+ void *arg __attribute__((unused)))
{
DBUG_ENTER("wsrep_rollback_process");
- mysql_mutex_lock(&LOCK_wsrep_rollback);
- wsrep_aborting_thd= NULL;
+ THD* thd= NULL;
+ wsrep_rollback_queue= new Wsrep_thd_queue(rollbacker);
- while (thd->killed == NOT_KILLED) {
- thd_proc_info(thd, "WSREP aborter idle");
+ thd_proc_info(rollbacker, "wsrep aborter idle");
+ while ((thd= wsrep_rollback_queue->pop_front()) != NULL)
+ {
+#ifdef OLD_MARIADB
+ thd_proc_info(thd, "wsrep aborter idle");
thd->mysys_var->current_mutex= &LOCK_wsrep_rollback;
thd->mysys_var->current_cond= &COND_wsrep_rollback;
@@ -496,52 +705,140 @@ static void wsrep_rollback_process(THD *thd)
mysql_mutex_unlock(&LOCK_wsrep_rollback);
mysql_mutex_lock(&aborting->LOCK_thd_data);
- if (aborting->wsrep_conflict_state== ABORTED)
+ if (aborting->wsrep_conflict_state()== ABORTED)
{
WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d",
(long long)aborting->real_id,
- aborting->wsrep_conflict_state);
+ aborting->wsrep_conflict_state());
mysql_mutex_unlock(&aborting->LOCK_thd_data);
mysql_mutex_lock(&LOCK_wsrep_rollback);
continue;
}
- aborting->wsrep_conflict_state= ABORTING;
mysql_mutex_unlock(&aborting->LOCK_thd_data);
set_current_thd(aborting);
aborting->store_globals();
- mysql_mutex_lock(&aborting->LOCK_thd_data);
- wsrep_client_rollback(aborting);
- WSREP_DEBUG("WSREP rollbacker aborted thd: (%lld %lld)",
- (longlong) aborting->thread_id,
- (longlong) aborting->real_id);
- mysql_mutex_unlock(&aborting->LOCK_thd_data);
+ if (wsrep_thd_is_SR(aborting))
+ {
+ WSREP_DEBUG("WSREP rollbacker aborting SR thd: (%lld %llu)",
+ aborting->thread_id, (long long)aborting->real_id);
+ wsrep_abort_SR_THD(thd, aborting);
+ }
+ else
+ {
+ mysql_mutex_lock(&aborting->LOCK_wsrep_thd);
+
+ /* prepare THD for rollback processing */
+ aborting->reset_for_next_command();
+ aborting->lex->sql_command= SQLCOM_ROLLBACK;
- set_current_thd(thd);
- thd->store_globals();
+ wsrep_client_rollback(aborting, true);
+ mysql_mutex_unlock(&aborting->LOCK_wsrep_thd);
+ WSREP_DEBUG("WSREP rollbacker aborted thd: (%lld %llu)",
+ aborting->thread_id, (long long)aborting->real_id);
+ }
mysql_mutex_lock(&LOCK_wsrep_rollback);
}
+#else
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() == ABORTED)
+ {
+ WSREP_DEBUG("rollbacker thd already aborted: %llu state: %d",
+ (long long)thd->real_id,
+ thd->wsrep_conflict_state());
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ continue;
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ thd_proc_info(rollbacker, "wsrep aborter active");
+
+ thd->store_globals();
+ if (wsrep_thd_is_SR(thd))
+ {
+ WSREP_DEBUG("rollbacker aborting SR thd: (%lld %llu)",
+ thd->thread_id, (long long)thd->real_id);
+ wsrep_abort_SR_THD(rollbacker, thd);
+ }
+ else
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+
+ /* prepare THD for rollback processing */
+ thd->reset_for_next_command();
+ thd->lex->sql_command= SQLCOM_ROLLBACK;
+
+ wsrep_client_rollback(thd, true);
+ thd->reset_globals();
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ WSREP_DEBUG("rollbacker aborted thd: (%lld %llu)",
+ thd->thread_id, (long long)thd->real_id);
+ }
+
+ thd_proc_info(rollbacker, "wsrep aborter idle");
+#endif
}
+
+ delete wsrep_rollback_queue;
+ wsrep_rollback_queue= NULL;
- mysql_mutex_unlock(&LOCK_wsrep_rollback);
sql_print_information("WSREP: rollbacker thread exiting");
+ DBUG_ASSERT(rollbacker->killed != NOT_KILLED);
DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting"));
DBUG_VOID_RETURN;
}
+static void wsrep_post_rollback_process(THD *post_rollbacker,
+ void *arg __attribute__((unused)))
+{
+ DBUG_ENTER("wsrep_post_rollback_process");
+ THD* thd= NULL;
+ wsrep_post_rollback_queue= new Wsrep_thd_queue(post_rollbacker);
+
+ while ((thd= wsrep_post_rollback_queue->pop_front()) != NULL)
+ {
+ thd->store_globals();
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTING);
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_ROLLBACK);
+ WSREP_DEBUG("post rollbacker calling post rollback for thd %lld, conf %s",
+ thd->thread_id, wsrep_thd_conflict_state_str(thd));
+
+ wsrep_post_rollback(thd);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+
+ delete wsrep_post_rollback_queue;
+ wsrep_post_rollback_queue= NULL;
+
+ DBUG_ASSERT(post_rollbacker->killed != NOT_KILLED);
+ DBUG_PRINT("wsrep",("wsrep post rollbacker thread exiting"));
+ DBUG_VOID_RETURN;
+}
+
void wsrep_create_rollbacker()
{
if (wsrep_provider && strcasecmp(wsrep_provider, "none"))
{
+ Wsrep_thd_args* args= new Wsrep_thd_args(wsrep_rollback_process, 0);
+
/* create rollbacker */
- if (create_wsrep_THD(wsrep_rollback_process))
+ if (create_wsrep_THD(args))
WSREP_WARN("Can't create thread to manage wsrep rollback");
- }
+
+ /* create post_rollbacker */
+ args= new Wsrep_thd_args(wsrep_post_rollback_process, 0);
+ if (create_wsrep_THD(args))
+ WSREP_WARN("Can't create thread to manage wsrep post rollback");
+ }
}
void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe)
@@ -560,7 +857,7 @@ enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd, my_bool sync)
{
if (sync) mysql_mutex_lock(&thd->LOCK_thd_data);
- state = thd->wsrep_conflict_state;
+ state = thd->wsrep_conflict_state();
if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data);
}
return state;
@@ -576,11 +873,13 @@ my_bool wsrep_thd_is_wsrep(THD *thd)
return status;
}
-my_bool wsrep_thd_is_BF(THD *thd, my_bool sync)
+//my_bool wsrep_thd_is_BF(THD *thd, my_bool sync)
+my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
{
my_bool status = FALSE;
- if (thd)
+ if (thd_ptr)
{
+ THD* thd = (THD*)thd_ptr;
// THD can be BF only if provider exists
if (wsrep_thd_is_wsrep(thd))
{
@@ -596,6 +895,21 @@ my_bool wsrep_thd_is_BF(THD *thd, my_bool sync)
return status;
}
+my_bool wsrep_thd_is_SR(void *thd_ptr)
+{
+ if (thd_ptr)
+ {
+ THD* thd = (THD*)thd_ptr;
+ return (thd->wsrep_SR_thd);
+ }
+ return false;
+}
+
+my_bool wsrep_thd_skip_locking(void *thd)
+{
+ return thd != NULL && ((THD*)thd)->wsrep_skip_locking;
+}
+
extern "C"
my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync)
{
@@ -613,7 +927,6 @@ my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync)
return status;
}
-extern "C"
my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
@@ -628,41 +941,66 @@ my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync)
return status;
}
+/*
+ Start async rollback process
+
+ Asserts thd->LOCK_wsrep_thd ownership
+ */
+void wsrep_fire_rollbacker(THD *thd)
+{
+
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT);
+
+ DBUG_PRINT("wsrep",("enqueuing trx abort for %llu", wsrep_thd_thread_id(thd)));
+ WSREP_DEBUG("enqueuing trx abort for (%llu)", wsrep_thd_thread_id(thd));
+
+ if (wsrep_rollback_queue->push_back(thd))
+ {
+ WSREP_WARN("duplicate thd %llu for rollbacker",
+ wsrep_thd_thread_id(thd));
+ }
+}
+
+
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal)
{
THD *victim_thd = (THD *) victim_thd_ptr;
THD *bf_thd = (THD *) bf_thd_ptr;
DBUG_ENTER("wsrep_abort_thd");
+ mysql_mutex_lock(&victim_thd->LOCK_wsrep_thd);
if ( (WSREP(bf_thd) ||
( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) &&
bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) &&
- victim_thd)
+ victim_thd &&
+ !victim_thd->wsrep_is_rolling_back())
{
- if ((victim_thd->wsrep_conflict_state == MUST_ABORT) ||
- (victim_thd->wsrep_conflict_state == ABORTED) ||
- (victim_thd->wsrep_conflict_state == ABORTING))
+ if (wsrep_thd_is_SR(victim_thd))
+ {
+ victim_thd->set_wsrep_conflict_state(MUST_ABORT);
+ wsrep_fire_rollbacker(victim_thd);
+ {
+ WSREP_INFO("rollbacker fired for aborting SR transaction");
+ }
+ }
+ else
{
- WSREP_DEBUG("wsrep_abort_thd called by %llu with victim %llu already "
- "aborted. Ignoring.",
- (bf_thd) ? (long long)bf_thd->real_id : 0,
- (long long)victim_thd->real_id);
- DBUG_RETURN(1);
+ WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ?
+ (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id);
+ mysql_mutex_unlock(&victim_thd->LOCK_wsrep_thd);
+ ha_abort_transaction(bf_thd, victim_thd, signal);
+ mysql_mutex_lock(&victim_thd->LOCK_wsrep_thd);
}
-
- WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ?
- (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id);
- ha_abort_transaction(bf_thd, victim_thd, signal);
}
else
{
WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd);
}
-
+ mysql_mutex_unlock(&victim_thd->LOCK_wsrep_thd);
DBUG_RETURN(1);
}
-extern "C"
int wsrep_thd_in_locking_session(void *thd_ptr)
{
if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) {
@@ -671,8 +1009,275 @@ int wsrep_thd_in_locking_session(void *thd_ptr)
return 0;
}
+THD* wsrep_start_SR_THD(char *thread_stack)
+{
+ THD* thd;
+ if (!(thd= new THD(0)))
+ {
+ WSREP_ERROR("Could not create THD for Streaming Replication");
+ goto err;
+ }
+
+ thd->thread_stack= thread_stack;
+
+ thd->real_id=pthread_self(); // Keep purify happy
+ mysql_mutex_lock(&LOCK_thread_count);
+ //add_global_thread(thd);
+ add_to_active_threads(thd);
+
+ thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id();
+ (void)mysql_mutex_unlock(&LOCK_thread_count);
+
+ thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
+ thd->security_ctx->skip_grants();
+ thd->proc_info= 0;
+ thd->set_command(COM_SLEEP);
+ thd->set_time();
+ thd->init_for_queries();
+
+ struct wsrep_thd_shadow shadow;
+
+ wsrep_prepare_bf_thd(thd, &shadow);
+
+ thd->wsrep_SR_thd = true;
+ WSREP_DEBUG("SR thread created, id: %lld thd: %p", thd->thread_id, thd);
+ err:
+ return thd;
+}
+
+void wsrep_end_SR_THD(THD *thd)
+{
+ WSREP_DEBUG("Stopping Streaming Replication thd: %lld", thd->thread_id);
+
+ close_thread_tables(thd);
+ mysql_mutex_lock(&LOCK_thread_count);
+ thd->unlink();
+ mysql_mutex_unlock(&LOCK_thread_count);
+
+ delete thd;
+ /* Remember that we don't have a THD */
+ //my_pthread_setspecific_ptr(THR_THD, 0);
+
+ my_thread_end();
+}
+
bool wsrep_thd_has_explicit_locks(THD *thd)
{
assert(thd);
return thd->mdl_context.has_explicit_locks();
}
+
+static void
+wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
+{
+ WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be "
+ "caused by:\n\t"
+ "1) unsupported configuration options combination, please check documentation.\n\t"
+ "2) a bug in the code.\n\t"
+ "3) a database corruption.\n Node consistency compromized, "
+ "need to abort. Restart the node to resync with cluster.",
+ (long long)bf_seqno, (long long)victim_seqno);
+ abort();
+}
+
+static bool wsrep_abort_committing(THD *bf_thd, THD *victim_thd)
+{
+ mysql_mutex_assert_owner(&victim_thd->LOCK_wsrep_thd);
+ DBUG_ASSERT(victim_thd->wsrep_query_state() == QUERY_COMMITTING);
+
+ wsrep_seqno_t const bf_seqno= bf_thd->wsrep_trx_meta.gtid.seqno;
+ wsrep_seqno_t victim_seqno= WSREP_SEQNO_UNDEFINED;
+ wsrep_status_t rcode=
+ wsrep->abort_certification(wsrep, bf_seqno, victim_thd->wsrep_trx_id(),
+ &victim_seqno);
+ bool must_abort= false;
+ switch (rcode)
+ {
+ case WSREP_OK:
+ /* The provider performed BF abort */
+ WSREP_DEBUG("Provider performed BF abort");
+ must_abort= true;
+ break;
+ case WSREP_NOT_ALLOWED:
+ /* The provider declined to do BF abort */
+ WSREP_DEBUG("Provider declined to BF abort, victim is waiting to commit "
+ "with seqno %lld", (long long)victim_seqno );
+ break;
+ case WSREP_TRX_MISSING:
+ /* The provider didn't yet know about the victim */
+ break;
+ case WSREP_WARNING:
+ WSREP_DEBUG("abort_pre_commit warning: %lu",
+ victim_thd->wsrep_trx_id());
+ break;
+ default:
+ WSREP_ERROR("abort_pre_commit bad exit: %d %lu",
+ rcode, victim_thd->wsrep_trx_id());
+ abort();
+ break;
+ }
+
+ return must_abort;
+}
+
+
+/*
+ Function wsrep_bf_abort() should be called by the storage engine
+ whenever a high priority transaction tries to abort another
+ transaction.
+
+ Whether the BF abort should happen depends on the vicim THD
+ state:
+
+ Non-SR transaction:
+ * If the victim THD has been assigned a GTID and the GTID sequence
+ number is smaller than BF THD sequence number, the BF abort
+ request is declined and the caller should wait.
+ * If the victim THD has not been assigned a GTID or the sequence
+ number of the GTID is higher than the BF THD sequence number,
+ the victim must abort in order to allow the BF THD to proceed.
+
+ SR transaction:
+ * If the victim THD has been assigned a GTID and the GTID sequence
+ number is smaller than BF THD sequence number *and* the victim
+ is committing the final fragment, the BF abort request is
+ declined and the caller should wait.
+ * Otherwise the victim transaction is aborted.
+
+ Exactly how the BF abort takes place depends on victim THD
+ wsrep_query_state:
+
+ * QUERY_COMMITTING and QUERY_COMMITTING_FRAGMENT: The victim
+ THD execution is between the provider pre_commit() hook
+ and the commit manager. The victim THD is signalled to abort
+ at server level and the caller should wait until the victim
+ rolls back.
+ * QUERY_EXEC: The victim THD is executing a query and the
+ caller should proceed to abort the transaction inside the
+ storage engine.
+ * QUERY_IDLE: The victim THD is idle and the responsibility
+ or rolling back the victim transaction is transferred to
+ rollbacker thread. The caller should wait until the rollbacker
+ thread finishes.
+ * QUERY_EXITING: The victim THD is in the process of closing the
+ connection. The caller should wait until the ongoing victim
+ transaction is rolled back.
+
+ @return Return value true indicates that the caller should
+ proceed with internal storage engine BF abort sequence,
+ false indicates that the caller should wait for
+ the lock.
+*/
+bool wsrep_bf_abort(void *bf_thd_ptr, void *victim_thd_ptr, bool signal)
+{
+ THD *bf_thd= (THD*)bf_thd_ptr;
+ THD *victim_thd= (THD*)victim_thd_ptr;
+
+ mysql_mutex_assert_owner(&victim_thd->LOCK_wsrep_thd);
+
+ WSREP_LOG_THD(bf_thd, "BF aborter before");
+ WSREP_LOG_THD(victim_thd, "victim before");
+
+ wsrep_seqno_t const bf_seqno= bf_thd->wsrep_trx_meta.gtid.seqno;
+ wsrep_seqno_t victim_seqno= WSREP_SEQNO_UNDEFINED;
+
+ if (victim_thd->wsrep_exec_mode == REPL_RECV)
+ {
+ wsrep_abort_slave_trx(bf_seqno, victim_seqno); /* Does not return */
+ }
+
+ DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock",
+ {
+ const char act[]=
+ "now "
+ "wait_for signal.wsrep_after_BF_victim_lock";
+ DBUG_ASSERT(!debug_sync_set_action(bf_thd,
+ STRING_WITH_LEN(act)));
+ };);
+
+ bool caller_must_bf_abort= false;
+ bool must_bf_abort= false;
+ bool must_fire_rollbacker= false;
+ switch (victim_thd->wsrep_query_state())
+ {
+ case QUERY_COMMITTING:
+ /*
+ The query is committing either transaction or fragment,
+ the BF abort is attempted via provider.
+ */
+ must_bf_abort= wsrep_abort_committing(bf_thd, victim_thd);
+ break;
+ case QUERY_ORDERED_COMMIT:
+ /*
+ Commit order has been grabbed, BF abort is not allowed.
+ */
+ break;
+ case QUERY_EXEC:
+ /*
+ The victim THD is in execution phase and may be executing
+ a query inside storage engine. The control for further actions
+ will be returned to the caller.
+ */
+ caller_must_bf_abort= true;
+ must_bf_abort= true;
+ break;
+ case QUERY_IDLE:
+ /*
+ The victim THD is idle. The victim must be marked as BF aborted
+ and the rollbacker thread must be signalled to do the actual rollback.
+ */
+ must_bf_abort= true;
+ must_fire_rollbacker= true;
+ break;
+ case QUERY_EXITING:
+ /*
+ The victim connection is closing, the caller should wait for the
+ rollback.
+ */
+ break;
+ }
+
+ if (must_bf_abort)
+ {
+ switch (victim_thd->wsrep_conflict_state())
+ {
+ case NO_CONFLICT:
+ wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT);
+ break;
+ case MUST_ABORT:
+ wsrep_thd_awake(victim_thd, signal);
+ /* Fall through */
+ case ABORTING:
+ case ABORTED:
+ case MUST_REPLAY:
+ case CERT_FAILURE:
+ /*
+ The victim is already in process of aborting the transaction,
+ the BF aborter should wait.
+ */
+ must_bf_abort= false;
+ caller_must_bf_abort= false;
+ must_fire_rollbacker= false;
+ break;
+ default:
+ WSREP_WARN("BF abort for victim in state %s",
+ wsrep_thd_conflict_state_str(victim_thd));
+ DBUG_ASSERT(0); /* Should not be here */
+ must_bf_abort= false;
+ caller_must_bf_abort= false;
+ must_fire_rollbacker= false;
+ break;
+ }
+ }
+
+ if (must_fire_rollbacker)
+ {
+ DBUG_ASSERT(must_bf_abort);
+ wsrep_fire_rollbacker(victim_thd);
+ }
+
+ WSREP_LOG_THD(victim_thd, "victim after");
+
+ return caller_must_bf_abort;
+
+}
diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h
index 5900668f3fb..996c1d0dddf 100644
--- a/sql/wsrep_thd.h
+++ b/sql/wsrep_thd.h
@@ -21,28 +21,194 @@
#ifdef WITH_WSREP
#include "sql_class.h"
+#include "wsrep_utils.h"
+#include <deque>
+class Wsrep_thd_queue
+{
+public:
+ Wsrep_thd_queue(THD* t) : thd(t)
+ {
+ mysql_mutex_init(key_LOCK_wsrep_thd_queue,
+ &LOCK_wsrep_thd_queue,
+ MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_wsrep_thd_queue, &COND_wsrep_thd_queue, NULL);
+ }
+ ~Wsrep_thd_queue()
+ {
+ mysql_mutex_destroy(&LOCK_wsrep_thd_queue);
+ mysql_cond_destroy(&COND_wsrep_thd_queue);
+ }
+ bool push_back(THD* thd)
+ {
+ DBUG_ASSERT(thd);
+ wsp::auto_lock lock(&LOCK_wsrep_thd_queue);
+ std::deque<THD*>::iterator it = queue.begin();
+ while (it != queue.end())
+ {
+ if (*it == thd)
+ {
+ return true;
+ }
+ it++;
+ }
+ queue.push_back(thd);
+ mysql_cond_signal(&COND_wsrep_thd_queue);
+ return false;
+ }
+ THD* pop_front()
+ {
+ wsp::auto_lock lock(&LOCK_wsrep_thd_queue);
+ while (queue.empty())
+ {
+ if (thd->killed != NOT_KILLED)
+ return NULL;
+
+ thd->mysys_var->current_mutex= &LOCK_wsrep_thd_queue;
+ thd->mysys_var->current_cond= &COND_wsrep_thd_queue;
+
+ mysql_cond_wait(&COND_wsrep_thd_queue, &LOCK_wsrep_thd_queue);
+
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ }
+ THD* ret= queue.front();
+ queue.pop_front();
+ return ret;
+ }
+private:
+ THD* thd;
+ std::deque<THD*> queue;
+ mysql_mutex_t LOCK_wsrep_thd_queue;
+ mysql_cond_t COND_wsrep_thd_queue;
+};
+
+void wsrep_prepare_bf_thd(THD*, struct wsrep_thd_shadow*);
+void wsrep_return_from_bf_mode(THD*, struct wsrep_thd_shadow*);
int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope);
-void wsrep_client_rollback(THD *thd);
+void wsrep_client_rollback(THD *thd, bool rollbacker = false);
void wsrep_replay_transaction(THD *thd);
void wsrep_create_appliers(long threads);
void wsrep_create_rollbacker();
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
my_bool signal);
-
+#ifndef OUT
/*
PA = Parallel Applying (on the slave side)
*/
extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
-extern my_bool wsrep_thd_is_BF(THD *thd, my_bool sync);
+//extern my_bool wsrep_thd_is_BF(THD *thd, my_bool sync);
+extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern my_bool wsrep_thd_is_wsrep(void *thd_ptr);
-enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
+//enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
+//extern int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
+//extern char* wsrep_thd_query(void *thd_ptr);
extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync);
-extern "C" int wsrep_thd_in_locking_session(void *thd_ptr);
+int wsrep_thd_in_locking_session(void *thd_ptr);
+THD* wsrep_start_SR_THD(char *thread_stack);
+void wsrep_end_SR_THD(THD* thd);
+extern my_bool wsrep_thd_is_SR(void *thd_ptr);
+extern my_bool wsrep_thd_skip_locking(void *thd);
+#endif
+
+/**
+ Helper functions to override error status
+
+ In many contexts it is desirable to mask the original error status
+ set for THD or it is necessary to change OK status to error.
+ This function implements the common logic for the most
+ of the cases.
+
+ Rules:
+ * If the diagnostics are has OK or EOF status, override it unconditionally
+ * If the error is either ER_ERROR_DURING_COMMIT or ER_LOCK_DEADLOCK
+ it is usually the correct error status to be returned to client,
+ so don't override those by default
+ */
+
+static inline void wsrep_override_error(THD *thd, uint error)
+{
+ Diagnostics_area *da= thd->get_stmt_da();
+ if (da->is_ok() ||
+ da->is_eof() ||
+ !da->is_set() ||
+ (da->is_error() &&
+ da->sql_errno() != error &&
+ da->sql_errno() != ER_ERROR_DURING_COMMIT &&
+ da->sql_errno() != ER_LOCK_DEADLOCK))
+ {
+ da->reset_diagnostics_area();
+ my_error(error, MYF(0));
+ }
+}
+
+/**
+ Override error with additional wsrep status.
+ */
+static inline void wsrep_override_error(THD *thd, uint error,
+ wsrep_status_t status)
+{
+ Diagnostics_area *da= thd->get_stmt_da();
+ if (da->is_ok() ||
+ !da->is_set() ||
+ (da->is_error() &&
+ da->sql_errno() != error &&
+ da->sql_errno() != ER_ERROR_DURING_COMMIT &&
+ da->sql_errno() != ER_LOCK_DEADLOCK))
+ {
+ da->reset_diagnostics_area();
+ my_error(error, MYF(0), status);
+ }
+}
+
+
+/**
+ Helper function to log THD wsrep context.
+
+ @param thd Pointer to THD
+ @param message Optional message
+ @param function Function where the call was made from
+ */
+static inline void wsrep_log_thd(THD *thd,
+ const char *message,
+ const char *function)
+{
+ WSREP_DEBUG("%s %s\n"
+ " thd: %llu thd_ptr: %p exec_mode: %s query_state: %s conflict_state: %s\n"
+ " next_trx_id: %lld trx_id: %lld seqno: %lld\n"
+ " is_streaming: %d fragments: %zu\n"
+ " sql_errno: %u message: %s\n"
+#define WSREP_THD_LOG_QUERIES
+#ifdef WSREP_THD_LOG_QUERIES
+ " command: %d query: %.72s"
+#endif /* WSREP_OBSERVER_LOG_QUERIES */
+ ,
+ function,
+ message ? message : "",
+ thd->thread_id,
+ thd,
+ wsrep_thd_exec_mode_str(thd),
+ wsrep_thd_query_state_str(thd),
+ wsrep_thd_conflict_state_str(thd),
+ (long long)thd->wsrep_next_trx_id(),
+ (long long)thd->wsrep_trx_id(),
+ (long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_is_streaming(),
+ thd->wsrep_SR_fragments.size(),
+ (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0),
+ (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->message() : "")
+#ifdef WSREP_THD_LOG_QUERIES
+ , thd->lex->sql_command,
+ WSREP_QUERY(thd)
+#endif /* WSREP_OBSERVER_LOG_QUERIES */
+ );
+}
+
+#define WSREP_LOG_THD(thd_, message_) wsrep_log_thd(thd_, message_, __FUNCTION__)
#else /* WITH_WSREP */
diff --git a/sql/wsrep_thd_pool.cc b/sql/wsrep_thd_pool.cc
new file mode 100644
index 00000000000..d65b5bde185
--- /dev/null
+++ b/sql/wsrep_thd_pool.cc
@@ -0,0 +1,122 @@
+/* Copyright (C) 2015 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#include <my_global.h>
+#include "my_pthread.h"
+#include "wsrep_mysqld.h"
+#include "wsrep_thd_pool.h"
+#include "wsrep_utils.h"
+#include "sql_class.h"
+//#include "global_threads.h"
+
+#include <list>
+
+static THD* wsrep_thd_pool_new_thd()
+{
+ THD *thd = new THD(next_thread_id());
+ thd->thread_stack= (char*) &thd;
+ thd->security_ctx->skip_grants();
+ thd->system_thread= SYSTEM_THREAD_GENERIC;
+
+ mysql_mutex_lock(&LOCK_thread_count);
+
+ thd->real_id=pthread_self(); // Keep purify happy
+
+ WSREP_DEBUG("Wsrep_thd_pool: creating system thread: %lld",
+ (long long)thd->thread_id);
+ thd->prior_thr_create_utime= thd->start_utime= thd->thr_create_utime;
+ (void) mysql_mutex_unlock(&LOCK_thread_count);
+
+ thd->variables.wsrep_on = 0;
+ thd->variables.sql_log_bin = 0;
+ thd->variables.option_bits &= ~OPTION_BIN_LOG;
+ thd->variables.tx_isolation = ISO_READ_COMMITTED;
+
+ thd->wsrep_exec_mode = REPL_RECV;
+ // thd->wsrep_exec_mode = LOCAL_STATE;
+
+ return thd;
+}
+
+Wsrep_thd_pool::Wsrep_thd_pool(size_t threads)
+ :
+ threads_(threads),
+ pool_()
+{
+ WSREP_DEBUG("Wsrep_thd_pool constructor");
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ pool_.reserve(threads);
+ for (size_t i= 0; i < threads; ++i)
+ {
+ pool_.push_back(wsrep_thd_pool_new_thd());
+ }
+}
+
+Wsrep_thd_pool::~Wsrep_thd_pool()
+{
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ while (!pool_.empty())
+ {
+ THD *thd = pool_.back();
+ WSREP_DEBUG("Wsrep_thd_pool: closing thread %lld",
+ (long long)thd->thread_id);
+
+ delete thd;
+
+ pool_.pop_back();
+ }
+}
+
+THD* Wsrep_thd_pool::get_thd(THD* thd)
+{
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ THD *ret= NULL;
+ if (pool_.empty())
+ {
+ ret= wsrep_thd_pool_new_thd();
+ }
+ else
+ {
+ ret= pool_.back();
+ pool_.pop_back();
+ }
+ if (thd)
+ {
+ ret->thread_stack = thd->thread_stack;
+ }
+ else
+ {
+ ret->thread_stack= (char*) &ret;
+ }
+ ret->store_globals();
+ return ret;
+}
+
+void Wsrep_thd_pool::release_thd(THD* thd)
+{
+ DBUG_ASSERT(!thd->mdl_context.has_locks());
+ DBUG_ASSERT(!thd->open_tables);
+ DBUG_ASSERT(thd->transaction.stmt.is_empty());
+ wsp::auto_lock lock(&LOCK_wsrep_thd_pool);
+ if (pool_.size() < threads_)
+ {
+ pool_.push_back(thd);
+ }
+ else
+ {
+ delete thd;
+ }
+}
diff --git a/sql/wsrep_thd_pool.h b/sql/wsrep_thd_pool.h
new file mode 100644
index 00000000000..af335ac3b87
--- /dev/null
+++ b/sql/wsrep_thd_pool.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2015 Codership Oy <info@codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+
+#ifndef WSREP_THD_POOL_H
+#define WSREP_THD_POOL_H
+
+#include <cstddef>
+#include <vector>
+
+class THD;
+
+class Wsrep_thd_pool
+{
+public:
+ Wsrep_thd_pool(size_t threads = 10);
+ ~Wsrep_thd_pool();
+ THD* get_thd(THD*);
+ void release_thd(THD*);
+private:
+ size_t threads_;
+ std::vector<THD*> pool_;
+};
+
+#endif /* !WSREP_THD_POOL_H */
diff --git a/sql/wsrep_trans_observer.cc b/sql/wsrep_trans_observer.cc
new file mode 100644
index 00000000000..9a914ea37b7
--- /dev/null
+++ b/sql/wsrep_trans_observer.cc
@@ -0,0 +1,1663 @@
+/* Copyright 2016 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/*
+ Implementation of wsrep transaction observer hooks.
+
+ * wsrep_after_row(): called after each row write/update/delete, will run
+ SR step
+ * wsrep_before_prepare(): SR table cleanup
+ * wsrep_after_prepare(): will run wsrep_certify() which replicates
+ and certifies transaction for transactions which have registered
+ binlog hton
+ * wsrep_before_commit(): run wsrep_certify() for autocommit
+ DML when binlog_format = STATEMENT and grab commit time
+ critical via section wsrep->commit_order_enter()
+ * wsrep_ordered_commit(): release commit time critical section
+ via wsrep->commit_order_leave()
+ * wsrep_after_commit(): release rest of the trx resources from
+ provider
+ * wsrep_before_rollback(): on SR rollback construct SR_trx_info
+ and send rollback event before actual rollback happens. Set
+ wsrep_exec_mode to LOCAL_ROLLBACK
+ * wsrep_after_rollback(): in case of statement rollback check if
+ it is safe for SR and if not, trigger full transaction rollback
+ * wsrep_after_command():
+ * run wsrep_SR_step()
+ * perform post rollback operations for thds which have
+ wsrep_exec_mode LOCAL_ROLLBACK
+ * perform wsrep_client_rollback() for thds with wsrep_conflict_state
+ MUST_ABORT or CERT_FAILURE
+ * run wsrep_client_rollback() for thd which has seqno assigned
+ * cleanup transaction after rollback
+ * do rollback process for threads which have BF aborted or have
+ failed certification but have not rolled back yet.
+ * replay transactions which need to be replayed
+
+
+ Note: The rollback processing has been postponed to after_command hook
+ because sometimes the rollback process needs to be done for threads
+ which have valid wsrep seqno and rollback for such a threads should
+ be done after all tables are closed in order to avoid deadlocks.
+ Although wsrep rollback steps would be possible to do earlier in
+ after_rollback hook, this approach was chosen for simplicity.
+*/
+
+
+#include "wsrep_trans_observer.h"
+#include "wsrep_mysqld.h"
+#include "wsrep_xid.h"
+#include "wsrep_sr.h"
+#include "wsrep_thd.h"
+
+#include "replication.h"
+#include "transaction.h"
+#include "sql_base.h" /* close_thread_tables() */
+#include "sql_class.h" /* THD */
+#include "sql_parse.h" /* stmt_causes_implicit_commit() */
+#include "rpl_filter.h" /* Rpl_filter */
+#include "log.h"
+#include "debug_sync.h" /* DEBUG_SYNC */
+
+#include <map>
+
+extern class SR_storage *wsrep_SR_store;
+extern Rpl_filter* binlog_filter;
+
+
+static void wsrep_wait_for_replayers(THD *thd)
+{
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ int replay_round= 0;
+ while (wsrep_replaying > 0 &&
+ thd->wsrep_conflict_state() == NO_CONFLICT &&
+ thd->killed == NOT_KILLED &&
+ !shutdown_in_progress)
+ {
+
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ mysql_mutex_lock(&thd->mysys_var->mutex);
+ thd_proc_info(thd, "wsrep waiting on replaying");
+ thd->mysys_var->current_mutex= &LOCK_wsrep_replaying;
+ thd->mysys_var->current_cond= &COND_wsrep_replaying;
+ mysql_mutex_unlock(&thd->mysys_var->mutex);
+
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ // Using timedwait is a hack to avoid deadlock in case if BF victim
+ // misses the signal.
+ struct timespec wtime;
+ clock_gettime(CLOCK_REALTIME, &wtime);
+ long prev_nsec = wtime.tv_nsec;
+ wtime.tv_nsec = (wtime.tv_nsec + 1000000) % 1000000000;
+ // If nsecs rolled over, increment seconds.
+ wtime.tv_sec += (wtime.tv_nsec < prev_nsec ? 1 : 0);
+ mysql_cond_timedwait(&COND_wsrep_replaying, &LOCK_wsrep_replaying,
+ &wtime);
+
+ if (replay_round++ % 100000 == 0)
+ WSREP_DEBUG("commit waiting for replaying: replayers %d, thd: (%lld) "
+ "conflict: %d (round: %d)",
+ wsrep_replaying, thd->thread_id,
+ thd->wsrep_conflict_state_unsafe(), replay_round);
+
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+
+ mysql_mutex_lock(&thd->mysys_var->mutex);
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ mysql_mutex_unlock(&thd->mysys_var->mutex);
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ }
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+}
+
+static int wsrep_prepare_data_for_replication(THD *thd)
+{
+ DBUG_ENTER("wsrep_prepare_data_for_replication");
+ size_t data_len= 0;
+ IO_CACHE* cache= wsrep_get_trans_cache(thd);
+
+ if (cache)
+ {
+ thd->binlog_flush_pending_rows_event(true);
+ enum wsrep_trx_status rcode= wsrep_write_cache(wsrep, thd, cache, &data_len);
+ if (rcode != WSREP_TRX_OK)
+ {
+ WSREP_ERROR("rbr write fail, data_len:: %zu",
+ data_len);
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT,
+ wsrep_trx_status_to_wsrep_status(rcode));
+ DBUG_RETURN(1);
+ }
+ }
+
+ if (data_len == 0)
+ {
+ if (thd->get_stmt_da()->is_ok() &&
+ thd->get_stmt_da()->affected_rows() > 0 &&
+ !binlog_filter->is_on())
+ {
+ WSREP_DEBUG("empty rbr buffer, query: %s, "
+ "affected rows: %llu, "
+ "changed tables: %d, "
+ "sql_log_bin: %d, "
+ "wsrep status (%d %d %d)",
+ WSREP_QUERY(thd),
+ thd->get_stmt_da()->affected_rows(),
+ stmt_has_updated_trans_table(thd),
+ thd->variables.sql_log_bin,
+ thd->wsrep_exec_mode, thd->wsrep_query_state_unsafe(),
+ thd->wsrep_conflict_state_unsafe());
+ }
+ else
+ {
+ WSREP_DEBUG("empty rbr buffer, query: %s", WSREP_QUERY(thd));
+ }
+
+ if (!thd->wsrep_is_streaming())
+ {
+ WSREP_ERROR("I/O error reading from thd's binlog iocache: "
+ "errno=%d, io cache code=%d", my_errno, cache->error);
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT);
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ Run wsrep pre_commit phase
+
+ Asserts thd->LOCK_wsrep_thd ownership
+ */
+static wsrep_trx_status wsrep_certify(THD *thd)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ DBUG_ENTER("wsrep_certify");
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+
+ /*
+ We must not proceed for certify() if there are threads
+ replaying transactions. This is because replaying thread
+ may have released some locks which this thread then acquired.
+
+ Now if the replaying ends before write set gets replicated,
+ the replayed write set may fall out of this write sets
+ certification range, so the conflict won't be detected.
+ This will lead to applying error later on.
+
+ Conflict state must be checked out once more after waiting
+ for replayers to detect if replaying transaction (or other)
+ has BF aborted this.
+ */
+ wsrep_wait_for_replayers(thd);
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ // Transaction was BF aborted
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ thd->set_wsrep_query_state(QUERY_COMMITTING);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DEBUG_SYNC(thd, "wsrep_before_replication");
+
+ if (wsrep_prepare_data_for_replication(thd))
+ {
+ /* Error will be set in function to prepare data */
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ if (thd->killed != NOT_KILLED)
+ {
+ WSREP_INFO("thd %lld killed with signal %d, skipping replication",
+ thd->thread_id, thd->killed);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_id())
+ {
+ WSREP_WARN("SQL statement was ineffective, THD: %lld\n"
+ "schema: %s \n"
+ "QUERY: %s\n"
+ " => Skipping replication",
+ thd->thread_id,
+ (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ uint32_t flags= WSREP_FLAG_TRX_END;
+ if (!thd->wsrep_PA_safe || thd->wsrep_is_streaming())
+ {
+ flags |= WSREP_FLAG_PA_UNSAFE;
+ }
+
+ if (thd->wsrep_is_streaming())
+ {
+ if (!wsrep_append_SR_keys(thd))
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+ }
+
+ wsrep_status_t rcode= wsrep->certify(wsrep,
+ (wsrep_conn_id_t) thd->thread_id,
+ &thd->wsrep_ws_handle,
+ flags,
+ &thd->wsrep_trx_meta);
+
+ WSREP_DEBUG("Trx certify(%lu): rcode %d, seqno %lld, trx %ld, "
+ "flags %u, conf %d, SQL: %s",
+ thd->thread_id, rcode,(long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx, flags, thd->wsrep_conflict_state_unsafe(),
+ thd->query());
+
+ DBUG_ASSERT((thd->wsrep_trx_meta.depends_on >= 0 &&
+ thd->wsrep_trx_meta.depends_on <
+ thd->wsrep_trx_meta.gtid.seqno) ||
+ WSREP_OK != rcode);
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+
+ DEBUG_SYNC(thd, "wsrep_after_replication");
+
+ if (WSREP_OK == rcode)
+ {
+ DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
+
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ rcode= WSREP_BF_ABORT;
+ WSREP_DEBUG("Not calling commit_order_enter() due to conflict state"
+ " == MUST_ABORT thd: %lu, seqno: %lld",
+ thd->thread_id, (long long)wsrep_thd_trx_seqno(thd));
+ }
+ }
+
+ wsrep_trx_status ret= WSREP_TRX_ERROR;
+
+ switch (rcode)
+ {
+ case WSREP_TRX_MISSING:
+ WSREP_WARN("Transaction missing in provider thd: %lld schema: %s SQL: %s",
+ thd->thread_id, (thd->db.str ? thd->db.str : "(null)"),
+ WSREP_QUERY(thd));
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_TRX_MISSING);
+ break;
+ case WSREP_BF_ABORT:
+ DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
+ thd->set_wsrep_conflict_state(MUST_REPLAY);
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ ++wsrep_replaying;
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ break;
+ case WSREP_OK:
+ /*
+ Ignore BF abort from storage engine in commit phase.
+ This however requires that the storage engine BF abort
+ respects QUERY_COMMITTING query state.
+
+ TODO: Consider removing this and respecting BF abort.
+ Also adjust allowed state transitions in
+ THD::set_wsrep_conflict_state().
+
+ NOTE: If we have rcode WSREP_OK here it means that transaction
+ entered commit critical section in wsrep->commit_order_enter()
+ call. It is a bug in a provider/BF abort code if it allowed
+ BF abort after that.
+ */
+ DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ thd->killed= NOT_KILLED;
+ WSREP_WARN("Ignoring MUST_ABORT state");
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ }
+
+ thd->wsrep_exec_mode= LOCAL_COMMIT;
+ DBUG_PRINT("wsrep", ("replicating commit success"));
+ DBUG_EXECUTE_IF("crash_last_fragment_commit_success",
+ DBUG_SUICIDE(););
+ ret= WSREP_TRX_OK;
+ break;
+ case WSREP_TRX_FAIL:
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
+ {
+ thd->set_wsrep_conflict_state(CERT_FAILURE);
+ WSREP_LOG_CONFLICT(NULL, thd, FALSE);
+ }
+ else
+ {
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT);
+ }
+ my_error(ER_LOCK_DEADLOCK, MYF(0), WSREP_TRX_FAIL);
+ ret= WSREP_TRX_CERT_FAIL;
+ break;
+ case WSREP_SIZE_EXCEEDED:
+ WSREP_ERROR("wsrep_certify(%lu): transaction size exceeded",
+ thd->thread_id);
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
+ ret= WSREP_TRX_SIZE_EXCEEDED;
+ break;
+ case WSREP_CONN_FAIL:
+ WSREP_DEBUG("wsrep_certify(%lu): replication aborted",
+ thd->thread_id);
+ my_error(ER_LOCK_DEADLOCK, MYF(0), WSREP_CONN_FAIL);
+ break;
+ case WSREP_WARNING:
+ WSREP_WARN("provider returned warning");
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_WARNING);
+ break;
+ case WSREP_NODE_FAIL:
+ WSREP_ERROR("replication aborted");
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_NODE_FAIL);
+ break;
+ case WSREP_NOT_IMPLEMENTED:
+ WSREP_ERROR("certify() or commit_order_enter() not implemented");
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_NOT_IMPLEMENTED);
+ break;
+ default:
+ WSREP_ERROR("wsrep_certify(%lu): unknown provider failure",
+ thd->thread_id);
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), rcode);
+ break;
+ }
+
+ /*
+ In case of success we keep the QUERY_COMMITTING
+ */
+ if (rcode != WSREP_OK)
+ {
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ }
+
+ DBUG_RETURN(ret);
+}
+
+static wsrep_trx_status wsrep_replicate_fragment(THD *thd)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ DBUG_ENTER("wsrep_replicate_fragment");
+ DBUG_ASSERT(thd->wsrep_exec_mode != REPL_RECV &&
+ thd->wsrep_exec_mode != TOTAL_ORDER);
+ DBUG_ASSERT(thd->wsrep_SR_rollback_replicated_for_trx !=
+ thd->wsrep_trx_id());
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+
+ wsrep_wait_for_replayers(thd);
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ // Transaction was BF aborted
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ thd->set_wsrep_query_state(QUERY_COMMITTING);
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ bool reset_trx_meta= false;
+ IO_CACHE *cache= wsrep_get_trans_cache(thd);
+ size_t data_len= 0;
+ uint32_t flags= (thd->wsrep_PA_safe ? 0 : WSREP_FLAG_PA_UNSAFE);
+ if (thd->wsrep_fragments_sent == 0)
+ {
+ flags |= WSREP_FLAG_TRX_START;
+ }
+
+ /*
+ thd->wsrep_fragments_sent must be incremented before wsrep_write_cache
+ to get thd->wsrep_rbr_buf populated. This also needs to be decremented
+ whenever error is returned from this function.
+ */
+ ++thd->wsrep_fragments_sent;
+ if (cache)
+ {
+ enum wsrep_trx_status rcode;
+ if ((rcode = wsrep_write_cache(wsrep, thd, cache, &data_len)) != WSREP_TRX_OK)
+ {
+ WSREP_ERROR("SR rbr write fail, data_len: %zu ret: %d",
+ data_len, rcode);
+ --thd->wsrep_fragments_sent;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(rcode);
+ }
+ }
+
+#if 0
+ WSREP_INFO("wsrep_replicate_fragment: base: %lu bytes: %u data_len %zu fragments_sent: %lu",
+ wsrep_get_fragment_base(thd),
+ wsrep_get_trans_cache_position(thd),
+ data_len,
+ thd->wsrep_fragments_sent);
+#endif
+
+ if (data_len == 0)
+ {
+ if (thd->get_stmt_da()->is_ok() &&
+ thd->get_stmt_da()->affected_rows() > 0 &&
+ !binlog_filter->is_on())
+ {
+ WSREP_WARN("empty rbr buffer, query: %s, "
+ "affected rows: %llu, "
+ "changed tables: %d, "
+ "sql_log_bin: %d, "
+ "wsrep status (%d %d %d)",
+ thd->query(), thd->get_stmt_da()->affected_rows(),
+ stmt_has_updated_trans_table(thd),
+ thd->variables.sql_log_bin,
+ thd->wsrep_exec_mode, thd->wsrep_query_state(),
+ thd->wsrep_conflict_state_unsafe());
+ }
+ else
+ {
+ WSREP_WARN("empty rbr buffer, query: %s", thd->query());
+ }
+ --thd->wsrep_fragments_sent;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID);
+ if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_id())
+ {
+ WSREP_WARN("SQL statement was ineffective, THD: %lld, buf: %zu\n"
+ "QUERY: %s\n"
+ " => Skipping fragment replication",
+ thd->thread_id, data_len, thd->query());
+ --thd->wsrep_fragments_sent;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+
+ THD *SR_thd= NULL;
+ if (wsrep_SR_store)
+ {
+ SR_thd= wsrep_SR_store->append_frag(thd, flags, thd->wsrep_rbr_buf,
+ data_len);
+ if (!SR_thd)
+ {
+ my_error(ER_BINLOG_ROW_LOGGING_FAILED, MYF(0));
+ --thd->wsrep_fragments_sent;
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ DBUG_RETURN(WSREP_TRX_ERROR);
+ }
+ }
+
+ my_free(thd->wsrep_rbr_buf);
+ thd->wsrep_rbr_buf= NULL;
+
+ DBUG_EXECUTE_IF("crash_replicate_fragment_before_certify",
+ DBUG_SUICIDE(););
+
+ wsrep_status_t rcode= wsrep->certify(wsrep,
+ (wsrep_conn_id_t)thd->thread_id,
+ &thd->wsrep_ws_handle,
+ flags,
+ &thd->wsrep_trx_meta);
+
+ WSREP_DEBUG("Fragment certify(%lu): rcode %d, seqno %lld, trx %ld, "
+ "flags %u, conf %d, SQL: %s",
+ thd->thread_id, rcode,(long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx, flags,
+ thd->wsrep_conflict_state_unsafe(),
+ thd->query());
+ DBUG_EXECUTE_IF("crash_replicate_fragment_after_certify",
+ DBUG_SUICIDE(););
+
+ bool frag_updated= false;
+ if (WSREP_OK == rcode)
+ {
+ DBUG_ASSERT(thd->wsrep_trx_has_seqno());
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ my_bool const must_abort= (thd->wsrep_conflict_state() == MUST_ABORT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ if (must_abort)
+ {
+ rcode= WSREP_BF_ABORT;
+ }
+ else
+ {
+ rcode= wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta);
+ if (rcode == WSREP_OK)
+ {
+ wsrep_xid_init(&SR_thd->wsrep_xid, thd->wsrep_trx_meta.gtid.uuid,
+ thd->wsrep_trx_meta.gtid.seqno);
+ wsrep_SR_store->update_frag_seqno(SR_thd, thd);
+ frag_updated= true;
+ rcode= wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, NULL);
+ if (rcode != WSREP_OK && rcode != WSREP_BF_ABORT)
+ {
+ WSREP_ERROR("wsrep_replicate_fragment(%lu): seqno %lld, trx %ld "
+ "Failed to leave commit order %d",
+ thd->thread_id,
+ (long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx,
+ rcode);
+ }
+ if (rcode == WSREP_OK)
+ {
+ rcode= wsrep->release(wsrep, &thd->wsrep_ws_handle);
+ if (rcode != WSREP_OK)
+ {
+ WSREP_ERROR("wsrep_replicate_fragment(%lu): seqno %lld, trx %ld "
+ "Failed to release ws handle %d",
+ thd->thread_id,
+ (long long)thd->wsrep_trx_meta.gtid.seqno,
+ thd->wsrep_trx_meta.stid.trx,
+ rcode);
+ }
+ }
+ reset_trx_meta= true;
+ }
+ else
+ {
+ DBUG_ASSERT(rcode == WSREP_BF_ABORT || rcode == WSREP_TRX_FAIL);
+ }
+ }
+ }
+
+ if (!frag_updated)
+ {
+ wsrep_SR_store->release_SR_thd(SR_thd);
+ SR_thd= NULL;
+ thd->store_globals();
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ /*
+ If the SR transaction was BF aborted at this stage
+ we abort whole transaction.
+ */
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ rcode= WSREP_BF_ABORT;
+ }
+
+ wsrep_trx_status ret;
+
+ switch (rcode)
+ {
+ case WSREP_OK:
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+ DBUG_PRINT("wsrep", ("replicating commit success"));
+ if (thd->killed != NOT_KILLED)
+ {
+ WSREP_DEBUG("thd %lld killed with signal %d, during fragment replication",
+ thd->thread_id, thd->killed);
+ }
+ DBUG_EXECUTE_IF("crash_replicate_fragment_success",
+ DBUG_SUICIDE(););
+ ret= WSREP_TRX_OK;
+ break;
+ case WSREP_BF_ABORT:
+ if (thd->wsrep_conflict_state() != MUST_ABORT)
+ {
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ }
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK, WSREP_TRX_FAIL);
+ ret= WSREP_TRX_ERROR;
+ break;
+ case WSREP_TRX_FAIL:
+ thd->set_wsrep_conflict_state(CERT_FAILURE);
+ WSREP_LOG_CONFLICT(NULL, thd, FALSE);
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK, WSREP_TRX_FAIL);
+ ret= WSREP_TRX_CERT_FAIL;
+ break;
+ case WSREP_SIZE_EXCEEDED:
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ ret= WSREP_TRX_SIZE_EXCEEDED;
+ break;
+ case WSREP_CONN_FAIL:
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
+ ret= WSREP_TRX_ERROR;
+ break;
+ default:
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ ret= WSREP_TRX_ERROR;
+ break;
+ }
+
+ thd->set_wsrep_query_state(QUERY_EXEC);
+
+ if (SR_thd && wsrep_thd_trx_seqno(thd) == WSREP_SEQNO_UNDEFINED)
+ {
+ --thd->wsrep_fragments_sent;
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ wsrep_SR_store->release_SR_thd(SR_thd);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->store_globals();
+ }
+
+ /*
+ Reset trx meta if pre_commit certify() (regardless of conflict state),
+ new seqno will be used for next fragment.
+ In case of failure GTID may be required in rollback process.
+ */
+ if (reset_trx_meta)
+ {
+ WSREP_DEBUG("Reset trx meta for %lu", thd->thread_id);
+ thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
+ thd->wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED;
+ }
+
+ DBUG_RETURN(ret);
+}
+
+static int wsrep_SR_step(THD *thd, uint unit)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ DBUG_ENTER("wsrep_SR_step");
+ if (!wsrep_may_produce_SR_step(thd) ||
+ unit != thd->variables.wsrep_trx_fragment_unit ||
+ thd->variables.wsrep_trx_fragment_size == 0 ||
+ thd->get_stmt_da()->is_error())
+ {
+#if 0
+ WSREP_DEBUG("wsrep_SR_step: skip, frag_size: %lu is_error: %d",
+ thd->variables.wsrep_trx_fragment_size,
+ thd->get_stmt_da()->is_error());
+#endif /* 0 */
+ DBUG_RETURN(0);
+ }
+
+ /*
+ Flush pending rows event into IO cache buffer
+ */
+ thd->binlog_flush_pending_rows_event(true);
+
+ wsrep_trx_status ret= WSREP_TRX_OK;
+ uint written= (wsrep_get_trans_cache_position(thd)
+ - wsrep_get_fragment_base(thd));
+ bool replicate= false;
+
+ switch (thd->variables.wsrep_trx_fragment_unit)
+ {
+ case WSREP_FRAG_BYTES:
+ if (written >= thd->variables.wsrep_trx_fragment_size)
+ replicate= true;
+ break;
+ case WSREP_FRAG_ROWS:
+ case WSREP_FRAG_STATEMENTS:
+ wsrep_append_fill_rate(thd, 1);
+ if (wsrep_get_fragment_fill(thd) >= thd->variables.wsrep_trx_fragment_size)
+ replicate= true;
+ break;
+ default:
+ wsrep_append_fill_rate(thd, 1);
+ replicate= true;
+ DBUG_ASSERT(0);
+ }
+
+ if (replicate)
+ {
+ WSREP_DEBUG("fragment fill: %lu fragment unit: %lu fragment size: %lu written: %u",
+ wsrep_get_fragment_fill(thd),
+ thd->variables.wsrep_trx_fragment_unit,
+ thd->variables.wsrep_trx_fragment_size,
+ written);
+
+ ret= wsrep_replicate_fragment(thd);
+ if (ret == WSREP_TRX_OK)
+ {
+ wsrep_reset_fragment_fill(thd, 0);
+ wsrep_step_fragment_base(thd, written);
+ }
+ }
+
+ if (ret)
+ {
+ if (!thd->get_stmt_da()->is_error())
+ {
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT,
+ wsrep_trx_status_to_wsrep_status(ret));
+ }
+ }
+
+ DBUG_RETURN(ret);
+}
+
+bool wsrep_replicate_GTID(THD *thd)
+{
+ if (thd->slave_thread)
+ {
+ WSREP_DEBUG("GTID replication");
+ DBUG_ASSERT (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id);
+ thd->set_wsrep_next_trx_id(thd->query_id);
+ (void)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle,
+ thd->wsrep_next_trx_id());
+ DBUG_ASSERT (WSREP_UNDEFINED_TRX_ID != thd->wsrep_ws_handle.trx_id);
+
+ int rcode= wsrep_certify(thd);
+ if (rcode)
+ {
+ WSREP_INFO("GTID replication failed: %d", rcode);
+ if (wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta))
+ {
+ WSREP_ERROR("wsrep::commit_order_enter fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+
+ if (wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, NULL))
+ {
+ WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+
+ thd->wsrep_replicate_GTID= false;
+ my_message(ER_ERROR_DURING_COMMIT,
+ "WSREP GTID replication was interrupted", MYF(0));
+
+ return true;
+ }
+ }
+ thd->wsrep_replicate_GTID= false;
+ return false;
+}
+
+
+/*
+ Utility methods to be called from hooks
+ */
+
+/*
+ Log some THD info and called context
+ */
+static void wsrep_log_thd(THD* thd, bool is_real_trans, const char *function)
+{
+ char message[10];
+ snprintf(message, sizeof(message), "real: %d", is_real_trans);
+ message[sizeof(message) - 1] = '\0';
+ wsrep_log_thd(thd, message, function);
+}
+
+
+/*
+ Determine if the hook should be run
+
+ @return 0 Failure
+ @return 1 Success
+*/
+static int wsrep_run_hook(const THD* thd, bool is_real_trans,
+ bool for_real_trans)
+{
+ return (WSREP(thd) && /* THD is non NULL, wsrep is enabled for thd
+ and is client thread */
+ thd->wsrep_exec_mode != TOTAL_ORDER && /* not TOI execution */
+ thd->wsrep_exec_mode != REPL_RECV && /* not applier or replayer */
+ (!for_real_trans || is_real_trans) &&
+ !(for_real_trans && /* CTAS SELECT phase */
+ WSREP_BINLOG_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT &&
+ thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
+ thd->lex->current_select->item_list.elements)
+ );
+}
+
+static inline
+int wsrep_is_effective_not_to_replay(THD *thd)
+{
+ mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd);
+ int ret= (
+ /* effective */
+ thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID &&
+ /* not to replay */
+ thd->wsrep_conflict_state() != MUST_REPLAY
+ );
+ return ret;
+}
+
+
+int wsrep_after_row(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_after_row");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ /*
+ We want to run this hook for each row, not just ones which
+ end autocommits or transactions.
+ */
+ if (!wsrep_run_hook(thd, is_real_trans, false))
+ {
+ DBUG_RETURN(0);
+ }
+
+
+#if 0
+ /*
+ Logging this hook is disabled, it gets very verbose.
+ */
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_row enter");
+#endif /* 0 */
+ int ret= 0;
+
+ /*
+ TODO: Move this before row operation, maybe before_row() hook.
+ */
+ if (!wsrep_certify_nonPK)
+ {
+ for (TABLE* table= thd->open_tables; table != NULL; table= table->next)
+ {
+ if (table->key_info == NULL || table->s->primary_key == MAX_KEY)
+ {
+ WSREP_DEBUG("No primary key found for table %s.%s",
+ table->s->db.str, table->s->table_name.str);
+ ret= 1;
+ break;
+ }
+ }
+ }
+
+ if (!ret)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
+ {
+ ret|= wsrep_SR_step(thd, WSREP_FRAG_BYTES);
+ ret|= wsrep_SR_step(thd, WSREP_FRAG_ROWS);
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+#if 0
+ /*
+ Logging this hook is disabled, it gets very verbose.
+ */
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_row leave");
+#endif /* 0 */
+
+
+ DBUG_RETURN(ret);
+}
+
+int wsrep_before_prepare(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_before_prepare");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ if (!wsrep_run_hook(thd, is_real_trans, true))
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_prepare enter");
+ }
+
+ int ret= 0;
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (wsrep_is_effective_not_to_replay(thd))
+ {
+ if (thd->wsrep_is_streaming())
+ {
+ DBUG_EXECUTE_IF("crash_last_fragment_commit_before_fragment_removal",
+ DBUG_SUICIDE(););
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ /*
+ We don't support implicit commit for SR transactions.
+ */
+ if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN))
+ {
+ wsrep_override_error(thd, ER_ERROR_DURING_COMMIT);
+ ret= 1;
+ }
+ else
+ {
+ /*
+ Disable SR temporarily in order to avoid SR step from
+ after_row() hook when deleting fragments.
+ */
+ ulong frag_size_orig= thd->variables.wsrep_trx_fragment_size;
+ thd->variables.wsrep_trx_fragment_size= 0;
+ wsrep_remove_SR_fragments(thd);
+ thd->variables.wsrep_trx_fragment_size= frag_size_orig;
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ DBUG_EXECUTE_IF("crash_last_fragment_commit_after_fragment_removal",
+ DBUG_SUICIDE(););
+ }
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_prepare leave");
+ }
+ DBUG_RETURN(ret);
+}
+
+int wsrep_after_prepare(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_after_prepare");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ if (!wsrep_run_hook(thd, is_real_trans, true))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_prepare enter");
+ }
+
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE);
+ /*
+ thd->wsrep_exec_mode will be set in wsrep_certify() according
+ to outcome
+ */
+ int ret= 1;
+
+ if (wsrep_is_effective_not_to_replay(thd))
+ {
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
+ {
+ ret= wsrep_certify(thd);
+ if (ret)
+ {
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_REPLAY ||
+ thd->get_stmt_da()->is_error());
+ }
+ }
+ else
+ {
+ /*
+ BF aborted before pre commit, set state to aborting
+ and return error to trigger rollback.
+ */
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT);
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ }
+ }
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_prepare leave");
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(ret);
+}
+
+int wsrep_before_commit(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_before_commit");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ /*
+ Applier/replayer codepath
+ */
+ if (thd->wsrep_exec_mode == REPL_RECV)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit enter");
+ if (is_real_trans)
+ {
+ DBUG_ASSERT(thd->wsrep_trx_must_order_commit());
+ if (wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta) != WSREP_OK)
+ {
+ WSREP_ERROR("Failed to enter applier commit order critical section");
+ DBUG_RETURN(1);
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_COMMITTING);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit leave");
+ DBUG_RETURN(0);
+ }
+
+
+ if (!wsrep_run_hook(thd, is_real_trans, true))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit enter");
+ }
+
+ int ret= 0;
+ if (thd->wsrep_exec_mode == LOCAL_STATE)
+ {
+ /*
+ We got here without having prepare phase first. This may
+ happen for example via trans_commit_stmt() -> tc_log->commit(thd, false)
+ in case of autocommit DML and binlog_format = STATEMENT.
+ */
+ if (wsrep_is_effective_not_to_replay(thd))
+ {
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
+ {
+ ret= wsrep_certify(thd);
+ }
+ else
+ {
+ /*
+ BF aborted before pre commit, set state to aborting
+ and return error to trigger rollback.
+ */
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT);
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ ret= 1;
+ }
+ }
+ }
+
+
+ if (!ret && wsrep_is_effective_not_to_replay(thd))
+ {
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ ret= 1;
+ }
+ else
+ {
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ wsrep_status_t rcode= wsrep->commit_order_enter(wsrep,
+ &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ switch (rcode)
+ {
+ case WSREP_OK:
+ wsrep_xid_init(&thd->wsrep_xid, thd->wsrep_trx_meta.gtid.uuid,
+ thd->wsrep_trx_meta.gtid.seqno);
+ break;
+ case WSREP_BF_ABORT:
+ DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
+ if (thd->wsrep_conflict_state() != MUST_ABORT)
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ ++wsrep_replaying;
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+ ret= 1;
+ break;
+ default:
+ WSREP_ERROR("Could not enter commit order critical section");
+ abort();
+ }
+ }
+ }
+
+ DBUG_ASSERT(ret ||
+ thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID ||
+ thd->wsrep_exec_mode == LOCAL_COMMIT);
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit leave");
+ }
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(ret);
+}
+
+int wsrep_ordered_commit(THD* thd, bool all, const wsrep_apply_error& err)
+{
+ DBUG_ENTER("wsrep_ordered_commit");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ /*
+ Applier/replayer codepath
+ */
+ if (thd->wsrep_exec_mode == REPL_RECV)
+ {
+ int ret= 0;
+ wsrep_log_thd(thd, is_real_trans, "wsrep_ordered_commit enter");
+ if (is_real_trans)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ bool run_commit_order_leave=
+ (thd->wsrep_query_state() != QUERY_ORDERED_COMMIT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ if (run_commit_order_leave)
+ {
+ wsrep_buf_t const err_buf= err.get_buf();
+ wsrep_status_t const rcode=
+ wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, &err_buf);
+
+ if (rcode != WSREP_OK)
+ {
+ DBUG_ASSERT(rcode == WSREP_NODE_FAIL);
+ if (err.is_null())
+ {
+ WSREP_ERROR("Failed to leave commit order critical section, "
+ "rcode: %d", rcode);
+ }
+ else
+ {
+ WSREP_WARN("Replication can't continue due to the error in a "
+ "writeset apply operation: %s", err.c_str());
+ }
+ ret= 1;
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+ }
+ DBUG_RETURN(ret);
+ }
+
+ if (!wsrep_run_hook(thd, is_real_trans, true))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_ordered_commit enter");
+ }
+
+ DBUG_ASSERT(thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID ||
+ (thd->wsrep_exec_mode == LOCAL_COMMIT &&
+ thd->wsrep_query_state() == QUERY_COMMITTING));
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+ if (wsrep_is_effective_not_to_replay(thd))
+ {
+ thd->wsrep_SR_fragments.clear();
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ if (wsrep_thd_trx_seqno(thd) != WSREP_SEQNO_UNDEFINED &&
+ wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, NULL))
+ {
+ WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT);
+ }
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_ordered_commit leave");
+ }
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(0);
+}
+
+int wsrep_after_commit(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_after_commit");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ if (!wsrep_run_hook(thd, is_real_trans, true))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_commit enter");
+ }
+
+ DBUG_ASSERT(thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID ||
+ (thd->wsrep_exec_mode == LOCAL_COMMIT &&
+ (thd->wsrep_query_state() == QUERY_COMMITTING ||
+ thd->wsrep_query_state() == QUERY_ORDERED_COMMIT)));
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == MUST_ABORT);
+
+ if (wsrep_is_effective_not_to_replay(thd))
+ {
+ if (thd->wsrep_query_state() == QUERY_COMMITTING)
+ {
+ thd->wsrep_SR_fragments.clear();
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ if (wsrep_thd_trx_seqno(thd) != WSREP_SEQNO_UNDEFINED &&
+ wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, NULL))
+ {
+ WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT);
+ }
+
+ DBUG_ASSERT(thd->wsrep_query_state() == QUERY_ORDERED_COMMIT);
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ if (wsrep->release(wsrep, &thd->wsrep_ws_handle))
+ {
+ WSREP_WARN("wsrep::release fail: %lld %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ }
+
+ if (thd->wsrep_conflict_state() == MUST_ABORT)
+ {
+ assert(0);
+ WSREP_LOG_THD(thd, "BF aborted at commit phase");
+ thd->killed= NOT_KILLED;
+ thd->set_wsrep_conflict_state(NO_CONFLICT);
+ }
+
+ wsrep_cleanup_transaction(thd);
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_commit leave");
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(0);
+}
+
+int wsrep_before_rollback(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_before_rollback");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ if (!wsrep_run_hook(thd, is_real_trans, false))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ (void)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle,
+ thd->wsrep_next_trx_id());
+
+ if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
+ {
+ WSREP_DEBUG("wsrep_before_rollback: setting trx_id to undefined, thd %llu %s",
+ thd->thread_id, thd->query());
+ }
+ }
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_rollback enter");
+ }
+
+ if (thd->wsrep_query_state() == QUERY_COMMITTING)
+ {
+ DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT);
+ WSREP_DEBUG("Query aborted while committing");
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ thd->set_wsrep_conflict_state(MUST_REPLAY);
+ thd->wsrep_exec_mode= LOCAL_STATE;
+ }
+
+ if (thd->wsrep_exec_mode != LOCAL_ROLLBACK &&
+ wsrep_is_effective_not_to_replay(thd) &&
+ (is_real_trans ||
+ (thd->wsrep_is_streaming() &&
+ (!wsrep_stmt_rollback_is_safe(thd) ||
+ thd->wsrep_conflict_state() != NO_CONFLICT))))
+ {
+ if (thd->wsrep_is_streaming() &&
+ /*
+ Cert failure will generate implicit rollback event on slaves
+
+ TODO: Need to do SR table cleanup on certification failure here.
+ */
+ thd->wsrep_conflict_state() != CERT_FAILURE &&
+ thd->wsrep_SR_rollback_replicated_for_trx != thd->wsrep_trx_id())
+ {
+ wsrep_prepare_SR_trx_info_for_rollback(thd);
+ thd->wsrep_SR_rollback_replicated_for_trx= thd->wsrep_trx_id();
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ DEBUG_SYNC(thd, "wsrep_before_SR_rollback");
+ WSREP_DEBUG("Replicating rollback for %ld %ld",
+ thd->thread_id, thd->wsrep_trx_id());
+ wsrep_status_t rcode= wsrep->rollback(wsrep,
+ thd->wsrep_trx_id(), NULL);
+ if (rcode != WSREP_OK)
+ {
+ WSREP_WARN("failed to send SR rollback for %lld", thd->thread_id);
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ }
+ thd->wsrep_exec_mode= LOCAL_ROLLBACK;
+ }
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_before_rollback leave");
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(0);
+}
+
+int wsrep_after_rollback(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_after_rollback");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ if (!wsrep_run_hook(thd, is_real_trans, false))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_rollback enter");
+ }
+
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || /* voluntary or stmt rollback */
+ thd->wsrep_conflict_state() == MUST_ABORT || /* BF abort */
+ thd->wsrep_conflict_state() == ABORTING || /* called from wsrep_client_rollback() */
+ thd->wsrep_conflict_state() == CERT_FAILURE || /* cert failure */
+ thd->wsrep_conflict_state() == MUST_REPLAY || /* BF abort with successful repl */
+ (thd->wsrep_conflict_state() == ABORTED) /* trans_rollback_stmt() from mysql_exec_command() */
+ );
+
+ if (!is_real_trans)
+ {
+ /*
+ Statement rollback
+ */
+ if ((thd->wsrep_is_streaming() && !wsrep_stmt_rollback_is_safe(thd)))
+ {
+ /*
+ Statement rollback is not safe, do full rollback and report to client.
+ */
+ if (thd->wsrep_conflict_state() == NO_CONFLICT)
+ {
+ /*
+ If the statement rollback is due to an error, such as ER_DUP_ENTRY,
+ the client may not expect a full transaction rollback.
+ Set the conflict state to must abort here so that after_command()
+ hook will override the error to ER_LOCK_DEADLOCK.
+ */
+ thd->set_wsrep_conflict_state(MUST_ABORT);
+ }
+
+ /*
+ From trans_rollback()
+ */
+ thd->server_status&=
+ ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ /*
+ Calling ha_rollback_trans() here will call rollback hooks recursively.
+ */
+ ha_rollback_trans(thd, TRUE);
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->variables.option_bits&= ~OPTION_BEGIN;
+ //thd->transaction.all.reset_unsafe_rollback_flags();
+ thd->transaction.all.m_unsafe_rollback_flags= 0;
+ thd->lex->start_transaction_opt= 0;
+ }
+ }
+ else
+ {
+ if (thd->wsrep_conflict_state() == ABORTED)
+ {
+ thd->wsrep_exec_mode= LOCAL_ROLLBACK;
+ }
+ if (wsrep_is_effective_not_to_replay(thd))
+ {
+ /*
+ Must have gone through before_rollback() hook at least once.
+ */
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_ROLLBACK);
+ }
+ }
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_rollback leave");
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(0);
+}
+
+int wsrep_after_command(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_after_command");
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ /*
+ We want to run this hook for each command, not just ones which
+ end autocommits or transactions.
+ */
+ if (!wsrep_run_hook(thd, is_real_trans, false))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_command enter");
+ }
+
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE ||
+ thd->wsrep_exec_mode == LOCAL_ROLLBACK);
+
+ int ret= 0;
+
+ switch (thd->wsrep_exec_mode)
+ {
+ case LOCAL_STATE:
+ /*
+ Run SR step if
+ - No conflict detected
+ - Trnsaction is active, it has acquired trx_id
+ - Not read-only command
+ */
+ if (thd->wsrep_conflict_state() == NO_CONFLICT &&
+ thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID &&
+ thd->lex->sql_command != SQLCOM_SELECT)
+ {
+ ret|= wsrep_SR_step(thd, WSREP_FRAG_BYTES);
+ ret|= wsrep_SR_step(thd, WSREP_FRAG_STATEMENTS);
+ }
+ break;
+ case LOCAL_ROLLBACK:
+ {
+ bool should_retry= false;
+ const bool forced_rollback(thd->wsrep_conflict_state() == MUST_ABORT ||
+ thd->wsrep_conflict_state() == CERT_FAILURE);
+
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT ||
+ thd->wsrep_conflict_state() == MUST_ABORT ||
+ thd->wsrep_conflict_state() == CERT_FAILURE);
+ /*
+ If conflict state is NO_CONFLICT the transaction was either
+ voluntary or done due to deadlock.
+ */
+ if (forced_rollback)
+ {
+ should_retry= !(
+ thd->wsrep_is_streaming() || // SR transactions do not retry
+ thd->spcont // SP code not patched to handle retry
+ );
+ wsrep_client_rollback(thd, false);
+ }
+ wsrep_post_rollback(thd);
+ if (forced_rollback)
+ {
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ }
+ wsrep_cleanup_transaction(thd);
+ DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE);
+ DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT);
+ /*
+ Retry autocommit in case of deadlock error, usually seen
+ as ER_LOCK_DEADLOCK, sometimes as ER_QUERY_INTERRUPTED.
+ */
+ if (should_retry && thd->get_stmt_da()->is_error() &&
+ (thd->get_stmt_da()->sql_errno() == ER_LOCK_DEADLOCK ||
+ thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED))
+ {
+ thd->set_wsrep_conflict_state(RETRY_AUTOCOMMIT);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (thd->wsrep_conflict_state() == MUST_ABORT ||
+ thd->wsrep_conflict_state() == CERT_FAILURE)
+ {
+ wsrep_client_rollback(thd);
+ wsrep_post_rollback(thd);
+ wsrep_override_error(thd, ER_LOCK_DEADLOCK);
+ wsrep_cleanup_transaction(thd);
+ }
+
+ if (thd->wsrep_conflict_state() == MUST_REPLAY &&
+ !thd->spcont)
+ {
+ /*
+ BF aborted during commit, must replay
+ */
+ wsrep_replay_transaction(thd);
+ }
+
+ if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID)
+ {
+ wsrep_log_thd(thd, is_real_trans, "wsrep_after_command leave");
+ }
+
+
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(ret);
+}
+
+int wsrep_before_GTID_binlog(THD* thd, bool all)
+{
+ DBUG_ENTER("wsrep_before_GTID_binlogt");
+ int ret= 0;
+
+ bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
+
+ if (!wsrep_run_hook(thd, is_real_trans, true))
+ {
+ DBUG_RETURN(0);
+ }
+
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ if (wsrep_replicate_GTID(thd))
+ {
+ ret = 1;
+ }
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ wsrep_status_t rcode;
+ if (!ret &&
+ (rcode = wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta)))
+ {
+ WSREP_ERROR("wsrep::commit_order_enter fail: %llu %d",
+ (long long)thd->thread_id, rcode);
+ ret= 1;
+ }
+
+ if (!ret &&
+ (rcode = wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle,
+ &thd->wsrep_trx_meta, NULL)))
+ {
+ WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d",
+ (long long)thd->thread_id, rcode);
+ ret= 1;
+ }
+
+ if (!ret)
+ {
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT);
+ thd->set_wsrep_query_state(QUERY_EXEC);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+ }
+
+ if (wsrep->release(wsrep, &thd->wsrep_ws_handle))
+ {
+ WSREP_WARN("wsrep::release fail: %lld %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+ mysql_mutex_lock(&thd->LOCK_wsrep_thd);
+ wsrep_cleanup_transaction(thd);
+ mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
+
+ DBUG_RETURN(ret);
+}
+
+int wsrep_register_trans_observer(void *p)
+{
+ return 0;
+}
+
+int wsrep_unregister_trans_observer(void *p)
+{
+ return 0;
+}
diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h
new file mode 100644
index 00000000000..91b6d25eb78
--- /dev/null
+++ b/sql/wsrep_trans_observer.h
@@ -0,0 +1,117 @@
+/* Copyright 2016 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef WSREP_TRANS_OBSERVER_H
+#define WSREP_TRANS_OBSERVER_H
+
+#include "my_global.h"
+#include "wsrep_applier.h" /* wsrep_apply_error */
+
+class THD;
+
+/*
+ Called after each row operation.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_after_row(THD*, bool);
+
+/*
+ Called before the transaction is prepared.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_before_prepare(THD*, bool);
+
+/*
+ Called after the transaction has been prepared.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_after_prepare(THD*, bool);
+
+
+/*
+ Called before the transaction is committed.
+
+ This function must be called from both client and
+ applier contexts before commit.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_before_commit(THD*, bool);
+
+/*
+ Called after the transaction has been ordered for commit.
+
+ This function must be called from both client and
+ applier contexts after the commit has been ordered.
+
+ @param thd Pointer to THD
+ @param all
+ @param err Error buffer in case of applying error
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_ordered_commit(THD* thd, bool all, const wsrep_apply_error& err);
+
+/*
+ Called after the transaction has been committed.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_after_commit(THD*, bool);
+
+/*
+ Called before the transaction is rolled back.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_before_rollback(THD*, bool);
+
+/*
+ Called after the transaction has been rolled back.
+
+ Return zero on succes, non-zero on failure.
+ */
+int wsrep_after_rollback(THD*, bool);
+
+/*
+ Called after each command.
+
+ Return zero on success, non-zero on failure.
+ */
+int wsrep_after_command(THD*, bool);
+
+/*
+ Called before a GTID is logged into binlog without committing a
+ transaction.
+
+ Return zero on success, non-zero on failure.
+ */
+int wsrep_before_GTID_binlog(THD* thd, bool);
+
+
+/*
+ Register wsrep transaction observer hooks
+*/
+int wsrep_register_trans_observer(void *p);
+
+/*
+ Unregister wsrep transaction observer hooks
+ */
+int wsrep_unregister_trans_observer(void *p);
+
+#endif /* WSREP_TRANS_OBSERVER */
diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc
index 3c341e222b3..e9dad5f1912 100644
--- a/sql/wsrep_utils.cc
+++ b/sql/wsrep_utils.cc
@@ -21,6 +21,7 @@
#endif
#include "mariadb.h"
+#include "my_pthread.h"
#include "wsrep_utils.h"
#include "wsrep_mysqld.h"
diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h
index 277cea9dc31..bb3203c87e9 100644
--- a/sql/wsrep_utils.h
+++ b/sql/wsrep_utils.h
@@ -21,6 +21,27 @@
unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6);
size_t wsrep_guess_ip (char* buf, size_t buf_len);
+namespace wsp {
+class node_status
+{
+public:
+ node_status() : status(WSREP_MEMBER_UNDEFINED) {}
+ void set(wsrep_member_status_t new_status,
+ const wsrep_view_info_t* view = 0)
+ {
+ if (status != new_status || 0 != view)
+ {
+ wsrep_notify_status(new_status, view);
+ status = new_status;
+ }
+ }
+ wsrep_member_status_t get() const { return status; }
+private:
+ wsrep_member_status_t status;
+};
+} /* namespace wsp */
+
+extern wsp::node_status local_status;
/* returns the length of the host part of the address string */
size_t wsrep_host_len(const char* addr, size_t addr_len);
@@ -219,6 +240,7 @@ public:
return &member_info_;
}
+#ifdef WITH_WSREP
int lock()
{
return mysql_mutex_lock(&LOCK_wsrep_config_state);
@@ -228,6 +250,7 @@ public:
{
return mysql_mutex_unlock(&LOCK_wsrep_config_state);
}
+#endif
private:
wsrep_view_info_t view_;
@@ -314,6 +337,17 @@ private:
char* string_;
};
+/* scope level lock */
+class auto_lock
+{
+public:
+ auto_lock(mysql_mutex_t* m) : m_(m) { mysql_mutex_lock(m_); }
+ ~auto_lock() { mysql_mutex_unlock(m_); }
+private:
+ mysql_mutex_t& operator =(mysql_mutex_t&);
+ mysql_mutex_t* const m_;
+};
+
#ifdef REMOVED
class lock
{
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 7fe120beb8e..758a804d384 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -28,8 +28,6 @@
ulong wsrep_reject_queries;
-static long wsrep_prev_slave_threads = wsrep_slave_threads;
-
int wsrep_init_vars()
{
wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME));
@@ -157,15 +155,15 @@ bool wsrep_start_position_verify (const char* start_str)
static
-bool wsrep_set_local_position(const char* const value, size_t length,
- bool const sst)
+bool wsrep_set_local_position(THD* thd, const char* const value,
+ size_t length, bool const sst)
{
wsrep_uuid_t uuid;
size_t const uuid_len = wsrep_uuid_scan(value, length, &uuid);
wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10);
if (sst) {
- return wsrep_sst_received (wsrep, uuid, seqno, NULL, 0, false);
+ wsrep_sst_received (thd, wsrep, uuid, seqno, NULL, 0, false);
} else {
// initialization
local_uuid = uuid;
@@ -194,7 +192,7 @@ bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var)
As part of further verification, we try to update the value and catch
errors (if any).
*/
- if (wsrep_set_local_position(var->save_result.string_value.str,
+ if (wsrep_set_local_position(thd, var->save_result.string_value.str,
var->save_result.string_value.length,
true))
{
@@ -226,7 +224,7 @@ bool wsrep_start_position_init (const char* val)
return true;
}
- if (wsrep_set_local_position (val, strlen(val), false))
+ if (wsrep_set_local_position (NULL, val, strlen(val), false))
{
WSREP_ERROR("Failed to set initial wsep_start_position: %s", val);
return true;
@@ -332,8 +330,6 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
{
bool rcode= false;
- bool wsrep_on_saved= thd->variables.wsrep_on;
- thd->variables.wsrep_on= false;
WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider);
@@ -344,9 +340,15 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
+ mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool);
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd);
- mysql_mutex_lock(&LOCK_global_system_variables);
+
+ /* provider status variables are allocated in provider library
+ and need to freed here, otherwise a dangling reference to
+ wsrep_status_vars would remain in THD
+ */
+ wsrep_free_status(thd);
if (wsrep_inited == 1)
wsrep_deinit(false);
@@ -364,10 +366,10 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
// we sure don't want to use old address with new provider
wsrep_cluster_address_init(NULL);
wsrep_provider_options_init(NULL);
+ if (!rcode)
+ refresh_provider_options();
- thd->variables.wsrep_on= wsrep_on_saved;
-
- refresh_provider_options();
+ mysql_mutex_lock(&LOCK_global_system_variables);
return rcode;
}
@@ -468,8 +470,6 @@ bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var)
bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
{
- bool wsrep_on_saved;
-
/* Do not proceed if wsrep provider is not loaded. */
if (!wsrep)
{
@@ -477,9 +477,6 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
return false;
}
- wsrep_on_saved= thd->variables.wsrep_on;
- thd->variables.wsrep_on= false;
-
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
@@ -487,16 +484,10 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
+ mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool);
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd);
- /*
- Unlock and lock LOCK_wsrep_slave_threads to maintain lock order & avoid
- any potential deadlock.
- */
- mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
- mysql_mutex_lock(&LOCK_global_system_variables);
- mysql_mutex_lock(&LOCK_wsrep_slave_threads);
if (wsrep_start_replication())
{
@@ -504,7 +495,13 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
wsrep_create_appliers(wsrep_slave_threads);
}
- thd->variables.wsrep_on= wsrep_on_saved;
+ /* locking order to be enforced is:
+ 1. LOCK_global_system_variables
+ 2. LOCK_wsrep_slave_threads
+ */
+ mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
+ mysql_mutex_lock(&LOCK_global_system_variables);
+ mysql_mutex_lock(&LOCK_wsrep_slave_threads);
return false;
}
@@ -594,8 +591,8 @@ void wsrep_node_address_init (const char* value)
static void wsrep_slave_count_change_update ()
{
- wsrep_slave_count_change += (wsrep_slave_threads - wsrep_prev_slave_threads);
- wsrep_prev_slave_threads = wsrep_slave_threads;
+ // wsrep_running_threads = appliers threads + 2 rollbacker threads
+ wsrep_slave_count_change = (wsrep_slave_threads - wsrep_running_threads + 2);
}
bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
@@ -667,6 +664,34 @@ bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var)
return false;
}
+bool wsrep_trx_fragment_size_check (sys_var *self, THD* thd, set_var* var)
+{
+ if (var->value == NULL) {
+ return false;
+ }
+
+ const ulong new_trx_fragment_size = var->value->val_uint();
+
+ if (!WSREP(thd) && new_trx_fragment_size > 0) {
+ push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_VALUE_FOR_VAR,
+ "Cannot set 'wsrep_trx_fragment_size' to a value other than "
+ "0 because wsrep is switched off.");
+ return true;
+ }
+
+ if (new_trx_fragment_size > 0 && !wsrep_provider_is_SR_capable()) {
+ push_warning (thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_VALUE_FOR_VAR,
+ "Cannot set 'wsrep_trx_fragment_size' to a value other than "
+ "0 because the wsrep_provider does not support streaming "
+ "replication.");
+ return true;
+ }
+
+ return false;
+}
+
bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type)
{
DBUG_ASSERT(wsrep);
@@ -687,16 +712,17 @@ bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type)
static SHOW_VAR wsrep_status_vars[]=
{
{"connected", (char*) &wsrep_connected, SHOW_BOOL},
- {"ready", (char*) &wsrep_ready, SHOW_BOOL},
+ {"ready", (char*) &wsrep_show_ready, SHOW_FUNC},
{"cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
{"cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG},
{"cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR},
{"cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH},
{"local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH},
- {"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_SIMPLE_FUNC},
+ {"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC},
{"provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR},
{"provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR},
{"provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
+ {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
{"thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH}
};
@@ -705,6 +731,30 @@ static int show_var_cmp(const void *var1, const void *var2)
return strcasecmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
}
+/*
+ * Status variables stuff below
+ */
+static inline void
+wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep)
+{
+ mysql->name = wsrep->name;
+ switch (wsrep->type) {
+ case WSREP_VAR_INT64:
+ mysql->value = (char*) &wsrep->value._int64;
+ mysql->type = SHOW_LONGLONG;
+ break;
+ case WSREP_VAR_STRING:
+ mysql->value = (char*) &wsrep->value._string;
+ mysql->type = SHOW_CHAR_PTR;
+ break;
+ case WSREP_VAR_DOUBLE:
+ mysql->value = (char*) &wsrep->value._double;
+ mysql->type = SHOW_DOUBLE;
+ break;
+ }
+}
+
+#ifdef OLD_MARIADB
int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope)
{
@@ -750,4 +800,78 @@ int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff,
v->name= 0; // terminator
return 0;
}
+#endif
+
+#if DYNAMIC
+// somehow this mysql status thing works only with statically allocated arrays.
+static SHOW_VAR* mysql_status_vars = NULL;
+static int mysql_status_len = -1;
+#else
+static SHOW_VAR mysql_status_vars[512 + 1];
+static const int mysql_status_len = 512;
+#endif
+
+static void export_wsrep_status_to_mysql(THD* thd)
+{
+ int wsrep_status_len, i;
+
+ wsrep_free_status(thd);
+
+ thd->wsrep_status_vars = wsrep->stats_get(wsrep);
+
+ if (!thd->wsrep_status_vars) {
+ return;
+ }
+
+ for (wsrep_status_len = 0;
+ thd->wsrep_status_vars[wsrep_status_len].name != NULL;
+ wsrep_status_len++) {
+ /* */
+ }
+
+#if DYNAMIC
+ if (wsrep_status_len != mysql_status_len) {
+ void* tmp = realloc (mysql_status_vars,
+ (wsrep_status_len + 1) * sizeof(SHOW_VAR));
+ if (!tmp) {
+
+ sql_print_error ("Out of memory for wsrep status variables."
+ "Number of variables: %d", wsrep_status_len);
+ return;
+ }
+
+ mysql_status_len = wsrep_status_len;
+ mysql_status_vars = (SHOW_VAR*)tmp;
+ }
+ /* @TODO: fix this: */
+#else
+ if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len;
+#endif
+
+ for (i = 0; i < wsrep_status_len; i++)
+ wsrep_assign_to_mysql (mysql_status_vars + i, thd->wsrep_status_vars + i);
+
+ mysql_status_vars[wsrep_status_len].name = NullS;
+ mysql_status_vars[wsrep_status_len].value = NullS;
+ mysql_status_vars[wsrep_status_len].type = SHOW_LONG;
+}
+
+int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff)
+{
+ if (WSREP_ON)
+ {
+ export_wsrep_status_to_mysql(thd);
+ var->type= SHOW_ARRAY;
+ var->value= (char *) &mysql_status_vars;
+ }
+ return 0;
+}
+void wsrep_free_status (THD* thd)
+{
+ if (thd->wsrep_status_vars)
+ {
+ wsrep->stats_free (wsrep, thd->wsrep_status_vars);
+ thd->wsrep_status_vars = 0;
+ }
+}
diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h
index 7d3ff50f1d2..8c1d0ddbf51 100644
--- a/sql/wsrep_var.h
+++ b/sql/wsrep_var.h
@@ -90,10 +90,13 @@ extern bool wsrep_slave_threads_update UPDATE_ARGS;
extern bool wsrep_desync_check CHECK_ARGS;
extern bool wsrep_desync_update UPDATE_ARGS;
-extern bool wsrep_max_ws_size_check CHECK_ARGS;
+extern bool wsrep_trx_fragment_size_check CHECK_ARGS;
+
extern bool wsrep_max_ws_size_update UPDATE_ARGS;
extern bool wsrep_reject_queries_update UPDATE_ARGS;
+extern bool wsrep_reject_queries_update UPDATE_ARGS;
+
#else /* WITH_WSREP */
#define WSREP_NONE
diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc
index 618c98eade7..e53a3fdeaad 100644
--- a/sql/wsrep_xid.cc
+++ b/sql/wsrep_xid.cc
@@ -46,8 +46,10 @@ void wsrep_xid_init(XID* xid, const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
int8store(xid->data + WSREP_XID_SEQNO_OFFSET,seqno);
}
-int wsrep_is_wsrep_xid(const XID* xid)
+//int wsrep_is_wsrep_xid(const XID* xid)
+int wsrep_is_wsrep_xid(const void* xid_ptr)
{
+ const XID* xid= reinterpret_cast<const XID*>(xid_ptr);
return (xid->formatID == 1 &&
xid->gtrid_length == WSREP_XID_GTRID_LEN &&
xid->bqual_length == 0 &&
@@ -114,17 +116,16 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
return FALSE;
}
-bool wsrep_set_SE_checkpoint(XID& xid)
+void wsrep_set_SE_checkpoint(XID& xid)
{
- return plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
- &xid);
+ plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid);
}
-bool wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
+void wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
{
XID xid;
wsrep_xid_init(&xid, uuid, seqno);
- return wsrep_set_SE_checkpoint(xid);
+ wsrep_set_SE_checkpoint(xid);
}
static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
@@ -144,13 +145,13 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
return FALSE;
}
-bool wsrep_get_SE_checkpoint(XID& xid)
+void wsrep_get_SE_checkpoint(XID& xid)
{
- return plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
+ plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
&xid);
}
-bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
+void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
{
uuid= WSREP_UUID_UNDEFINED;
seqno= WSREP_SEQNO_UNDEFINED;
@@ -159,24 +160,27 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
memset(&xid, 0, sizeof(xid));
xid.formatID= -1;
- if (wsrep_get_SE_checkpoint(xid))
- {
- return true;
- }
+ wsrep_get_SE_checkpoint(xid);
- if (xid.formatID == -1) // nil XID
- {
- return false;
- }
+ if (xid.formatID == -1) return; // nil XID
if (!wsrep_is_wsrep_xid(&xid))
{
WSREP_WARN("Read non-wsrep XID from storage engines.");
- return false;
+ return;
}
uuid= *wsrep_xid_uuid(xid);
seqno= wsrep_xid_seqno(xid);
+}
- return false;
+void
+wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size)
+{
+ const THD *thd= (const THD*)thd_ptr;
+ DBUG_ASSERT(xid_size == sizeof(xid_t));
+ if (xid_size == sizeof(xid_t))
+ {
+ *(xid_t*) xid = thd->wsrep_xid;
+ }
}
diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h
index 5b33a904de1..04dedb1f583 100644
--- a/sql/wsrep_xid.h
+++ b/sql/wsrep_xid.h
@@ -15,22 +15,22 @@
#ifndef WSREP_XID_H
#define WSREP_XID_H
-
#include <my_config.h>
-
+
#ifdef WITH_WSREP
#include "../wsrep/wsrep_api.h"
#include "handler.h" // XID typedef
void wsrep_xid_init(xid_t*, const wsrep_uuid_t&, wsrep_seqno_t);
+extern "C" int wsrep_is_wsrep_xid(const void* xid);
const wsrep_uuid_t* wsrep_xid_uuid(const XID&);
wsrep_seqno_t wsrep_xid_seqno(const XID&);
-//void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */
-bool wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&);
-//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */
-bool wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t);
+//void wsrep_get_SE_checkpoint(XID&); uncomment if needed
+void wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&);
+//void wsrep_set_SE_checkpoint(XID&); uncomment if needed
+void wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t);
#endif /* WITH_WSREP */
#endif /* WSREP_UTILS_H */
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index a0c4baad64d..bc96e91c486 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -44,8 +44,8 @@ Created April 08, 2011 Vasil Dimov
#include <algorithm>
-#include "mysql/service_wsrep.h" /* wsrep_recovery */
#include <my_service_manager.h>
+#include "mysql/service_wsrep.h" /* wsrep_recovery */
enum status_severity {
STATUS_INFO,
@@ -824,7 +824,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
if (srv_buffer_pool_load_at_startup) {
#ifdef WITH_WSREP
- if (!wsrep_recovery) {
+ if (!get_wsrep_recovery()) {
#endif /* WITH_WSREP */
buf_load();
#ifdef WITH_WSREP
@@ -858,7 +858,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
"Dumping of buffer pool not started"
" as load was incomplete");
#ifdef WITH_WSREP
- } else if (wsrep_recovery) {
+ } else if (get_wsrep_recovery()) {
#endif /* WITH_WSREP */
} else {
buf_dump(FALSE/* do complete dump at shutdown */);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index b0af34814af..56d41bf00b6 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -153,13 +153,11 @@ void close_thread_tables(THD* thd);
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
static inline wsrep_ws_handle_t*
-wsrep_ws_handle(THD* thd, const trx_t* trx) {
+wsrep_ws_handle(THD* thd) {
return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd),
- (wsrep_trx_id_t)trx->id);
+ wsrep_thd_next_trx_id(thd));
}
-extern TC_LOG* tc_log;
-extern void wsrep_cleanup_transaction(THD *thd);
static int
wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
my_bool signal);
@@ -167,6 +165,15 @@ static void
wsrep_fake_trx_id(handlerton* hton, THD *thd);
static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
+
+extern bool wsrep_prepare_key_for_innodb(
+ THD* thd,
+ const uchar *cache_key,
+ size_t cache_key_len,
+ const uchar* row_id,
+ size_t row_id_len,
+ wsrep_buf_t* key,
+ size_t* key_len);
#endif /* WITH_WSREP */
/** to protect innobase_open_files */
@@ -4658,6 +4665,14 @@ innobase_commit(
this one, to allow then to group commit with us. */
thd_wakeup_subsequent_commits(thd, 0);
+#ifdef WITH_WSREP
+ /* Serialisation history has been written, so the
+ commit is now ordered. */
+ if (trx->mysql_thd) {
+ (void)wsrep_ordered_commit_if_no_binlog(trx->mysql_thd);
+ }
+#endif /* WITH_WSREP */
+
/* Now do a write + flush of logs. */
trx_commit_complete_for_mysql(trx);
@@ -5137,7 +5152,8 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
{
DBUG_ENTER("innobase_kill_query");
#ifdef WITH_WSREP
- if (wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) {
+ if (wsrep_on(thd) &&
+ wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) {
/* if victim has been signaled by BF thread and/or aborting
is already progressing, following query aborting is not necessary
any more.
@@ -6636,7 +6652,6 @@ ha_innobase::close()
UNIV_INTERN
ulint
wsrep_innobase_mysql_sort(
-/*======================*/
/* out: str contains sort string */
int mysql_type, /* in: MySQL type */
uint charset_number, /* in: number of the charset */
@@ -7060,7 +7075,6 @@ Stores a key value for a row to a buffer.
UNIV_INTERN
uint
wsrep_store_key_val_for_row(
-/*=========================*/
THD* thd,
TABLE* table,
uint keynr, /*!< in: key number */
@@ -7072,7 +7086,8 @@ wsrep_store_key_val_for_row(
{
KEY* key_info = table->key_info + keynr;
KEY_PART_INFO* key_part = key_info->key_part;
- KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts;
+ KEY_PART_INFO* end =
+ key_part + key_info->user_defined_key_parts;
char* buff_start = buff;
enum_field_types mysql_type;
Field* field;
@@ -8779,7 +8794,6 @@ calc_row_difference(
static
int
wsrep_calc_row_hash(
-/*================*/
byte* digest, /*!< in/out: md5 sum */
const uchar* row, /*!< in: row in MySQL format */
TABLE* table, /*!< in: table in MySQL data
@@ -10310,7 +10324,6 @@ wsrep_dict_foreign_find_index(
extern dberr_t
wsrep_append_foreign_key(
-/*===========================*/
trx_t* trx, /*!< in: trx */
dict_foreign_t* foreign, /*!< in: foreign key constraint */
const rec_t* rec, /*!<in: clustered index record */
@@ -10455,7 +10468,8 @@ wsrep_append_foreign_key(
wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
- if (!wsrep_prepare_key(
+ if (!wsrep_prepare_key_for_innodb(
+ thd,
(const uchar*)cache_key,
cache_key_len + 1,
(const uchar*)key, len+1,
@@ -10471,7 +10485,7 @@ wsrep_append_foreign_key(
rcode = (int)wsrep->append_key(
wsrep,
- wsrep_ws_handle(thd, trx),
+ wsrep_ws_handle(thd),
&wkey,
1,
shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
@@ -10491,7 +10505,6 @@ wsrep_append_foreign_key(
static int
wsrep_append_key(
-/*=============*/
THD *thd,
trx_t *trx,
TABLE_SHARE *table_share,
@@ -10502,6 +10515,9 @@ wsrep_append_key(
{
DBUG_ENTER("wsrep_append_key");
bool const copy = true;
+ DBUG_PRINT("enter",
+ ("thd: %lld trx: %lld", wsrep_thd_thread_id(thd),
+ (long long)trx->id));
#ifdef WSREP_DEBUG_PRINT
fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ",
(shared) ? "Shared" : "Exclusive",
@@ -10515,7 +10531,8 @@ wsrep_append_key(
wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
- if (!wsrep_prepare_key(
+ if (!wsrep_prepare_key_for_innodb(
+ thd,
(const uchar*)table_share->table_cache_key.str,
table_share->table_cache_key.length,
(const uchar*)key, key_len,
@@ -10531,7 +10548,7 @@ wsrep_append_key(
int rcode = (int)wsrep->append_key(
wsrep,
- wsrep_ws_handle(thd, trx),
+ wsrep_ws_handle(thd),
&wkey,
1,
shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
@@ -10574,7 +10591,6 @@ referenced_by_foreign_key2(
int
ha_innobase::wsrep_append_keys(
-/*===========================*/
THD *thd,
bool shared,
const uchar* record0, /* in: row in MySQL format */
@@ -10664,12 +10680,10 @@ ha_innobase::wsrep_append_keys(
thd, trx, table_share,
keyval0, len+1, shared);
- if (rcode) {
- DBUG_RETURN(rcode);
- }
+ if (rcode) DBUG_RETURN(rcode);
- if (key_info->flags & HA_NOSAME || shared)
- key_appended = true;
+ if (key_info->flags & HA_NOSAME || shared)
+ key_appended = true;
} else {
WSREP_DEBUG("NULL key skipped: %s",
wsrep_thd_query(thd));
@@ -16754,7 +16768,10 @@ ha_innobase::get_auto_increment(
thd_get_thread_id(ha_thd()),
current, autoinc);
- if (!wsrep_on(ha_thd())) {
+#ifdef WITH_WSREP
+ if (!wsrep_on(ha_thd()))
+#endif
+ {
current = autoinc - m_prebuilt->autoinc_increment;
}
@@ -18793,8 +18810,13 @@ wsrep_innobase_kill_one_trx(
DBUG_RETURN(1);
}
+ if (wsrep_thd_trx_id(thd) == WSREP_UNDEFINED_TRX_ID) {
+ wsrep_ws_handle(thd);
+ }
+
WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
+ wsrep_thd_LOCK(thd);
WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF
"), victim: (%lu) trx: " TRX_ID_FMT,
signal, bf_seqno,
@@ -18806,104 +18828,8 @@ wsrep_innobase_kill_one_trx(
wsrep_thd_conflict_state(thd, FALSE),
wsrep_thd_ws_handle(thd)->trx_id);
- wsrep_thd_LOCK(thd);
- DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock",
- {
- const char act[]=
- "now "
- "wait_for signal.wsrep_after_BF_victim_lock";
- DBUG_ASSERT(!debug_sync_set_action(bf_thd,
- STRING_WITH_LEN(act)));
- };);
-
-
- if (wsrep_thd_query_state(thd) == QUERY_EXITING) {
- WSREP_DEBUG("kill trx EXITING for " TRX_ID_FMT,
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- DBUG_RETURN(0);
- }
-
- if (wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
- WSREP_DEBUG("withdraw for BF trx: " TRX_ID_FMT ", state: %d",
- victim_trx->id,
- wsrep_thd_get_conflict_state(thd));
- }
-
- switch (wsrep_thd_get_conflict_state(thd)) {
- case NO_CONFLICT:
- wsrep_thd_set_conflict_state(thd, MUST_ABORT);
- break;
- case MUST_ABORT:
- WSREP_DEBUG("victim " TRX_ID_FMT " in MUST ABORT state",
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- DBUG_RETURN(0);
- break;
- case ABORTED:
- case ABORTING: // fall through
- default:
- WSREP_DEBUG("victim " TRX_ID_FMT " in state %d",
- victim_trx->id, wsrep_thd_get_conflict_state(thd));
- wsrep_thd_UNLOCK(thd);
- DBUG_RETURN(0);
- break;
- }
-
- switch (wsrep_thd_query_state(thd)) {
- case QUERY_COMMITTING:
- enum wsrep_status rcode;
-
- WSREP_DEBUG("kill query for: %ld",
- thd_get_thread_id(thd));
- WSREP_DEBUG("kill trx QUERY_COMMITTING for " TRX_ID_FMT,
- victim_trx->id);
-
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- } else {
- wsrep_t *wsrep= get_wsrep();
- rcode = wsrep->abort_pre_commit(
- wsrep, bf_seqno,
- (wsrep_trx_id_t)wsrep_thd_ws_handle(thd)->trx_id
- );
-
- switch (rcode) {
- case WSREP_WARNING:
- WSREP_DEBUG("cancel commit warning: "
- TRX_ID_FMT,
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- DBUG_RETURN(1);
- break;
- case WSREP_OK:
- break;
- default:
- WSREP_ERROR(
- "cancel commit bad exit: %d "
- TRX_ID_FMT,
- rcode, victim_trx->id);
- /* unable to interrupt, must abort */
- /* note: kill_mysql() will block, if we cannot.
- * kill the lock holder first.
- */
- abort();
- break;
- }
- }
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- break;
- case QUERY_EXEC:
- /* it is possible that victim trx is itself waiting for some
- * other lock. We need to cancel this waiting
- */
- WSREP_DEBUG("kill trx QUERY_EXEC for " TRX_ID_FMT,
- victim_trx->id);
-
+ if (wsrep_bf_abort(bf_thd, thd, signal))
+ {
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
if (victim_trx->lock.wait_lock) {
@@ -18916,9 +18842,8 @@ wsrep_innobase_kill_one_trx(
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
lock_cancel_waiting_and_release(wait_lock);
}
-
wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
+ wsrep_thd_awake(thd, signal);
} else {
/* abort currently executing query */
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu",
@@ -18936,47 +18861,10 @@ wsrep_innobase_kill_one_trx(
wsrep_thd_trx_seqno(thd));
}
}
- break;
- case QUERY_IDLE:
- {
- WSREP_DEBUG("kill IDLE for " TRX_ID_FMT, victim_trx->id);
-
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- WSREP_DEBUG("kill BF IDLE, seqno: %lld",
- (long long)wsrep_thd_trx_seqno(thd));
- wsrep_thd_UNLOCK(thd);
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- DBUG_RETURN(0);
- }
- /* This will lock thd from proceeding after net_read() */
- wsrep_thd_set_conflict_state(thd, ABORTING);
-
- wsrep_lock_rollback();
-
- if (wsrep_aborting_thd_contains(thd)) {
- WSREP_WARN("duplicate thd aborter %lu",
- (ulong) thd_get_thread_id(thd));
- } else {
- wsrep_aborting_thd_enqueue(thd);
- DBUG_PRINT("wsrep",("enqueuing trx abort for %lu",
- thd_get_thread_id(thd)));
- WSREP_DEBUG("enqueuing trx abort for (%lu)",
- thd_get_thread_id(thd));
- }
-
- DBUG_PRINT("wsrep",("signalling wsrep rollbacker"));
- WSREP_DEBUG("signaling aborter");
- wsrep_unlock_rollback();
- wsrep_thd_UNLOCK(thd);
-
- break;
}
- default:
- WSREP_WARN("bad wsrep query state: %d",
- wsrep_thd_query_state(thd));
+ else
+ {
wsrep_thd_UNLOCK(thd);
- break;
}
DBUG_RETURN(0);
@@ -18995,11 +18883,25 @@ wsrep_abort_transaction(
trx_t* victim_trx = thd_to_trx(victim_thd);
trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
+ if (wsrep_debug)
+ {
+ wsrep_thd_LOCK(victim_thd);
+ WSREP_DEBUG("abort transaction: BF: %s victim: %s conf: %d",
+ wsrep_thd_query(bf_thd),
+ wsrep_thd_query(victim_thd),
+ wsrep_thd_conflict_state(victim_thd, FALSE));
+ wsrep_thd_UNLOCK(victim_thd);
+ }
- WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d",
+ if (wsrep_debug)
+ {
+ wsrep_thd_LOCK(victim_thd);
+ WSREP_DEBUG("abort transaction: BF: %s victim: %s conf: %d",
wsrep_thd_query(bf_thd),
wsrep_thd_query(victim_thd),
- wsrep_thd_conflict_state(victim_thd, FALSE));
+ wsrep_thd_get_conflict_state(victim_thd));
+ wsrep_thd_UNLOCK(victim_thd);
+ }
if (victim_trx) {
lock_mutex_enter();
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index f2bb8aa5ef2..dc13b8d82ca 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -599,11 +599,9 @@ thd_get_work_part_info(
struct trx_t;
#ifdef WITH_WSREP
#include <mysql/service_wsrep.h>
-//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
-
+#ifdef OUT
extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
-
extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
extern "C" void wsrep_thd_set_query_state(
THD *thd, enum wsrep_query_state state);
@@ -616,6 +614,7 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
#endif
+#endif
extern const struct _ft_vft ft_vft_result;
@@ -660,10 +659,6 @@ innobase_index_name_is_reserved(
be created. */
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
-#ifdef WITH_WSREP
-//extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
-#endif
-
/** Parse hint for table and its indexes, and update the information
in dictionary.
@param[in] thd Connection thread
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index 1313705f119..28bc8f9e565 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -240,6 +240,11 @@ wsrep_innobase_kill_one_trx(void * const thd_ptr,
ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length,
unsigned int buf_length);
+my_bool wsrep_thd_is_SR(void *thd_ptr);
+my_bool wsrep_thd_skip_locking(void *thd_ptr);
+void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr);
+extern "C" void wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size);
+bool wsrep_bf_abort(void *bf_thd_ptr, void *victim_thd_ptr, bool signal);
#endif /* WITH_WSREP */
/**********************************************************************//**
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 76d4e9caba0..114a2f8f349 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -270,6 +270,23 @@ trx_commit_step(
/*============*/
que_thr_t* thr); /*!< in: query thread */
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+/*==============*/
+ FILE* f, /*!< in: output stream */
+ const trx_t* trx, /*!< in: transaction */
+ ulint max_query_len) /*!< in: max query length to print,
+ or 0 to use the default max length */
+ MY_ATTRIBUTE((nonnull));
+#endif /* WITH_WSREP */
/**********************************************************************//**
Prints info about a transaction.
Caller must hold trx_sys.mutex. */
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 4d93f2c449c..8669c7345bb 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -778,9 +778,7 @@ lock_rec_has_to_wait(
<< wsrep_thd_query(lock2->trx->mysql_thd);
}
- if (wsrep_trx_order_before(trx->mysql_thd,
- lock2->trx->mysql_thd)
- && (type_mode & LOCK_MODE_MASK) == LOCK_X
+ if ((type_mode & LOCK_MODE_MASK) == LOCK_X
&& (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) {
if (for_locking || wsrep_debug) {
/* exclusive lock conflicts are not
@@ -1115,11 +1113,14 @@ wsrep_kill_victim(
}
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
+ if (!bf_this) return;
+
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) ||
- (bf_this && bf_other && wsrep_trx_order_before(
- trx->mysql_thd, lock->trx->mysql_thd))) {
+// (bf_this && bf_other && wsrep_trx_order_before(
+// trx->mysql_thd, lock->trx->mysql_thd))) {
+ (bf_this)) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug) {
@@ -7005,6 +7006,9 @@ DeadlockChecker::trx_rollback()
trx_t* trx = m_wait_lock->trx;
print("*** WE ROLL BACK TRANSACTION (1)\n");
+#ifdef WITH_WSREP
+ wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd);
+#endif
trx_mutex_enter(trx);
diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc
index 4a3adaa4757..955ce8c7b8f 100644
--- a/storage/innobase/lock/lock0wait.cc
+++ b/storage/innobase/lock/lock0wait.cc
@@ -195,8 +195,8 @@ wsrep_is_BF_lock_timeout(
if (wsrep_on_trx(trx)
&& wsrep_thd_is_BF(trx->mysql_thd, FALSE)
&& trx->error_state != DB_DEADLOCK) {
- ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id)
- << " query: " << wsrep_thd_query(trx->mysql_thd);
+ ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id)
+ << " query: " << wsrep_thd_query(trx->mysql_thd);
if (!locked) {
lock_mutex_enter();
}
@@ -214,7 +214,9 @@ wsrep_is_BF_lock_timeout(
os_event_set(srv_monitor_event);
return true;
}
- return false;
+
+
+ return false;
}
#endif /* WITH_WSREP */
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 37ae828d09d..96db940e769 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -50,6 +50,11 @@ Created 4/20/1996 Heikki Tuuri
#include "fts0types.h"
#include "m_string.h"
#include "gis0geo.h"
+#include "log.h"
+#include "wsrep_mysqld.h"
+#ifdef WITH_WSREP
+#include "wsrep_schema.h"
+#endif
/*************************************************************************
IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -3240,9 +3245,26 @@ row_ins_clust_index_entry(
n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0;
+#ifdef WITH_WSREP
+ const bool skip_locking
+ = wsrep_thd_skip_locking(thr_get_trx(thr)->mysql_thd);
+ ulint flags = skip_locking | index->table->is_temporary()
+ ? BTR_NO_LOCKING_FLAG
+ : index->table->no_rollback() ? BTR_NO_ROLLBACK : 0;
+#ifdef UNIV_DEBUG
+ if (skip_locking && sr_table_name_full_str != index->table->name.m_name) {
+ WSREP_ERROR("Record locking is disabled in this thread, "
+ "but the table being modified is not "
+ "`%s`: `%s`.", sr_table_name_full_str.c_str(),
+ index->table->name.m_name);
+ ut_error;
+ }
+#endif /* UNIV_DEBUG */
+#else
ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
: index->table->is_temporary()
? BTR_NO_LOCKING_FLAG : 0;
+#endif /* WITH_WSREP */
const ulint orig_n_fields = entry->n_fields;
/* Try first optimistic descent to the B-tree */
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index b68efbfa7be..fe49d298bbc 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -56,6 +56,15 @@ Created 12/19/1997 Heikki Tuuri
#include "ha_prototypes.h"
#include "srv0mon.h"
#include "ut0new.h"
+#include "m_string.h" /* for my_sys.h */
+#include "my_sys.h" /* DEBUG_SYNC_C */
+#ifdef WITH_WSREP
+#include "wsrep_schema.h"
+#endif
+#include "my_compare.h" /* enum icp_result */
+#include "thr_lock.h"
+#include "handler.h"
+#include "ha_innodb.h"
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
@@ -4503,6 +4512,13 @@ row_search_mvcc(
set_also_gap_locks = FALSE;
}
+#ifdef WITH_WSREP
+ if (wsrep_thd_skip_locking(trx->mysql_thd)) {
+
+ ut_ad(sr_table_name_full_str == prebuilt->table->name.m_name);
+ set_also_gap_locks = FALSE;
+ }
+#endif /* WITH_WSREP */
/* Note that if the search mode was GE or G, then the cursor
naturally moves upward (in fetch next) in alphabetical order,
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 447132dcf86..ab15601d001 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -2450,6 +2450,10 @@ row_upd_sec_index_entry(
row_ins_sec_index_entry() below */
if (!rec_get_deleted_flag(
rec, dict_table_is_comp(index->table))) {
+#ifdef WITH_WSREP
+ const upd_node_t* parent =
+ static_cast<const upd_node_t*>(node->common.parent);
+#endif /* WITH_WSREP */
err = btr_cur_del_mark_set_sec_rec(
flags, btr_cur, TRUE, thr, &mtr);
if (err != DB_SUCCESS) {
@@ -2457,8 +2461,11 @@ row_upd_sec_index_entry(
}
#ifdef WITH_WSREP
if (!referenced && foreign
- && wsrep_must_process_fk(node, trx)
- && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
+ && wsrep_on(trx->mysql_thd)
+ && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)
+ && (!parent || que_node_get_type(parent) != QUE_NODE_UPDATE ||
+ !parent->cascade_node)
+ ) {
ulint* offsets = rec_get_offsets(
rec, index, NULL, true,
@@ -2997,7 +3004,8 @@ row_upd_del_mark_clust_rec(
err = row_upd_check_references_constraints(
node, pcur, index->table, index, offsets, thr, mtr);
#ifdef WITH_WSREP
- } else if (foreign && wsrep_must_process_fk(node, trx)) {
+ } else if (trx && wsrep_on(trx->mysql_thd) && err == DB_SUCCESS
+ && wsrep_must_process_fk(node, trx)) {
err = wsrep_row_upd_check_foreign_constraints(
node, pcur, index->table, index, offsets, thr, mtr);
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index c0864e40622..048d06d2835 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -186,6 +186,11 @@ trx_rollback_to_savepoint(
partial rollback requested, or NULL for
complete rollback */
{
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd) && savept == NULL) {
+ wsrep_handle_SR_rollback(NULL, trx->mysql_thd);
+ }
+#endif /* WITH_WSREP */
ut_ad(!trx_mutex_own(trx));
trx_start_if_not_started_xa(trx, true);
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 81ad85dca7d..12bbd8be1e7 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -61,7 +61,8 @@ trx_rseg_update_wsrep_checkpoint(
long long xid_seqno = wsrep_xid_seqno(xid);
const byte* xid_uuid = wsrep_xid_uuid(xid);
- if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) {
+ if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid) &&
+ xid_seqno != -1) {
ut_ad(xid_seqno > wsrep_seqno);
} else {
memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid);
diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h
index 1d6bc059d3d..0923507a1db 100644
--- a/wsrep/wsrep_api.h
+++ b/wsrep/wsrep_api.h
@@ -48,6 +48,7 @@
#define WSREP_H
#include <stdint.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
@@ -62,7 +63,7 @@ extern "C" {
* *
**************************************************************************/
-#define WSREP_INTERFACE_VERSION "25"
+#define WSREP_INTERFACE_VERSION "26"
/*! Empty backend spec */
#define WSREP_NONE "none"
@@ -110,27 +111,40 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *);
#define WSREP_CAP_UNORDERED ( 1ULL << 12 )
#define WSREP_CAP_ANNOTATION ( 1ULL << 13 )
#define WSREP_CAP_PREORDERED ( 1ULL << 14 )
+#define WSREP_CAP_STREAMING ( 1ULL << 15 )
+#define WSREP_CAP_SNAPSHOT ( 1ULL << 16 )
+#define WSREP_CAP_NBO ( 1ULL << 17 )
+typedef uint32_t wsrep_cap_t; //!< capabilities bitmask
/*!
- * Writeset flags
+ * Writeset flags
*
- * COMMIT the writeset and all preceding writesets must be committed
+ * TRX_END the writeset and all preceding writesets must be committed
* ROLLBACK all preceding writesets in a transaction must be rolled back
* ISOLATION the writeset must be applied AND committed in isolation
* PA_UNSAFE the writeset cannot be applied in parallel
* COMMUTATIVE the order in which the writeset is applied does not matter
* NATIVE the writeset contains another writeset in this provider format
*
- * Note that some of the flags are mutually exclusive (e.g. COMMIT and
+ * TRX_START shall be set on the first trx fragment by provider
+ * TRX_PREPARE shall be set on the fragment which prepares the transaction
+ *
+ * Note that some of the flags are mutually exclusive (e.g. TRX_END and
* ROLLBACK).
*/
-#define WSREP_FLAG_COMMIT ( 1ULL << 0 )
+#define WSREP_FLAG_TRX_END ( 1ULL << 0 )
#define WSREP_FLAG_ROLLBACK ( 1ULL << 1 )
#define WSREP_FLAG_ISOLATION ( 1ULL << 2 )
#define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 )
#define WSREP_FLAG_COMMUTATIVE ( 1ULL << 4 )
#define WSREP_FLAG_NATIVE ( 1ULL << 5 )
+#define WSREP_FLAG_TRX_START ( 1ULL << 6 )
+#define WSREP_FLAG_TRX_PREPARE ( 1ULL << 7 )
+#define WSREP_FLAG_SNAPSHOT ( 1ULL << 8 )
+
+#define WSREP_FLAGS_LAST WSREP_FLAG_SNAPSHOT
+#define WSREP_FLAGS_MASK ((WSREP_FLAGS_LAST << 1) - 1)
typedef uint64_t wsrep_trx_id_t; //!< application transaction ID
@@ -158,7 +172,8 @@ typedef enum wsrep_status
WSREP_CONN_FAIL, //!< error in client connection, must abort
WSREP_NODE_FAIL, //!< error in node state, wsrep must reinit
WSREP_FATAL, //!< fatal error, server must abort
- WSREP_NOT_IMPLEMENTED //!< feature not implemented
+ WSREP_NOT_IMPLEMENTED, //!< feature not implemented
+ WSREP_NOT_ALLOWED //!< operation not allowed
} wsrep_status_t;
@@ -178,8 +193,9 @@ typedef enum wsrep_cb_status
/*!
* UUID type - for all unique IDs
*/
-typedef struct wsrep_uuid {
+typedef union wsrep_uuid {
uint8_t data[16];
+ size_t alignment;
} wsrep_uuid_t;
/*! Undefined UUID */
@@ -202,6 +218,18 @@ wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid);
extern int
wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len);
+/*!
+ * @brief Compare two UUIDs
+ *
+ * Performs a byte by byte comparison of lhs and rhs.
+ * Returns 0 if lhs and rhs match, otherwise -1 or 1 according to the
+ * difference of the first byte that differs in lsh and rhs.
+ *
+ * @return -1, 0, 1 if lhs is respectively smaller, equal, or greater than rhs
+ */
+extern int
+wsrep_uuid_compare (const wsrep_uuid_t* lhs, const wsrep_uuid_t* rhs);
+
#define WSREP_MEMBER_NAME_LEN 32 //!< maximum logical member name length
#define WSREP_INCOMING_LEN 256 //!< max Domain Name length + 0x00
@@ -237,6 +265,14 @@ wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid);
extern int
wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len);
+/*!
+ * Source/server transaction ID (trx ID assigned at originating node)
+ */
+typedef struct wsrep_stid {
+ wsrep_uuid_t node; //!< source node ID
+ wsrep_trx_id_t trx; //!< local trx ID at source
+ wsrep_conn_id_t conn; //!< local connection ID at source
+} wsrep_stid_t;
/*!
* Transaction meta data
@@ -244,10 +280,24 @@ wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len);
typedef struct wsrep_trx_meta
{
wsrep_gtid_t gtid; /*!< Global transaction identifier */
- wsrep_seqno_t depends_on; /*!< Sequence number part of the last transaction
- this transaction depends on */
+ wsrep_stid_t stid; /*!< Source transaction identifier */
+ wsrep_seqno_t depends_on; /*!< Sequence number of the last transaction
+ this transaction may depend on */
} wsrep_trx_meta_t;
+/*! Abstract data buffer structure */
+typedef struct wsrep_buf
+{
+ const void* ptr; /*!< Pointer to data buffer */
+ size_t len; /*!< Length of buffer */
+} wsrep_buf_t;
+
+/*! Transaction handle struct passed for wsrep transaction handling calls */
+typedef struct wsrep_ws_handle
+{
+ wsrep_trx_id_t trx_id; //!< transaction ID
+ void* opaque; //!< opaque provider transaction context data
+} wsrep_ws_handle_t;
/*!
* member status
@@ -288,17 +338,53 @@ typedef struct wsrep_view_info {
wsrep_gtid_t state_id; //!< global state ID
wsrep_seqno_t view; //!< global view number
wsrep_view_status_t status; //!< view status
- wsrep_bool_t state_gap; //!< gap between global and local states
+ wsrep_cap_t capabilities;//!< capabilities available in the view
int my_idx; //!< index of this member in the view
int memb_num; //!< number of members in the view
int proto_ver; //!< application protocol agreed on the view
wsrep_member_info_t members[1];//!< array of member information
} wsrep_view_info_t;
+
+/*!
+ * @brief connected to group
+ *
+ * This handler is called once the first primary view is seen.
+ * The purpose of this call is to provide basic information only,
+ * like node UUID and group UUID.
+ */
+typedef enum wsrep_cb_status (*wsrep_connected_cb_t) (
+ void* app_ctx,
+ const wsrep_view_info_t* view
+);
+
+
+/*!
+ * @brief group view handler
+ *
+ * This handler is called in *total order* corresponding to the group
+ * configuration change. It is to provide a vital information about
+ * new group view.
+ *
+ * @param app_ctx application context
+ * @param recv_ctx receiver context
+ * @param view new view on the group
+ * @param state current state
+ * @param state_len length of current state
+ */
+typedef enum wsrep_cb_status (*wsrep_view_cb_t) (
+ void* app_ctx,
+ void* recv_ctx,
+ const wsrep_view_info_t* view,
+ const char* state,
+ size_t state_len
+);
+
+
/*!
* Magic string to tell provider to engage into trivial (empty) state transfer.
* No data will be passed, but the node shall be considered JOINED.
- * Should be passed in sst_req parameter of wsrep_view_cb_t.
+ * Should be passed in sst_req parameter of wsrep_sst_cb_t.
*/
#define WSREP_STATE_TRANSFER_TRIVIAL "trivial"
@@ -306,40 +392,39 @@ typedef struct wsrep_view_info {
* Magic string to tell provider not to engage in state transfer at all.
* The member will stay in WSREP_MEMBER_UNDEFINED state but will keep on
* receiving all writesets.
- * Should be passed in sst_req parameter of wsrep_view_cb_t.
+ * Should be passed in sst_req parameter of wsrep_sst_cb_t.
*/
#define WSREP_STATE_TRANSFER_NONE "none"
+
/*!
- * @brief group view handler
+ * @brief Creates and returns State Snapshot Transfer request for provider.
*
- * This handler is called in total order corresponding to the group
- * configuration change. It is to provide a vital information about
- * new group view. If view info indicates existence of discontinuity
- * between group and member states, state transfer request message
- * should be filled in by the callback implementation.
+ * This handler is called whenever the node is found to miss some of events
+ * from the cluster history (e.g. fresh node joining the cluster).
+ * SST will be used if it is impossible (or impractically long) to replay
+ * missing events, which may be not known in advance, so the node must always
+ * be ready to accept full SST or abort in case event replay is impossible.
+ *
+ * Normally SST request is an opaque buffer that is passed to the
+ * chosen SST donor node and must contain information sufficient for
+ * donor to deliver SST (typically SST method and delivery address).
+ * See above macros WSREP_STATE_TRANSFER_TRIVIAL and WSREP_STATE_TRANSFER_NONE
+ * to modify the standard provider behavior.
*
* @note Currently it is assumed that sst_req is allocated using
* malloc()/calloc()/realloc() and it will be freed by
- * wsrep implementation.
+ * wsrep provider.
*
* @param app_ctx application context
- * @param recv_ctx receiver context
- * @param view new view on the group
- * @param state current state
- * @param state_len lenght of current state
* @param sst_req location to store SST request
* @param sst_req_len location to store SST request length or error code,
* value of 0 means no SST.
*/
-typedef enum wsrep_cb_status (*wsrep_view_cb_t) (
- void* app_ctx,
- void* recv_ctx,
- const wsrep_view_info_t* view,
- const char* state,
- size_t state_len,
- void** sst_req,
- size_t* sst_req_len
+typedef enum wsrep_cb_status (*wsrep_sst_request_cb_t) (
+ void* app_ctx,
+ void** sst_req,
+ size_t* sst_req_len
);
@@ -349,47 +434,24 @@ typedef enum wsrep_cb_status (*wsrep_view_cb_t) (
* This handler is called from wsrep library to apply replicated writeset
* Must support brute force applying for multi-master operation
*
- * @param recv_ctx receiver context pointer provided by the application
- * @param data data buffer containing the writeset
- * @param size data buffer size
- * @param flags WSREP_FLAG_... flags
- * @param meta transaction meta data of the writeset to be applied
+ * @param recv_ctx receiver context pointer provided by the application
+ * @param ws_handle internal provider writeset handle
+ * @param flags WSREP_FLAG_... flags
+ * @param data data buffer containing the writeset
+ * @param meta transaction meta data of the writeset to be applied
+ * @param exit_loop set to true to exit receive loop
*
- * @return success code:
- * @retval WSREP_OK
- * @retval WSREP_NOT_IMPLEMENTED appl. does not support the writeset format
- * @retval WSREP_ERROR failed to apply the writeset
+ * @return error code:
+ * @retval 0 - success
+ * @retval non-0 - application-specific error code
*/
typedef enum wsrep_cb_status (*wsrep_apply_cb_t) (
- void* recv_ctx,
- const void* data,
- size_t size,
- uint32_t flags,
- const wsrep_trx_meta_t* meta
-);
-
-
-/*!
- * @brief commit callback
- *
- * This handler is called to commit the changes made by apply callback.
- *
- * @param recv_ctx receiver context pointer provided by the application
- * @param flags WSREP_FLAG_... flags
- * @param meta transaction meta data of the writeset to be committed
- * @param exit set to true to exit recv loop
- * @param commit true - commit writeset, false - rollback writeset
- *
- * @return success code:
- * @retval WSREP_OK
- * @retval WSREP_ERROR call failed
- */
-typedef enum wsrep_cb_status (*wsrep_commit_cb_t) (
- void* recv_ctx,
- uint32_t flags,
- const wsrep_trx_meta_t* meta,
- wsrep_bool_t* exit,
- wsrep_bool_t commit
+ void* recv_ctx,
+ const wsrep_ws_handle_t* ws_handle,
+ uint32_t flags,
+ const wsrep_buf_t* data,
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* exit_loop
);
@@ -401,12 +463,10 @@ typedef enum wsrep_cb_status (*wsrep_commit_cb_t) (
*
* @param recv_ctx receiver context pointer provided by the application
* @param data data buffer containing the writeset
- * @param size data buffer size
*/
typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) (
- void* recv_ctx,
- const void* data,
- size_t size
+ void* recv_ctx,
+ const wsrep_buf_t* data
);
@@ -421,21 +481,17 @@ typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) (
*
* @param app_ctx application context
* @param recv_ctx receiver context
- * @param msg state transfer request message
- * @param msg_len state transfer request message length
+ * @param str_msg state transfer request message
* @param gtid current state ID on this node
* @param state current wsrep internal state buffer
- * @param state_len current wsrep internal state buffer len
* @param bypass bypass snapshot transfer, only transfer uuid:seqno pair
*/
typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) (
void* app_ctx,
void* recv_ctx,
- const void* msg,
- size_t msg_len,
+ const wsrep_buf_t* str_msg,
const wsrep_gtid_t* state_id,
- const char* state,
- size_t state_len,
+ const wsrep_buf_t* state,
wsrep_bool_t bypass
);
@@ -448,8 +504,10 @@ typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) (
* rest of the cluster.
*
* @param app_ctx application context
+ *
+ * @return wsrep_cb_status enum
*/
-typedef void (*wsrep_synced_cb_t) (void* app_ctx);
+typedef enum wsrep_cb_status (*wsrep_synced_cb_t) (void* app_ctx);
/*!
@@ -469,21 +527,21 @@ struct wsrep_init_args
/* Application initial state information. */
const wsrep_gtid_t* state_id; //!< Application state GTID
- const char* state; //!< Initial state for wsrep provider
- size_t state_len; //!< Length of state buffer
+ const wsrep_buf_t* state; //!< Initial state for wsrep provider
/* Application callbacks */
- wsrep_log_cb_t logger_cb; //!< logging handler
- wsrep_view_cb_t view_handler_cb; //!< group view change handler
+ wsrep_log_cb_t logger_cb; //!< logging handler
+ wsrep_connected_cb_t connected_cb; //!< connected to group
+ wsrep_view_cb_t view_cb; //!< group view change handler
+ wsrep_sst_request_cb_t sst_request_cb; //!< SST request creator
/* Applier callbacks */
- wsrep_apply_cb_t apply_cb; //!< apply callback
- wsrep_commit_cb_t commit_cb; //!< commit callback
- wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions
+ wsrep_apply_cb_t apply_cb; //!< apply callback
+ wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions
/* State Snapshot Transfer callbacks */
- wsrep_sst_donate_cb_t sst_donate_cb; //!< starting to donate
- wsrep_synced_cb_t synced_cb; //!< synced with group
+ wsrep_sst_donate_cb_t sst_donate_cb; //!< donate SST
+ wsrep_synced_cb_t synced_cb; //!< synced with group
};
@@ -502,20 +560,13 @@ struct wsrep_stats_var
const char* name; //!< variable name
wsrep_var_type_t type; //!< variable value type
union {
- int64_t _integer64;
+ int64_t _int64;
double _double;
const char* _string;
} value; //!< variable value
};
-/*! Abstract data buffer structure */
-typedef struct wsrep_buf
-{
- const void* ptr; /*!< Pointer to data buffer */
- size_t len; /*!< Length of buffer */
-} wsrep_buf_t;
-
/*! Key struct used to pass certification keys for transaction handling calls.
* A key consists of zero or more key parts. */
typedef struct wsrep_key
@@ -526,7 +577,7 @@ typedef struct wsrep_key
/*! Key type:
* EXCLUSIVE conflicts with any key type
- * SEMI reserved. If not supported, should be interpeted as EXCLUSIVE
+ * SEMI reserved. If not supported, should be interpreted as EXCLUSIVE
* SHARED conflicts only with EXCLUSIVE keys */
typedef enum wsrep_key_type
{
@@ -549,13 +600,6 @@ typedef enum wsrep_data_type
} wsrep_data_type_t;
-/*! Transaction handle struct passed for wsrep transaction handling calls */
-typedef struct wsrep_ws_handle
-{
- wsrep_trx_id_t trx_id; //!< transaction ID
- void* opaque; //!< opaque provider transaction context data
-} wsrep_ws_handle_t;
-
/*!
* @brief Helper method to reset trx writeset handle state when trx id changes
*
@@ -585,11 +629,11 @@ typedef struct wsrep_po_handle { void* opaque; } wsrep_po_handle_t;
static const wsrep_po_handle_t WSREP_PO_INITIALIZER = { NULL };
-typedef struct wsrep wsrep_t;
+typedef struct wsrep_st wsrep_t;
/*!
* wsrep interface for dynamically loadable libraries
*/
-struct wsrep {
+struct wsrep_st {
const char *version; //!< interface version string
@@ -603,11 +647,15 @@ struct wsrep {
const struct wsrep_init_args* args);
/*!
- * @brief Returns provider capabilities flag bitmap
+ * @brief Returns provider capabilities bitmap
+ *
+ * Note that these are potential provider capabilities. Provider will
+ * offer only capabilities supported by all members in the view
+ * (see wsrep_view_info).
*
* @param wsrep provider handle
*/
- uint64_t (*capabilities) (wsrep_t* wsrep);
+ wsrep_cap_t (*capabilities) (wsrep_t* wsrep);
/*!
* @brief Passes provider-specific configuration string to provider.
@@ -616,7 +664,7 @@ struct wsrep {
* @param conf configuration string
*
* @retval WSREP_OK configuration string was parsed successfully
- * @retval WSREP_WARNING could't not parse conf string, no action taken
+ * @retval WSREP_WARNING could not parse configuration string, no action taken
*/
wsrep_status_t (*options_set) (wsrep_t* wsrep, const char* conf);
@@ -633,7 +681,7 @@ struct wsrep {
/*!
* @brief Opens connection to cluster
*
- * Returns when either node is ready to operate as a part of the clsuter
+ * Returns when either node is ready to operate as a part of the cluster
* or fails to reach operating status.
*
* @param wsrep provider handle
@@ -642,7 +690,7 @@ struct wsrep {
* @param state_donor name of the node to be asked for state transfer.
* @param bootstrap a flag to request initialization of a new wsrep
* service rather then a connection to the existing one.
- * clister_url may still carry important initialization
+ * cluster_url may still carry important initialization
* parameters, like backend spec and/or listen address.
*/
wsrep_status_t (*connect) (wsrep_t* wsrep,
@@ -672,52 +720,100 @@ struct wsrep {
wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx);
/*!
- * @brief Replicates/logs result of transaction to other nodes and allocates
- * required resources.
+ * @brief Tells provider that a given writeset has a read view associated
+ * with it.
+ *
+ * @param wsrep provider handle
+ * @param handle writeset handle
+ * @param rv read view GTID established by the caller or if NULL,
+ * provider will infer it internally.
+ */
+ wsrep_status_t (*assign_read_view)(wsrep_t* wsrep,
+ wsrep_ws_handle_t* handle,
+ const wsrep_gtid_t* rv);
+
+ /*!
+ * @brief Certifies transaction with provider.
*
* Must be called before transaction commit. Returns success code, which
* caller must check.
- * In case of WSREP_OK, starts commit critical section, transaction can
- * commit. Otherwise transaction must rollback.
+ *
+ * In case of WSREP_OK, transaction can proceed to commit.
+ * Otherwise transaction must rollback.
+ *
+ * In case of a failure there are two conceptually different situations:
+ * - the writeset was not ordered. In that case meta struct shall contain
+ * undefined GTID: WSREP_UUID_UNDEFINED:WSREP_SEQNO_UNDEFINED.
+ * - the writeset was successfully ordered, but failed certification.
+ * In this case meta struct shall contain a valid GTID.
+ *
+ * Regardless of the return code, if meta struct contains a valid GTID
+ * the commit order critical section must be entered with that GTID.
*
* @param wsrep provider handle
- * @param ws_handle writeset of committing transaction
* @param conn_id connection ID
+ * @param ws_handle writeset of committing transaction
* @param flags fine tuning the replication WSREP_FLAG_*
* @param meta transaction meta data
*
- * @retval WSREP_OK cluster-wide commit succeeded
+ * @retval WSREP_OK writeset successfully certified, can commit
* @retval WSREP_TRX_FAIL must rollback transaction
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*pre_commit)(wsrep_t* wsrep,
- wsrep_conn_id_t conn_id,
- wsrep_ws_handle_t* ws_handle,
- uint32_t flags,
- wsrep_trx_meta_t* meta);
+ wsrep_status_t (*certify)(wsrep_t* wsrep,
+ wsrep_conn_id_t conn_id,
+ wsrep_ws_handle_t* ws_handle,
+ uint32_t flags,
+ wsrep_trx_meta_t* meta);
/*!
- * @brief Releases resources after transaction commit.
+ * @brief Enters commit order critical section.
*
- * Ends commit critical section.
+ * Anything executed between this call and commit_order_leave() will be
+ * executed in provider enforced order.
*
* @param wsrep provider handle
- * @param ws_handle writeset of committing transaction
- * @retval WSREP_OK post_commit succeeded
+ * @param ws_handle internal provider writeset handle
+ * @param meta transaction meta data
+ *
+ * @retval WSREP_OK commit order entered successfully
+ * @retval WSREP_NODE_FAIL must close all connections and reinit
+ */
+ wsrep_status_t (*commit_order_enter)(wsrep_t* wsrep,
+ const wsrep_ws_handle_t* ws_handle,
+ const wsrep_trx_meta_t* meta);
+
+ /*!
+ * @brief Leaves commit order critical section
+ *
+ * Anything executed between commit_order_enter() and this call will be
+ * executed in provider enforced order.
+ *
+ * @param wsrep provider handle
+ * @param ws_handle internal provider writeset handle
+ * @param meta transaction meta data
+ * @param error buffer containing error info (null/empty for no error)
+ *
+ * @retval WSREP_OK commit order left successfully
+ * @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*post_commit) (wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle);
+ wsrep_status_t (*commit_order_leave)(wsrep_t* wsrep,
+ const wsrep_ws_handle_t* ws_handle,
+ const wsrep_trx_meta_t* meta,
+ const wsrep_buf_t* error);
/*!
- * @brief Releases resources after transaction rollback.
+ * @brief Releases resources after transaction commit/rollback.
+ *
+ * Ends total order critical section.
*
* @param wsrep provider handle
* @param ws_handle writeset of committing transaction
- * @retval WSREP_OK post_rollback succeeded
+ * @retval WSREP_OK release succeeded
*/
- wsrep_status_t (*post_rollback)(wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle);
+ wsrep_status_t (*release) (wsrep_t* wsrep,
+ wsrep_ws_handle_t* ws_handle);
/*!
* @brief Replay trx as a slave writeset
@@ -743,24 +839,44 @@ struct wsrep {
void* trx_ctx);
/*!
- * @brief Abort pre_commit() call of another thread.
+ * @brief Abort certify() call of another thread.
*
* It is possible, that some high-priority transaction needs to abort
- * another transaction which is in pre_commit() call waiting for resources.
+ * another transaction which is in certify() call waiting for resources.
*
- * The kill routine checks that abort is not attmpted against a transaction
+ * The kill routine checks that abort is not attempted against a transaction
* which is front of the caller (in total order).
*
+ * If the abort was successful, the victim sequence number is stored
+ * into location pointed by the victim_seqno.
+ *
* @param wsrep provider handle
* @param bf_seqno seqno of brute force trx, running this cancel
* @param victim_trx transaction to be aborted, and which is committing
+ * @param victim_seqno seqno of the victim transaction if assigned
*
- * @retval WSREP_OK abort secceded
- * @retval WSREP_WARNING abort failed
+ * @retval WSREP_OK abort succeeded
+ * @retval WSREP_NOT_ALLOWED the provider declined the abort request
+ * @retval WSREP_TRX_MISSING the victim_trx was missing
+ * @retval WSREP_WARNING abort failed
*/
- wsrep_status_t (*abort_pre_commit)(wsrep_t* wsrep,
- wsrep_seqno_t bf_seqno,
- wsrep_trx_id_t victim_trx);
+ wsrep_status_t (*abort_certification)(wsrep_t* wsrep,
+ wsrep_seqno_t bf_seqno,
+ wsrep_trx_id_t victim_trx,
+ wsrep_seqno_t* victim_seqno);
+
+ /*!
+ * @brief Send a rollback fragment on behalf of trx
+ *
+ * @param wsrep provider handle
+ * @param trx transaction to be rolled back
+ * @param data data to append to the fragment
+ *
+ * @retval WSREP_OK rollback fragment sent successfully
+ */
+ wsrep_status_t (*rollback)(wsrep_t* wsrep,
+ wsrep_trx_id_t trx,
+ const wsrep_buf_t* data);
/*!
* @brief Appends a row reference to transaction writeset
@@ -772,7 +888,7 @@ struct wsrep {
* @param ws_handle writeset handle
* @param keys array of keys
* @param count length of the array of keys
- * @param type type ot the key
+ * @param type type of the key
* @param copy can be set to FALSE if keys persist through commit.
*/
wsrep_status_t (*append_key)(wsrep_t* wsrep,
@@ -797,33 +913,54 @@ struct wsrep {
* @param type type of data
* @param copy can be set to FALSE if data persists through commit.
*/
- wsrep_status_t (*append_data)(wsrep_t* wsrep,
- wsrep_ws_handle_t* ws_handle,
- const struct wsrep_buf* data,
- size_t count,
- enum wsrep_data_type type,
- wsrep_bool_t copy);
+ wsrep_status_t (*append_data)(wsrep_t* wsrep,
+ wsrep_ws_handle_t* ws_handle,
+ const wsrep_buf_t* data,
+ size_t count,
+ enum wsrep_data_type type,
+ wsrep_bool_t copy);
/*!
- * @brief Get causal ordering for read operation
+ * @brief Blocks until the given GTID is committed
*
- * This call will block until causal ordering with all possible
- * preceding writes in the cluster is guaranteed. If pointer to
- * gtid is non-null, the call stores the global transaction ID
- * of the last transaction which is guaranteed to be ordered
- * causally before this call.
+ * This call will block the caller until the given GTID
+ * is guaranteed to be committed, or until a timeout occurs.
+ * The timeout value is given in parameter tout, if tout is -1,
+ * then the global causal read timeout applies.
*
- * @param wsrep provider handle
- * @param gtid location to store GTID
+ * If no pointer upto is provided the call will block until
+ * causal ordering with all possible preceding writes in the
+ * cluster is guaranteed.
+ *
+ * If pointer to gtid is non-null, the call stores the global
+ * transaction ID of the last transaction which is guaranteed
+ * to be committed when the call returns.
+ *
+ * @param wsrep provider handle
+ * @param upto gtid to wait upto
+ * @param tout timeout in seconds
+ * -1 wait for global causal read timeout
+ * @param gtid location to store GTID
+ */
+ wsrep_status_t (*sync_wait)(wsrep_t* wsrep,
+ wsrep_gtid_t* upto,
+ int tout,
+ wsrep_gtid_t* gtid);
+
+ /*!
+ * @brief Returns the last committed gtid
+ *
+ * @param gtid location to store GTID
*/
- wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_gtid_t* gtid);
+ wsrep_status_t (*last_committed_id)(wsrep_t* wsrep,
+ wsrep_gtid_t* gtid);
/*!
* @brief Clears allocated connection context.
*
* Whenever a new connection ID is passed to wsrep provider through
* any of the API calls, a connection context is allocated for this
- * connection. This call is to explicitly notify provider fo connection
+ * connection. This call is to explicitly notify provider of connection
* closing.
*
* @param wsrep provider handle
@@ -837,28 +974,51 @@ struct wsrep {
/*!
* @brief Replicates a query and starts "total order isolation" section.
*
+ * Regular mode:
+ *
* Replicates the action spec and returns success code, which caller must
* check. Total order isolation continues until to_execute_end() is called.
+ * Regular "total order isolation" is achieved by calling to_execute_start()
+ * with WSREP_FLAG_TRX_START and WSREP_FLAG_TRX_END set.
+ *
+ * Two-phase mode:
+ *
+ * In this mode a query execution is split in two phases. The first phase is
+ * acquiring total order isolation to access critical section and the
+ * second phase is to release acquired resources in total order.
+ *
+ * To start the first phase the call is made with WSREP_FLAG_TRX_START set.
+ * The action is replicated and success code is returned. The total order
+ * isolation continues until to_execute_end() is called. However, the provider
+ * will keep the reference to the operation for conflict resolution purposes.
+ *
+ * The second phase is started with WSREP_FLAG_TRX_END set. Provider
+ * returns once it has achieved total ordering isolation for second phase.
+ * Total order isolation continues until to_execute_end() is called.
+ * All references to the operation are cleared by provider before
+ * call to to_execute_end() returns.
*
* @param wsrep provider handle
* @param conn_id connection ID
* @param keys array of keys
- * @param keys_num lenght of the array of keys
+ * @param keys_num length of the array of keys
* @param action action buffer array to be executed
* @param count action buffer count
+ * @param flags flags
* @param meta transaction meta data
*
* @retval WSREP_OK cluster commit succeeded
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*to_execute_start)(wsrep_t* wsrep,
- wsrep_conn_id_t conn_id,
- const wsrep_key_t* keys,
- size_t keys_num,
- const struct wsrep_buf* action,
- size_t count,
- wsrep_trx_meta_t* meta);
+ wsrep_status_t (*to_execute_start)(wsrep_t* wsrep,
+ wsrep_conn_id_t conn_id,
+ const wsrep_key_t* keys,
+ size_t keys_num,
+ const wsrep_buf_t* action,
+ size_t count,
+ uint32_t flags,
+ wsrep_trx_meta_t* meta);
/*!
* @brief Ends the total order isolation section.
@@ -866,14 +1026,18 @@ struct wsrep {
* Marks the end of total order isolation. TO locks are freed
* and other transactions are free to commit from this point on.
*
- * @param wsrep provider handle
+ * @param wsrep provider handle
* @param conn_id connection ID
+ * @param error error information about TOI operation (empty for no error)
*
* @retval WSREP_OK cluster commit succeeded
* @retval WSREP_CONN_FAIL must close client connection
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*to_execute_end)(wsrep_t* wsrep, wsrep_conn_id_t conn_id);
+ wsrep_status_t (*to_execute_end)(wsrep_t* wsrep,
+ wsrep_conn_id_t conn_id,
+ const wsrep_buf_t* error);
+
/*!
* @brief Collects preordered replication events into a writeset.
@@ -888,11 +1052,11 @@ struct wsrep {
* @retval WSREP_TRX_FAIL operation failed (e.g. trx size exceeded limit)
* @retval WSREP_NODE_FAIL must close all connections and reinit
*/
- wsrep_status_t (*preordered_collect) (wsrep_t* wsrep,
- wsrep_po_handle_t* handle,
- const struct wsrep_buf* data,
- size_t count,
- wsrep_bool_t copy);
+ wsrep_status_t (*preordered_collect) (wsrep_t* wsrep,
+ wsrep_po_handle_t* handle,
+ const wsrep_buf_t* data,
+ size_t count,
+ wsrep_bool_t copy);
/*!
* @brief "Commits" preordered writeset to cluster.
@@ -943,20 +1107,18 @@ struct wsrep {
* @param wsrep provider handle
* @param state_id state ID
* @param state initial state provided by SST donor
- * @param state_len length of state buffer
* @param rcode 0 or negative error code of the operation.
*/
wsrep_status_t (*sst_received)(wsrep_t* wsrep,
const wsrep_gtid_t* state_id,
- const void* state,
- size_t state_len,
+ const wsrep_buf_t* state,
int rcode);
/*!
* @brief Generate request for consistent snapshot.
*
- * If successfull, this call will generate internally SST request
+ * If successful, this call will generate internally SST request
* which in turn triggers calling SST donate callback on the nodes
* specified in donor_spec. If donor_spec is null, callback is
* called only locally. This call will block until sst_sent is called
@@ -967,13 +1129,12 @@ struct wsrep {
* @param msg_len length of context message
* @param donor_spec list of snapshot donors
*/
- wsrep_status_t (*snapshot)(wsrep_t* wsrep,
- const void* msg,
- size_t msg_len,
- const char* donor_spec);
+ wsrep_status_t (*snapshot)(wsrep_t* wsrep,
+ const wsrep_buf_t* msg,
+ const char* donor_spec);
/*!
- * @brief Returns an array fo status variables.
+ * @brief Returns an array of status variables.
* Array is terminated by Null variable name.
*
* @param wsrep provider handle
@@ -1020,7 +1181,7 @@ struct wsrep {
* @brief Request to resynchronize with cluster.
*
* Effectively turns on flow control. Asynchronous - actual synchronization
- * event to be deliverred via sync_cb.
+ * event to be delivered via sync_cb.
*/
wsrep_status_t (*resync) (wsrep_t* wsrep);
@@ -1086,7 +1247,7 @@ struct wsrep {
void (*free)(wsrep_t* wsrep);
void *dlh; //!< reserved for future use
- void *ctx; //!< reserved for implemetation private context
+ void *ctx; //!< reserved for implementation private context
};
@@ -1094,7 +1255,7 @@ struct wsrep {
*
* @brief Loads wsrep library
*
- * @param spec path to wsrep library. If NULL or WSREP_NONE initialises dummy
+ * @param spec path to wsrep library. If NULL or WSREP_NONE initializes dummy
* pass-through implementation.
* @param hptr wsrep handle
* @param log_cb callback to handle loader messages. Otherwise writes to stderr.
diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c
index e48dcff39a1..9000261af3d 100644
--- a/wsrep/wsrep_dummy.c
+++ b/wsrep/wsrep_dummy.c
@@ -19,6 +19,7 @@
#include "wsrep_api.h"
#include <errno.h>
+#include <stdbool.h>
#include <string.h>
/*! Dummy backend context. */
@@ -62,7 +63,7 @@ static wsrep_status_t dummy_init (wsrep_t* w,
return WSREP_OK;
}
-static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused)))
+static wsrep_cap_t dummy_capabilities (wsrep_t* w __attribute__((unused)))
{
return 0;
}
@@ -84,15 +85,8 @@ static wsrep_status_t dummy_options_set(
static char* dummy_options_get (wsrep_t* w)
{
- char *options;
-
- WSREP_DBUG_ENTER(w);
- options= WSREP_DUMMY(w)->options;
-
- if (options)
- options= strdup(WSREP_DUMMY(w)->options);
-
- return options;
+ WSREP_DBUG_ENTER(w);
+ return strdup(WSREP_DUMMY(w)->options);
}
static wsrep_status_t dummy_connect(
@@ -119,7 +113,16 @@ static wsrep_status_t dummy_recv(wsrep_t* w,
return WSREP_OK;
}
-static wsrep_status_t dummy_pre_commit(
+static wsrep_status_t dummy_assign_read_view(
+ wsrep_t* w,
+ wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ const wsrep_gtid_t* rv __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_certify(
wsrep_t* w,
const wsrep_conn_id_t conn_id __attribute__((unused)),
wsrep_ws_handle_t* ws_handle __attribute__((unused)),
@@ -130,15 +133,26 @@ static wsrep_status_t dummy_pre_commit(
return WSREP_OK;
}
-static wsrep_status_t dummy_post_commit(
+static wsrep_status_t dummy_commit_order_enter(
wsrep_t* w,
- wsrep_ws_handle_t* ws_handle __attribute__((unused)))
+ const wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ const wsrep_trx_meta_t* meta __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
}
-static wsrep_status_t dummy_post_rollback(
+static wsrep_status_t dummy_commit_order_leave(
+ wsrep_t* w,
+ const wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ const wsrep_trx_meta_t* meta __attribute__((unused)),
+ const wsrep_buf_t* error __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_release(
wsrep_t* w,
wsrep_ws_handle_t* ws_handle __attribute__((unused)))
{
@@ -155,10 +169,20 @@ static wsrep_status_t dummy_replay_trx(
return WSREP_OK;
}
-static wsrep_status_t dummy_abort_pre_commit(
+static wsrep_status_t dummy_abort_certification(
wsrep_t* w,
const wsrep_seqno_t bf_seqno __attribute__((unused)),
- const wsrep_trx_id_t trx_id __attribute__((unused)))
+ const wsrep_trx_id_t trx_id __attribute__((unused)),
+ wsrep_seqno_t *victim_seqno __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_rollback(
+ wsrep_t* w,
+ const wsrep_trx_id_t trx __attribute__((unused)),
+ const wsrep_buf_t* data __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -170,7 +194,7 @@ static wsrep_status_t dummy_append_key(
const wsrep_key_t* key __attribute__((unused)),
const size_t key_num __attribute__((unused)),
const wsrep_key_type_t key_type __attribute__((unused)),
- const wsrep_bool_t copy __attribute__((unused)))
+ const bool copy __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -182,13 +206,23 @@ static wsrep_status_t dummy_append_data(
const struct wsrep_buf* data __attribute__((unused)),
const size_t count __attribute__((unused)),
const wsrep_data_type_t type __attribute__((unused)),
- const wsrep_bool_t copy __attribute__((unused)))
+ const bool copy __attribute__((unused)))
+{
+ WSREP_DBUG_ENTER(w);
+ return WSREP_OK;
+}
+
+static wsrep_status_t dummy_sync_wait(
+ wsrep_t* w,
+ wsrep_gtid_t* upto __attribute__((unused)),
+ int tout __attribute__((unused)),
+ wsrep_gtid_t* gtid __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
}
-static wsrep_status_t dummy_causal_read(
+static wsrep_status_t dummy_last_committed_id(
wsrep_t* w,
wsrep_gtid_t* gtid __attribute__((unused)))
{
@@ -211,6 +245,7 @@ static wsrep_status_t dummy_to_execute_start(
const size_t key_num __attribute__((unused)),
const struct wsrep_buf* data __attribute__((unused)),
const size_t count __attribute__((unused)),
+ const uint32_t flags __attribute__((unused)),
wsrep_trx_meta_t* meta __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
@@ -219,7 +254,8 @@ static wsrep_status_t dummy_to_execute_start(
static wsrep_status_t dummy_to_execute_end(
wsrep_t* w,
- const wsrep_conn_id_t conn_id __attribute__((unused)))
+ const wsrep_conn_id_t conn_id __attribute__((unused)),
+ const wsrep_buf_t* err __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -260,8 +296,7 @@ static wsrep_status_t dummy_sst_sent(
static wsrep_status_t dummy_sst_received(
wsrep_t* w,
const wsrep_gtid_t* state_id __attribute__((unused)),
- const void* state __attribute__((unused)),
- const size_t state_len __attribute__((unused)),
+ const wsrep_buf_t* state __attribute__((unused)),
const int rcode __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
@@ -270,9 +305,8 @@ static wsrep_status_t dummy_sst_received(
static wsrep_status_t dummy_snapshot(
wsrep_t* w,
- const void* msg __attribute__((unused)),
- const size_t msg_len __attribute__((unused)),
- const char* donor_spec __attribute__((unused)))
+ const wsrep_buf_t* msg __attribute__((unused)),
+ const char* donor_spec __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_OK;
@@ -325,10 +359,10 @@ static wsrep_status_t dummy_resync (wsrep_t* w)
}
static wsrep_status_t dummy_lock (wsrep_t* w,
- const char* s __attribute__((unused)),
- wsrep_bool_t r __attribute__((unused)),
- uint64_t o __attribute__((unused)),
- int64_t t __attribute__((unused)))
+ const char* s __attribute__((unused)),
+ bool r __attribute__((unused)),
+ uint64_t o __attribute__((unused)),
+ int64_t t __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
return WSREP_NOT_IMPLEMENTED;
@@ -342,13 +376,13 @@ static wsrep_status_t dummy_unlock (wsrep_t* w,
return WSREP_OK;
}
-static wsrep_bool_t dummy_is_locked (wsrep_t* w,
- const char* s __attribute__((unused)),
- uint64_t* o __attribute__((unused)),
- wsrep_uuid_t* t __attribute__((unused)))
+static bool dummy_is_locked (wsrep_t* w,
+ const char* s __attribute__((unused)),
+ uint64_t* o __attribute__((unused)),
+ wsrep_uuid_t* t __attribute__((unused)))
{
WSREP_DBUG_ENTER(w);
- return 0;
+ return false;
}
static wsrep_t dummy_iface = {
@@ -360,14 +394,18 @@ static wsrep_t dummy_iface = {
&dummy_connect,
&dummy_disconnect,
&dummy_recv,
- &dummy_pre_commit,
- &dummy_post_commit,
- &dummy_post_rollback,
+ &dummy_assign_read_view,
+ &dummy_certify,
+ &dummy_commit_order_enter,
+ &dummy_commit_order_leave,
+ &dummy_release,
&dummy_replay_trx,
- &dummy_abort_pre_commit,
+ &dummy_abort_certification,
+ &dummy_rollback,
&dummy_append_key,
&dummy_append_data,
- &dummy_causal_read,
+ &dummy_sync_wait,
+ &dummy_last_committed_id,
&dummy_free_connection,
&dummy_to_execute_start,
&dummy_to_execute_end,
diff --git a/wsrep/wsrep_gtid.c b/wsrep/wsrep_gtid.c
index 45148785c25..a02543ab523 100644
--- a/wsrep/wsrep_gtid.c
+++ b/wsrep/wsrep_gtid.c
@@ -53,7 +53,7 @@ wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid)
/*!
* Write GTID to string
- * @return length of GTID stirng representation of -EMSGSIZE if string is too
+ * @return length of GTID string representation or -EMSGSIZE if string is too
* short
*/
int
diff --git a/wsrep/wsrep_listener.c b/wsrep/wsrep_listener.c
new file mode 100644
index 00000000000..7d1558c3014
--- /dev/null
+++ b/wsrep/wsrep_listener.c
@@ -0,0 +1,261 @@
+/* Copyright (C) 2012 Codership Oy <info@codersihp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*! @file Example of wsrep event listener. Outputs description of received
+ * events to stdout. To get a general picture you should start with
+ * main() function. */
+
+#include <wsrep_api.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+
+/*! This is global application context, it will be used by wsrep callbacks */
+struct application_context
+{};
+
+static struct application_context global_ctx;
+
+/*! This is receiving thread context, it will be used by wsrep callbacks */
+struct receiver_context
+{
+ char msg[4096];
+};
+
+/* wsrep provider handle (global for simplicty) */
+static wsrep_t* wsrep = NULL;
+
+/*! This is a logger callback which library will be using to log events. */
+static void
+logger_cb (wsrep_log_level_t level __attribute__((unused)), const char* msg)
+{
+ fprintf (stderr, "WSREP: %s\n", msg);
+}
+
+/*! This will be called on cluster view change (nodes joining, leaving, etc.).
+ * Each view change is the point where application may be pronounced out of
+ * sync with the current cluster view and need state transfer.
+ * It is guaranteed that no other callbacks are called concurrently with it. */
+static wsrep_cb_status_t
+view_cb (void* app_ctx __attribute__((unused)),
+ void* recv_ctx __attribute__((unused)),
+ const wsrep_view_info_t* view,
+ const char* state __attribute__((unused)),
+ size_t state_len __attribute__((unused)))
+{
+ printf ("New cluster membership view: %d nodes, my index is %d, "
+ "global seqno: %lld\n",
+ view->memb_num, view->my_idx, (long long)view->state_id.seqno);
+
+ return WSREP_CB_SUCCESS;
+}
+
+/*! This will be called on cluster view change (nodes joining, leaving, etc.).
+ * Each view change is the point where application may be pronounced out of
+ * sync with the current cluster view and need state transfer.
+ * It is guaranteed that no other callbacks are called concurrently with it. */
+static wsrep_cb_status_t
+sst_request_cb (void** sst_req,
+ size_t* sst_req_len)
+{
+ /* For simplicity we're skipping state transfer by using magic string
+ * as a state transfer request.
+ * This node will not be considered JOINED (having full state)
+ * by other cluster members. */
+ *sst_req = strdup(WSREP_STATE_TRANSFER_NONE);
+
+ if (*sst_req)
+ *sst_req_len = strlen(*sst_req) + 1;
+ else
+ *sst_req_len = -ENOMEM;
+
+ return WSREP_CB_SUCCESS;
+}
+
+/*! This is called to "apply" writeset.
+ * If writesets don't conflict on keys, it may be called concurrently to
+ * utilize several CPU cores. */
+static wsrep_cb_status_t
+apply_cb (void* recv_ctx,
+ const wsrep_ws_handle_t* ws_handle __attribute__((unused)),
+ uint32_t flags __attribute__((unused)),
+ const wsrep_buf_t* ws __attribute__((unused)),
+ const wsrep_trx_meta_t* meta,
+ wsrep_bool_t* exit_loop __attribute__((unused)))
+{
+ struct receiver_context* ctx = (struct receiver_context*)recv_ctx;
+
+ snprintf (ctx->msg, sizeof(ctx->msg),
+ "Got writeset %lld, size %zu", (long long)meta->gtid.seqno,
+ ws->len);
+
+ bool const commit = flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK);
+
+ wsrep->commit_order_enter(wsrep, ws_handle);
+ if (commit) puts(ctx->msg);
+ wsrep->commit_order_leave(wsrep, ws_handle, NULL);
+
+ return WSREP_CB_SUCCESS;
+}
+
+/* The following callbacks are stubs and not used in this example. */
+static wsrep_cb_status_t
+unordered_cb(void* recv_ctx __attribute__((unused)),
+ const wsrep_buf_t* data __attribute__((unused)))
+{
+ return WSREP_CB_SUCCESS;
+}
+
+static wsrep_cb_status_t
+sst_donate_cb (void* app_ctx __attribute__((unused)),
+ void* recv_ctx __attribute__((unused)),
+ const wsrep_buf_t* msg __attribute__((unused)),
+ const wsrep_gtid_t* state_id __attribute__((unused)),
+ const wsrep_buf_t* state __attribute__((unused)),
+ wsrep_bool_t bypass __attribute__((unused)))
+{
+ return WSREP_CB_SUCCESS;
+}
+
+static wsrep_cb_status_t synced_cb (void* app_ctx __attribute__((unused)))
+{
+ return WSREP_CB_SUCCESS;
+}
+
+/* This is the listening thread. It blocks in wsrep::recv() call until
+ * disconnect from cluster. It will apply and commit writesets through the
+ * callbacks defined avbove. */
+static void*
+recv_thread (void* arg)
+{
+ struct receiver_context* ctx = (struct receiver_context*)arg;
+
+ wsrep_status_t rc = wsrep->recv(wsrep, ctx);
+
+ fprintf (stderr, "Receiver exited with code %d", rc);
+
+ return NULL;
+}
+
+/* This is a signal handler to demonstrate graceful cluster leave. */
+static void
+graceful_leave (int signum)
+{
+ printf ("Got signal %d, exiting...\n", signum);
+ wsrep->disconnect(wsrep);
+}
+
+int main (int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ fprintf (stderr, "Usage: %s </path/to/wsrep/provider> <wsrep URI> "
+ "<cluster name>\n", argv[0]);
+ exit (EXIT_FAILURE);
+ }
+
+ const char* const wsrep_provider = argv[1];
+ const char* const wsrep_uri = argv[2];
+ const char* const cluster_name = argv[3];
+
+ /* Now let's load and initialize provider */
+ wsrep_status_t rc = wsrep_load (wsrep_provider, &wsrep, logger_cb);
+ if (WSREP_OK != rc)
+ {
+ fprintf (stderr, "Failed to load wsrep provider '%s'\n",wsrep_provider);
+ exit (EXIT_FAILURE);
+ }
+
+ wsrep_gtid_t state_id = { WSREP_UUID_UNDEFINED, WSREP_SEQNO_UNDEFINED };
+
+ /* wsrep provider initialization arguments */
+ struct wsrep_init_args wsrep_args =
+ {
+ .app_ctx = &global_ctx,
+
+ .node_name = "example listener",
+ .node_address = "",
+ .node_incoming = "",
+ .data_dir = ".", // working directory
+ .options = "",
+ .proto_ver = 127, // maximum supported application event protocol
+
+ .state_id = &state_id,
+ .state = NULL,
+
+ .logger_cb = logger_cb,
+ .view_cb = view_cb,
+ .sst_request_cb = sst_request_cb,
+ .apply_cb = apply_cb,
+ .unordered_cb = unordered_cb,
+ .sst_donate_cb = sst_donate_cb,
+ .synced_cb = synced_cb
+ };
+
+ rc = wsrep->init(wsrep, &wsrep_args);
+ if (WSREP_OK != rc)
+ {
+ fprintf (stderr, "wsrep::init() failed: %d\n", rc);
+ exit (EXIT_FAILURE);
+ }
+
+ /* Connect to cluster */
+ rc = wsrep->connect (wsrep, cluster_name, wsrep_uri, "", 0);
+ if (0 != rc)
+ {
+ fprintf (stderr,
+ "wsrep::connect() failed: %d (%s)\n", rc, strerror(-rc));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Now let's start several listening threads*/
+ int const num_threads = 4;
+ struct receiver_context thread_ctx[num_threads];
+ pthread_t threads[num_threads];
+
+ int i;
+ for (i = 0; i < num_threads; i++)
+ {
+ int err = pthread_create (
+ &threads[i], NULL, recv_thread, &thread_ctx[i]);
+
+ if (err)
+ {
+ fprintf (stderr, "Failed to start thread %d: %d (%s)",
+ i, err, strerror(err));
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ signal (SIGTERM, graceful_leave);
+ signal (SIGINT, graceful_leave);
+
+ /* Listening threads are now running and receiving writesets. Wait for them
+ * to join. Threads will join after signal handler closes wsrep connection*/
+ for (i = 0; i < num_threads; i++)
+ {
+ pthread_join (threads[i], NULL);
+ }
+
+ /* Unload provider after nobody uses it any more. */
+ wsrep_unload (wsrep);
+
+ return 0;
+}
diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c
index 1321538742f..31618de420e 100644
--- a/wsrep/wsrep_loader.c
+++ b/wsrep/wsrep_loader.c
@@ -56,9 +56,10 @@ static int wsrep_check_iface_version(const char* found, const char* iface_ver)
static int verify(const wsrep_t *wh, const char *iface_ver)
{
char msg[128];
+ const size_t msg_len = sizeof(msg);
#define VERIFY(_p) if (!(_p)) { \
- snprintf(msg, sizeof(msg), "wsrep_load(): verify(): %s\n", # _p); \
+ snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \
logger (WSREP_LOG_ERROR, msg); \
return EINVAL; \
}
@@ -75,11 +76,13 @@ static int verify(const wsrep_t *wh, const char *iface_ver)
VERIFY(wh->connect);
VERIFY(wh->disconnect);
VERIFY(wh->recv);
- VERIFY(wh->pre_commit);
- VERIFY(wh->post_commit);
- VERIFY(wh->post_rollback);
+ VERIFY(wh->assign_read_view);
+ VERIFY(wh->certify);
+ VERIFY(wh->commit_order_enter);
+ VERIFY(wh->commit_order_leave);
+ VERIFY(wh->release);
VERIFY(wh->replay_trx);
- VERIFY(wh->abort_pre_commit);
+ VERIFY(wh->abort_certification);
VERIFY(wh->append_key);
VERIFY(wh->append_data);
VERIFY(wh->free_connection);
@@ -134,8 +137,9 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
int ret = 0;
void *dlh = NULL;
wsrep_loader_fun dlfun;
- char msg[1025];
- msg[sizeof(msg)-1] = 0;
+ char msg[1024];
+ const size_t msg_len = sizeof(msg) - 1;
+ msg[msg_len] = 0;
if (NULL != log_cb)
logger = log_cb;
@@ -143,7 +147,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
if (!(spec && hptr))
return EINVAL;
- snprintf (msg, sizeof(msg)-1,
+ snprintf (msg, msg_len,
"wsrep_load(): loading provider library '%s'", spec);
logger (WSREP_LOG_INFO, msg);
@@ -161,7 +165,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
}
if (!(dlh = dlopen(spec, RTLD_NOW | RTLD_LOCAL))) {
- snprintf(msg, sizeof(msg)-1, "wsrep_load(): dlopen(): %s", dlerror());
+ snprintf(msg, msg_len, "wsrep_load(): dlopen(): %s", dlerror());
logger (WSREP_LOG_ERROR, msg);
ret = EINVAL;
goto out;
@@ -178,14 +182,14 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb)
}
if ((ret = (*dlfun)(*hptr)) != 0) {
- snprintf(msg, sizeof(msg)-1, "wsrep_load(): loader failed: %s",
+ snprintf(msg, msg_len, "wsrep_load(): loader failed: %s",
strerror(ret));
logger (WSREP_LOG_ERROR, msg);
goto out;
}
if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) {
- snprintf (msg, sizeof(msg)-1,
+ snprintf (msg, msg_len,
"wsrep_load(): interface version mismatch: my version %s, "
"provider version %s", WSREP_INTERFACE_VERSION,
(*hptr)->version);
@@ -201,7 +205,7 @@ out:
free(*hptr);
*hptr = NULL;
} else {
- snprintf (msg, sizeof(msg)-1,
+ snprintf (msg, msg_len,
"wsrep_load(): %s %s by %s loaded successfully.",
(*hptr)->provider_name, (*hptr)->provider_version,
(*hptr)->provider_vendor);
diff --git a/wsrep/wsrep_uuid.c b/wsrep/wsrep_uuid.c
index 54ae4ab5ed5..419594db127 100644
--- a/wsrep/wsrep_uuid.c
+++ b/wsrep/wsrep_uuid.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
+#include <string.h>
#include "wsrep_api.h"
@@ -81,3 +82,13 @@ wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len)
return -EMSGSIZE;
}
}
+
+/*!
+ * Compare two UUIDs
+ * @return -1, 0, 1 if lhs is respectively smaller, equal, or greater than rhs
+ */
+int
+wsrep_uuid_compare (const wsrep_uuid_t* lhs, const wsrep_uuid_t* rhs)
+{
+ return memcmp(lhs, rhs, sizeof(wsrep_uuid_t));
+}