[Commits] 0f85f09fd77: MDEV-16405: Merge Galera 4 changes from mariaDB_wsrep to 10.4
revision-id: 0f85f09fd77be9479bd603e467c76b8856deafed (mariadb-10.3.6-158-g0f85f09fd77) parent(s): f545e3cfa9fcc6b706a6e0ee6f2af2124e514e18 author: Jan Lindström committer: Jan Lindström timestamp: 2018-10-13 08:41:48 +0300 message: MDEV-16405: Merge Galera 4 changes from mariaDB_wsrep to 10.4 Phase I. --- .gitmodules | 4 + CMakeLists.txt | 16 +- cmake/plugin.cmake | 4 + cmake/wsrep.cmake | 2 +- extra/mariabackup/CMakeLists.txt | 2 +- extra/mariabackup/wsrep.cc | 4 +- include/mysql/service_wsrep.h | 239 +- include/thr_lock.h | 6 +- include/wsrep.h | 38 +- mysql-test/include/check-testcase.test | 46 + mysql-test/include/galera_cluster.inc | 6 + .../galera => }/include/galera_have_debug_sync.inc | 0 mysql-test/include/galera_wait_sync_point.inc | 11 + mysql-test/include/have_ipv6.inc | 20 + mysql-test/include/kill_galera.inc | 20 + mysql-test/include/mtr_warnings.sql | 46 + mysql-test/include/restart_mysqld.inc | 1 - mysql-test/include/wait_until_connected_again.inc | 2 +- mysql-test/include/wait_wsrep_ready.inc | 13 + mysql-test/include/wsrep_wait_disconnect.inc | 20 + mysql-test/lib/My/ConfigFactory.pm | 6 +- mysql-test/mysql-test-run.pl | 125 + mysql-test/r/mysqld--help-notwin.result | 1472 +++++++++++ mysql-test/r/query_cache_size_functionality.result | 226 ++ mysql-test/r/query_cache_type_functionality.result | 250 ++ mysql-test/suite/galera/disabled.def | 2 +- mysql-test/suite/galera/galera_2nodes.cnf | 25 +- .../suite/galera/galera_2nodes_as_master.cnf | 12 + mysql-test/suite/galera/galera_2nodes_as_slave.cnf | 47 +- mysql-test/suite/galera/galera_3nodes_as_slave.cnf | 59 +- mysql-test/suite/galera/galera_4nodes.cnf | 15 + .../suite/galera/include/galera_load_provider.inc | 68 + mysql-test/suite/galera/include/galera_resume.inc | 2 +- .../suite/galera/include/galera_sst_restore.inc | 2 +- .../suite/galera/include/galera_st_clean_slave.inc | 1 + .../galera/include/galera_st_disconnect_slave.inc | 8 + .../galera/include/galera_unload_provider.inc | 8 + mysql-test/suite/galera/r/GAL-382.result | 2 + mysql-test/suite/galera/r/GAL-401.result | 2 + mysql-test/suite/galera/r/GAL-480.result | 2 + mysql-test/suite/galera/r/GCF-1081.result | 47 + mysql-test/suite/galera/r/GCF-939.result | 13 + mysql-test/suite/galera/r/MDEV-15443.result | 2 + mysql-test/suite/galera/r/MW-252.result | 2 + mysql-test/suite/galera/r/MW-258.result | 2 + mysql-test/suite/galera/r/MW-259.result | 2 + mysql-test/suite/galera/r/MW-284.result | 4 + mysql-test/suite/galera/r/MW-285.result | 2 + mysql-test/suite/galera/r/MW-292.result | 27 +- mysql-test/suite/galera/r/MW-309.result | 2 + mysql-test/suite/galera/r/MW-313.result | 2 + mysql-test/suite/galera/r/MW-328A.result | 18 +- mysql-test/suite/galera/r/MW-328B.result | 2 + mysql-test/suite/galera/r/MW-328C.result | 2 + mysql-test/suite/galera/r/MW-328D.result | 2 + mysql-test/suite/galera/r/MW-328E.result | 2 + mysql-test/suite/galera/r/MW-329.result | 9 +- mysql-test/suite/galera/r/MW-336.result | 2 + mysql-test/suite/galera/r/MW-357.result | 2 + mysql-test/suite/galera/r/MW-360.result | 41 + mysql-test/suite/galera/r/MW-369.result | 65 +- mysql-test/suite/galera/r/MW-388.result | 6 +- mysql-test/suite/galera/r/MW-402.result | 76 +- mysql-test/suite/galera/r/MW-416.result | 6 +- mysql-test/suite/galera/r/MW-86-wait1.result | 17 +- mysql-test/suite/galera/r/MW-86-wait8.result | 16 +- mysql-test/suite/galera/r/MW-86.result | 78 + mysql-test/suite/galera/r/basic.result | 2 + mysql-test/suite/galera/r/binlog_checksum.result | 2 + mysql-test/suite/galera/r/create.result | 2 + .../suite/galera/r/enforce_storage_engine.result | 2 + .../suite/galera/r/enforce_storage_engine2.result | 2 + mysql-test/suite/galera/r/ev51914.result | 2 + mysql-test/suite/galera/r/fk.result | 2 + mysql-test/suite/galera/r/galera#414.result | 2 + mysql-test/suite/galera/r/galera_admin.result | 2 + .../galera/r/galera_alter_engine_innodb.result | 2 + .../galera/r/galera_alter_engine_myisam.result | 2 + .../suite/galera/r/galera_alter_table_force.result | 2 + .../galera/r/galera_applier_ftwrl_table.result | 2 + .../r/galera_applier_ftwrl_table_alter.result | 2 + mysql-test/suite/galera/r/galera_as_master.result | 4 + .../suite/galera/r/galera_as_master_gtid.result | 44 +- .../suite/galera/r/galera_as_master_large.result | 2 + .../suite/galera/r/galera_as_slave_autoinc.result | 4 + .../suite/galera/r/galera_as_slave_gtid.result | 2 + .../r/galera_as_slave_gtid_replicate_do_db.result | 160 ++ .../galera_as_slave_gtid_replicate_do_db_cc.result | 315 +++ .../suite/galera/r/galera_as_slave_nonprim.result | 18 + .../galera/r/galera_autoinc_sst_xtrabackup.result | 2 + mysql-test/suite/galera/r/galera_bf_abort.result | 4 +- .../r/galera_bf_abort_flush_for_export.result | 2 + .../galera/r/galera_bf_abort_for_update.result | 6 +- .../suite/galera/r/galera_bf_abort_ftwrl.result | 2 + .../suite/galera/r/galera_bf_abort_get_lock.result | 4 +- .../galera/r/galera_bf_abort_group_commit.result | 685 +++++ .../galera/r/galera_bf_abort_lock_table.result | 2 + .../suite/galera/r/galera_bf_abort_shutdown.result | 9 + .../suite/galera/r/galera_bf_abort_sleep.result | 4 +- .../r/galera_bf_background_statistics.result | 4 +- .../suite/galera/r/galera_bf_lock_wait.result | 2 + .../suite/galera/r/galera_binlog_cache_size.result | 2 + .../suite/galera/r/galera_binlog_checksum.result | 2 + .../r/galera_binlog_event_max_size_max.result | 2 + .../r/galera_binlog_event_max_size_min.result | 2 + .../suite/galera/r/galera_binlog_row_image.result | 2 + .../suite/galera/r/galera_commit_empty.result | 15 + .../suite/galera/r/galera_create_function.result | 2 + .../suite/galera/r/galera_create_procedure.result | 2 + .../galera/r/galera_create_table_as_select.result | 103 + .../suite/galera/r/galera_create_table_like.result | 2 + .../suite/galera/r/galera_create_trigger.result | 2 + .../suite/galera/r/galera_ddl_multiline.result | 2 + mysql-test/suite/galera/r/galera_defaults.result | 23 +- .../suite/galera/r/galera_delete_limit.result | 2 + .../suite/galera/r/galera_desync_overlapped.result | 2 + mysql-test/suite/galera/r/galera_drop_multi.result | 2 + mysql-test/suite/galera/r/galera_enum.result | 4 +- mysql-test/suite/galera/r/galera_events.result | 2 + .../suite/galera/r/galera_fk_cascade_delete.result | 2 + .../suite/galera/r/galera_fk_cascade_update.result | 2 + .../suite/galera/r/galera_fk_conflict.result | 4 +- .../suite/galera/r/galera_fk_mismatch.result | 2 + .../suite/galera/r/galera_fk_multicolumn.result | 2 + .../suite/galera/r/galera_fk_multitable.result | 2 + mysql-test/suite/galera/r/galera_fk_no_pk.result | 2 + .../galera/r/galera_fk_selfreferential.result | 2 + mysql-test/suite/galera/r/galera_fk_setnull.result | 2 + .../suite/galera/r/galera_flush_local.result | 2 + .../galera/r/galera_forced_binlog_format.result | 20 +- mysql-test/suite/galera/r/galera_ftwrl.result | 2 + .../suite/galera/r/galera_ftwrl_drain.result | 2 + mysql-test/suite/galera/r/galera_fulltext.result | 2 + .../r/galera_gcache_recover_full_gcache.result | 2 +- .../suite/galera/r/galera_gcs_fc_limit.result | 2 + .../suite/galera/r/galera_gcs_fragment.result | 2 +- .../galera/r/galera_gcs_max_packet_size.result | 2 + mysql-test/suite/galera/r/galera_gra_log.result | 2 + mysql-test/suite/galera/r/galera_gtid.result | 2 + mysql-test/suite/galera/r/galera_gtid_slave.result | 11 +- .../galera/r/galera_gtid_slave_sst_rsync.result | 106 +- .../suite/galera/r/galera_insert_ignore.result | 2 + .../suite/galera/r/galera_insert_multi.result | 4 +- .../galera/r/galera_ist_innodb_flush_logs.result | 22 + .../suite/galera/r/galera_ist_progress.result | 5 + .../suite/galera/r/galera_ist_recv_bind.result | 2 + .../galera/r/galera_ist_restart_joiner.result | 3 +- mysql-test/suite/galera/r/galera_ist_rsync.result | 2 + .../suite/galera/r/galera_ist_xtrabackup-v2.result | 38 + mysql-test/suite/galera/r/galera_kill_ddl.result | 1 + .../suite/galera/r/galera_kill_largechanges.result | 1 + .../suite/galera/r/galera_kill_smallchanges.result | 1 + mysql-test/suite/galera/r/galera_lock_table.result | 2 + mysql-test/suite/galera/r/galera_log_bin.result | 4 + .../suite/galera/r/galera_log_output_csv.result | 2 + .../suite/galera/r/galera_many_columns.result | 4 +- .../suite/galera/r/galera_many_indexes.result | 4 +- mysql-test/suite/galera/r/galera_many_rows.result | 4 +- .../suite/galera/r/galera_many_tables_nopk.result | 4 +- .../suite/galera/r/galera_many_tables_pk.result | 4 +- mysql-test/suite/galera/r/galera_mdev_10812.result | 2 + mysql-test/suite/galera/r/galera_mdev_13787.result | 2 + mysql-test/suite/galera/r/galera_mdl_race.result | 4 +- .../suite/galera/r/galera_multi_database.result | 2 + .../suite/galera/r/galera_myisam_autocommit.result | 2 + .../galera/r/galera_myisam_transactions.result | 2 + mysql-test/suite/galera/r/galera_nopk_bit.result | 4 +- mysql-test/suite/galera/r/galera_nopk_blob.result | 4 +- .../galera/r/galera_nopk_large_varchar.result | 4 +- .../suite/galera/r/galera_nopk_unicode.result | 4 +- .../r/galera_parallel_apply_lock_table.result | 8 +- .../r/galera_parallel_autoinc_largetrx.result | 4 +- .../r/galera_parallel_autoinc_manytrx.result | 4 +- .../suite/galera/r/galera_parallel_simple.result | 2 + .../suite/galera/r/galera_pk_bigint_signed.result | 4 +- .../galera/r/galera_pk_bigint_unsigned.result | 4 +- .../galera/r/galera_prepared_statement.result | 2 + .../suite/galera/r/galera_query_cache.result | 2 + .../galera/r/galera_query_cache_sync_wait.result | 2 + mysql-test/suite/galera/r/galera_read_only.result | 2 + .../galera/r/galera_repl_key_format_flat16.result | 2 + .../suite/galera/r/galera_repl_max_ws_size.result | 4 +- .../suite/galera/r/galera_restart_nochanges.result | 2 + .../r/galera_restart_on_unknown_option.result | 2 + mysql-test/suite/galera/r/galera_rsu_add_pk.result | 2 + .../suite/galera/r/galera_rsu_drop_pk.result | 2 + mysql-test/suite/galera/r/galera_rsu_error.result | 2 + mysql-test/suite/galera/r/galera_rsu_simple.result | 2 + .../suite/galera/r/galera_rsu_wsrep_desync.result | 2 + mysql-test/suite/galera/r/galera_sbr.result | 2 + mysql-test/suite/galera/r/galera_sbr_binlog.result | 2 + .../galera/r/galera_schema_dirty_reads.result | 2 + .../suite/galera/r/galera_serializable.result | 8 +- mysql-test/suite/galera/r/galera_server.result | 2 + .../suite/galera/r/galera_sql_log_bin_zero.result | 2 + mysql-test/suite/galera/r/galera_ssl.result | 2 + .../suite/galera/r/galera_ssl_compression.result | 2 + .../suite/galera/r/galera_sst_mysqldump.result | 114 + mysql-test/suite/galera/r/galera_sst_rsync.result | 2 +- .../suite/galera/r/galera_sst_xtrabackup-v2.result | 110 + ...alera_sst_xtrabackup-v2_encrypt_with_key.result | 2 + .../suite/galera/r/galera_status_cluster.result | 2 + .../galera/r/galera_status_local_index.result | 2 + .../galera/r/galera_status_local_state.result | 2 + .../suite/galera/r/galera_suspend_slave.result | 2 + .../suite/galera/r/galera_sync_wait_show.result | 2 + .../r/galera_toi_alter_auto_increment.result | 2 + .../suite/galera/r/galera_toi_ddl_error.result | 5 + .../suite/galera/r/galera_toi_ddl_fk_update.result | 2 + .../suite/galera/r/galera_toi_ddl_locking.result | 32 +- .../galera/r/galera_toi_ddl_nonconflicting.result | 2 + .../galera/r/galera_toi_ddl_sequential.result | 2 + .../suite/galera/r/galera_toi_drop_database.result | 6 +- mysql-test/suite/galera/r/galera_toi_ftwrl.result | 2 + .../galera/r/galera_toi_lock_exclusive.result | 4 +- .../suite/galera/r/galera_toi_lock_shared.result | 2 + .../suite/galera/r/galera_toi_truncate.result | 4 +- .../galera/r/galera_transaction_read_only.result | 2 + .../galera/r/galera_transaction_replay.result | 96 +- mysql-test/suite/galera/r/galera_truncate.result | 2 + .../galera/r/galera_truncate_temporary.result | 2 + .../galera/r/galera_unicode_identifiers.result | 2 + mysql-test/suite/galera/r/galera_unicode_pk.result | 6 +- .../suite/galera/r/galera_update_limit.result | 2 + .../suite/galera/r/galera_v1_row_events.result | 2 + .../suite/galera/r/galera_var_OSU_method.result | 2 + .../suite/galera/r/galera_var_OSU_method2.result | 2 + .../r/galera_var_auto_inc_control_off.result | 4 +- .../galera/r/galera_var_auto_inc_control_on.result | 2 + .../galera/r/galera_var_certify_nonPK_off.result | 2 + .../galera/r/galera_var_cluster_address.result | 8 +- .../suite/galera/r/galera_var_desync_on.result | 2 + .../suite/galera/r/galera_var_dirty_reads.result | 4 +- .../suite/galera/r/galera_var_fkchecks.result | 2 + .../galera/r/galera_var_gtid_domain_id.result | 2 + .../galera/r/galera_var_ignore_apply_errors.result | 154 ++ .../r/galera_var_innodb_disallow_writes.result | 2 + .../galera/r/galera_var_load_data_splitting.result | 2 + .../suite/galera/r/galera_var_log_bin.result | 2 + .../suite/galera/r/galera_var_max_ws_rows.result | 2 + .../suite/galera/r/galera_var_max_ws_size.result | 4 +- .../r/galera_var_mysql_replication_bundle.result | 2 + .../suite/galera/r/galera_var_node_address.result | 2 + .../galera/r/galera_var_reject_queries.result | 2 + .../r/galera_var_replicate_myisam_off.result | 2 + .../galera/r/galera_var_replicate_myisam_on.result | 2 + .../suite/galera/r/galera_var_slave_threads.result | 207 +- .../suite/galera/r/galera_var_sst_auth.result | 2 + .../suite/galera/r/galera_var_sync_wait.result | 2 + .../suite/galera/r/galera_var_wsrep_on_off.result | 2 + .../suite/galera/r/galera_wan_restart_ist.result | 2 + .../suite/galera/r/galera_wan_restart_sst.result | 2 + .../galera/r/galera_wsrep_desync_wsrep_on.result | 2 + .../galera/r/galera_wsrep_log_conficts.result | 4 +- .../suite/galera/r/galera_wsrep_new_cluster.result | 2 + .../r/galera_wsrep_provider_options_syntax.result | 2 + .../galera/r/galera_zero_length_column.result | 2 + mysql-test/suite/galera/r/grant.result | 2 + mysql-test/suite/galera/r/lp1276424.result | 2 + mysql-test/suite/galera/r/lp1347768.result | 2 + mysql-test/suite/galera/r/lp1376747-2.result | 2 + mysql-test/suite/galera/r/lp1376747-3.result | 2 + mysql-test/suite/galera/r/lp1376747-4.result | 2 + mysql-test/suite/galera/r/lp1376747.result | 2 + mysql-test/suite/galera/r/lp1438990.result | 2 + mysql-test/suite/galera/r/lp959512.result | 2 + mysql-test/suite/galera/r/mdev_10518.result | 2 + mysql-test/suite/galera/r/mdev_9290.result | 2 + mysql-test/suite/galera/r/mysql-wsrep#110.result | 2 + mysql-test/suite/galera/r/mysql-wsrep#198.result | 2 + mysql-test/suite/galera/r/mysql-wsrep#201.result | 2 + mysql-test/suite/galera/r/mysql-wsrep#216.result | 11 + mysql-test/suite/galera/r/mysql-wsrep#237.result | 4 +- mysql-test/suite/galera/r/mysql-wsrep#247.result | 2 + mysql-test/suite/galera/r/mysql-wsrep#31.result | 2 + mysql-test/suite/galera/r/mysql-wsrep#90.result | 2 + mysql-test/suite/galera/r/partition.result | 6 +- mysql-test/suite/galera/r/pxc-421.result | 2 + mysql-test/suite/galera/r/query_cache.result | 2 + mysql-test/suite/galera/r/rename.result | 2 + mysql-test/suite/galera/r/rpl_row_annotate.result | 8 +- mysql-test/suite/galera/r/sql_log_bin.result | 2 + mysql-test/suite/galera/r/unique_key.result | 2 + mysql-test/suite/galera/r/view.result | 2 + .../galera/r/wsrep_trx_fragment_size_non_sr.result | 25 + .../galera/r/wsrep_trx_fragment_size_sr.result | 15 + mysql-test/suite/galera/suite.pm | 2 + mysql-test/suite/galera/t/GAL-419.test | 4 +- mysql-test/suite/galera/t/GCF-1081.test | 72 + mysql-test/suite/galera/t/GCF-939.test | 31 + mysql-test/suite/galera/t/MW-284.test | 2 + mysql-test/suite/galera/t/MW-292.test | 50 +- mysql-test/suite/galera/t/MW-328A.test | 40 +- mysql-test/suite/galera/t/MW-329.test | 28 +- mysql-test/suite/galera/t/MW-336.test | 9 +- mysql-test/suite/galera/t/MW-360-master.opt | 2 + mysql-test/suite/galera/t/MW-360.test | 100 + mysql-test/suite/galera/t/MW-369.inc | 7 +- mysql-test/suite/galera/t/MW-369.test | 1 - mysql-test/suite/galera/t/MW-388.test | 5 +- mysql-test/suite/galera/t/MW-402.test | 56 +- mysql-test/suite/galera/t/MW-416.test | 8 +- mysql-test/suite/galera/t/MW-86-master.opt | 1 + mysql-test/suite/galera/t/MW-86-wait1.test | 13 +- mysql-test/suite/galera/t/MW-86-wait8.test | 11 +- mysql-test/suite/galera/t/MW-86.test | 193 ++ mysql-test/suite/galera/t/disabled.def | 13 + .../t/galera_applier_ftwrl_table_alter-master.opt | 2 +- mysql-test/suite/galera/t/galera_as_master.test | 2 + .../suite/galera/t/galera_as_master_gtid.cnf | 2 - .../suite/galera/t/galera_as_master_gtid.test | 24 +- .../t/galera_as_master_gtid_change_master.cnf | 2 - .../t/galera_as_master_gtid_change_master.test | 2 + mysql-test/suite/galera/t/galera_as_slave.test | 19 +- .../suite/galera/t/galera_as_slave_autoinc.test | 20 +- .../suite/galera/t/galera_as_slave_gtid.test | 21 +- .../t/galera_as_slave_gtid_replicate_do_db.cnf | 17 + .../t/galera_as_slave_gtid_replicate_do_db.test | 150 ++ .../t/galera_as_slave_gtid_replicate_do_db_cc.test | 176 ++ .../suite/galera/t/galera_as_slave_nonprim.test | 28 +- .../suite/galera/t/galera_as_slave_preordered.test | 19 +- .../t/galera_as_slave_replication_bundle.test | 13 +- .../galera/t/galera_autoinc_sst_xtrabackup.cnf | 2 +- .../galera/t/galera_bf_abort_group_commit.cnf | 15 + .../galera/t/galera_bf_abort_group_commit.test | 76 + .../suite/galera/t/galera_bf_abort_shutdown.test | 22 + mysql-test/suite/galera/t/galera_commit_empty.test | 35 + .../galera/t/galera_create_table_as_select.test | 145 ++ mysql-test/suite/galera/t/galera_defaults.test | 4 +- .../galera/t/galera_forced_binlog_format.test | 5 +- mysql-test/suite/galera/t/galera_ftwrl_drain.test | 2 +- .../t/galera_gcache_recover_full_gcache.test | 4 +- mysql-test/suite/galera/t/galera_gcs_fragment.test | 2 +- mysql-test/suite/galera/t/galera_gtid-master.opt | 2 +- mysql-test/suite/galera/t/galera_gtid_slave.test | 14 + .../galera/t/galera_gtid_slave_sst_rsync.test | 109 +- .../galera/t/galera_ist_innodb_flush_logs.cnf | 2 +- mysql-test/suite/galera/t/galera_ist_progress.test | 4 +- .../suite/galera/t/galera_ist_restart_joiner.test | 2 +- .../suite/galera/t/galera_ist_xtrabackup-v2.cnf | 2 +- mysql-test/suite/galera/t/galera_kill_applier.test | 1 - mysql-test/suite/galera/t/galera_log_bin.test | 2 + mysql-test/suite/galera/t/galera_migrate.cnf | 2 + .../galera/t/galera_parallel_apply_lock_table.test | 6 +- .../galera/t/galera_parallel_autoinc_manytrx.test | 2 +- .../suite/galera/t/galera_parallel_simple.test | 2 +- mysql-test/suite/galera/t/galera_pc_recovery.test | 93 + mysql-test/suite/galera/t/galera_split_brain.test | 6 +- mysql-test/suite/galera/t/galera_ssl_upgrade.test | 4 + mysql-test/suite/galera/t/galera_sst_mysqldump.cnf | 6 +- .../suite/galera/t/galera_sst_mysqldump.test | 3 +- .../galera/t/galera_sst_mysqldump_with_key.cnf | 4 + .../galera/t/galera_sst_xtrabackup-v2-options.cnf | 2 +- .../suite/galera/t/galera_sst_xtrabackup-v2.cnf | 2 +- .../galera_sst_xtrabackup-v2_encrypt_with_key.cnf | 2 +- .../suite/galera/t/galera_toi_ddl_error.test | 5 + .../suite/galera/t/galera_toi_ddl_locking.test | 53 +- .../suite/galera/t/galera_transaction_replay.test | 201 +- .../suite/galera/t/galera_var_cluster_address.test | 11 +- .../suite/galera/t/galera_var_dirty_reads.test | 6 +- .../galera/t/galera_var_ignore_apply_errors.test | 235 ++ mysql-test/suite/galera/t/galera_var_log_bin.cnf | 5 + .../galera/t/galera_var_retry_autocommit.test | 18 +- .../suite/galera/t/galera_var_slave_threads.test | 123 +- .../galera/t/galera_vote_drop_temporary-master.opt | 1 + .../suite/galera/t/galera_wsrep_new_cluster.test | 1 - .../suite/galera/t/mysql-wsrep#198-master.opt | 1 + mysql-test/suite/galera/t/mysql-wsrep#237.test | 4 +- mysql-test/suite/galera/t/partition.test | 16 +- mysql-test/suite/galera/t/rpl_row_annotate.test | 6 +- .../galera/t/wsrep_trx_fragment_size_non_sr.test | 26 + .../suite/galera/t/wsrep_trx_fragment_size_sr.test | 22 + mysql-test/suite/galera_3nodes/galera_3nodes.cnf | 1 + .../suite/galera_3nodes/include/galera_suspend.inc | 2 +- .../r/galera_certification_ccc.result | 2 + .../r/galera_certification_double_failure.result | 5 +- .../r/galera_ipv6_xtrabackup-v2.result | 3 - .../r/galera_ist_gcache_rollover.result | 2 + .../r/galera_parallel_apply_3nodes.result | 4 +- .../galera_3nodes/r/galera_pc_bootstrap.result | 13 + .../suite/galera_3nodes/r/galera_pc_weight.result | 1 - .../galera_3nodes/r/galera_wsrep_schema.result | 77 + mysql-test/suite/galera_3nodes/t/GAL-501.test | 6 + .../t/galera_certification_double_failure.test | 2 + .../t/galera_evs_suspect_timeout.test | 6 +- mysql-test/suite/galera_3nodes/t/galera_garbd.test | 5 +- .../galera_3nodes/t/galera_ipv6_mysqldump.cnf | 6 + .../galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf | 4 + .../galera_3nodes/t/galera_ipv6_xtrabackup-v2.test | 30 +- .../t/galera_ist_gcache_rollover.test | 2 +- .../t/galera_parallel_apply_3nodes.test | 2 +- .../suite/galera_3nodes/t/galera_pc_weight.cnf | 8 +- .../suite/galera_3nodes/t/galera_pc_weight.test | 27 +- .../t/galera_slave_options_ignore.test | 1 + .../suite/galera_3nodes/t/galera_wsrep_schema.test | 74 + .../suite/galera_3nodes_ee/galera_3nodes.cnf | 1 + .../include/galera_check_voting_recovery.inc | 58 + mysql-test/suite/galera_3nodes_ee/my.cnf | 1 + mysql-test/suite/galera_3nodes_ee/r/GCF-354.result | 23 + mysql-test/suite/galera_3nodes_ee/r/GCF-361.result | 16 + mysql-test/suite/galera_3nodes_ee/r/GCF-363.result | 31 + mysql-test/suite/galera_3nodes_ee/r/GCF-376.result | 48 + .../galera_3nodes_ee/r/galera-features#115.result | 21 + .../galera_3nodes_ee/r/galera-features#119.result | 19 + .../galera_3nodes_ee/r/galera-features#79.result | 32 + .../r/galera_nbo_kill_master.result | 27 + .../r/galera_nbo_kill_slave_ist.result | 35 + .../r/galera_nbo_kill_slave_sst.result | 33 + .../r/galera_nbo_master_majority_failure.result | 46 + .../r/galera_nbo_master_majority_success.result | 50 + .../r/galera_nbo_master_minority_failure.result | 52 + .../r/galera_nbo_master_minority_success.result | 52 + .../r/galera_nbo_master_non_prim_failure.result | 42 + .../r/galera_nbo_master_non_prim_success.result | 32 + .../r/galera_nbo_shutdown_slave_ist.result | 28 + .../r/galera_nbo_slave_non_prim.result | 35 + .../galera_3nodes_ee/r/galera_toi_vote.result | 19 + .../r/galera_vote_rejoin_mysqldump.result | 60 + .../suite/galera_3nodes_ee/r/galera_vote_sr.result | 52 + .../r/mysql-wsrep-features#131.result | 12 + mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf | 4 + mysql-test/suite/galera_3nodes_ee/t/GCF-354.test | 59 + mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf | 4 + mysql-test/suite/galera_3nodes_ee/t/GCF-361.test | 47 + mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf | 8 + mysql-test/suite/galera_3nodes_ee/t/GCF-363.test | 68 + mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf | 4 + mysql-test/suite/galera_3nodes_ee/t/GCF-376.test | 84 + .../galera_3nodes_ee/t/galera-features#115.cnf | 4 + .../galera_3nodes_ee/t/galera-features#115.test | 67 + .../galera_3nodes_ee/t/galera-features#119.test | 61 + .../galera_3nodes_ee/t/galera-features#79.test | 75 + .../galera_3nodes_ee/t/galera_nbo_kill_master.test | 73 + .../t/galera_nbo_kill_slave_ist.test | 73 + .../t/galera_nbo_kill_slave_sst.cnf | 11 + .../t/galera_nbo_kill_slave_sst.test | 70 + .../t/galera_nbo_master_majority_failure.cnf | 4 + .../t/galera_nbo_master_majority_failure.test | 38 + .../t/galera_nbo_master_majority_success.cnf | 4 + .../t/galera_nbo_master_majority_success.test | 38 + .../t/galera_nbo_master_minority_failure.cnf | 4 + .../t/galera_nbo_master_minority_failure.test | 35 + .../t/galera_nbo_master_minority_success.cnf | 4 + .../t/galera_nbo_master_minority_success.test | 41 + .../t/galera_nbo_master_non_prim_failure.test | 92 + .../t/galera_nbo_master_non_prim_success.test | 80 + .../t/galera_nbo_shutdown_slave_ist.test | 66 + .../t/galera_nbo_slave_non_prim.test | 69 + .../suite/galera_3nodes_ee/t/galera_toi_vote.cnf | 4 + .../suite/galera_3nodes_ee/t/galera_toi_vote.test | 63 + .../t/galera_vote_rejoin_mysqldump.cnf | 4 + .../t/galera_vote_rejoin_mysqldump.test | 80 + .../galera_3nodes_ee/t/galera_vote_sr-master.opt | 2 + .../suite/galera_3nodes_ee/t/galera_vote_sr.test | 87 + .../t/mysql-wsrep-features#131.test | 39 + .../suite/galera_3nodes_sr/galera_3nodes.cnf | 1 + mysql-test/suite/galera_3nodes_sr/my.cnf | 1 + mysql-test/suite/galera_3nodes_sr/r/GCF-336.result | 26 + mysql-test/suite/galera_3nodes_sr/r/GCF-582.result | 23 + mysql-test/suite/galera_3nodes_sr/r/GCF-606.result | 23 + mysql-test/suite/galera_3nodes_sr/r/GCF-609.result | 20 + .../suite/galera_3nodes_sr/r/GCF-810A.result | 256 ++ .../suite/galera_3nodes_sr/r/GCF-810B.result | 100 + .../suite/galera_3nodes_sr/r/GCF-810C.result | 177 ++ mysql-test/suite/galera_3nodes_sr/r/GCF-817.result | 33 + mysql-test/suite/galera_3nodes_sr/r/GCF-832.result | 15 + .../r/galera_sr_isolate_master.result | 62 + .../galera_3nodes_sr/r/galera_sr_join_slave.result | 25 + .../r/galera_sr_kill_master.result | 22 + .../r/galera_sr_kill_slave_after_apply.result | 38 + ...alera_sr_kill_slave_after_apply_rollback.result | 44 + ...lera_sr_kill_slave_after_apply_rollback2.result | 31 + .../r/galera_sr_kill_slave_before_apply.result | 27 + .../r/galera_sr_threeway_split.result | 84 + mysql-test/suite/galera_3nodes_sr/t/GCF-336.test | 47 + mysql-test/suite/galera_3nodes_sr/t/GCF-582.test | 39 + mysql-test/suite/galera_3nodes_sr/t/GCF-606.test | 80 + mysql-test/suite/galera_3nodes_sr/t/GCF-609.test | 30 + mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test | 137 + mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test | 49 + mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test | 70 + mysql-test/suite/galera_3nodes_sr/t/GCF-817.test | 101 + mysql-test/suite/galera_3nodes_sr/t/GCF-832.test | 36 + mysql-test/suite/galera_3nodes_sr/t/disabled.def | 0 .../t/galera_sr_isolate_master.test | 127 + .../galera_3nodes_sr/t/galera_sr_join_slave.test | 56 + .../galera_3nodes_sr/t/galera_sr_kill_master.test | 56 + .../t/galera_sr_kill_slave_after_apply.test | 75 + .../galera_sr_kill_slave_after_apply_rollback.test | 76 + ...galera_sr_kill_slave_after_apply_rollback2.test | 56 + .../t/galera_sr_kill_slave_before_apply.test | 71 + .../t/galera_sr_threeway_split.cnf | 5 + .../t/galera_sr_threeway_split.test | 169 ++ mysql-test/suite/galera_ee/galera_2nodes.cnf | 1 + mysql-test/suite/galera_ee/galera_4nodes.cnf | 1 + mysql-test/suite/galera_ee/my.cnf | 1 + mysql-test/suite/galera_ee/r/GCF-329A.result | 30 + mysql-test/suite/galera_ee/r/GCF-329B.result | 16 + mysql-test/suite/galera_ee/r/GCF-360.result | 416 ++++ mysql-test/suite/galera_ee/r/GCF-421.result | 14 + mysql-test/suite/galera_ee/r/GCF-546.result | 28 + mysql-test/suite/galera_ee/r/GCF-563.result | 52 + mysql-test/suite/galera_ee/r/GCF-849.result | 11 + mysql-test/suite/galera_ee/r/GCF-854.result | 16 + .../suite/galera_ee/r/galera-features#117.result | 29 + .../r/galera_nbo_alter_conflicting.result | 14 + .../suite/galera_ee/r/galera_nbo_alter_copy.result | 44 + .../galera_ee/r/galera_nbo_alter_engine.result | 22 + .../r/galera_nbo_alter_error_duplicate.result | 30 + .../galera_ee/r/galera_nbo_alter_exclusive.result | 37 + .../galera_ee/r/galera_nbo_alter_inplace.result | 39 + .../galera_ee/r/galera_nbo_alter_multi.result | 11 + .../r/galera_nbo_alter_nonconflicting.result | 29 + .../galera_ee/r/galera_nbo_alter_parallel.result | 45 + .../galera_ee/r/galera_nbo_alter_partition.result | 26 + .../galera_ee/r/galera_nbo_alter_rename.result | 19 + .../suite/galera_ee/r/galera_nbo_alter_toi.result | 38 + .../galera_ee/r/galera_nbo_create_index.result | 36 + .../suite/galera_ee/r/galera_nbo_ddl_error.result | 22 + .../galera_ee/r/galera_nbo_error_on_all.result | 13 + .../suite/galera_ee/r/galera_nbo_local_mdl.result | 12 + .../galera_ee/r/galera_nbo_processlist.result | 35 + .../suite/galera_ee/r/galera_nbo_sst_slave.result | 23 + .../galera_ee/r/galera_nbo_temporary_table.result | 14 + .../galera_ee/r/galera_nbo_unsupported.result | 26 + .../galera_ee/r/galera_vote_rejoin_ddl.result | 44 + .../galera_ee/r/galera_vote_rejoin_dml.result | 47 + .../galera_ee/r/mysql-wsrep-features#127.result | 5 + .../galera_ee/r/mysql-wsrep-features#128.result | 7 + .../galera_ee/r/mysql-wsrep-features#131.result | 12 + .../galera_ee/r/mysql-wsrep-features#132.result | 18 + mysql-test/suite/galera_ee/t/GCF-329A.test | 42 + mysql-test/suite/galera_ee/t/GCF-329B.test | 53 + mysql-test/suite/galera_ee/t/GCF-360.cnf | 17 + mysql-test/suite/galera_ee/t/GCF-360.test | 64 + mysql-test/suite/galera_ee/t/GCF-421.test | 46 + mysql-test/suite/galera_ee/t/GCF-546.test | 47 + mysql-test/suite/galera_ee/t/GCF-563.test | 63 + mysql-test/suite/galera_ee/t/GCF-849.test | 39 + mysql-test/suite/galera_ee/t/GCF-854.test | 42 + .../suite/galera_ee/t/galera-features#117.cnf | 4 + .../suite/galera_ee/t/galera-features#117.test | 37 + .../galera_ee/t/galera_nbo_alter_conflicting.test | 57 + .../suite/galera_ee/t/galera_nbo_alter_copy.test | 67 + .../suite/galera_ee/t/galera_nbo_alter_engine.test | 31 + .../t/galera_nbo_alter_error_duplicate.test | 34 + .../galera_ee/t/galera_nbo_alter_exclusive.test | 64 + .../galera_ee/t/galera_nbo_alter_inplace.test | 67 + .../suite/galera_ee/t/galera_nbo_alter_multi.test | 15 + .../t/galera_nbo_alter_nonconflicting.test | 57 + .../galera_ee/t/galera_nbo_alter_parallel.test | 65 + .../galera_ee/t/galera_nbo_alter_partition.test | 29 + .../suite/galera_ee/t/galera_nbo_alter_rename.test | 31 + .../suite/galera_ee/t/galera_nbo_alter_toi.test | 53 + .../suite/galera_ee/t/galera_nbo_create_index.test | 34 + .../suite/galera_ee/t/galera_nbo_ddl_error.test | 38 + .../suite/galera_ee/t/galera_nbo_error_on_all.test | 21 + .../suite/galera_ee/t/galera_nbo_local_mdl.test | 55 + .../suite/galera_ee/t/galera_nbo_processlist.test | 81 + .../suite/galera_ee/t/galera_nbo_sst_slave.test | 89 + .../t/galera_nbo_temporary_table-master.opt | 2 + .../galera_ee/t/galera_nbo_temporary_table.test | 37 + .../suite/galera_ee/t/galera_nbo_unsupported.test | 42 + .../suite/galera_ee/t/galera_vote_rejoin_ddl.cnf | 5 + .../suite/galera_ee/t/galera_vote_rejoin_ddl.test | 87 + .../suite/galera_ee/t/galera_vote_rejoin_dml.cnf | 4 + .../suite/galera_ee/t/galera_vote_rejoin_dml.test | 91 + .../galera_ee/t/mysql-wsrep-features#127.test | 16 + .../t/mysql-wsrep-features#128-master.opt | 1 + .../galera_ee/t/mysql-wsrep-features#128.test | 11 + .../galera_ee/t/mysql-wsrep-features#131.test | 38 + .../galera_ee/t/mysql-wsrep-features#132.test | 39 + mysql-test/suite/galera_sr/galera_2nodes.cnf | 1 + mysql-test/suite/galera_sr/my.cnf | 1 + mysql-test/suite/galera_sr/r/GCF-1008.result | 70 + mysql-test/suite/galera_sr/r/GCF-1018.result | 15 + mysql-test/suite/galera_sr/r/GCF-1018B.result | 8 + mysql-test/suite/galera_sr/r/GCF-1043A.result | 21 + mysql-test/suite/galera_sr/r/GCF-1043B.result | 15 + mysql-test/suite/galera_sr/r/GCF-1051.result | 46 + mysql-test/suite/galera_sr/r/GCF-1060.result | 15 + mysql-test/suite/galera_sr/r/GCF-437.result | 12 + mysql-test/suite/galera_sr/r/GCF-561.result | 42 + mysql-test/suite/galera_sr/r/GCF-571.result | 67 + mysql-test/suite/galera_sr/r/GCF-572.result | 37 + mysql-test/suite/galera_sr/r/GCF-574.result | 11 + mysql-test/suite/galera_sr/r/GCF-580.result | 13 + mysql-test/suite/galera_sr/r/GCF-585.result | 25 + mysql-test/suite/galera_sr/r/GCF-597.result | 15 + mysql-test/suite/galera_sr/r/GCF-620.result | 14 + mysql-test/suite/galera_sr/r/GCF-623.result | 22 + mysql-test/suite/galera_sr/r/GCF-627.result | 18 + mysql-test/suite/galera_sr/r/GCF-845.result | 14 + mysql-test/suite/galera_sr/r/GCF-851.result | 24 + mysql-test/suite/galera_sr/r/GCF-867.result | 2 + mysql-test/suite/galera_sr/r/GCF-889.result | 18 + mysql-test/suite/galera_sr/r/GCF-900.result | 13 + .../suite/galera_sr/r/galera-features#56.result | 32 + .../suite/galera_sr/r/galera_sr_bf_abort.result | 448 ++++ mysql-test/suite/galera_sr/r/galera_sr_blob.result | 15 + .../suite/galera_sr/r/galera_sr_cc_master.result | 45 + .../suite/galera_sr/r/galera_sr_cc_slave.result | 46 + .../suite/galera_sr/r/galera_sr_concurrent.result | 28 + .../suite/galera_sr/r/galera_sr_conflict.result | 14 + .../r/galera_sr_conflict_on_commit.result | 22 + .../r/galera_sr_conflict_on_commit2.result | 19 + .../galera_sr_conflict_with_rollback_master.result | 22 + .../suite/galera_sr/r/galera_sr_ddl_master.result | 41 + .../suite/galera_sr/r/galera_sr_ddl_schema.result | 18 + .../suite/galera_sr/r/galera_sr_ddl_slave.result | 42 + .../galera_sr/r/galera_sr_ddl_unrelated.result | 34 + .../galera_sr/r/galera_sr_dupkey_error.result | 36 + .../suite/galera_sr/r/galera_sr_fk_conflict.result | 34 + mysql-test/suite/galera_sr/r/galera_sr_gtid.result | 57 + .../galera_sr/r/galera_sr_insert_select.result | 11 + .../r/galera_sr_kill_all_nobootstrap.result | 21 + .../r/galera_sr_kill_all_norecovery.result | 22 + .../r/galera_sr_kill_all_pcrecovery.result | 22 + .../galera_sr/r/galera_sr_kill_connection.result | 25 + .../suite/galera_sr/r/galera_sr_kill_query.result | 17 + .../suite/galera_sr/r/galera_sr_kill_slave.result | 39 + .../galera_sr/r/galera_sr_large_fragment.result | 28 + .../suite/galera_sr/r/galera_sr_load_data.result | 8 + .../r/galera_sr_load_data_splitting.result | 9 + .../suite/galera_sr/r/galera_sr_log_bin.result | 124 + .../galera_sr/r/galera_sr_many_fragments.result | 28 + .../suite/galera_sr/r/galera_sr_myisam.result | 11 + .../galera_sr/r/galera_sr_mysqldump_sst.result | 40 + .../galera_sr/r/galera_sr_parallel_apply.result | 26 + .../suite/galera_sr/r/galera_sr_rollback.result | 29 + .../galera_sr/r/galera_sr_rollback_retry.result | 26 + .../r/galera_sr_rollback_savepoint.result | 33 + .../r/galera_sr_rollback_statement.result | 22 + mysql-test/suite/galera_sr/r/galera_sr_sbr.result | 16 + .../galera_sr/r/galera_sr_shutdown_master.result | 20 + .../galera_sr/r/galera_sr_shutdown_slave.result | 29 + .../galera_sr/r/galera_sr_small_gcache.result | 10 + .../galera_sr/r/galera_sr_table_contents.result | 198 ++ .../r/galera_sr_transaction_replay.result | 101 + .../galera_sr/r/galera_sr_unit_statements.result | 18 + .../galera_sr/r/galera_sr_v1_row_events.result | 20 + .../suite/galera_sr/r/galera_sr_ws_size.result | 29 + .../suite/galera_sr/r/galera_sr_ws_size2.result | 28 + .../r/galera_var_ignore_apply_errors_sr.result | 22 + .../suite/galera_sr/r/mysql-wsrep#215.result | 88 + .../galera_sr/r/mysql-wsrep-features#136.result | 65 + .../galera_sr/r/mysql-wsrep-features#138.result | 17 + .../galera_sr/r/mysql-wsrep-features#14.result | 8 + .../galera_sr/r/mysql-wsrep-features#148.result | 27 + .../galera_sr/r/mysql-wsrep-features#15.result | 8 + .../galera_sr/r/mysql-wsrep-features#165.result | 752 ++++++ .../galera_sr/r/mysql-wsrep-features#213.result | 26 + .../galera_sr/r/mysql-wsrep-features#214.result | 46 + .../galera_sr/r/mysql-wsrep-features#22.result | 26 + .../galera_sr/r/mysql-wsrep-features#27.result | 17 + .../galera_sr/r/mysql-wsrep-features#29.result | 14 + .../galera_sr/r/mysql-wsrep-features#32.result | 27 + .../galera_sr/r/mysql-wsrep-features#35.result | 26 + .../galera_sr/r/mysql-wsrep-features#8.result | 27 + .../galera_sr/r/mysql-wsrep-features#9.result | 12 + .../galera_sr/r/mysql-wsrep-features#93.result | 15 + .../galera_sr/r/mysql-wsrep-features#96.result | 26 + mysql-test/suite/galera_sr/t/GCF-1008.inc | 36 + mysql-test/suite/galera_sr/t/GCF-1008.test | 18 + mysql-test/suite/galera_sr/t/GCF-1018.test | 38 + mysql-test/suite/galera_sr/t/GCF-1018B.test | 40 + mysql-test/suite/galera_sr/t/GCF-1043A.test | 13 + mysql-test/suite/galera_sr/t/GCF-1043B.test | 13 + mysql-test/suite/galera_sr/t/GCF-1051.test | 52 + mysql-test/suite/galera_sr/t/GCF-1060.test | 9 + mysql-test/suite/galera_sr/t/GCF-437.test | 21 + mysql-test/suite/galera_sr/t/GCF-561.test | 65 + mysql-test/suite/galera_sr/t/GCF-571.test | 54 + mysql-test/suite/galera_sr/t/GCF-572.test | 54 + mysql-test/suite/galera_sr/t/GCF-574.test | 27 + mysql-test/suite/galera_sr/t/GCF-580.test | 27 + mysql-test/suite/galera_sr/t/GCF-585.test | 44 + mysql-test/suite/galera_sr/t/GCF-597.test | 29 + mysql-test/suite/galera_sr/t/GCF-620.test | 22 + mysql-test/suite/galera_sr/t/GCF-623.test | 31 + mysql-test/suite/galera_sr/t/GCF-627.test | 30 + mysql-test/suite/galera_sr/t/GCF-845.test | 30 + mysql-test/suite/galera_sr/t/GCF-851.test | 24 + mysql-test/suite/galera_sr/t/GCF-867.test | 42 + mysql-test/suite/galera_sr/t/GCF-889.test | 28 + mysql-test/suite/galera_sr/t/GCF-900.test | 28 + mysql-test/suite/galera_sr/t/disabled.def | 4 + .../suite/galera_sr/t/galera-features#56.test | 55 + .../suite/galera_sr/t/galera_sr_bf_abort.inc | 145 ++ .../suite/galera_sr/t/galera_sr_bf_abort.test | 48 + mysql-test/suite/galera_sr/t/galera_sr_blob.test | 38 + .../suite/galera_sr/t/galera_sr_cc_master.test | 87 + .../suite/galera_sr/t/galera_sr_cc_slave.test | 86 + .../suite/galera_sr/t/galera_sr_concurrent.test | 45 + .../suite/galera_sr/t/galera_sr_conflict.test | 45 + .../galera_sr/t/galera_sr_conflict_on_commit.test | 45 + .../galera_sr/t/galera_sr_conflict_on_commit2.test | 46 + .../t/galera_sr_conflict_with_rollback_master.test | 44 + .../suite/galera_sr/t/galera_sr_ddl_master.test | 63 + .../suite/galera_sr/t/galera_sr_ddl_schema.test | 43 + .../suite/galera_sr/t/galera_sr_ddl_slave.test | 65 + .../suite/galera_sr/t/galera_sr_ddl_unrelated.test | 53 + .../suite/galera_sr/t/galera_sr_dupkey_error.test | 59 + .../suite/galera_sr/t/galera_sr_fk_conflict.test | 62 + .../suite/galera_sr/t/galera_sr_gtid-master.opt | 1 + mysql-test/suite/galera_sr/t/galera_sr_gtid.test | 46 + .../suite/galera_sr/t/galera_sr_insert_select.test | 33 + .../t/galera_sr_kill_all_nobootstrap.test | 52 + .../galera_sr/t/galera_sr_kill_all_norecovery.cnf | 4 + .../galera_sr/t/galera_sr_kill_all_norecovery.test | 53 + .../galera_sr/t/galera_sr_kill_all_pcrecovery.test | 54 + .../galera_sr/t/galera_sr_kill_connection.test | 59 + .../suite/galera_sr/t/galera_sr_kill_query.test | 53 + .../suite/galera_sr/t/galera_sr_kill_slave.cnf | 4 + .../suite/galera_sr/t/galera_sr_kill_slave.test | 80 + .../t/galera_sr_large_fragment-master.opt | 1 + .../galera_sr/t/galera_sr_large_fragment.test | 58 + .../suite/galera_sr/t/galera_sr_load_data.test | 39 + .../galera_sr/t/galera_sr_load_data_splitting.test | 50 + .../suite/galera_sr/t/galera_sr_log_bin-master.opt | 1 + .../suite/galera_sr/t/galera_sr_log_bin.test | 70 + .../galera_sr/t/galera_sr_many_fragments.test | 53 + mysql-test/suite/galera_sr/t/galera_sr_myisam.test | 29 + .../suite/galera_sr/t/galera_sr_mysqldump_sst.cnf | 11 + .../suite/galera_sr/t/galera_sr_mysqldump_sst.test | 79 + .../galera_sr/t/galera_sr_parallel_apply.test | 59 + .../suite/galera_sr/t/galera_sr_rollback.test | 76 + .../galera_sr/t/galera_sr_rollback_retry.test | 55 + .../galera_sr/t/galera_sr_rollback_savepoint.test | 51 + .../galera_sr/t/galera_sr_rollback_statement.test | 61 + mysql-test/suite/galera_sr/t/galera_sr_sbr.test | 31 + .../galera_sr/t/galera_sr_shutdown_master.test | 45 + .../galera_sr/t/galera_sr_shutdown_slave.test | 63 + .../suite/galera_sr/t/galera_sr_small_gcache.cnf | 6 + .../suite/galera_sr/t/galera_sr_small_gcache.test | 21 + .../galera_sr/t/galera_sr_table_contents.test | 49 + .../galera_sr/t/galera_sr_transaction_replay.test | 260 ++ .../galera_sr/t/galera_sr_unit_statements.test | 47 + .../galera_sr/t/galera_sr_v1_row_events-master.opt | 1 + .../suite/galera_sr/t/galera_sr_v1_row_events.test | 27 + .../suite/galera_sr/t/galera_sr_ws_size.test | 70 + .../suite/galera_sr/t/galera_sr_ws_size2.test | 62 + .../t/galera_var_ignore_apply_errors_sr.test | 37 + mysql-test/suite/galera_sr/t/mysql-wsrep#215.test | 161 ++ .../t/mysql-wsrep-features#136-master.opt | 1 + .../galera_sr/t/mysql-wsrep-features#136.test | 41 + .../galera_sr/t/mysql-wsrep-features#138.test | 25 + .../suite/galera_sr/t/mysql-wsrep-features#14.test | 21 + .../galera_sr/t/mysql-wsrep-features#148.test | 60 + .../suite/galera_sr/t/mysql-wsrep-features#15.test | 17 + .../suite/galera_sr/t/mysql-wsrep-features#165.inc | 104 + .../galera_sr/t/mysql-wsrep-features#165.test | 41 + .../galera_sr/t/mysql-wsrep-features#213.test | 63 + .../galera_sr/t/mysql-wsrep-features#214.test | 86 + .../suite/galera_sr/t/mysql-wsrep-features#22.test | 47 + .../suite/galera_sr/t/mysql-wsrep-features#27.test | 29 + .../suite/galera_sr/t/mysql-wsrep-features#29.test | 23 + .../galera_sr/t/mysql-wsrep-features#32-master.opt | 1 + .../suite/galera_sr/t/mysql-wsrep-features#32.test | 44 + .../suite/galera_sr/t/mysql-wsrep-features#35.test | 46 + .../suite/galera_sr/t/mysql-wsrep-features#8.test | 63 + .../suite/galera_sr/t/mysql-wsrep-features#9.test | 44 + .../suite/galera_sr/t/mysql-wsrep-features#93.test | 29 + .../suite/galera_sr/t/mysql-wsrep-features#96.test | 45 + .../suite/innodb/r/innodb-index-online-fk.result | 10 +- mysql-test/suite/innodb/t/galera.skip | 53 + .../suite/innodb/t/innodb-index-online-fk.test | 10 +- packaging/deb-in/CMakeLists.txt | 357 +++ plugin/wsrep_info/plugin.cc | 2 + scripts/mysqld_safe.sh | 11 +- scripts/wsrep_sst_mysqldump.sh | 1 + scripts/wsrep_sst_xtrabackup-v2.sh | 2 +- sql/CMakeLists.txt | 20 +- sql/event_data_objects.cc | 13 +- sql/events.cc | 1 - sql/ha_partition.cc | 7 + sql/ha_partition.h | 3 + sql/handler.cc | 282 ++- sql/handler.h | 4 + sql/item_create.cc | 101 + sql/item_func.cc | 5 +- sql/item_strfunc.cc | 99 + sql/item_strfunc.h | 51 + sql/lock.cc | 82 +- sql/log.cc | 258 +- sql/log.h | 19 + sql/log_event.cc | 38 +- sql/mdl.cc | 79 +- sql/mysqld.cc | 83 +- sql/protocol.cc | 20 +- sql/service_wsrep.cc | 335 +++ sql/slave.cc | 122 +- sql/sp_head.cc | 29 +- sql/sql_acl.cc | 5 +- sql/sql_base.cc | 26 +- sql/sql_class.cc | 158 +- sql/sql_class.h | 148 +- sql/sql_connect.cc | 31 +- sql/sql_insert.cc | 98 +- sql/sql_lex.cc | 5 +- sql/sql_load.cc | 9 +- sql/sql_parse.cc | 680 ++--- sql/sql_parse.h | 6 + sql/sql_plugin.cc | 6 +- sql/sql_plugin_services.ic | 30 +- sql/sql_prepare.cc | 48 - sql/sql_repl.cc | 11 + sql/sql_table.cc | 32 +- sql/sql_trigger.cc | 2 +- sql/sql_truncate.cc | 15 +- sql/sys_vars.cc | 40 +- sql/table.cc | 7 + sql/table_cache.cc | 32 +- sql/transaction.cc | 55 +- sql/wsrep_applier.cc | 314 +-- sql/wsrep_applier.h | 66 +- sql/wsrep_binlog.cc | 349 ++- sql/wsrep_binlog.h | 64 +- sql/wsrep_client_service.cc | 300 +++ sql/wsrep_client_service.h | 64 + sql/wsrep_client_state.h | 47 + sql/wsrep_condition_variable.h | 54 + sql/wsrep_dummy.cc | 9 +- sql/wsrep_high_priority_service.cc | 681 +++++ sql/wsrep_high_priority_service.h | 118 + sql/wsrep_hton.cc | 1 + sql/wsrep_mutex.h | 50 + sql/wsrep_mysqld.cc | 2612 +++++++++++--------- sql/wsrep_mysqld.h | 448 +++- sql/wsrep_notify.cc | 1 + sql/wsrep_plugin.cc | 53 + sql/wsrep_priv.h | 13 +- sql/wsrep_schema.cc | 1319 ++++++++++ sql/wsrep_schema.h | 167 ++ sql/wsrep_server_service.cc | 277 +++ sql/wsrep_server_service.h | 75 + sql/wsrep_server_state.cc | 78 + sql/wsrep_server_state.h | 68 + sql/wsrep_sst.cc | 421 ++-- sql/wsrep_sst.h | 28 +- sql/wsrep_storage_service.cc | 244 ++ sql/wsrep_storage_service.h | 48 + sql/wsrep_tc.h | 0 sql/wsrep_thd.cc | 708 ++---- sql/wsrep_thd.h | 217 +- sql/wsrep_thd_pool.cc | 125 + sql/wsrep_thd_pool.h | 37 + sql/wsrep_trans_observer.h | 369 +++ sql/wsrep_types.h | 29 + sql/wsrep_utils.cc | 2 + sql/wsrep_utils.h | 32 + sql/wsrep_var.cc | 253 +- sql/wsrep_var.h | 6 +- sql/wsrep_xid.cc | 112 +- sql/wsrep_xid.h | 18 +- storage/innobase/buf/buf0dump.cc | 5 +- storage/innobase/handler/ha_innodb.cc | 409 ++- storage/innobase/handler/ha_innodb.h | 33 +- storage/innobase/include/ha_prototypes.h | 10 +- storage/innobase/include/trx0trx.h | 17 + storage/innobase/lock/lock0lock.cc | 47 +- storage/innobase/lock/lock0wait.cc | 12 +- storage/innobase/row/row0ins.cc | 50 +- storage/innobase/row/row0sel.cc | 14 + storage/innobase/row/row0upd.cc | 20 +- storage/innobase/srv/srv0conc.cc | 7 +- storage/innobase/srv/srv0srv.cc | 4 +- storage/innobase/trx/trx0roll.cc | 5 + storage/innobase/trx/trx0rseg.cc | 17 +- storage/innobase/trx/trx0trx.cc | 3 + wsrep-lib | 1 + wsrep/CMakeLists.txt | 26 - wsrep/wsrep_api.h | 539 ++-- wsrep/wsrep_dummy.c | 114 +- wsrep/wsrep_gtid.c | 2 +- wsrep/wsrep_listener.c | 261 ++ wsrep/wsrep_loader.c | 28 +- wsrep/wsrep_uuid.c | 11 + 878 files changed, 34996 insertions(+), 4897 deletions(-) diff --git a/.gitmodules b/.gitmodules index 6419657e501..61d4c06dd4e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,7 @@ [submodule "storage/rocksdb/rocksdb"] path = storage/rocksdb/rocksdb url = https://github.com/facebook/rocksdb.git +[submodule "wsrep-lib"] + path = wsrep-lib + url = https://github.com/codership/wsrep-lib.git + branch = master diff --git a/CMakeLists.txt b/CMakeLists.txt index 93146fa94e9..73aa8638ce8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -382,6 +382,16 @@ 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) +ADD_SUBDIRECTORY(wsrep-lib) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26) +LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/wsrep-lib/src) +LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/wsrep-lib/wsrep-API) +ENDIF() + ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(dbug) ADD_SUBDIRECTORY(strings) @@ -403,10 +413,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) @@ -426,7 +432,7 @@ INCLUDE(cmake/tags.cmake) -INCLUDE(for_clients) +#INCLUDE(for_clients) ADD_SUBDIRECTORY(scripts) ADD_SUBDIRECTORY(support-files) diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 5a5fcd616fc..61fe26da9ef 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -42,6 +42,10 @@ MACRO(MYSQL_ADD_PLUGIN) ${PCRE_INCLUDES} ${SSL_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR}) +IF(WITH_WSREP) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/include) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26) +ENDIF() LIST(GET ARG_UNPARSED_ARGUMENTS 0 plugin) SET(SOURCES ${ARG_UNPARSED_ARGUMENTS}) 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/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt index 7df5fa17903..08745ea1e61 100644 --- a/extra/mariabackup/CMakeLists.txt +++ b/extra/mariabackup/CMakeLists.txt @@ -41,7 +41,7 @@ IF(NOT HAVE_SYSTEM_REGEX) ENDIF() IF(WITH_WSREP) - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib) ENDIF() ADD_DEFINITIONS(-UMYSQL_SERVER) diff --git a/extra/mariabackup/wsrep.cc b/extra/mariabackup/wsrep.cc index c3ad1b53a21..793a2a0eb21 100644 --- a/extra/mariabackup/wsrep.cc +++ b/extra/mariabackup/wsrep.cc @@ -83,7 +83,7 @@ xb_write_galera_info(bool incremental_prepare) } wsrep_uuid_t uuid; - memcpy(uuid.data, wsrep_xid_uuid(&xid), sizeof(uuid.data)); + memcpy(uuid.data, get_wsrep_xid_uuid(&xid), sizeof(uuid.data)); if (wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)) < 0) { return; @@ -99,7 +99,7 @@ xb_write_galera_info(bool incremental_prepare) exit(EXIT_FAILURE); } - seqno = wsrep_xid_seqno(&xid); + seqno = get_wsrep_xid_seqno(&xid); msg("mariabackup: Recovered WSREP position: %s:%lld\n", uuid_str, (long long) seqno); diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index cefba6303fe..82fecdb3d2e 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -1,19 +1,13 @@ #ifndef MYSQL_SERVICE_WSREP_INCLUDED -/* Copyright (c) 2015 MariaDB Corporation Ab - - 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. +#define MYSQL_SERVICE_WSREP_INCLUDED - 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. +#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED)) - 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 */ +#else +/* Copyright (c) 2015 MariaDB Corporation Ab + 2018 Codership Oy <info@codership.com> +*/ /** @file wsrep service @@ -21,11 +15,9 @@ Interface to WSREP functionality in the server. For engines that want to support galera. */ - +#include <my_pthread.h> #ifdef __cplusplus -extern "C" { #endif - enum wsrep_conflict_state { NO_CONFLICT, MUST_ABORT, @@ -48,7 +40,8 @@ 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 { @@ -56,7 +49,6 @@ enum wsrep_query_state { QUERY_EXEC, QUERY_COMMITTING, QUERY_EXITING, - QUERY_ROLLINGBACK, }; enum wsrep_trx_status { @@ -65,14 +57,11 @@ enum wsrep_trx_status { WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */ WSREP_TRX_ERROR, /* native mysql error */ }; - struct xid_t; -struct wsrep; struct wsrep_ws_handle; struct wsrep_buf; extern struct wsrep_service_st { - struct wsrep * (*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,43 +69,32 @@ 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); - 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); - 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_wsrep_func)(MYSQL_THD thd); - char * (*wsrep_thd_query_func)(THD *thd); - enum wsrep_query_state (*wsrep_thd_query_state_func)(THD *thd); - const char * (*wsrep_thd_query_state_str_func)(THD *thd); - int (*wsrep_thd_retry_counter_func)(THD *thd); - void (*wsrep_thd_set_conflict_state_func)(THD *thd, enum wsrep_conflict_state state); + my_bool (*wsrep_on_func)(const 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)(const void* thd_ptr); + void (*wsrep_thd_UNLOCK_func)(const void* thd_ptr); + void (*wsrep_thd_awake_func)(const void* thd, my_bool signal); + my_thread_id (*wsrep_thd_thread_id_func)(const void* thd); + my_bool (*wsrep_thd_is_wsrep_on_func)(const void* thd); + const char * (*wsrep_thd_query_func)(const void* thd); bool (*wsrep_thd_ignore_table_func)(THD *thd); - long long (*wsrep_thd_trx_seqno_func)(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)(); + long long (*wsrep_thd_trx_seqno_func)(const void* thd); + my_bool (*wsrep_thd_is_aborting_func)(const void* thd); + my_bool (*wsrep_trx_order_before_func)(const void* left_ptr, const void* right_ptr); + void (*wsrep_thd_xid_func)(const void *thd_ptr, void *xid, size_t xid_size); void (*wsrep_set_data_home_dir_func)(const char *data_dir); } *wsrep_service; +#define MYSQL_SERVICE_WSREP_INCLUDED +#endif + #ifdef MYSQL_DYNAMIC_PLUGIN -#define get_wsrep() wsrep_service->get_wsrep_func() + +#define MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED #define get_wsrep_certify_nonPK() wsrep_service->get_wsrep_certify_nonPK_func() #define get_wsrep_debug() wsrep_service->get_wsrep_debug_func() #define get_wsrep_drupal_282555_workaround() wsrep_service->get_wsrep_drupal_282555_workaround_func() @@ -124,50 +102,31 @@ 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 get_wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X) +#define get_wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X) #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) -#define wsrep_thd_conflict_state(T,S) wsrep_service->wsrep_thd_conflict_state_func(T,S) -#define wsrep_thd_conflict_state_str(T) wsrep_service->wsrep_thd_conflict_state_str_func(T) -#define wsrep_thd_exec_mode(T) wsrep_service->wsrep_thd_exec_mode_func(T) -#define wsrep_thd_exec_mode_str(T) wsrep_service->wsrep_thd_exec_mode_str_func(T) -#define wsrep_thd_get_conflict_state(T) wsrep_service->wsrep_thd_get_conflict_state_func(T) -#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) -#define wsrep_thd_is_wsrep(T) wsrep_service->wsrep_thd_is_wsrep_func(T) +#define wsrep_thd_thread_id(T) wsrep_service->wsrep_thd_thread_id_func(T) +#define wsrep_thd_is_wsrep_on(T) wsrep_service->wsrep_thd_is_wsrep_on_func(T) #define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T) -#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_xid(T,X,S) wsrep_service->wsrep_thd_xid_func(T,X,S) #define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) -#define wsrep_debug get_wsrep_debug() -#define wsrep_log_conflicts get_wsrep_log_conflicts() -#define wsrep_certify_nonPK get_wsrep_certify_nonPK() -#define wsrep_load_data_splitting get_wsrep_load_data_splitting() -#define wsrep_drupal_282555_workaround get_wsrep_drupal_282555_workaround() -#define wsrep_recovery get_wsrep_recovery() -#define wsrep_protocol_version get_wsrep_protocol_version() +#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) #else +#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED extern my_bool wsrep_debug; extern my_bool wsrep_log_conflicts; extern my_bool wsrep_certify_nonPK; @@ -175,27 +134,19 @@ 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); -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); -enum wsrep_conflict_state wsrep_thd_conflict_state(MYSQL_THD thd, my_bool sync); -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); -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); +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" const char *wsrep_thd_query(const void* thd); +int wsrep_is_wsrep_xid(const void* xid); +extern "C" long long get_wsrep_xid_seqno(const struct xid_t* xid); +const unsigned char* get_wsrep_xid_uuid(const struct xid_t* xid); 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); +my_bool wsrep_trx_is_aborting(const void* thd); +my_bool wsrep_trx_order_before(const void* thd1, const void* thd2); long get_wsrep_protocol_version(); -long long wsrep_thd_trx_seqno(THD *thd); +extern "C" long long wsrep_thd_trx_seqno(const void* thd); my_bool get_wsrep_certify_nonPK(); my_bool get_wsrep_debug(); my_bool get_wsrep_drupal_282555_workaround(); @@ -203,27 +154,99 @@ 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_wsrep(MYSQL_THD thd); -struct wsrep *get_wsrep(); +my_bool wsrep_thd_is_wsrep(const void* thd); 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_set_data_home_dir(const char *data_dir); -#endif +/* from mysql wsrep-lib */ +#include "my_global.h" +#include "my_pthread.h" +/* Must match to definition in sql/mysqld.h */ +typedef int64 query_id_t; + +extern "C" my_bool wsrep_global_on(); + +/* Return true if wsrep is enabled for a thd. This means that + wsrep is enabled globally and the thd has wsrep on */ +extern "C" my_bool wsrep_on(const void* thd); +/* Lock thd wsrep lock */ +extern "C" void wsrep_thd_LOCK(const void* thd); +/* Unlock thd wsrep lock */ +extern "C" void wsrep_thd_UNLOCK(const void* thd); + +/* Return true if thd has wsrep_on */ +extern "C" my_bool wsrep_thd_is_wsrep_on(const void* thd); +/* Return thd id */ +extern "C" my_thread_id wsrep_thd_thread_id(const void* thd); + +/* Return thd client state string */ +extern "C" const char* wsrep_thd_client_state_str(const void* thd); +/* Return thd client mode string */ +extern "C" const char* wsrep_thd_client_mode_str(const void* thd); +/* Return thd transaction state string */ +extern "C" const char* wsrep_thd_transaction_state_str(const void* thd); + +/* Return current query id */ +extern "C" query_id_t wsrep_thd_query_id(const void* thd); +/* Return current transaction id */ +extern "C" query_id_t wsrep_thd_transaction_id(const void* thd); +/* Mark thd own transaction as aborted */ +extern "C" void wsrep_thd_self_abort(void *thd); +/* Return true if thd is in replicating mode */ +extern "C" my_bool wsrep_thd_is_local(const void *thd); +/* Return true if thd is in high priority mode */ +/* todo: rename to is_high_priority() */ +extern "C" my_bool wsrep_thd_is_applying(const void *thd); +/* Return true if thd is in TOI mode */ +extern "C" my_bool wsrep_thd_is_toi(const void* thd); +/* Return true if thd is in replicating TOI mode */ +extern "C" my_bool wsrep_thd_is_local_toi(const void* thd); +/* Return true if thd is in RSU mode */ +extern "C" my_bool wsrep_thd_is_in_rsu(const void* thd); +/* Return true if thd is in BF mode, either high_priority or TOI */ +extern "C" my_bool wsrep_thd_is_BF(const void* thd, my_bool sync); +/* Return true if thd is streaming */ +extern "C" my_bool wsrep_thd_is_SR(const void* thd); +extern "C" void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr); +/* Return XID associated to thd */ +extern "C" void wsrep_thd_xid(const void* thd, void* xid, size_t size); +/* Return thd retry counter */ +extern "C" int wsrep_thd_retry_counter(const void*); +/* Signal thd to awake from wait */ +extern "C" void wsrep_thd_awake(const void* thd, my_bool signal); +/* BF abort victim_thd */ +extern "C" my_bool wsrep_thd_bf_abort(const void* bf_thd, void* victim_thd, + my_bool signal); +/* Return true if left thd is ordered before right thd */ +extern "C" my_bool wsrep_thd_order_before(const void* left, const void* right); +/* Return true if thd should skip locking. This means that the thd + is operating on shared resource inside commit order critical section. */ +extern "C" my_bool wsrep_thd_skip_locking(const void*); +/* Return true if thd is aborting */ +extern "C" my_bool wsrep_thd_is_aborting(const void*); + + +enum Wsrep_key_type +{ + wsrep_key_shared, + wsrep_key_semi_shared, + wsrep_key_semi_exclusive, + wsrep_key_exclusive +}; +struct wsrep_key; +struct wsrep_key_array; +extern "C" int wsrep_thd_append_key(void*, + const struct wsrep_key* key, + int n_keys, + enum Wsrep_key_type); #ifdef __cplusplus -} -#endif +#include <string> +extern const std::string sr_table_name_full_str; +#endif /* __cplusplus */ -#define MYSQL_SERVICE_WSREP_INCLUDED #endif - +#endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/include/thr_lock.h b/include/thr_lock.h index e6451bf21c4..b775e846681 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -168,9 +168,9 @@ void thr_set_lock_wait_callback(void (*before_wait)(void), void (*after_wait)(void)); #ifdef WITH_WSREP - typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool); - typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool); - typedef int (* wsrep_on_fun)(void *); + typedef my_bool (* wsrep_thd_is_brute_force_fun)(const void *, my_bool); + typedef my_bool(* wsrep_abort_thd_fun)(const void *, void *, my_bool); + typedef my_bool (* wsrep_on_fun)(const void *); void wsrep_thr_lock_init( wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun, my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun); diff --git a/include/wsrep.h b/include/wsrep.h index c7f598906bb..77d50fc7678 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -28,12 +28,14 @@ goto error; #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \ - if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, \ - table_list_, alter_info_)) \ + if (WSREP_ON && WSREP(thd) && wsrep_thd_is_local(thd) && \ + wsrep_to_isolation_begin(thd, db_, table_, \ + table_list_, alter_info_)) \ goto error; -#define WSREP_TO_ISOLATION_END \ - if (WSREP_ON && (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER))) \ +#define WSREP_TO_ISOLATION_END \ + if ((WSREP(thd) && thd && wsrep_thd_is_local_toi(thd)) || \ + wsrep_thd_is_in_rsu(thd)) \ wsrep_to_isolation_end(thd); /* @@ -44,6 +46,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__) @@ -55,18 +62,17 @@ wsrep_sync_wait(thd_, before_)) goto error; } #else -#define IF_WSREP(A,B) B -#define DBUG_ASSERT_IF_WSREP(A) -#define WSREP_DEBUG(...) -#define WSREP_INFO(...) -#define WSREP_WARN(...) -#define WSREP_ERROR(...) -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) -#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) -#define WSREP_TO_ISOLATION_END -#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) -#define WSREP_SYNC_WAIT(thd_, before_) - +//#define IF_WSREP(A,B) B +//#define DBUG_ASSERT_IF_WSREP(A) +//#define WSREP_DEBUG(...) +//#define WSREP_INFO(...) +//#define WSREP_WARN(...) +//#define WSREP_ERROR(...) +//#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) +//#define WSREP_TO_ISOLATION_END +//#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) +//#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) +//#define WSREP_SYNC_WAIT(thd_, before_) #endif /* WITH_WSREP */ #endif /* WSREP_INCLUDED */ diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index a9c8e13fa7c..ac4a40e8b05 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -103,5 +103,51 @@ cat_file $datadir.tempfiles.txt; remove_file $datadir.tempfiles.txt; list_files $datadir/mysql #sql*; +# +# Check that SHOW ENGINE INNODB STATUS does not show any active transactions +# We do this only if wsrep provider is loaded, to avoid disturbing any non-Galera MTR tests +# + +if (`SELECT @@wsrep_on`) { + if (`SELECT COUNT(*) FROM information_schema.innodb_trx WHERE trx_mysql_thread_id != 0`) { + if ($before) { + --echo Before test start. + } + if (!$before) { + --echo After test end. + } + --echo There is one or more active InnoDB transaction(s) when there should be none. Dumping some diagnostics. + + --enable_query_log + + SET GLOBAL innodb_status_output_locks=ON; + SHOW ENGINE INNODB STATUS; + SET GLOBAL innodb_status_output_locks=default; + + --vertical_results + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.processlist; + + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.innodb_trx; + + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.innodb_locks; + + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.innodb_lock_waits; + --horizontal_results + --disable_query_log + } +} + --enable_query_log 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 similarity index 100% rename from mysql-test/suite/galera/include/galera_have_debug_sync.inc rename to 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_until_connected_again.inc b/mysql-test/include/wait_until_connected_again.inc index 26168d10558..e0594c37190 100644 --- a/mysql-test/include/wait_until_connected_again.inc +++ b/mysql-test/include/wait_until_connected_again.inc @@ -11,7 +11,7 @@ let $counter= 5000; let $mysql_errno= 9999; while ($mysql_errno) { - --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013 + --error 0,1205,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013 show status; dec $counter; 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 d481058902f..29271a97387 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 }, ); # diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 28792d2ad01..426821270c3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -414,6 +414,7 @@ sub main { } check_ssl_support(); check_debug_support(); + check_wsrep_support(); if (!$opt_suites) { $opt_suites= join ',', collect_default_suites(@DEFAULT_SUITES); @@ -2902,6 +2903,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 +3415,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; @@ -5413,6 +5517,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()) { @@ -5421,7 +5540,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/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result new file mode 100644 index 00000000000..b7db372a704 --- /dev/null +++ b/mysql-test/r/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/r/query_cache_size_functionality.result b/mysql-test/r/query_cache_size_functionality.result new file mode 100644 index 00000000000..7563b3e61eb --- /dev/null +++ b/mysql-test/r/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/r/query_cache_type_functionality.result b/mysql-test/r/query_cache_type_functionality.result new file mode 100644 index 00000000000..134d8c3a066 --- /dev/null +++ b/mysql-test/r/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/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 840e69db71f..1e0ffd120da 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/GAL-480.result b/mysql-test/suite/galera/r/GAL-480.result index 143f48a69e3..8a4f8edcdd6 100644 --- a/mysql-test/suite/galera/r/GAL-480.result +++ b/mysql-test/suite/galera/r/GAL-480.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 CHAR(10), f0 integer) ENGINE=InnoDB; FLUSH TABLE t1 FOR EXPORT; 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..24d4eab67e5 --- /dev/null +++ b/mysql-test/suite/galera/r/GCF-939.result @@ -0,0 +1,13 @@ +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 +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 e35044d872b..5961d1f3e24 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; INSERT INTO t1 values(0); connection node_1; 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..3e532b3e12d 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 () @@ -18,7 +20,7 @@ connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; SET SESSION wsrep_sync_wait = 0; -SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue'; +SET SESSION DEBUG_SYNC = 'wsrep_after_certification SIGNAL wsrep_after_certification_reached WAIT_FOR wsrep_after_certification_continue'; CALL insert_proc ();; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached"; @@ -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..3bcd89a0cd0 100644 --- a/mysql-test/suite/galera/r/MW-416.result +++ b/mysql-test/suite/galera/r/MW-416.result @@ -109,6 +109,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_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..08833cbd503 --- /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_certification 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_background_statistics.result b/mysql-test/suite/galera/r/galera_bf_background_statistics.result index c2c3fce2b14..a8c8842b8e1 100644 --- a/mysql-test/suite/galera/r/galera_bf_background_statistics.result +++ b/mysql-test/suite/galera/r/galera_bf_background_statistics.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT @@innodb_stats_persistent; @@innodb_stats_persistent 1 @@ -27,7 +29,7 @@ SELECT SLEEP(1000);; connection node_1; ALTER TABLE t1 CHANGE f2 f2 INTEGER NOT NULL DEFAULT 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_commit_empty.result b/mysql-test/suite/galera/r/galera_commit_empty.result new file mode 100644 index 00000000000..75b94c54b1e --- /dev/null +++ b/mysql-test/suite/galera/r/galera_commit_empty.result @@ -0,0 +1,15 @@ +connection node_2; +connection node_1; +START TRANSACTION; +COMMIT; +START TRANSACTION; +COMMIT; +START TRANSACTION READ ONLY; +COMMIT; +START TRANSACTION; +COMMIT; +START TRANSACTION; +START TRANSACTION; +COMMIT; +wsrep_last_committed_diff +1 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 8083784bb01..9590ed2963b 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,9 +54,17 @@ 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; <GMC AST_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; <GM CAST_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_CLUSTER_CAPABILITIES +WSREP_CLUSTER_WEIGHT +WSREP_OPEN_CONNECTIONS +WSREP_OPEN_TRANSACTIONS +WSREP_PROVIDER_CAPABILITIES 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_fragment.result b/mysql-test/suite/galera/r/galera_gcs_fragment.result index 0c9c1819f60..d39458ecb22 100644 --- a/mysql-test/suite/galera/r/galera_gcs_fragment.result +++ b/mysql-test/suite/galera/r/galera_gcs_fragment.result @@ -11,7 +11,7 @@ SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); SET GLOBAL wsrep_provider_options = 'signal=gcs_core_after_frag_send'; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ERROR HY000: Got error 6 during COMMIT INSERT INTO t1 VALUES (3, "cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); SELECT * FROM t1; f1 f2 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 e3bf407ddaa..146cae1e896 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 @@ -86,3 +96,15 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +connection node_1; +connection node_2; +connection node_1; +connection node_2; +connection node_1; +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_2; +connection node_2; +connection node_1; +connection node_1a_galera_st_kill_slave_ddl; +connection node_1; +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 8a7c02ab1b6..19453af2eec 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 099d944d491..f9fdc70e9d0 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 @@ -259,3 +285,15 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +connection node_1; +connection node_2; +connection node_1; +connection node_2; +connection node_1; +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_2; +connection node_2; +connection node_1; +connection node_1a_galera_st_kill_slave_ddl; +connection node_1; +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 b11353fcbcc..b2e49e25dd6 100644 --- a/mysql-test/suite/galera/r/galera_kill_ddl.result +++ b/mysql-test/suite/galera/r/galera_kill_ddl.result @@ -1,5 +1,6 @@ call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*"); connection node_1; +connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_kill_largechanges.result b/mysql-test/suite/galera/r/galera_kill_largechanges.result index f4de101fef8..c14c28e348c 100644 --- a/mysql-test/suite/galera/r/galera_kill_largechanges.result +++ b/mysql-test/suite/galera/r/galera_kill_largechanges.result @@ -1,5 +1,6 @@ call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*"); connection node_1; +connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; 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_kill_smallchanges.result b/mysql-test/suite/galera/r/galera_kill_smallchanges.result index 2ee291004b0..f327a0713cd 100644 --- a/mysql-test/suite/galera/r/galera_kill_smallchanges.result +++ b/mysql-test/suite/galera/r/galera_kill_smallchanges.result @@ -1,5 +1,6 @@ call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*"); connection node_1; +connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; connection node_2; 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..48625b3ba4a 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; @@ -30,7 +32,7 @@ COUNT(*) = 1 SELECT COUNT(*) = 1 FROM t2; COUNT(*) = 1 1 -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committed%'; COUNT(*) = 2 1 SET GLOBAL wsrep_slave_threads = 1;; 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..09a415d47eb 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); @@ -12,7 +14,7 @@ COUNT(*) = 20000 SELECT COUNT(DISTINCT f1) = 20000 FROM t1; COUNT(DISTINCT f1) = 20000 1 -SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'wsrep applier committed%'; COUNT(*) = 4 1 connection default; 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 07433399081..ce49b491778 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 73285d723c1..081a82e6e7d 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); @@ -11,7 +13,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 77848bc751f..5db1be8c910 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_auto_inc_control_on.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result index b71cf4c831d..48c649b66a8 100644 --- a/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result +++ b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE=InnoDB; SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); 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..8c1070e43ce 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 @@ -11,7 +15,7 @@ Variable_name Value wsrep_ready OFF SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value -wsrep_cluster_status non-Primary +wsrep_cluster_status Disconnected SHOW STATUS LIKE 'wsrep_local_state'; Variable_name Value wsrep_local_state 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 26798e51926..6a2e501eee2 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..eae4e267df9 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -1,8 +1,6 @@ -connection node_1; connection node_2; connection node_1; connection node_2; -connection node_2; CREATE TABLE t1(i INT) ENGINE=INNODB; INSERT INTO t1 VALUES(1); SELECT * FROM t1; @@ -16,7 +14,7 @@ Variable_name Value wsrep_ready OFF SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value -wsrep_cluster_status non-Primary +wsrep_cluster_status Disconnected SELECT * FROM t1; ERROR 08S01: WSREP has not yet prepared node for application use SELECT 1 FROM t1; 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 7696d1e3f4f..cf45861c8ad 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 c28cc091ae9..e774e620ccd 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,8 +15,11 @@ 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; @@ -23,35 +28,197 @@ 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; 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_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#216.result b/mysql-test/suite/galera/r/mysql-wsrep#216.result new file mode 100644 index 00000000000..b07589d0c04 --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#216.result @@ -0,0 +1,11 @@ +SET GLOBAL wsrep_debug = ON; +CREATE USER u1 IDENTIFIED BY 'plaintext_password'; +CREATE USER u1 IDENTIFIED BY 'plaintext_password'; +ERROR HY000: Operation CREATE USER failed for 'u1'@'%' +0 +0 +2 +1 +DROP USER u1; +CALL mtr.add_suppression('Operation CREATE USER failed'); + \ No newline at end of file diff --git a/mysql-test/suite/galera/r/mysql-wsrep#237.result b/mysql-test/suite/galera/r/mysql-wsrep#237.result index 19503dd5781..bc348613d25 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#237.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#237.result @@ -1,6 +1,8 @@ +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'; +SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue'; INSERT INTO t values (1);; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; 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 8592a68141c..5dabd38a982 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..4139ecd6472 --- /dev/null +++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result @@ -0,0 +1,15 @@ +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; +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/suite.pm b/mysql-test/suite/galera/suite.pm index 233aa020a94..62d89f70dac 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -83,6 +83,8 @@ push @::global_suppressions, qr|WSREP: JOIN message from member .* in non-primary configuration. Ignored.|, qr(WSREP: Failed to remove page file .*), qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*), + qr|Query apply failed:*|, + qr(WSREP: Ignoring error*), ); $ENV{PATH}="$epath:$ENV{PATH}"; 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..637d656996e --- /dev/null +++ b/mysql-test/suite/galera/t/GCF-939.test @@ -0,0 +1,31 @@ +# +# 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 +# TODO replace_regex is somehow broken, it will filter out +# result totally if replacement string is already in result +# fixed this temporarily by calling list_files twice +# to get GRA_.log two times, this works for some reason +# +--replace_regex /GRA_.+\.log/GRA_.log/ +--list_files $MYSQLTEST_VARDIR/mysqld.2/data GRA_*.log +--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 09aad1bcf60..097d4ac4ff6 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/big_test.inc @@ -25,7 +30,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 @@ -44,14 +49,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 4bdbfb2ecff..67715c24992 100644 --- a/mysql-test/suite/galera/t/MW-336.test +++ b/mysql-test/suite/galera/t/MW-336.test @@ -11,9 +11,8 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 1; - --let $wait_timeout=600 ---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 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); @@ -31,11 +30,11 @@ while ($count) --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; @@ -62,7 +61,7 @@ while ($count) } --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..9cf176434ba 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; @@ -41,11 +40,11 @@ SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; --connection node_1 SET SESSION wsrep_sync_wait = 0; -SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue'; +SET SESSION DEBUG_SYNC = 'wsrep_after_certification SIGNAL wsrep_after_certification_reached WAIT_FOR wsrep_after_certification_continue'; --send CALL insert_proc (); --connection node_1a -SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached"; +SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_certification_reached"; SET GLOBAL DEBUG_DBUG = ""; 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..48eada95cb8 100644 --- a/mysql-test/suite/galera/t/MW-416.test +++ b/mysql-test/suite/galera/t/MW-416.test @@ -2,11 +2,10 @@ --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 @@ -131,4 +130,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.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf index 19517556331..75caba5420a 100644 --- a/mysql-test/suite/galera/t/galera_as_master_gtid.cnf +++ b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf @@ -1,8 +1,6 @@ !include ../galera_2nodes_as_master.cnf [mysqld] -gtid-mode=ON log-bin=mysqld-bin log-slave-updates -enforce-gtid-consistency binlog-format=ROW 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.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf index 19517556331..75caba5420a 100644 --- a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf +++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf @@ -1,8 +1,6 @@ !include ../galera_2nodes_as_master.cnf [mysqld] -gtid-mode=ON log-bin=mysqld-bin log-slave-updates -enforce-gtid-consistency binlog-format=ROW 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..8c105b3c37c --- /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_certification 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_commit_empty.test b/mysql-test/suite/galera/t/galera_commit_empty.test new file mode 100644 index 00000000000..4e1a1e4eb2c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_commit_empty.test @@ -0,0 +1,35 @@ +# Test empty transactions. +# +# Check that the empty transaction gets terminated by starting and new +# transaction after it. If the empty transaction is not terminated +# appropriately, the following START TRANSACTION will fail. +# +# Also check that empty transactions don't generate any write sets. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +START TRANSACTION; +COMMIT; + +START TRANSACTION; +COMMIT; + +START TRANSACTION READ ONLY; +COMMIT; + +START TRANSACTION; +COMMIT; + +START TRANSACTION; +START TRANSACTION; +COMMIT; + +--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 AS wsrep_last_committed_diff +--enable_query_log 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 0ad97916302..f5e1566d731 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_gcs_fragment.test b/mysql-test/suite/galera/t/galera_gcs_fragment.test index 80d3a5cb659..a36f5f05257 100644 --- a/mysql-test/suite/galera/t/galera_gcs_fragment.test +++ b/mysql-test/suite/galera/t/galera_gcs_fragment.test @@ -54,7 +54,7 @@ INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # Deadlock error should be returned since write set send was # interrupted by gcs --connection node_1 ---error ER_LOCK_DEADLOCK +--error ER_ERROR_DURING_COMMIT --reap # Do additional insert to verify that node_1 remain operational 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_kill_applier.test b/mysql-test/suite/galera/t/galera_kill_applier.test index d04b72bce0a..b66e0bcbbd0 100644 --- a/mysql-test/suite/galera/t/galera_kill_applier.test +++ b/mysql-test/suite/galera/t/galera_kill_applier.test @@ -6,7 +6,6 @@ --source include/have_innodb.inc --connection node_1 ---sleep 2 --let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE IS NULL LIMIT 1` --disable_query_log 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..5a33c16c86e 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; @@ -44,7 +44,7 @@ UNLOCK TABLES; --eval SET SESSION wsrep_sync_wait = $wsrep_sync_wait_orig; SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) = 1 FROM t2; -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committed%'; --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test index 8680d62a36d..d2156cb3577 100644 --- a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test @@ -42,7 +42,7 @@ while ($count) SELECT COUNT(*) = 20000 FROM t1; SELECT COUNT(DISTINCT f1) = 20000 FROM t1; -SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'wsrep applier committed%'; --disable_query_log --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; 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.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf index 574ae28b54a..cf2ba68d0cf 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf @@ -5,7 +5,9 @@ [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' - +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' - +wsrep_causal_reads=0 +wsrep_sync_wait=0 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_mysqldump_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf index 44e5573b3e6..b7bca487fc5 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf @@ -5,9 +5,13 @@ [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld] wsrep_debug=ON 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..85ae73ffda4 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; @@ -29,7 +29,7 @@ SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; # Must return 'OFF' SHOW STATUS LIKE 'wsrep_ready'; -# Must return 'Non-primary' +# Must return 'Disconnected' SHOW STATUS LIKE 'wsrep_cluster_status'; # Must return 0 = 'Initialized' @@ -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..cdb12bea9ed 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -32,7 +32,7 @@ SET SESSION wsrep_sync_wait=0; # Must return 'OFF' SHOW STATUS LIKE 'wsrep_ready'; -# Must return 'Non-primary' +# Must return 'Disconnected' SHOW STATUS LIKE 'wsrep_cluster_status'; --error ER_UNKNOWN_COM_ERROR @@ -53,6 +53,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 +66,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 +74,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_retry_autocommit.test b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test index 142f02546b4..8fc4a3e338d 100644 --- a/mysql-test/suite/galera/t/galera_var_retry_autocommit.test +++ b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test @@ -16,7 +16,7 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 0; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue'; --send INSERT INTO t1 (f1) VALUES (2) --connection node_1a @@ -42,8 +42,8 @@ DROP TABLE t1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 1; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue'; ---send INSERT INTO t1 (f1) VALUES (2) +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue'; +--send INSERT INTO t1 (f1) VALUES (3) --connection node_1a SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; @@ -68,12 +68,16 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 1; SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit'; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 2'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue EXECUTE 2'; +--sleep 5 +show processlist; ---send INSERT INTO t1 VALUES (2); +--send INSERT INTO t1 VALUES (4); --connection node_1a SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +--sleep 5 +show processlist; --connection node_2 TRUNCATE TABLE t1; @@ -107,9 +111,9 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 64; SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit'; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 64'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_rep WAIT_FOR continue EXECUTE 64'; ---send INSERT INTO t1 VALUES (2) +--send INSERT INTO t1 VALUES (5) --disable_query_log --disable_result_log 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 80edcb2aff9..122d7dd5ae2 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 @@ -37,9 +38,15 @@ INSERT INTO t1 VALUES (1); --let $wait_condition = SELECT COUNT(*) = 1 FROM t1; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) 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 + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +--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 # @@ -63,51 +70,113 @@ while ($count) --enable_result_log --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; + +# +# test phase for bug https://github.com/codership/mysql-wsrep/issues/319 +# ---echo # ---echo # lp:1372840 - Changing wsrep_slave_threads causes future connections to hang ---echo # +# 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/mysql-wsrep#237.test b/mysql-test/suite/galera/t/mysql-wsrep#237.test index cba8dfeb275..174266bdbc5 100644 --- a/mysql-test/suite/galera/t/mysql-wsrep#237.test +++ b/mysql-test/suite/galera/t/mysql-wsrep#237.test @@ -7,13 +7,13 @@ CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB; --connection node_1 -SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; +SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue'; --send INSERT INTO t values (1); --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 COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_replication' +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_certification' --source include/wait_condition.inc --connection node_2 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 e1528c6f74f..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; @@ -11,6 +13,7 @@ connection node_3; INSERT INTO t2 VALUES (1); connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +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_parallel_apply_3nodes.result b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result index 4f9951c382f..8211fb8501e 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result +++ b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.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_3; @@ -12,7 +14,7 @@ connection node_3; SELECT f1 = 111 FROM t1; f1 = 111 1 -SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%committed%'; COUNT(*) IN (1, 2) 1 SET GLOBAL wsrep_slave_threads = 1;; 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 9f845ffe776..d991e497706 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result @@ -67,7 +67,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'; SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 1 SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; 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_mysqldump.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf index 3728e1ce005..1412ab4c808 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf @@ -8,15 +8,21 @@ wsrep-cluster-address=gcomm:// wsrep_provider_options='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' +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='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' +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='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' wsrep_node_incoming_address='[::1]:@mysqld.3.port' +wsrep_causal_reads=0 +wsrep_sync_wait=0 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_parallel_apply_3nodes.test b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test index 7d80d8036a1..659df2b3c93 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test +++ b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test @@ -31,7 +31,7 @@ SET GLOBAL wsrep_slave_threads = 2; --connection node_3 SELECT f1 = 111 FROM t1; -SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%committed%'; --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; 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 0a94e7cd85d..2959a49327e 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 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; @@ -55,6 +55,9 @@ SHOW STATUS LIKE 'wsrep_local_state_comment'; --connection node_1 # 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 @@ -66,24 +69,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'; -SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; - -# Resume cluster connectivity on node_1 ---connection node_1 -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 +# wait for nodes 2 and 3 to reconnect --connection node_2 ---source include/wait_condition.inc +--source include/galera_wait_ready.inc --connection node_3 ---source include/wait_condition.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_condition.inc +--source include/galera_wait_ready.inc # On all nodes, we now expect a Primary component of size 3, weight 3, Synced and ready SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; 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 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..541ac3cddfb --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1008.result @@ -0,0 +1,70 @@ +connection node_2; +connection node_1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +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; +SET GLOBAL wsrep_provider_options = 'dbug=d,before_local_commit_monitor_enter'; +connection node_2; +COMMIT; +connection node_2b; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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'); +connection node_2b; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_2a; +SET GLOBAL wsrep_provider_options = 'signal=before_local_commit_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +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; +SET GLOBAL wsrep_provider_options = 'dbug=d,before_certify_apply_monitor_enter'; +connection node_2; +COMMIT; +connection node_2b; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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'); +connection node_2b; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_2a; +SET GLOBAL wsrep_provider_options = 'signal=before_certify_apply_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_2; +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..cc90461291d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1043A.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +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') +connection node_1; +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;;; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +connection node_2; +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..56e1f575047 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1051.result @@ -0,0 +1,46 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; +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; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +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; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +connection node_2; +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..7bf522aae36 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-571.result @@ -0,0 +1,67 @@ +connection node_2; +connection node_1; +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%'; +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 +0 +connection node_1; +ROLLBACK TO SAVEPOINT A; +connection node_1a; +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 +0 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%'; +COUNT(*) = 1 +0 +connection node_2; +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 +0 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%'; +COUNT(*) = 1 +0 +connection node_1; +ROLLBACK; +connection node_1a; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +connection node_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..9a2ff2b294f --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-572.result @@ -0,0 +1,37 @@ +connection node_2; +connection node_1; +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; +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; +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 +connection node_1a; +INSERT INTO t1 VALUES(15, 'node2'); +connection node_1; +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..3ee69c6c4b3 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-580.result @@ -0,0 +1,13 @@ +connection node_2; +connection node_1; +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..1d04b6f9cee --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera-features#56.result @@ -0,0 +1,32 @@ +connection node_2; +connection node_1; +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; +SET GLOBAL wsrep_slave_threads = 4; +SET SESSION wsrep_trx_fragment_size = 1; +connection node_1; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +connection node_1a; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +connection node_2; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +connection node_1; +connection node_1a; +connection node_2; +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 +0 +connection default; +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..be631d1d916 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result @@ -0,0 +1,57 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 1 +1 +SET SESSION wsrep_trx_fragment_size=1; +UPDATE t1 SET f1 = 2; +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; +COUNT(*) = 1 +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 256; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000002 <Pos> Gtid_list 1 <End_log_pos> [] +mysqld-bin.000002 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001 +mysqld-bin.000002 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000002 +mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1 +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> BEGIN GTID 0-1-2 +mysqld-bin.000002 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1) +mysqld-bin.000002 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000002 <Pos> Write_rows_v1 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 2 <End_log_pos> BEGIN GTID 0-2-3 +mysqld-bin.000002 <Pos> Annotate_rows 2 <End_log_pos> UPDATE t1 SET f1 = 2 +mysqld-bin.000002 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000002 <Pos> Update_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000002 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +connection node_2; +SELECT 1 FROM DUAL; +1 +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 256; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000003 <Pos> Gtid_list 2 <End_log_pos> [] +mysqld-bin.000003 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000003 +mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1 +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> BEGIN GTID 0-1-2 +mysqld-bin.000003 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1) +mysqld-bin.000003 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000003 <Pos> Write_rows_v1 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> BEGIN GTID 0-2-3 +mysqld-bin.000003 <Pos> Annotate_rows 2 <End_log_pos> UPDATE t1 SET f1 = 2 +mysqld-bin.000003 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000003 <Pos> Update_rows_v1 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..cb8e84383bc --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result @@ -0,0 +1,124 @@ +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; +connection node_2; +connection node_1; +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; +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); +connection node_2; +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +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; +COUNT(*) = 2 +1 +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> BEGIN GTID 0-1-1 +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> 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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +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 2 <End_log_pos> BEGIN GTID 0-2-3 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-4 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +connection node_2; +SELECT COUNT(*) = 2 FROM t4; +COUNT(*) = 2 +1 +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 2 <End_log_pos> [] +mysqld-bin.000001 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000001 +mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-1 +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> 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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +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 2 <End_log_pos> BEGIN GTID 0-2-3 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-4 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.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..ab090e5c2a7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result @@ -0,0 +1,20 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 1 +1 +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; +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..25bc2e11a3e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result @@ -0,0 +1,65 @@ +connection node_2; +connection node_1; +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; +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; +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) 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),(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> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (3),(4) +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=### */ +connection node_2; +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +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 2 <End_log_pos> [] +mysqld-bin.000001 <Pos> Binlog_checkpoint 2 <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) 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),(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> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (3),(4) +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=### */ +connection node_1; +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..ca749a45e9a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +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; +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; +connection node_1; +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..ceb7da60df6 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-585.test @@ -0,0 +1,44 @@ +# +# 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); +# 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 (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..45b77a99da1 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test @@ -0,0 +1,59 @@ +# +# 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 +# Deadlock error instead of dupkey since the transaction is SR and +# statement rollback is not safe. +--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..6623c33c484 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt @@ -0,0 +1 @@ + --log-bin --log-slave-updates --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..56464ba6f63 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test @@ -0,0 +1,46 @@ +# +# Test basic Galera operation +# + +--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 256; + +--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 256; + +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..7dfa7850c15 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test @@ -0,0 +1,70 @@ +# +# 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 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); + +--connection node_2 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +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 'mysqld-bin.000001' FROM 256; + +--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 'mysqld-bin.000001' FROM 256; + +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..06e56d3c9cd --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test @@ -0,0 +1,41 @@ +# SR transactions are not binlogged #136 + +--source include/galera_cluster.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 +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 'mysqld-bin.000001' FROM 256; + +--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 'mysqld-bin.000001' FROM 256; + +--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 2de384806b2..485ee9c2dd2 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 e3eac1963dc..538af496739 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -16,21 +16,28 @@ IF(WITH_WSREP AND NOT EMBEDDED_LIBRARY) - SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep) SET(WSREP_SOURCES + wsrep_client_service.cc + wsrep_high_priority_service.cc + wsrep_server_service.cc + wsrep_storage_service.cc + wsrep_server_state.cc + 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_thd_pool.cc + wsrep_schema.cc + wsrep_plugin.cc + service_wsrep.cc ) - SET(WSREP_LIB wsrep) + SET(WSREP_LIB wsrep-lib wsrep_api_v26) ELSE() SET(WSREP_SOURCES wsrep_dummy.cc) ENDIF() @@ -42,7 +49,6 @@ ${PCRE_INCLUDES} ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/sql -${WSREP_INCLUDES} ) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index a6803982171..4cb703f51ca 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -32,7 +32,10 @@ #include "event_db_repository.h" #include "sp_head.h" #include "sql_show.h" // append_definer, append_identifier - +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ /** @addtogroup Event_Scheduler @{ @@ -1343,6 +1346,10 @@ Event_job_data::execute(THD *thd, bool drop) thd->reset_for_next_command(); +#ifdef WITH_WSREP + wsrep_open(thd); + wsrep_before_command(thd); +#endif /* WITH_WSREP */ /* MySQL parser currently assumes that current database is either present in THD or all names in all statements are fully specified. @@ -1517,6 +1524,10 @@ Event_job_data::execute(THD *thd, bool drop) if (save_sctx) event_sctx.restore_security_context(thd, save_sctx); #endif +#ifdef WITH_WSREP + wsrep_after_command_ignore_result(thd); + wsrep_close(thd); +#endif /* WITH_WSREP */ thd->lex->unit.cleanup(); thd->end_statement(); thd->cleanup_after_query(); diff --git a/sql/events.cc b/sql/events.cc index 567baa5f90b..9d315ab8c08 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 f5302119187..e7236032259 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 8a374fe87b7..aec4d9031ab 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1507,5 +1507,8 @@ class ha_partition :public handler 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 20d42fbc7a2..19d31b32381 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -53,9 +53,14 @@ #endif #include "semisync_master.h" -#include "wsrep_mysqld.h" +#include "mysql/service_wsrep.h" #include "wsrep.h" +#include "wsrep_mysqld.h" +#include "wsrep_binlog.h" #include "wsrep_xid.h" +#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 @@ -251,6 +256,9 @@ handlerton *ha_checktype(THD *thd, handlerton *hton, bool no_substitute) if (no_substitute) return NULL; +#ifdef WITH_WSREP + (void)wsrep_after_rollback(thd, false); +#endif /* WITH_WSREP */ return ha_default_handlerton(thd); } /* ha_checktype */ @@ -1163,17 +1171,30 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) static int prepare_or_error(handlerton *ht, THD *thd, bool all) { + #ifdef WITH_WSREP + if (WSREP(thd) && ht->db_type == DB_TYPE_INNODB && + wsrep_before_prepare(thd, all)) + { + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + return(1); + } +#endif /* WITH_WSREP */ + int err= ht->prepare(ht, thd, all); status_var_increment(thd->status_var.ha_prepare_count); if (err) { - /* 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) -#endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); } +#ifdef WITH_WSREP + if (WSREP(thd) && ht->db_type == DB_TYPE_INNODB && + wsrep_after_prepare(thd, all)) + { + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + err= 1; + } +#endif /* WITH_WSREP */ + return err; } @@ -1357,8 +1378,11 @@ int ha_commit_trans(THD *thd, bool all) DBUG_RETURN(2); } +#ifdef WITH_WSREP + bool trans_was_empty= true; +#endif /* WITH_WSREP */ #ifdef WITH_ARIA_STORAGE_ENGINE - ha_maria::implicit_commit(thd, TRUE); + ha_maria::implicit_commit(thd, TRUE); #endif if (!ha_info) @@ -1368,6 +1392,13 @@ int ha_commit_trans(THD *thd, bool all) */ if (is_real_trans) thd->transaction.cleanup(); +#ifdef WITH_WSREP + if (WSREP(thd) && all && !error && trans_was_empty) + { + WSREP_DEBUG("was empty handler"); + wsrep_commit_empty(thd, all); + } +#endif /* WITH_WSREP */ DBUG_RETURN(0); } @@ -1378,6 +1409,7 @@ int ha_commit_trans(THD *thd, bool all) thd->stmt_map.close_transient_cursors(); uint rw_ha_count= ha_check_and_coalesce_trx_read_only(thd, ha_info, all); + trans->rw_ha_count= rw_ha_count; /* rw_trans is TRUE when we in a transaction changing data */ bool rw_trans= is_real_trans && (rw_ha_count > (thd->is_current_stmt_binlog_disabled()?0U:1U)); @@ -1451,6 +1483,12 @@ int ha_commit_trans(THD *thd, bool all) } } #endif +#ifdef WITH_WSREP + if (rw_ha_count) + { + trans_was_empty= false; + } +#endif /* WITH_WSREP */ if (trans->no_2pc || (rw_ha_count <= 1)) { @@ -1489,7 +1527,7 @@ int ha_commit_trans(THD *thd, bool all) if (!error && WSREP_ON && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid)) { // xid was rewritten by wsrep - xid= wsrep_xid_seqno(thd->transaction.xid_state.xid); + xid= wsrep_xid_seqno(thd->transaction.xid_state.xid).get(); } #endif /* WITH_WSREP */ @@ -1498,18 +1536,33 @@ int ha_commit_trans(THD *thd, bool all) error= commit_one_phase_2(thd, all, trans, is_real_trans); goto done; } - + DEBUG_SYNC(thd, "ha_commit_trans_before_log_and_order"); 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_thd_data); + if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort) + { + mysql_mutex_unlock(&thd->LOCK_thd_data); + (void)tc_log->unlog(cookie, xid); + goto wsrep_err; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); + } +#endif /* WITH_WSREP */ DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE();); if (tc_log->unlog(cookie, xid)) { @@ -1517,7 +1570,7 @@ int ha_commit_trans(THD *thd, bool all) goto end; } -done: + done: DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE();); mysql_mutex_assert_not_owner(&LOCK_prepare_ordered); @@ -1531,7 +1584,20 @@ int ha_commit_trans(THD *thd, bool all) goto end; /* Come here if error and we need to rollback. */ -err: +#ifdef WITH_WSREP + wsrep_err: + mysql_mutex_lock(&thd->LOCK_thd_data); + if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort) + { + WSREP_DEBUG("BF abort has happened after prepare & certify"); + mysql_mutex_unlock(&thd->LOCK_thd_data); + ha_rollback_trans(thd, TRUE); + } + else + mysql_mutex_unlock(&thd->LOCK_thd_data); + +#endif /* WITH_WSREP */ + err: error= 1; /* Transaction was rolled back */ /* In parallel replication, rollback is delayed, as there is extra replication @@ -1540,7 +1606,10 @@ int ha_commit_trans(THD *thd, bool all) */ if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec)) ha_rollback_trans(thd, all); - + else + { + WSREP_DEBUG("rollback skipped %d %d",thd->rgi_slave, thd->rgi_slave->is_parallel_exec); + } end: if (rw_trans && mdl_request.ticket) { @@ -1552,6 +1621,13 @@ int ha_commit_trans(THD *thd, bool all) */ thd->mdl_context.release_lock(mdl_request.ticket); } +#ifdef WITH_WSREP + if (WSREP(thd) && all && !error && trans_was_empty) + { + wsrep_commit_empty(thd, all); + } +#endif /* WITH_WSREP */ + DBUG_RETURN(error); } @@ -1626,6 +1702,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) } trans->ha_list= 0; trans->no_2pc=0; + trans->rw_ha_count= 0; if (all) { #ifdef HAVE_QUERY_CACHE @@ -1674,7 +1751,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) { @@ -1709,6 +1785,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 */ @@ -1724,9 +1803,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_trx().state(), + thd->query()); #endif /* WITH_WSREP */ } status_var_increment(thd->status_var.ha_rollback_count); @@ -1735,6 +1814,7 @@ int ha_rollback_trans(THD *thd, bool all) } trans->ha_list= 0; trans->no_2pc=0; + trans->rw_ha_count= 0; } /* @@ -1745,6 +1825,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) { @@ -1918,7 +2007,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, for (int i=0; i < got; i ++) { my_xid x= IF_WSREP(WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ? - wsrep_xid_seqno(info->list[i]) : + (wsrep_xid_seqno(info->list[i])).get() : info->list[i].get_my_xid(), info->list[i].get_my_xid()); if (!x) // not "mine" - that is generated by external TM @@ -2269,6 +2358,7 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) DBUG_ENTER("ha_rollback_to_savepoint"); trans->no_2pc=0; + trans->rw_ha_count= 0; /* rolling back to savepoint in all storage engines that were part of the transaction when the savepoint was set @@ -2297,11 +2387,26 @@ 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); error=1; } +#ifdef WITH_WSREP + if (ht->db_type == DB_TYPE_INNODB) + { + WSREP_DEBUG("ha_rollback_to_savepoint: run after_rollback hook"); + (void) wsrep_after_rollback(thd, !thd->in_sub_stmt); + } +#endif // WITH_WSREP status_var_increment(thd->status_var.ha_rollback_count); ha_info_next= ha_info->next(); ha_info->reset(); /* keep it conveniently zero-filled */ @@ -2318,6 +2423,16 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) */ int ha_savepoint(THD *thd, SAVEPOINT *sv) { +#ifdef WITH_WSREP + /* + Register binlog hton for savepoint processing if wsrep binlog + emulation is on. + */ + if (WSREP_EMULATE_BINLOG(thd) && wsrep_thd_is_local(thd)) + { + wsrep_register_binlog_handler(thd, thd->in_multi_stmt_transaction_mode()); + } +#endif /* WITH_WSREP */ int error=0; THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : &thd->transaction.all); @@ -5933,6 +6048,12 @@ bool handler::check_table_binlog_row_based(bool binlog_row) return false; if (unlikely((table->in_use->variables.sql_log_bin_off))) return 0; /* Called by partitioning engine */ +#ifdef WITH_WSREP + if (!table->in_use->variables.sql_log_bin) + return 0; /* wsrep patch sets sql_log_bin directly to silence + binlogging + */ +#endif /* WITH_WSREP */ if (unlikely((!check_table_binlog_row_based_done))) { check_table_binlog_row_based_done= 1; @@ -5963,15 +6084,16 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row) Otherwise, return 'true' if binary logging is on. */ IF_WSREP(((WSREP_EMULATE_BINLOG(thd) && - (thd->wsrep_exec_mode != REPL_RECV)) || + wsrep_thd_is_local(thd)) || ((WSREP(thd) || (thd->variables.option_bits & OPTION_BIN_LOG)) && mysql_bin_log.is_open())), - (thd->variables.option_bits & OPTION_BIN_LOG) && - mysql_bin_log.is_open())); + (thd->variables.option_bits & OPTION_BIN_LOG) && + mysql_bin_log.is_open())); } + /** @brief Write table maps for all (manually or automatically) locked tables to the binary log. Also, if binlog_annotate_row_events is ON, @@ -6062,6 +6184,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 @@ -6096,20 +6228,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)) @@ -6221,6 +6339,27 @@ 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 && + wsrep_thd_is_local(thd) && + 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)) + { + DBUG_RETURN(ER_LOCK_DEADLOCK); + } + DBUG_RETURN(0); +} +#endif /* WITH_WSREP */ int handler::ha_write_row(uchar *buf) { @@ -6243,7 +6382,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); } @@ -6275,6 +6423,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; } @@ -6330,6 +6486,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; } @@ -6519,7 +6683,7 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) DBUG_ENTER("ha_abort_transaction"); if (!WSREP(bf_thd) && !(bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU && - bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { + wsrep_thd_is_toi(bf_thd))) { DBUG_RETURN(0); } @@ -6535,52 +6699,16 @@ 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: %" PRIu64, 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."); - +#ifdef OUT + (void *)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, thd->query_id); +#endif DBUG_VOID_RETURN; } #endif /* WITH_WSREP */ diff --git a/sql/handler.h b/sql/handler.h index 362c6784377..78936b2bbd4 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1661,6 +1661,9 @@ struct THD_TRANS { /* true is not all entries in the ht[] support 2pc */ bool no_2pc; +#ifdef WITH_WSREP + int rw_ha_count; +#endif /* WITH_WSREP */ /* storage engines that registered in this transaction */ Ha_trx_info *ha_list; /* @@ -1695,6 +1698,7 @@ struct THD_TRANS void reset() { no_2pc= FALSE; + rw_ha_count= 0; modified_non_trans_table= FALSE; m_unsafe_rollback_flags= 0; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 87bf69f3c96..a4c3de5f8fb 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3193,6 +3193,45 @@ class Create_func_within : public Create_func_arg2 }; #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 @@ -6905,6 +6944,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; @@ -7347,6 +7443,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)}, +#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_func.cc b/sql/item_func.cc index ea6a39ab150..df3c30209e0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -59,6 +59,9 @@ #ifdef NO_EMBEDDED_ACCESS_CHECKS #define sp_restore_security_context(A,B) while (0) {} #endif +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif /* WITH_WSREP */ bool check_reserved_words(const LEX_CSTRING *name) { @@ -2495,7 +2498,7 @@ void Item_func_rand::seed_random(Item *arg) THD *thd= current_thd; if (WSREP(thd)) { - if (thd->wsrep_exec_mode==REPL_RECV) + if (wsrep_thd_is_applying(current_thd)) tmp= thd->wsrep_rand; else tmp= thd->wsrep_rand= (uint32) arg->val_int(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6c82c580858..5d65637c134 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5264,3 +5264,102 @@ 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 gtid= current_thd->wsrep_cs().last_written_gtid(); + if (gtid_str.alloc(wsrep::gtid_c_str_len())) + { + my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len()); + null_value= true; + return NULL; + } + + ssize_t gtid_len= gtid_print_to_c_str(gtid, (char*)gtid_str.ptr(), + wsrep::gtid_c_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 >id_str; +} + +String * Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str) +{ + /* TODO: Should call Wsrep_server_state.instance().last_committed_gtid() + instead. */ + wsrep::gtid gtid= Wsrep_server_state::instance().provider().last_committed_gtid(); + if (gtid_str.alloc(wsrep::gtid_c_str_len())) + { + my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len()); + null_value= true; + return NULL; + } + ssize_t gtid_len= wsrep::gtid_print_to_c_str(gtid, (char*)gtid_str.ptr(), + wsrep::gtid_c_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 >id_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(), >id); + if (gtid_len < 0) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return 0LL; + } + + if (gtid.seqno == WSREP_SEQNO_UNDEFINED && + wsrep_uuid_compare(>id.uuid, &WSREP_UUID_UNDEFINED) == 0) + { + return 1LL; + } + + enum wsrep::provider::status status= + wsrep_sync_wait_upto(current_thd, >id, timeout); + + if (status) + { + int err; + switch (status) { + case wsrep::provider::error_transaction_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 762a3c2559e..5b6a08d4285 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1804,5 +1804,56 @@ class Item_temptable_rowid :public Item_str_func Item *get_copy(THD *thd) { 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..5c0c39cc068 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1084,21 +1084,16 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) thd->mdl_context.release_lock(m_mdl_blocks_commits_lock); m_mdl_blocks_commits_lock= NULL; #ifdef WITH_WSREP - if (WSREP(thd) || wsrep_node_is_donor()) + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + if (server_state.state() == Wsrep_server_state::s_donor) { + /* TODO: maybe redundant here?: */ wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - wsrep->resume(wsrep); - /* resync here only if we did implicit desync earlier */ - if (!wsrep_desync && wsrep_node_is_synced()) - { - int ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("resync failed %d for FTWRL: db: %s, query: %s", - ret, thd->get_db(), thd->query()); - DBUG_VOID_RETURN; - } - } + server_state.resume(); + } + else if (WSREP(thd)) + { + server_state.resume_and_resync(); } #endif /* WITH_WSREP */ } @@ -1134,9 +1129,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 +1138,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, @@ -1156,60 +1152,32 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT; #ifdef WITH_WSREP + /* Native threads should bail out before wsrep oprations to follow. - Donor servicing thread is an exception, it should pause provider but not desync, - as it is already desynced in donor state + Donor servicing thread is an exception, it should pause provider + but not desync, as it is already desynced in donor state */ - if (!WSREP(thd) && !wsrep_node_is_donor()) + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + if (!WSREP(thd) && server_state.state() != Wsrep_server_state::s_donor) { DBUG_RETURN(FALSE); } - /* if already desynced or donor, avoid double desyncing - if not in PC and synced, desyncing is not possible either - */ - if (wsrep_desync || !wsrep_node_is_synced()) + wsrep::seqno paused_seqno; + if (server_state.state() == Wsrep_server_state::s_donor) { - WSREP_DEBUG("desync set upfont, skipping implicit desync for FTWRL: %d", - wsrep_desync); + paused_seqno= server_state.pause(); } else { - int rcode; - WSREP_DEBUG("running implicit desync for node"); - rcode = wsrep->desync(wsrep); - if (rcode != WSREP_OK) - { - WSREP_WARN("FTWRL desync failed %d for schema: %s, query: %s", - rcode, thd->get_db(), thd->query()); - my_message(ER_LOCK_DEADLOCK, "wsrep desync failed for FTWRL", MYF(0)); - DBUG_RETURN(TRUE); - } + paused_seqno= server_state.desync_and_pause(); } - - long long ret = wsrep->pause(wsrep); - if (ret >= 0) + WSREP_INFO("Server paused at: %lld", paused_seqno.get()); + if (paused_seqno.get() >= 0) { - wsrep_locked_seqno= ret; + wsrep_locked_seqno= paused_seqno.get(); } - 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)); - - 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 */ + #endif /* WITH_WSREP */ DBUG_RETURN(FALSE); } diff --git a/sql/log.cc b/sql/log.cc index a56117a4ac1..c412be4bb67 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 @@ -1703,7 +1705,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); @@ -2297,8 +2300,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_trx().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); @@ -5970,7 +5982,9 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone, DBUG_PRINT("enter", ("standalone: %d", standalone)); #ifdef WITH_WSREP - if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode && !thd->variables.gtid_seq_no) + if (WSREP(thd) && + (wsrep_thd_trx_seqno(thd) > 0) && + wsrep_gtid_mode && !thd->variables.gtid_seq_no) { domain_id= wsrep_gtid_domain_id; } else { @@ -6287,7 +6301,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) */ /* applier and replayer can skip writing binlog events */ if ((WSREP_EMULATE_BINLOG(thd) && - IF_WSREP(thd->wsrep_exec_mode != REPL_RECV, 0)) || is_open()) + IF_WSREP(thd->wsrep_cs().mode() == wsrep::client_state::m_local, 0)) || is_open()) { my_off_t UNINIT_VAR(my_org_b_tell); #ifdef HAVE_REPLICATION @@ -7703,7 +7717,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) && + 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)) + { + /* + 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) @@ -8087,7 +8124,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) && + 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)) + { + /* + 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); /* @@ -8926,9 +8987,27 @@ 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) && WSREP_EMULATE_BINLOG(thd) && wsrep_before_commit(thd, all)) + { + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + return(0); + } +#endif /* WITH_WSREP */ mysql_mutex_lock(&LOCK_commit_ordered); run_commit_ordered(thd, all); mysql_mutex_unlock(&LOCK_commit_ordered); + //if (WSREP(thd) && !thd->wsrep_apply_toi) +#ifdef WITH_WSREP + if (WSREP(thd) && WSREP_EMULATE_BINLOG(thd)) + { + /* + TODO: Ordered commit should be done after the transaction + has been queued for group commit. + */ + (void) wsrep_after_commit(thd, all); + } +#endif /* WITH_WSREP */ } if (need_prepare_ordered) @@ -9626,6 +9705,37 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all, if (err) DBUG_RETURN(0); +#ifdef WITH_WSREP + /* + if binary logging is on and transaction happened by group commit, no need for commit hooks + here any more + */ + if (WSREP(thd) && + thd->wsrep_cs().transaction().state() != wsrep::transaction::state::s_committed && + thd->wsrep_cs().mode() != wsrep::client_state::m_local && + wsrep_before_commit(thd, all)) + { + return(0); + } + +#endif /* WITH_WSREP */ +#ifdef WITH_WSREP + if (WSREP(thd) && + thd->wsrep_cs().transaction().state() != wsrep::transaction::state::s_committed && + thd->wsrep_cs().mode() != wsrep::client_state::m_local) + { + /* + 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; /* @@ -10592,7 +10702,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 (0); +} + +static int wsrep_plugin_deinit(void *p) +{ + WSREP_INFO("wsrep_plugin_deinit()"); + return (0); +} + +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*) @@ -10606,16 +10753,23 @@ IO_CACHE * get_trans_log(THD * thd) } -bool wsrep_trans_cache_is_empty(THD *thd) +uint wsrep_get_trans_cache_position(THD *thd) { - binlog_cache_mngr *const cache_mngr= - (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - return (!cache_mngr || cache_mngr->trx_cache.empty()); + 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 thd_binlog_trx_reset(THD * thd) +void wsrep_thd_binlog_trx_reset(THD * thd) { + DBUG_ENTER("wsrep_thd_binlog_trx_reset"); + WSREP_DEBUG("wsrep_thd_binlog_reset"); /* todo: fix autocommit select to not call the caller */ @@ -10634,6 +10788,7 @@ void thd_binlog_trx_reset(THD * thd) } } thd->clear_binlog_table_maps(); + DBUG_VOID_RETURN; } @@ -10646,4 +10801,87 @@ 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_cs().mode() == wsrep::client_state::m_local) + 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_sr().fragments_certified() > 0 && + (trx_cache->get_prev_position() == MY_OFF_T_UNDEF || + trx_cache->get_prev_position() < thd->wsrep_sr().bytes_certified())) + { + WSREP_DEBUG("statement rollback is not safe for streaming replication" + " pre-stmt_pos: %llu, frag repl pos: %lu\nThread: %lu, SQL: %s", + trx_cache->get_prev_position(), + thd->wsrep_sr().bytes_certified(), + 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 @@ class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging 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 63af9015ae9..1322704999e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -44,6 +44,9 @@ #include "compat56.h" #include "wsrep_mysqld.h" #include "sql_insert.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif #else #include "mysqld_error.h" #endif /* MYSQL_CLIENT */ @@ -5743,6 +5746,14 @@ START SLAVE; . Query: '%s'", expected_error, thd->query()); "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 */ } /* @@ -11256,13 +11267,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) { WSREP_WARN("BF applier failed to open_and_lock_tables: %u, fatal: %d " "wsrep = (exec_mode: %d conflict_state: %d seqno: %lld)", - thd->get_stmt_da()->sql_errno(), - thd->is_fatal_error, - thd->wsrep_exec_mode, - thd->wsrep_conflict_state, - (long long)wsrep_thd_trx_seqno(thd)); + thd->get_stmt_da()->sql_errno(), + thd->is_fatal_error, + thd->wsrep_cs().mode(), + thd->wsrep_trx().state(), + (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)) { @@ -11399,10 +11410,10 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) #ifdef HAVE_QUERY_CACHE #ifdef WITH_WSREP /* - Moved invalidation right before the call to rows_event_stmt_cleanup(), - to avoid query cache being polluted with stale entries. + Moved invalidation right before the call to rows_event_stmt_cleanup(), + to avoid query cache being polluted with stale entries, */ - if (! (WSREP(thd) && (thd->wsrep_exec_mode == REPL_RECV))) + if (! (WSREP(thd) && wsrep_thd_is_applying(thd))) { #endif /* WITH_WSREP */ query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); @@ -11515,6 +11526,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) @@ -11602,7 +11620,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) restore_empty_query_table_list(thd->lex); #if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE) - if (WSREP(thd) && thd->wsrep_exec_mode == REPL_RECV) + if (WSREP(thd) && wsrep_thd_is_applying(thd)) { query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); } diff --git a/sql/mdl.cc b/sql/mdl.cc index f03fc89fcc1..fd419a68e3a 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -24,9 +24,12 @@ #include <mysql/plugin.h> #include <mysql/service_thd_wait.h> #include <mysql/psi/mysql_stage.h> +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#include "debug_sync.h" #include "wsrep_mysqld.h" #include "wsrep_thd.h" - +#endif /* WITH_WSREP */ #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_wait_LOCK_wait_status; @@ -1073,7 +1076,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 +1087,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 +1161,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 +1188,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 +1549,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 +1561,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((const void*)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 +1582,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 +1594,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 +1629,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 76455177a6e..0758603a810 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -70,10 +70,13 @@ #include "scheduler.h" #include <waiting_threads.h> #include "debug_sync.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" #include "wsrep_mysqld.h" #include "wsrep_var.h" #include "wsrep_thd.h" #include "wsrep_sst.h" +#endif /* WITH_WSREP */ #include "proxy_protocol.h" #include "sql_callback.h" @@ -1554,7 +1557,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 @@ -1656,11 +1658,12 @@ static void close_connections(void) #ifdef WITH_WSREP /* skip wsrep system threads as well */ - if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier)) + if (WSREP(tmp) && (wsrep_thd_is_applying(tmp) || tmp->wsrep_applier)) continue; #endif tmp->set_killed(KILL_SERVER_HARD); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data); mysql_mutex_lock(&tmp->LOCK_thd_kill); if (tmp->mysys_var) { @@ -1685,6 +1688,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_thd_data); } mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list @@ -1747,7 +1751,7 @@ static void close_connections(void) * The code here makes sure mysqld will not hang during shutdown * even if wsrep provider has problems in shutting down. */ - if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV) + if (WSREP(tmp) && wsrep_thd_is_applying(tmp)) { sql_print_information("closing wsrep system thread"); tmp->set_killed(KILL_CONNECTION); @@ -1770,6 +1774,13 @@ static void close_connections(void) mysql_mutex_unlock(&LOCK_thread_count); } end_slave(); +#ifdef WITH_WSREP + if (wsrep_inited == 1) + { + wsrep_deinit(); + wsrep_deinit_server(); + } +#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); @@ -1927,14 +1938,18 @@ static void kill_server(int sig) /* Stop wsrep threads in case they are running. */ if (wsrep_running_threads > 0) { - wsrep_stop_replication(NULL); + wsrep_shutdown_replication(); } close_connections(); +#ifdef WITH_WSREP if (wsrep_inited == 1) - wsrep_deinit(true); - + { + wsrep_deinit(); + wsrep_deinit_server(); + } +#endif if (sig != MYSQL_KILL_SIGNAL && sig != 0) unireg_abort(1); /* purecov: inspected */ @@ -2016,8 +2031,7 @@ extern "C" void unireg_abort(int exit_code) disable_log_notes= 1; #ifdef WITH_WSREP - /* Check if wsrep class is used. If yes, then cleanup wsrep */ - if (wsrep) + if (Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected) { /* This is an abort situation, we cannot expect to gracefully close all @@ -2025,7 +2039,7 @@ extern "C" void unireg_abort(int exit_code) */ wsrep_close_client_connections(FALSE); shutdown_in_progress= 1; - wsrep->disconnect(wsrep); + Wsrep_server_state::instance().disconnect(); WSREP_INFO("Service disconnected."); wsrep_close_threads(NULL); /* this won't close all threads */ sleep(1); /* so give some time to exit for those which can */ @@ -2033,7 +2047,10 @@ extern "C" void unireg_abort(int exit_code) /* In bootstrap mode we deinitialize wsrep here. */ if (opt_bootstrap && wsrep_inited) - wsrep_deinit(true); + { + wsrep_deinit(); + wsrep_deinit_server(); + } } #endif // WITH_WSREP @@ -2078,7 +2095,9 @@ static void mysqld_exit(int exit_code) #ifdef SAFEMALLOC sf_report_leaked_memory(0); #endif +#ifdef TODO DBUG_SLOW_ASSERT(global_status_var.global_memory_used == 0); +#endif } cleanup_tls(); DBUG_LEAVE; @@ -2772,6 +2791,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); + } } @@ -5117,7 +5144,8 @@ static int init_server_components() wsrep_thr_init(); #endif - if (WSREP_ON && !wsrep_recovery && !opt_abort) /* WSREP BEFORE SE */ + if (wsrep_init_server()) unireg_abort(1); + if (!wsrep_recovery) { if (opt_bootstrap) // bootsrap option given - disable wsrep functionality { @@ -5827,24 +5855,12 @@ int mysqld_main(int argc, char **argv) } else { - wsrep_SE_initialized(); - - if (wsrep_before_SE()) - { - /*! in case of no SST wsrep waits in view handler callback */ - 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."); - } - } - else + if (!wsrep_before_SE()) { wsrep_init_startup (false); } + wsrep_init_globals(); wsrep_create_appliers(wsrep_slave_threads - 1); } } @@ -8158,6 +8174,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} @@ -9619,8 +9649,7 @@ void refresh_status(THD *thd) /* Reset some global variables */ reset_status_vars(); #ifdef WITH_WSREP - if (WSREP_ON) - wsrep->stats_reset(wsrep); + Wsrep_server_state::instance().provider().reset_status(); #endif /* WITH_WSREP */ /* Reset the counters of all key caches (default and named). */ diff --git a/sql/protocol.cc b/sql/protocol.cc index 7eee9283989..9bb8a31d8c6 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -551,8 +551,24 @@ 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_thd_data() 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 + */ + DBUG_ASSERT(thd->wsrep_trx().state() != wsrep::transaction::s_replaying); + if (WSREP(thd) && thd->wsrep_trx().state() == + wsrep::transaction::s_replaying) + { + WSREP_ERROR("attempting net_end_statement while replaying"); + return; + } + DBUG_ENTER("Protocol::end_statement"); DBUG_ASSERT(! thd->get_stmt_da()->is_sent()); bool error= FALSE; diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc new file mode 100644 index 00000000000..1b7dc53203b --- /dev/null +++ b/sql/service_wsrep.cc @@ -0,0 +1,335 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mariadb.h" + +#include "mysql/service_wsrep.h" +#include "wsrep/key.hpp" +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#include "sql_class.h" +#include "debug_sync.h" + +extern "C" my_bool wsrep_global_on() +{ + return WSREP_ON; +} + +extern "C" my_bool wsrep_on(const void *thd) +{ + return (int)(WSREP(((const THD*)thd))); +} + +extern "C" void wsrep_thd_LOCK(const void* thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + mysql_mutex_lock(&thd->LOCK_thd_data); +} + +extern "C" void wsrep_thd_UNLOCK(const void* thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + mysql_mutex_unlock(&thd->LOCK_thd_data); +} + + +extern "C" my_bool wsrep_thd_is_wsrep_on(const void *thd) +{ + return ((const THD*)thd)->variables.wsrep_on; +} + +extern "C" my_thread_id wsrep_thd_thread_id(const void *thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return thd->thread_id; +} + +extern "C" const char* wsrep_thd_client_state_str(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return wsrep::to_c_string(thd->wsrep_cs().state()); +} + +extern "C" const char* wsrep_thd_client_mode_str(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return wsrep::to_c_string(thd->wsrep_cs().mode()); +} + +extern "C" const char* wsrep_thd_transaction_state_str(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return wsrep::to_c_string(thd->wsrep_cs().transaction().state()); +} + + +extern "C" const char *wsrep_thd_query(const void *thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + return (thd) ? thd->query() : NULL; +} + +extern "C" query_id_t wsrep_thd_query_id(const void* thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + return thd->query_id; +} + +extern "C" query_id_t wsrep_thd_transaction_id(const void* thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + return thd->wsrep_cs().transaction().id().get(); +} + +extern "C" long long wsrep_thd_trx_seqno(const void* thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + const wsrep::client_state& cs= thd->wsrep_cs(); + if (cs.mode() == wsrep::client_state::m_toi) + { + return cs.toi_meta().seqno().get(); + } + else + { + return cs.transaction().ws_meta().seqno().get(); + } +} + +extern "C" void wsrep_thd_self_abort(void* thd_ptr) +{ + THD* thd= (THD*)thd_ptr; + thd->wsrep_cs().bf_abort(wsrep::seqno(0)); +} + +extern "C" my_bool wsrep_thd_is_local(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd->wsrep_cs().mode() == wsrep::client_state::m_local); +} + +extern "C" my_bool wsrep_thd_is_applying(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority); +} + +extern "C" my_bool wsrep_thd_is_toi(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd->wsrep_cs().mode() == wsrep::client_state::m_toi); +} + +extern "C" my_bool wsrep_thd_is_local_toi(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd->wsrep_cs().mode() == wsrep::client_state::m_toi && + thd->wsrep_cs().toi_mode() == wsrep::client_state::m_local); + +} + +extern "C" my_bool wsrep_thd_is_in_rsu(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd->wsrep_cs().mode() == wsrep::client_state::m_rsu); +} + +extern "C" my_bool wsrep_thd_is_BF(const void *thd_ptr, my_bool sync) +{ + THD* thd= (THD*)thd_ptr; + my_bool status = FALSE; + if (thd_ptr) + { + if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); + status = (wsrep_thd_is_applying(thd) || wsrep_thd_is_toi(thd)); + if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); + } + return status; +} + +extern "C" my_bool wsrep_thd_is_SR(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd && thd->wsrep_cs().transaction().is_streaming()); +} + +extern "C" void wsrep_handle_SR_rollback(void *bf_thd_ptr, + void *victim_thd_ptr) +{ + DBUG_ASSERT(victim_thd_ptr); + if (!victim_thd_ptr) return; + + THD* bf_thd= (THD*)bf_thd_ptr; + THD* victim_thd= (THD*)victim_thd_ptr; + WSREP_DEBUG("handle rollback, for deadlock: thd %llu trx_id %lu frags %lu conf %s", + victim_thd->thread_id, + victim_thd->wsrep_trx_id(), + victim_thd->wsrep_sr().fragments_certified(), + wsrep_thd_transaction_state_str(victim_thd)); + if (bf_thd) victim_thd->store_globals(); + if (!bf_thd) + { + DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback"); + } + if (bf_thd) + { + wsrep_bf_abort(bf_thd, victim_thd); + } + else + { + wsrep_thd_self_abort(victim_thd); + } + if (bf_thd) bf_thd->store_globals(); +} + +extern "C" 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; + } +} + +extern "C" void wsrep_thd_awake(const void* thd_ptr, my_bool signal) +{ + THD* thd= (THD*)thd_ptr; + if (signal) + { + //mysql_mutex_lock(&thd->LOCK_thd_data); + thd->awake(KILL_QUERY); + //mysql_mutex_unlock(&thd->LOCK_thd_data); + } + else + { + mysql_mutex_lock(&LOCK_wsrep_replaying); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } +} + +extern "C" my_bool wsrep_thd_bf_abort(const void* bf_thd_ptr, + void* victim_thd_ptr, + my_bool signal) +{ + const THD* bf_thd= (const THD*)bf_thd_ptr; + THD* victim_thd= (THD*)victim_thd_ptr; + my_bool ret= wsrep_bf_abort(bf_thd, victim_thd); + /* + Send awake signal if victim was BF aborted or does not + have wsrep on. Note that this should never interrupt RSU + as RSU has paused the provider. + */ + if ((ret || !wsrep_on(victim_thd)) && signal) + { + wsrep_thd_awake((const void*)victim_thd, signal); + } + return ret; +} + +extern "C" my_bool wsrep_thd_skip_locking(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return thd != NULL && thd->wsrep_skip_locking; +} + +extern "C" my_bool wsrep_thd_order_before(const void *left_ptr, + const void *right_ptr) +{ + const THD* left= (const THD*)left_ptr; + const THD* right= (const THD*)right_ptr; + if (wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) { + WSREP_DEBUG("BF conflict, order: %lld %lld\n", + (long long)wsrep_thd_trx_seqno(left), + (long long)wsrep_thd_trx_seqno(right)); + return TRUE; + } + WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", + (long long)wsrep_thd_trx_seqno(left), + (long long)wsrep_thd_trx_seqno(right)); + return FALSE; +} + +extern "C" my_bool wsrep_thd_is_high_priority(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + return (thd != 0 && thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority); +} + +extern "C" my_bool wsrep_thd_is_aborting(const void* thd_ptr) +{ + const THD* thd= (const THD*)thd_ptr; + mysql_mutex_assert_owner(&thd->LOCK_thd_data); + if (thd != 0) + { + const wsrep::client_state& cs(thd->wsrep_cs()); + const enum wsrep::transaction::state tx_state(cs.transaction().state()); + switch (tx_state) + { + case wsrep::transaction::s_must_abort: + return (cs.state() == wsrep::client_state::s_exec || + cs.state() == wsrep::client_state::s_result); + case wsrep::transaction::s_aborting: + case wsrep::transaction::s_aborted: + return true; + default: + return false; + } + } + return false; +} + +static inline enum wsrep::key::type +map_key_type(enum Wsrep_key_type type) +{ + switch (type) + { + case wsrep_key_shared: return wsrep::key::shared; + case wsrep_key_semi_shared: return wsrep::key::semi_shared; + case wsrep_key_semi_exclusive: return wsrep::key::semi_exclusive; + case wsrep_key_exclusive: return wsrep::key::exclusive; + } + return wsrep::key::exclusive; +} + +extern "C" int wsrep_thd_append_key(void* thd_ptr, + const struct wsrep_key* key, + int n_keys, + enum Wsrep_key_type key_type) +{ + THD* thd= (THD*)thd_ptr; + Wsrep_client_state& client_state(thd->wsrep_cs()); + DBUG_ASSERT(client_state.transaction().active()); + int ret= 0; + for (int i= 0; i < n_keys && ret == 0; ++i) + { + wsrep::key wsrep_key(map_key_type(key_type)); + for (size_t kp= 0; kp < key[i].key_parts_num; ++kp) + { + wsrep_key.append_key_part(key[i].key_parts[kp].ptr, key[i].key_parts[kp].len); + } + ret= client_state.append_key(wsrep_key); + } + return ret; +} + +extern "C" long long get_wsrep_xid_seqno(const struct xid_t* xid) +{ + return wsrep_xid_seqno(*xid).get(); +} + +extern const unsigned char* get_wsrep_xid_uuid(const struct xid_t* xid) +{ + return (const unsigned char*)wsrep_xid_uuid(*xid).data(); +} diff --git a/sql/slave.cc b/sql/slave.cc index bb1300d36e6..391d7b846f8 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -53,6 +53,10 @@ // Create_file_log_event, // Format_description_log_event #include "wsrep_mysqld.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#include "wsrep_trans_observer.h" +#endif #ifdef HAVE_REPLICATION @@ -3917,14 +3921,20 @@ 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_thd_data); + if (exec_res && + thd->wsrep_trx().state() != wsrep::transaction::s_executing) { - WSREP_DEBUG("SQL apply failed, res %d conflict state: %d", - exec_res, thd->wsrep_conflict_state); + WSREP_DEBUG("SQL apply failed, res %d conflict state: %s", + exec_res, wsrep_thd_transaction_state_str(thd)); 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_thd_data); + } #endif #ifndef DBUG_OFF @@ -4217,6 +4227,13 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, } if (ev) { +#ifdef WITH_WSREP + if (wsrep_before_statement(thd)) + { + WSREP_INFO("Wsrep before statement error"); + DBUG_RETURN(1); + } +#endif /* WITH_WSREP */ int exec_res; Log_event_type typ= ev->get_type_code(); @@ -4248,9 +4265,9 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && (ev->server_id != global_system_variables.server_id || rli->replicate_same_server_id) && - rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) - ? rli->group_master_log_pos - : ev->log_pos - ev->data_written)) + rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) + ? rli->group_master_log_pos + : ev->log_pos - ev->data_written)) { sql_print_information("Slave SQL thread stopped because it reached its" " UNTIL position %llu", rli->until_pos()); @@ -4261,6 +4278,9 @@ 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 + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ delete ev; DBUG_RETURN(1); } @@ -4298,7 +4318,14 @@ 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 + { + wsrep_after_statement(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,9 +4347,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 + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); } - if (opt_gtid_ignore_duplicates && rli->mi->using_gtid != Master_info::USE_GTID_NO) { @@ -4334,7 +4363,10 @@ 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; - DBUG_RETURN(1); +#ifdef WITH_WSREP + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ + DBUG_RETURN(1); } /* If we need to skip this event group (because the GTID was already @@ -4362,11 +4394,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, retry. */ if (unlikely(exec_res == 2)) +#ifdef WITH_WSREP + { + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); - #ifdef WITH_WSREP + } mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == NO_CONFLICT) + if (thd->wsrep_cs().current_error() == wsrep::e_success) { mysql_mutex_unlock(&thd->LOCK_thd_data); #endif /* WITH_WSREP */ @@ -4381,8 +4417,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, We were in a transaction which has been rolled back because of a temporary error; let's seek back to BEGIN log event and retry it all again. - Note, if lock wait timeout (innodb_lock_wait_timeout exceeded) - there is no rollback since 5.0.13 (ref: manual). + Note, if lock wait timeout (innodb_lock_wait_timeout exceeded) + there is no rollback since 5.0.13 (ref: manual). We have to not only seek but also a) init_master_info(), to seek back to hot relay log's start @@ -4450,7 +4486,10 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, #endif /* WITH_WSREP */ thread_safe_increment64(&rli->executed_entries); - DBUG_RETURN(exec_res); +#ifdef WITH_WSREP + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ + DBUG_RETURN(exec_res); } mysql_mutex_unlock(&rli->data_lock); rli->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_READ_FAILURE, NULL, @@ -5376,12 +5415,6 @@ pthread_handler_t handle_slave_sql(void *arg) } #endif -#ifdef WITH_WSREP - thd->wsrep_exec_mode= LOCAL_STATE; - /* synchronize with wsrep replication */ - if (WSREP_ON) - wsrep_ready_wait(); -#endif DBUG_PRINT("master_info",("log_file_name: %s position: %llu", rli->group_master_log_name, rli->group_master_log_pos)); @@ -5515,10 +5548,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_thd_data); + + if (thd->wsrep_cs().current_error()) + { + wsrep_node_dropped = TRUE; + rli->abort_slave = TRUE; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); } #endif /* WITH_WSREP */ @@ -5551,6 +5590,10 @@ pthread_handler_t handle_slave_sql(void *arg) "log '%s' at position %llu%s", RPL_LOG_NAME, rli->group_master_log_pos, tmp.c_ptr_safe()); } +#ifdef WITH_WSREP + wsrep_after_command_before_result(thd); + wsrep_after_command_after_result(thd); +#endif /* WITH_WSREP */ err_before_start: @@ -5662,24 +5705,23 @@ pthread_handler_t handle_slave_sql(void *arg) 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; + } + } + // TODO 10.4 has deleted following line: + //wsrep_close(thd); #endif /* WITH_WSREP */ /* diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c86edc47bf9..b769868119e 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_trx().state() == wsrep::transaction::s_executing)) + { + /* + 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_statement(thd); + } +#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_acl.cc b/sql/sql_acl.cc index bf18581de4f..5fd0ddce1d4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -54,6 +54,9 @@ #include "sql_array.h" #include "sql_hset.h" #include "password.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif /* WITH_WSREP */ #include "sql_plugin_compat.h" @@ -3339,7 +3342,6 @@ bool change_password(THD *thd, LEX_USER *user) WSREP_TO_ISOLATION_END; thd->set_query(query_save); - thd->wsrep_exec_mode = LOCAL_STATE; } #endif /* WITH_WSREP */ thd->restore_stmt_binlog_format(save_binlog_format); @@ -3502,7 +3504,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, WSREP_TO_ISOLATION_END; thd->set_query(query_save); - thd->wsrep_exec_mode = LOCAL_STATE; } #endif /* WITH_WSREP */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 220fcf6cc34..9d2c6b81169 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -61,8 +61,12 @@ #ifdef __WIN__ #include <io.h> #endif +#ifdef WITH_WSREP #include "wsrep_mysqld.h" #include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ + bool No_such_table_error_handler::handle_condition(THD *, @@ -874,10 +878,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) @@ -3859,7 +3872,7 @@ lock_table_names(THD *thd, const DDL_options_st &options, if (create_table) #ifdef WITH_WSREP if (thd->lex->sql_command != SQLCOM_CREATE_TABLE && - thd->wsrep_exec_mode != REPL_RECV) + !thd->wsrep_applier) #endif lock_wait_timeout= 0; // Don't wait for timeout } @@ -4281,8 +4294,8 @@ bool open_tables(THD *thd, const DDL_options_st &options, (*start) && (*start)->table && (*start)->table->file->ht == myisam_hton && - wsrep_thd_exec_mode(thd) == LOCAL_STATE && - !is_stat_table(&(*start)->db, &(*start)->alias) && + wsrep_thd_is_local(thd) && + !is_stat_table(&(*start)->db, &(*start)->alias) && thd->get_command() != COM_STMT_PREPARE && ((thd->lex->sql_command == SQLCOM_INSERT || thd->lex->sql_command == SQLCOM_INSERT_SELECT || @@ -4293,7 +4306,10 @@ bool open_tables(THD *thd, const DDL_options_st &options, thd->lex->sql_command == SQLCOM_LOAD || thd->lex->sql_command == SQLCOM_DELETE))) { - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); + wsrep_before_rollback(thd, true); + wsrep_after_rollback(thd, true); + wsrep_after_statement(thd); + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); } error: diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a4ecdfb1297..a3cabaf7c5d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -65,10 +65,15 @@ #include "sql_parse.h" // is_update_query #include "sql_callback.h" #include "lock.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +//#include "wsrep_client_service.h" #include "wsrep_mysqld.h" +#include "wsrep_binlog.h" /* wsrep_fragment_unit() */ #include "wsrep_thd.h" #include "sql_connect.h" #include "my_atomic.h" +#endif /* WITH_WSREP */ #ifdef HAVE_SYS_SYSCALL_H #include <sys/syscall.h> @@ -533,6 +538,12 @@ char *thd_security_context(THD *thd, return thd_get_error_context_description(thd, buffer, length, max_query_len); } #endif +#ifdef WITH_WSREP +extern "C" bool wsrep_consistency_check(void *thd) +{ + return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; +} +#endif /* WITH_WSREP */ /** Implementation of Drop_table_error_handler::handle_condition(). @@ -628,6 +639,27 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) derived_tables_processing(FALSE), waiting_on_group_commit(FALSE), has_waiter(FALSE), spcont(NULL), +#ifdef WITH_WSREP + m_wsrep_mutex(LOCK_thd_data), + m_wsrep_cond(COND_wsrep_thd), + wsrep_applier(is_wsrep_applier), + wsrep_applier_closing(false), + wsrep_client_thread(false), + wsrep_apply_toi(false), + wsrep_po_handle(WSREP_PO_INITIALIZER), + wsrep_po_cnt(0), + wsrep_apply_format(0), + wsrep_ignore_table(false), + +/* wsrep-lib */ + m_wsrep_client_service(this, m_wsrep_client_state), + m_wsrep_client_state(this, + m_wsrep_mutex, + m_wsrep_cond, + Wsrep_server_state::instance(), + m_wsrep_client_service, + wsrep::client_id(thread_id)), +#endif /*WITH_WSREP */ m_parser_state(NULL), #if defined(ENABLED_DEBUG_SYNC) debug_sync_control(0), @@ -639,17 +671,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) tdc_hash_pins(0), xid_hash_pins(0), m_tmp_tables_locked(false) -#ifdef WITH_WSREP - , - wsrep_applier(is_wsrep_applier), - wsrep_applier_closing(false), - wsrep_client_thread(false), - wsrep_apply_toi(false), - wsrep_po_handle(WSREP_PO_INITIALIZER), - wsrep_po_cnt(0), - wsrep_apply_format(0), - wsrep_ignore_table(false) -#endif { ulong tmp; bzero(&variables, sizeof(variables)); @@ -771,8 +792,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) *scramble= '\0'; #ifdef WITH_WSREP - wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID; - wsrep_ws_handle.opaque = NULL; + mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); wsrep_retry_counter = 0; wsrep_PA_safe = true; wsrep_retry_query = NULL; @@ -782,9 +802,14 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; + 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 @@ -1049,10 +1074,25 @@ Sql_condition* THD::raise_condition(uint sql_errno, is_slave_error= 1; // needed to catch query errors during replication - if (!da->is_error()) +#ifdef WITH_WSREP + /* + With wsrep we allow converting BF abort error to warning if + errors are ignored. + */ + if (!is_fatal_error && + no_errors && + (wsrep_trx().bf_aborted() || wsrep_retry_counter)) { - set_row_count_func(-1); - da->set_error_status(sql_errno, msg, sqlstate, ucid, cond); + WSREP_DEBUG("BF abort error converted to warning"); + } + else +#endif /* WITH_WSREP */ + { + if (!da->is_error()) + { + set_row_count_func(-1); + da->set_error_status(sql_errno, msg, sqlstate, ucid, cond); + } } } @@ -1220,12 +1260,10 @@ void THD::init(bool skip_lock) first_successful_insert_id_in_prev_stmt_for_binlog= 0; 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; + mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); wsrep_last_query_id= 0; - wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; - wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED; + wsrep_xid.null(); + wsrep_skip_locking= FALSE; wsrep_converted_lock_session= false; wsrep_retry_counter= 0; wsrep_rgi= NULL; @@ -1234,10 +1272,17 @@ void THD::init(bool skip_lock) wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; - wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; + wsrep_rbr_buf = NULL; + wsrep_nbo_ctx = NULL; wsrep_affected_rows = 0; + m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_replicate_GTID = false; wsrep_skip_wsrep_GTID = false; + if (!wsrep_applier && variables.wsrep_trx_fragment_size) + { + wsrep_cs().enable_streaming(wsrep_fragment_unit(variables.wsrep_trx_fragment_unit), + variables.wsrep_trx_fragment_size); + } #endif /* WITH_WSREP */ if (variables.sql_log_bin) @@ -1460,12 +1505,20 @@ void THD::cleanup(void) DBUG_ASSERT(cleanup_done == 0); set_killed(KILL_CONNECTION); + DEBUG_SYNC(this, "thd_cleanup_start"); #ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE if (transaction.xid_state.xa_state == XA_PREPARED) { #error xid_state in the cache should be replaced by the allocated value } #endif +#ifdef WITH_WSREP + if (wsrep_cs().state() != wsrep::client_state::s_none) + { + wsrep_cs().cleanup(); + } + wsrep_client_thread= false; +#endif /* WITH_WSREP */ mysql_ha_cleanup(this); locked_tables_list.unlock_locked_tables(this); @@ -1582,6 +1635,10 @@ void THD::reset_for_reuse() #ifdef SIGNAL_WITH_VIO_CLOSE active_vio = 0; #endif +#ifdef WITH_WSREP + mysql_cond_destroy(&COND_wsrep_thd); + wsrep_free_status(this); +#endif /* WITH_WSREP */ } @@ -1608,15 +1665,20 @@ 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_thd_data); mysql_mutex_lock(&LOCK_thd_kill); mysql_mutex_unlock(&LOCK_thd_kill); + if (WSREP(this)) mysql_mutex_unlock(&LOCK_thd_data); -#ifdef WITH_WSREP - delete wsrep_rgi; -#endif if (!free_connection_done) free_connection(); +#ifdef WITH_WSREP + if (wsrep_rgi != NULL) { + delete wsrep_rgi; + wsrep_rgi = NULL; + } +#endif mdl_context.destroy(); free_root(&transaction.mem_root,MYF(0)); @@ -1798,6 +1860,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_thd_data); mysql_mutex_assert_owner(&LOCK_thd_kill); print_aborted_warning(3, "KILLED"); @@ -1982,14 +2045,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((const 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); @@ -2220,12 +2290,6 @@ void THD::cleanup_after_query() /* reset table map for multi-table update */ table_map_for_update= 0; m_binlog_invoker= INVOKER_NONE; -#ifdef WITH_WSREP - if (TOTAL_ORDER == wsrep_exec_mode) - { - wsrep_exec_mode = LOCAL_STATE; - } -#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY if (rgi_slave) @@ -2233,7 +2297,6 @@ void THD::cleanup_after_query() #endif #ifdef WITH_WSREP - wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; if (!in_active_multi_stmt_transaction()) wsrep_affected_rows= 0; #endif /* WITH_WSREP */ @@ -4973,11 +5036,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; @@ -5460,6 +5525,10 @@ 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 + set_wsrep_next_trx_id(query_id); + WSREP_DEBUG("assigned new next query and trx id: %lu", wsrep_next_trx_id()); +#endif /* WITH_WSREP */ } /** Assign a new value to thd->mysys_var. */ @@ -5905,9 +5974,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()) @@ -6229,7 +6316,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) 5. Error: Cannot modify table that uses a storage engine limited to row-logging when binlog_format = STATEMENT */ - if (IF_WSREP((!WSREP(this) || wsrep_exec_mode == LOCAL_STATE),1)) + if (IF_WSREP((!WSREP(this) || + wsrep_cs().mode() == wsrep::client_state::m_local),1)) { my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), ""); } diff --git a/sql/sql_class.h b/sql/sql_class.h index d8f0a794222..c97c1d55c1a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -61,8 +61,18 @@ void set_thd_stage_info(void *thd, #include "my_apc.h" #include "rpl_gtid.h" + +#ifdef WITH_WSREP +/* wsrep-lib */ +#include "wsrep_client_service.h" +#include "wsrep_client_state.h" +#include "wsrep_mutex.h" +#include "wsrep_condition_variable.h" + #include "wsrep_mysqld.h" +class Wsrep_applier_service; +#endif class Reprepare_observer; class Relay_log_info; struct rpl_group_info; @@ -706,10 +716,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; @@ -3208,7 +3220,6 @@ class THD :public Statement, 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. @@ -3216,7 +3227,6 @@ class THD :public Statement, query_id_t first_query_id; } binlog_evt_union; - mysql_cond_t COND_wsrep_thd; /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser @@ -3299,9 +3309,15 @@ class THD :public Statement, void awake_no_mutex(killed_state state_to_set); void awake(killed_state state_to_set) { + /* + mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires + to grab LOCK_thd_data here + */ + mysql_mutex_lock(&LOCK_thd_data); mysql_mutex_lock(&LOCK_thd_kill); awake_no_mutex(state_to_set); mysql_mutex_unlock(&LOCK_thd_kill); + mysql_mutex_unlock(&LOCK_thd_data); } /** Disconnect the associated communication endpoint. */ @@ -4480,6 +4496,13 @@ class THD :public Statement, void set_query_id(query_id_t new_query_id) { query_id= new_query_id; +#ifdef WITH_WSREP + if (WSREP(this)) + { + 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) { @@ -4739,48 +4762,112 @@ class THD :public Statement, } #ifdef WITH_WSREP - const bool wsrep_applier; /* dedicated slave applier thread */ + 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; - wsrep_trx_meta_t wsrep_trx_meta; + 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; + + mysql_cond_t COND_wsrep_thd; + + // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 uint32 wsrep_rand; - Relay_log_info *wsrep_rli; rpl_group_info *wsrep_rgi; - wsrep_ws_handle_t wsrep_ws_handle; + bool wsrep_converted_lock_session; + char wsrep_info[128]; /* string for dynamic 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; + std::vector<wsrep::provider::status_variable> 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 */ + bool wsrep_apply_toi; /* applier processing in TOI */ + 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; + /* When enabled, do not replicate/binlog updates from the current table that's being processed. At the moment, it is used to keep mysql.gtid_slave_pos table updates from being replicated to other nodes via galera replication. */ bool wsrep_ignore_table; - wsrep_gtid_t wsrep_sync_wait_gtid; - ulong wsrep_affected_rows; - bool wsrep_replicate_GTID; - bool wsrep_skip_wsrep_GTID; + + + /* + 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() + 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 m_wsrep_client_state.transaction().id().get(); + } + + + /* + Set next trx id + */ + void set_wsrep_next_trx_id(query_id_t query_id) + { + 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 */ + /* wsrep-lib */ + Wsrep_mutex m_wsrep_mutex; + Wsrep_condition_variable m_wsrep_cond; + Wsrep_client_service m_wsrep_client_service; + Wsrep_client_state m_wsrep_client_state; + +public: + Wsrep_client_state& wsrep_cs() { return m_wsrep_client_state; } + const Wsrep_client_state& wsrep_cs() const { return m_wsrep_client_state; } + const wsrep::transaction& wsrep_trx() const + { return m_wsrep_client_state.transaction(); } + const wsrep::streaming_context& wsrep_sr() const + { return m_wsrep_client_state.transaction().streaming_context(); } + /* Pointer to applier service for streaming THDs. This is needed to + be able to delete applier service object in case of background + rollback. */ + Wsrep_applier_service* wsrep_applier_service; #endif /* WITH_WSREP */ /* Handling of timeouts for commands */ @@ -6271,7 +6358,7 @@ class select_dumpvar :public select_result_interceptor { 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. @@ -6289,7 +6376,7 @@ class select_dumpvar :public select_result_interceptor { 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. @@ -6333,6 +6420,13 @@ class select_dumpvar :public select_result_interceptor { */ #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..90cb7e9d76f 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -37,7 +37,11 @@ // reset_host_errors #include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL #include "sql_callback.h" + +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" /* wsrep open/close */ #include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ #include "proxy_protocol.h" HASH global_user_stats, global_client_stats, global_table_stats; @@ -1177,17 +1181,6 @@ bool login_connection(THD *thd) void end_connection(THD *thd) { NET *net= &thd->net; -#ifdef WITH_WSREP - if (WSREP(thd)) - { - wsrep_status_t rcode= wsrep->free_connection(wsrep, thd->thread_id); - if (rcode) { - WSREP_WARN("wsrep failed to free connection context: %lld code: %d", - (longlong) thd->thread_id, rcode); - } - } - thd->wsrep_client_thread= 0; -#endif plugin_thdvar_cleanup(thd); if (thd->user_connect) @@ -1322,7 +1315,7 @@ bool thd_prepare_connection(THD *thd) prepare_new_connection_state(thd); #ifdef WITH_WSREP - thd->wsrep_client_thread= 1; + thd->wsrep_client_thread= true; #endif /* WITH_WSREP */ return FALSE; } @@ -1384,7 +1377,6 @@ void do_handle_one_connection(CONNECT *connect) thd->thread_stack= (char*) &thd; if (setup_connection_thread_globals(thd)) return; - for (;;) { bool create_user= TRUE; @@ -1395,6 +1387,9 @@ void do_handle_one_connection(CONNECT *connect) create_user= FALSE; goto end_thread; } +#ifdef WITH_WSREP + wsrep_open(thd); +#endif /* WITH_WSREP */ while (thd_is_connection_alive(thd)) { @@ -1405,13 +1400,9 @@ void do_handle_one_connection(CONNECT *connect) end_connection(thd); #ifdef WITH_WSREP - if (WSREP(thd)) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_EXITING; - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif + wsrep_close(thd); +#endif /* WITH_WSREP */ + end_thread: close_connection(thd); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 51acf10a98a..ff4ebc8d986 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -82,6 +82,11 @@ #include "debug_sync.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#include "wsrep_trans_observer.h" /* wsrep_start_transction() */ +#endif /* WITH_WSREP */ + #ifndef EMBEDDED_LIBRARY static bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, TABLE_LIST *table_list); @@ -3902,10 +3907,13 @@ 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)); +#ifdef WITH_WSREP + error= (thd->wsrep_cs().current_error()) ? -1 : + (thd->locked_tables_mode <= LTM_LOCK_TABLES) ? +#else + error= (thd->locked_tables_mode <= LTM_LOCK_TABLES) ? +#endif /* WITH_WSREP */ + table->file->ha_end_bulk_insert() : 0; if (likely(!error) && unlikely(thd->is_error())) error= thd->get_stmt_da()->sql_errno(); @@ -4504,9 +4512,10 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) /* suppress_use */ FALSE, errcode); } - - ha_fake_trx_id(thd); - +#ifdef WITH_WSREP + // ha_wsrep_fake_trx_id(thd); + wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); +#endif return result; } @@ -4564,54 +4573,59 @@ bool select_create::send_eof() if (!table->s->tmp_table) { #ifdef WITH_WSREP - if (WSREP_ON) + if (WSREP(thd)) { - /* - append table level exclusive key for CTAS - */ - wsrep_key_arr_t key_arr= {0, 0}; - wsrep_prepare_keys_for_isolation(thd, - create_table->db.str, - 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); - wsrep_keys_free(&key_arr); - if (rcode) { - DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); - WSREP_ERROR("Appending table key for CTAS failed: %s, %d", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void", rcode); - return true; - } - /* If commit fails, we should be able to reset the OK status. */ - thd->get_stmt_da()->set_overwrite_status(TRUE); + if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); + } + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + WSREP_DEBUG("CTAS key append for trx: %lu thd %lu query %lld ", + thd->wsrep_trx_id(), thd->thread_id, thd->query_id); + + /* + append table level exclusive key for CTAS + */ + wsrep_key_arr_t key_arr= {0, 0}; + wsrep_prepare_keys_for_isolation(thd, + create_table->db.str, + create_table->table_name.str, + table_list, + &key_arr); + int rcode= wsrep_thd_append_key(thd, key_arr.keys, key_arr.keys_len, + wsrep_key_exclusive); + wsrep_keys_free(&key_arr); + if (rcode) + { + DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); + WSREP_ERROR("Appending table key for CTAS failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + DBUG_RETURN(true); + } + /* If commit fails, we should be able to reset the OK status. */ + thd->get_stmt_da()->set_overwrite_status(true); } #endif /* WITH_WSREP */ trans_commit_stmt(thd); if (!(thd->variables.option_bits & OPTION_GTID_BEGIN)) trans_commit_implicit(thd); #ifdef WITH_WSREP - if (WSREP_ON) + if (WSREP(thd)) { thd->get_stmt_da()->set_overwrite_status(FALSE); mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state != NO_CONFLICT) + if (thd->wsrep_trx().state() != wsrep::transaction::s_executing) { - WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s", - (longlong) thd->thread_id, thd->wsrep_conflict_state, - thd->query()); - mysql_mutex_unlock(&thd->LOCK_thd_data); - abort_result_set(); - DBUG_RETURN(true); + WSREP_DEBUG("select_create commit failed, thd: %lu err: %s %s", + thd->thread_id, wsrep_thd_transaction_state_str(thd), + WSREP_QUERY(thd)); + mysql_mutex_unlock(&thd->LOCK_thd_data); + abort_result_set(); + DBUG_RETURN(true); } mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->wsrep_cs().after_statement(); } #endif /* WITH_WSREP */ } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4a5aedcfbd0..2cb9b0e2115 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -32,6 +32,9 @@ #include "sql_cte.h" #include "sql_signal.h" #include "sql_partition.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif /* WITH_WSREP*/ void LEX::parse_error(uint err_number) @@ -1828,7 +1831,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) else { #ifdef WITH_WSREP - if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE) + if (WSREP(thd) && version == 99997 && wsrep_thd_is_local(thd)) { WSREP_DEBUG("consistency check: %s", thd->query()); thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED; 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 aa669f42c6f..71bdec30a08 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -109,10 +109,12 @@ #include "../storage/maria/ha_maria.h" #endif +#include "mysql/service_wsrep.h" #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); @@ -880,6 +882,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) @@ -1177,6 +1189,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; @@ -1185,7 +1198,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 @@ -1215,19 +1228,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) @@ -1268,29 +1268,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)) { @@ -1298,20 +1275,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,10 +1328,11 @@ bool do_command(THD *thd) if (WSREP(thd)) { /* - Bail out if DB snapshot has not been installed. - */ - if (!thd->wsrep_applier && - (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) && + * bail out if DB snapshot has not been installed. We however, + * allow queries "SET" and "SHOW", they are trapped later in execute_command + */ + if (!(thd->wsrep_applier) && + (!wsrep_ready_get() || wsrep_reject_queries != WSREP_REJECT_NONE) && (server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0) { my_message(ER_UNKNOWN_COM_ERROR, @@ -1384,7 +1348,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); @@ -1393,37 +1357,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: @@ -1496,6 +1429,36 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables) DBUG_RETURN(FALSE); } +#ifdef WITH_WSREP +static my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables) +{ + int opt_readonly_saved = opt_readonly; + ulong flag_saved = (ulong)(thd->security_ctx->master_access & SUPER_ACL); + + opt_readonly = 0; + thd->security_ctx->master_access &= ~SUPER_ACL; + + my_bool ret = !deny_updates_if_read_only_option(thd, all_tables); + + opt_readonly = opt_readonly_saved; + thd->security_ctx->master_access |= flag_saved; + + return ret; +} + +static void wsrep_copy_query(THD *thd) +{ + thd->wsrep_retry_command = thd->get_command(); + thd->wsrep_retry_query_len = thd->query_length(); + if (thd->wsrep_retry_query) { + my_free(thd->wsrep_retry_query); + } + thd->wsrep_retry_query = (char *)my_malloc( + thd->wsrep_retry_query_len + 1, MYF(0)); + strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len); + thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0'; +} +#endif /* WITH_WSREP */ /** check COM_MULTI packet @@ -1579,38 +1542,28 @@ bool dispatch_command(enum enum_server_command command, THD *thd, compile_time_assert(COM_END == 255); #ifdef WITH_WSREP - if (WSREP(thd)) + int err= wsrep_before_command(thd); + /* + Aborted by background rollbacker thread. Jump straight to dispatch_end + label where the error handling is performed. + */ + if (err) { - if (!thd->in_multi_stmt_transaction_mode()) - { - thd->wsrep_PA_safe= true; - } - - 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); - } + thd->store_globals(); + WSREP_LOG_THD(thd, "enter found BF aborted"); + DBUG_ASSERT(!thd->mdl_context.has_locks()); + DBUG_ASSERT(!thd->get_stmt_da()->is_set()); /* 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) + if (command != COM_STMT_CLOSE && + command != COM_QUIT) { - mysql_mutex_unlock(&thd->LOCK_thd_data); - my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", - MYF(0)); + my_error(ER_LOCK_DEADLOCK, MYF(0)); WSREP_DEBUG("Deadlock error for: %s", thd->query()); thd->reset_killed(); thd->mysys_var->abort = 0; - thd->wsrep_conflict_state = NO_CONFLICT; thd->wsrep_retry_counter = 0; goto dispatch_end; } - mysql_mutex_unlock(&thd->LOCK_thd_data); } #endif /* WITH_WSREP */ #if defined(ENABLED_PROFILING) @@ -1659,6 +1612,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); @@ -1843,8 +1803,27 @@ 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_thd_data); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; + thd->wsrep_retry_counter = 0; + mysql_mutex_unlock(&thd->LOCK_thd_data); +#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); @@ -1933,8 +1912,28 @@ 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_thd_data); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; + thd->wsrep_retry_counter = 0; + mysql_mutex_unlock(&thd->LOCK_thd_data); +#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); @@ -2372,7 +2371,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #ifdef WITH_WSREP dispatch_end: - + /* + BF aborted before sending response back to client + */ + wsrep_after_command_before_result(thd); + if (wsrep_current_error(thd) && + !(command == COM_STMT_PREPARE || + command == COM_STMT_FETCH || + command == COM_STMT_SEND_LONG_DATA || + command == COM_STMT_CLOSE + )) + { + /* todo: Pass wsrep client state current error to override */ + wsrep_override_error(thd, wsrep_current_error(thd), + wsrep_current_error_status(thd)); + WSREP_LOG_THD(thd, "leave"); + } if (WSREP(thd)) { /* @@ -2383,8 +2397,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, || 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; + do_end_of_statement= + thd->wsrep_trx().state() != wsrep::transaction::s_replaying; +#ifdef TODO + thd->wsrep_conflict_state != REPLAYING && + thd->wsrep_conflict_state != RETRY_AUTOCOMMIT; +#endif mysql_mutex_unlock(&thd->LOCK_thd_data); } else @@ -2407,9 +2425,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, query_cache_end_of_result(thd); } } - if (drop_more_results) - thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; - + if (likely(!thd->is_error() && !thd->killed_errno())) mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); @@ -2457,6 +2473,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Check that some variables are reset properly */ DBUG_ASSERT(thd->abort_on_warning == 0); thd->lex->restore_set_statement_var(); +#ifdef WITH_WSREP + wsrep_after_command_after_result(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -3418,7 +3437,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 @@ -3448,8 +3467,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) && + !(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) && @@ -3614,7 +3633,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 @@ -3637,6 +3656,13 @@ mysql_execute_command(THD *thd) } } thd->transaction.stmt.mark_trans_did_ddl(); +#ifdef WITH_WSREP + /* Clean up the previous transaction on implicit commit */ + if (wsrep_thd_is_local(thd) && wsrep_after_statement(thd)) + { + goto error; + } +#endif /* WITH_WSREP */ } #ifndef DBUG_OFF @@ -3685,6 +3711,37 @@ 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); + } + + /* + Always start a new transaction for a wsrep THD unless the + current command is DDL or explicit BEGIN. This will guarantee that + the THD is BF abortable even if it does not generate any + changes and takes only read locks. If the statement does not + start a multi STMT transaction, the wsrep_transaction is + committed as empty at the end of this function. + + Transaction is started for BEGIN in trans_begin(), for DDL the + implicit commit took care of committing previous transaction + above and a new transaction should not be started. + */ + if (WSREP(thd) && + wsrep_thd_is_local(thd) && + lex->sql_command != SQLCOM_BEGIN && + !(sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS)) + { + wsrep_start_trx_if_not_started(thd); + } +#endif /* WITH_WSREP */ + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -3746,12 +3803,16 @@ 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) + 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; /* @@ -4554,9 +4615,7 @@ mysql_execute_command(THD *thd) 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; @@ -4705,9 +4764,7 @@ mysql_execute_command(THD *thd) 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 @@ -4765,9 +4822,7 @@ mysql_execute_command(THD *thd) 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; @@ -4887,9 +4942,7 @@ mysql_execute_command(THD *thd) 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; @@ -4949,9 +5002,7 @@ mysql_execute_command(THD *thd) 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; @@ -5767,6 +5818,7 @@ mysql_execute_command(THD *thd) 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); @@ -5806,20 +5858,7 @@ mysql_execute_command(THD *thd) thd->set_killed(KILL_CONNECTION); thd->print_aborted_warning(3, "RELEASE"); } -#ifdef WITH_WSREP - if (WSREP(thd)) { - - if (thd->wsrep_conflict_state == NO_CONFLICT || - thd->wsrep_conflict_state == REPLAYING) - { - my_ok(thd); - } - } else { -#endif /* WITH_WSREP */ - my_ok(thd); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ + my_ok(thd); break; } case SQLCOM_ROLLBACK: @@ -5855,17 +5894,7 @@ mysql_execute_command(THD *thd) /* Disconnect the current client connection. */ if (tx_release) thd->set_killed(KILL_CONNECTION); -#ifdef WITH_WSREP - if (WSREP(thd)) { - if (thd->wsrep_conflict_state == NO_CONFLICT) { - my_ok(thd); - } - } else { -#endif /* WITH_WSREP */ - my_ok(thd); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ + my_ok(thd); break; } case SQLCOM_RELEASE_SAVEPOINT: @@ -6309,6 +6338,17 @@ mysql_execute_command(THD *thd) 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(); @@ -6335,25 +6375,6 @@ mysql_execute_command(THD *thd) 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. */ @@ -6369,9 +6390,6 @@ mysql_execute_command(THD *thd) /* 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 @@ -6433,9 +6451,10 @@ mysql_execute_command(THD *thd) 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. */ @@ -6448,11 +6467,31 @@ mysql_execute_command(THD *thd) (longlong) thd->thread_id); thd->mdl_context.release_transactional_locks(); } + + /* + Current command did not start multi STMT transaction and the command + did not cause commit to happen (e.g. read only). Commit the wsrep + transaction as empty. + */ + if (!thd->in_active_multi_stmt_transaction() && + thd->wsrep_trx().active() && + thd->wsrep_trx().state() == wsrep::transaction::s_executing) + { + wsrep_commit_empty(thd, true); + } + + + /* + 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) { @@ -6572,12 +6611,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); @@ -6596,6 +6635,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; } @@ -7617,6 +7658,7 @@ void THD::reset_for_next_command(bool do_clear_error) stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; #ifdef WITH_WSREP + THD *thd= this; /* Autoinc variables should be adjusted only for locally executed transactions. Appliers and replayers are either processing ROW @@ -7625,8 +7667,8 @@ void THD::reset_for_next_command(bool do_clear_error) use autoinc values passed in binlog events, not the values forced by the cluster. */ - if (WSREP(this) && wsrep_exec_mode == LOCAL_STATE && - !slave_thread && wsrep_auto_increment_control) + if (WSREP(thd) && wsrep_thd_is_local(thd) && + !thd->slave_thread && wsrep_auto_increment_control) { variables.auto_increment_offset= global_system_variables.auto_increment_offset; @@ -7843,144 +7885,157 @@ 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, +#ifdef WITH_WSREP +static void wsrep_prepare_for_autocommit_retry(THD* thd, + char* rawbuf, + uint length, + Parser_state* parser_state) +{ + thd->clear_error(); + close_thread_tables(thd); + thd->wsrep_retry_counter++; // grow + wsrep_copy_query(thd); + thd->set_time(); + parser_state->reset(rawbuf, length); + + /* 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()) + { + 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.str : ""), + &thd->security_ctx->priv_user[0], + (char *) thd->security_ctx->host_or_ip); + + /* Performance Schema Interface instrumentation, begin */ + thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi, + com_statement_info[thd->get_command()].m_key); + MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), + thd->query_length()); + + DBUG_ASSERT(thd->wsrep_trx().active() == false); + thd->wsrep_cs().reset_error(); + thd->set_query_id(next_query_id()); +} + +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 bool is_autocommit= !thd->in_multi_stmt_transaction_mode() && - thd->wsrep_conflict_state == NO_CONFLICT && - !thd->wsrep_applier; - + wsrep_read_only_option(thd, thd->lex->query_tables); + bool retry_autocommit; do { - if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) - { - thd->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); - MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), - thd->query_length()); - - DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit", - { - const char act[]= - "now " - "SIGNAL wsrep_retry_autocommit_reached " - "WAIT_FOR wsrep_retry_autocommit_continue"; - DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); - }); + retry_autocommit= false; + DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit", + { + const char act[]= + "now " + "SIGNAL wsrep_retry_autocommit_reached " + "WAIT_FOR wsrep_retry_autocommit_continue"; + DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); + }); WSREP_DEBUG("Retry autocommit query: %s", thd->query()); - } - - mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, - is_next_command); + mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, is_next_command); - if (WSREP(thd)) { - /* wsrep BF abort in query exec phase */ - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) { - wsrep_client_rollback(thd); - WSREP_DEBUG("abort in exec query state, avoiding autocommit"); - } + /* + Convert all ER_QUERY_INTERRUPTED errors to ER_LOCK_DEADLOCK + if the transaction was BF aborted. This can happen when the + transaction is being BF aborted via thd->awake() while it is + still executing. - if (thd->wsrep_conflict_state == MUST_REPLAY) - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - if (thd->lex->explain) - delete_explain_query(thd->lex); - mysql_mutex_lock(&thd->LOCK_thd_data); + Note that this must be done before wsrep_after_statement() call + since it clears the transaction for autocommit queries. + */ + if (((thd->get_stmt_da()->is_error() && + thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED) || + !thd->get_stmt_da()->is_set()) && + thd->wsrep_trx().bf_aborted()) + { + WSREP_DEBUG("overriding error: %d with DEADLOCK", + (thd->get_stmt_da()->is_error()) ? + thd->get_stmt_da()->sql_errno() : 0); - wsrep_replay_transaction(thd); - } + thd->killed = NOT_KILLED; + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + } - /* setting error code for BF aborted trxs */ - if (thd->wsrep_conflict_state == ABORTED || - thd->wsrep_conflict_state == CERT_FAILURE) + if (wsrep_after_statement(thd) && is_autocommit) + { + thd->reset_for_next_command(); + thd->killed= NOT_KILLED; + if (is_autocommit && + thd->lex->sql_command != SQLCOM_SELECT && + thd->wsrep_retry_counter < thd->variables.wsrep_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)) - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - WSREP_DEBUG("wsrep retrying AC query: %s", - (thd->query()) ? thd->query() : "void"); - - /* Performance Schema Interface instrumentation, end */ - MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); - thd->m_statement_psi= NULL; - thd->m_digest= NULL; - // Released thd->LOCK_thd_data above as below could end up - // close_thread_tables()/close_open_tables()/close_thread_table()/mysql_mutex_lock(&thd->LOCK_thd_data) - close_thread_tables(thd); - - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; - thd->wsrep_retry_counter++; // grow - wsrep_copy_query(thd); - thd->set_time(); - parser_state->reset(rawbuf, length); - mysql_mutex_unlock(&thd->LOCK_thd_data); - } - else - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - // This does dirty read to wsrep variables but it is only a debug code - WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", - (thd->wsrep_conflict_state == 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)); - - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->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(); + WSREP_DEBUG("wsrep retrying AC query: %lu %s", + thd->wsrep_retry_counter, WSREP_QUERY(thd)); + wsrep_prepare_for_autocommit_retry(thd, rawbuf, length, parser_state); + if (thd->lex->explain) + delete_explain_query(thd->lex); + retry_autocommit= true; } else { - set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok - mysql_mutex_unlock(&thd->LOCK_thd_data); + WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + wsrep_thd_transaction_state_str(thd), + thd->thread_id, + is_autocommit, + thd->wsrep_retry_counter, + thd->variables.wsrep_retry_autocommit, + WSREP_QUERY(thd)); + my_error(ER_LOCK_DEADLOCK, MYF(0)); + thd->killed= NOT_KILLED; + thd->wsrep_retry_counter= 0; // reset } } - - /* If retry is requested clean up explain structure */ - if ((thd->wsrep_conflict_state == RETRY_AUTOCOMMIT || - thd->wsrep_conflict_state == MUST_REPLAY ) - && thd->lex->explain) + else { - delete_explain_query(thd->lex); + set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok } - - } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT); + } while (retry_autocommit); 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(), + WSREP_DEBUG("releasing retry_query: " + "conf %s sent %d kill %d errno %d SQL %s", + wsrep_thd_transaction_state_str(thd), + 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; thd->wsrep_retry_query_len = 0; thd->wsrep_retry_command = COM_CONNECT; } -#endif /* WITH_WSREP */ + return false; } +#endif /* WITH_WSREP */ /* @@ -8932,6 +8987,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_thd_data); mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete break; } @@ -8960,7 +9016,8 @@ 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); +#ifdef WITH_WSREP if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY))) { /* @@ -8986,15 +9043,22 @@ 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) && !tmp->wsrep_applier) +#else + if ((thd->security_ctx->master_access & SUPER_ACL) || + thd->security_ctx->user_matches(tmp->security_ctx)) +#endif /* WITH_WSREP */ { + //if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data); tmp->awake_no_mutex(kill_signal); + //if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_thd_data); 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_thd_data); } DBUG_PRINT("exit", ("%d", error)); DBUG_RETURN(error); @@ -9052,7 +9116,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_thd_data); mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete + } } } mysql_mutex_unlock(&LOCK_thread_count); @@ -9074,6 +9141,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_thd_data); (*rows)++; } while ((ptr= next_ptr)); } diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 1027872898a..ef8f2a11ee0 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -18,6 +18,10 @@ #include "sql_acl.h" /* GLOBAL_ACLS */ +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif /* WITH_WSREP */ + class Comp_creator; class Item; class Object_creation_ctx; @@ -37,6 +41,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..8f48a6d1b7f 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) @@ -2832,7 +2837,6 @@ sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length, plugin_ref plugin; DBUG_ENTER("find_sys_var_ex"); DBUG_PRINT("enter", ("var '%.*s'", (int)length, str)); - if (!locked) mysql_mutex_lock(&LOCK_plugin); mysql_prlock_rdlock(&LOCK_system_variables_hash); diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 8de53aa2161..3749a6b6101 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -142,7 +142,6 @@ static struct thd_error_context_service_st thd_error_context_handler= { }; static struct wsrep_service_st wsrep_handler = { - get_wsrep, get_wsrep_certify_nonPK, get_wsrep_debug, get_wsrep_drupal_282555_workaround, @@ -150,38 +149,23 @@ 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, + get_wsrep_xid_seqno, + get_wsrep_xid_uuid, 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_conflict_state_str, - wsrep_thd_exec_mode, - wsrep_thd_exec_mode_str, - wsrep_thd_get_conflict_state, - wsrep_thd_is_BF, - wsrep_thd_is_wsrep, + wsrep_thd_thread_id, + wsrep_thd_is_wsrep_on, wsrep_thd_query, - wsrep_thd_query_state, - wsrep_thd_query_state_str, - wsrep_thd_retry_counter, - wsrep_thd_set_conflict_state, wsrep_thd_ignore_table, wsrep_thd_trx_seqno, - wsrep_thd_ws_handle, - wsrep_trx_is_aborting, + wsrep_thd_is_aborting, wsrep_trx_order_before, - wsrep_unlock_rollback, + wsrep_thd_xid, wsrep_set_data_home_dir }; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 09d31470a00..c50ae14025d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4206,30 +4206,6 @@ Prepared_statement::execute_loop(String *expanded_query, error= execute(expanded_query, open_cursor) || thd->is_error(); thd->m_reprepare_observer= NULL; -#ifdef WITH_WSREP - - if (WSREP_ON) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - 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; - break; - - case MUST_REPLAY: - (void) wsrep_replay_transaction(thd); - break; - - default: - break; - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ if (unlikely(error) && (sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) && @@ -4402,30 +4378,6 @@ Prepared_statement::execute_bulk_loop(String *expanded_query, error= execute(expanded_query, open_cursor) || thd->is_error(); thd->m_reprepare_observer= NULL; -#ifdef WITH_WSREP - - if (WSREP_ON) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - 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; - break; - - case MUST_REPLAY: - (void) wsrep_replay_transaction(thd); - break; - - default: - break; - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ if (unlikely(error) && (sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) && 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 b04d869bf1d..a8db937f6c3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2646,7 +2646,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, 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(), @@ -2697,7 +2697,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, end: #ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = false; + thd->wsrep_skip_wsrep_GTID = false; #endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -7559,6 +7559,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); @@ -9781,6 +9794,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_trigger.cc b/sql/sql_trigger.cc index fd128f8dc1c..a14f3473c12 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -517,7 +517,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) } #ifdef WITH_WSREP - if (thd->wsrep_exec_mode == LOCAL_STATE) + // if (thd->wsrep_exec_mode == LOCAL_STATE) WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); #endif diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 798e929170c..7b9ed483755 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -419,9 +419,20 @@ 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. + */ + if (WSREP(thd) && thd->wsrep_nbo_ctx) { + hton_can_recreate= false; + } + else + { + 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 6d2dbbf646e..1d015e42683 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5404,7 +5404,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", @@ -5441,7 +5441,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), @@ -5491,7 +5491,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)); @@ -5511,12 +5511,46 @@ 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), + ON_UPDATE(wsrep_trx_fragment_size_update)); + +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 08b71114310..01fad6c388d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -250,6 +250,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/table_cache.cc b/sql/table_cache.cc index 682f9455d26..8b8f66c057f 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -1141,8 +1141,38 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, All_share_tables_list::Iterator it(element->all_tables); while ((table= it++)) { - if (table->in_use == thd) +#ifdef WITH_WSREP + if (remove_type == TDC_RT_REMOVE_ALL || + remove_type == TDC_RT_REMOVE_NOT_OWN || + remove_type == TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE) + { + if (table->in_use != thd) + { + /* + We may end up here if we were granted some MDL + lock even if another thd was already granted. + In that case we expect their wsrep_conflict_state + to be either ABORTING or CERT_FAILURE. + See wsrep_grant_mdl_exception() + */ + enum wsrep::transaction::state state= + table->in_use->wsrep_trx().state(); + if (state == wsrep::transaction::s_cert_failed || + state == wsrep::transaction::s_aborting) + { + WSREP_DEBUG("Table_cache_manager::free_table assert skipped"); + } + else + { + DBUG_ASSERT(0); + } + } + } + my_refs++; +#else my_refs++; + +#endif /* WITH_WSREP */ } } mysql_mutex_unlock(&element->LOCK_table_share); diff --git a/sql/transaction.cc b/sql/transaction.cc index 1c2820200d1..6d5cba859aa 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -24,6 +24,9 @@ #include "debug_sync.h" // DEBUG_SYNC #include "sql_acl.h" #include "semisync_master.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY /** @@ -135,8 +138,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 +185,16 @@ 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); +#ifdef WITH_WSREP + if (wsrep_thd_is_local(thd)) + { + res= res || wsrep_after_statement(thd); + } +#endif /* WITH_WSREP */ } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -252,9 +255,14 @@ 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); + if (wsrep_thd_is_local(thd)) + { + if (wsrep_sync_wait(thd)) + DBUG_RETURN(TRUE); + if (!thd->tx_read_only && + wsrep_start_transaction(thd, thd->wsrep_next_trx_id())) + DBUG_RETURN(TRUE); + } #endif /* WITH_WSREP */ thd->variables.option_bits|= OPTION_BEGIN; @@ -299,8 +307,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 +317,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 +372,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 +409,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 +419,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 +511,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 +570,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 +723,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 +935,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 +956,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 1f50ee55711..4321d332215 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -14,12 +14,17 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mariadb.h" +#include "mysql/service_wsrep.h" +#include "wsrep_applier.h" + #include "wsrep_priv.h" #include "wsrep_binlog.h" // wsrep_dump_rbr_buf() #include "wsrep_xid.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" /* @@ -27,7 +32,6 @@ At the end (*buf) is shitfed to point to the following event or NULL and (*buf_len) will be changed to account just being read bytes of the 1st event. */ - static Log_event* wsrep_read_log_event( char **arg_buf, size_t *arg_buf_len, const Format_description_log_event *description_event) @@ -62,12 +66,13 @@ 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; } -Format_description_log_event* wsrep_get_apply_format(THD* thd) +Format_description_log_event* +wsrep_get_apply_format(THD* thd) { if (thd->wsrep_apply_format) { @@ -79,45 +84,77 @@ 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) { - char *buf= (char *)events_buf; - int rcode= 0; - int event= 1; - Log_event_type typ; + Diagnostics_area::Sql_condition_iterator it= + thd->get_stmt_da()->sql_conditions(); + const Sql_condition* cond; - DBUG_ENTER("wsrep_apply_events"); + 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 */ + } - if (thd->killed == KILL_CONNECTION && - thd->wsrep_conflict_state != REPLAYING) + 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++) { - WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", - (long long) wsrep_thd_trx_seqno(thd)); - DBUG_RETURN(WSREP_CB_FAILURE); + 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); } - 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); + *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, + Relay_log_info* rli, + const void* events_buf, + size_t buf_len) +{ + char *buf= (char *)events_buf; + int rcode= 0; + int event= 1; + Log_event_type typ; + DBUG_ENTER("wsrep_apply_events"); if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", (long long) wsrep_thd_trx_seqno(thd)); - while(buf_len) + while (buf_len) { int exec_res; Log_event* ev= wsrep_read_log_event(&buf, &buf_len, - wsrep_get_apply_format(thd)); - + wsrep_get_apply_format(thd)); if (!ev) { 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; } @@ -147,9 +184,6 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, thd->set_server_id(ev->server_id); thd->set_time(); // time the query thd->transaction.start_time.reset(thd); - 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) { @@ -168,7 +202,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; @@ -178,230 +212,14 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, } event++; - 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)); - - if (thd->wsrep_conflict_state == MUST_ABORT) { - WSREP_WARN("RBR 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); - } - 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); - +error: 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); -} - -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) -{ - THD* const thd((THD*)ctx); - - assert(thd->wsrep_apply_toi == false); - - // Allow tests to block the applier thread using the DBUG facilities. - DBUG_EXECUTE_IF("sync.wsrep_apply_cb", - { - const char act[]= - "now " - "SIGNAL sync.wsrep_apply_cb_reached " - "WAIT_FOR signal.wsrep_apply_cb"; - DBUG_ASSERT(!debug_sync_set_action(thd, - 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) - thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS; - else - thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; - - 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; - - if (flags & WSREP_FLAG_ISOLATION) - { - 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_cb_status_t rcode(wsrep_apply_events(thd, buf, buf_len)); - -#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 */ - - if (WSREP_CB_SUCCESS != rcode) - { - wsrep_dump_rbr_buf_with_header(thd, buf, buf_len); - } - - if (thd->has_thd_temporary_tables()) - { - WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..", - thd->thread_id); - thd->close_temporary_tables(); - } - - return rcode; -} - -static wsrep_cb_status_t wsrep_commit(THD* const thd) -{ -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Committing %lld", (long long)wsrep_thd_trx_seqno(thd)); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Committing"); -#endif /* WSREP_PROC_INFO */ - - wsrep_cb_status_t const rcode(trans_commit(thd) ? - WSREP_CB_FAILURE : WSREP_CB_SUCCESS); - - if (WSREP_CB_SUCCESS == rcode) - { - thd->wsrep_rgi->cleanup_context(thd, false); -#ifdef GTID_SUPPORT - thd->variables.gtid_next.set_automatic(); -#endif /* GTID_SUPPORT */ - if (thd->wsrep_apply_toi) - { - wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, - thd->wsrep_trx_meta.gtid.seqno); - } - } - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Committed %lld", (long long) wsrep_thd_trx_seqno(thd)); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Committed"); -#endif /* WSREP_PROC_INFO */ - - return rcode; -} - -static wsrep_cb_status_t wsrep_rollback(THD* const 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 */ - - wsrep_cb_status_t const rcode(trans_rollback(thd) ? - WSREP_CB_FAILURE : WSREP_CB_SUCCESS); - -#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 */ - - return rcode; -} - -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); - - assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd)); - - wsrep_cb_status_t rcode; - - if (commit) - rcode = wsrep_commit(thd); - else - rcode = wsrep_rollback(thd); - - /* 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) - { - mysql_mutex_lock(&LOCK_wsrep_slave_threads); - if (wsrep_slave_count_change < 0) - { - wsrep_slave_count_change++; - *exit = true; - } - mysql_mutex_unlock(&LOCK_wsrep_slave_threads); - } - - if (thd->wsrep_applier) - { - /* From trans_begin() */ - thd->variables.option_bits|= OPTION_BEGIN; - thd->server_status|= SERVER_STATUS_IN_TRANS; - thd->wsrep_apply_toi= false; - } - - return rcode; -} - - -wsrep_cb_status_t wsrep_unordered_cb(void* const ctx, - const void* const data, - size_t const size) -{ - return WSREP_CB_SUCCESS; + DBUG_RETURN(rcode); } diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h index f19d2d46d0c..875c025785b 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,56 @@ #include <my_config.h> #include "../wsrep/wsrep_api.h" -void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev); -Format_description_log_event* wsrep_get_apply_format(THD* thd); +#include "sql_class.h" // THD class + +int wsrep_apply_events(THD* thd, + Relay_log_info* rli, + 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); +/* 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 -wsrep_cb_status_t wsrep_commit_cb(void *ctx, - uint32_t flags, - const wsrep_trx_meta_t* meta, - wsrep_bool_t* exit, - bool commit); +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_; +}; + +class Format_description_log_event; +void wsrep_set_apply_format(THD*, Format_description_log_event*); +Format_description_log_event* wsrep_get_apply_format(THD* thd); +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 0cbcdcd64aa..c961ef4b68f 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -14,12 +14,19 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mariadb.h" +#include "mysql/service_wsrep.h" #include "wsrep_binlog.h" #include "wsrep_priv.h" #include "log.h" #include "log_event.h" #include "wsrep_applier.h" +#include "transaction.h" + +const char *wsrep_fragment_units[] = { "bytes", "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. @@ -111,130 +118,6 @@ heap_size(size_t length) return (length + HEAP_PAGE_SIZE - 1)/HEAP_PAGE_SIZE*HEAP_PAGE_SIZE; } -/* append data to writeset */ -static inline wsrep_status_t -wsrep_append_data(wsrep_t* const wsrep, - wsrep_ws_handle_t* const ws, - const void* const data, - size_t const len) -{ - struct wsrep_buf const buff = { data, len }; - wsrep_status_t const rc(wsrep->append_data(wsrep, ws, &buff, 1, - WSREP_DATA_ORDERED, true)); - DBUG_DUMP("buff", (uchar*) data, len); - if (rc != WSREP_OK) - { - WSREP_WARN("append_data() returned %d", rc); - } - - return rc; -} - -/* - Write the contents of a cache to wsrep provider. - - This function quite the same as MYSQL_BIN_LOG::write_cache(), - with the exception that here we write in buffer instead of log file. - - 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) -{ - 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)) - { - WSREP_ERROR("failed to initialize io-cache"); - DBUG_RETURN(ER_ERROR_ON_WRITE); - } - - int err(WSREP_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); - - uint length(my_b_bytes_in_cache(cache)); - if (unlikely(0 == length)) length = my_b_fill(cache); - - if (likely(length > 0)) do - { - total_length += length; - /* - Bail out if buffer grows too large. - A temporary fix to avoid allocating indefinitely large buffer, - not a real limit on a writeset size which includes other things - like header and keys. - */ - if (unlikely(total_length > wsrep_max_ws_size)) - { - WSREP_WARN("transaction size limit (%lu) exceeded: %zu", - wsrep_max_ws_size, total_length); - err = 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)); - if (!tmp) - { - WSREP_ERROR("could not (re)allocate buffer: %zu + %u", - allocated, length); - err = WSREP_TRX_SIZE_EXCEEDED; - goto cleanup; - } - - heap_buf = tmp; - buf = heap_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(buf + used, cache->read_pos, length); - used = total_length; - if (cache->file < 0) - { - cache->read_pos= cache->read_end; - break; - } - } while ((length = my_b_fill(cache))); - - if (used > 0) - err = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used); - - if (WSREP_OK == err) *len = total_length; - -cleanup: - if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) - { - WSREP_ERROR("failed to reinitialize io-cache"); - } - - if (unlikely(WSREP_OK != err)) - { - wsrep_dump_rbr_buf_with_header(thd, buf, used); - } - - my_free(heap_buf); - DBUG_RETURN(err); -} - /* Write the contents of a cache to wsrep provider. @@ -243,62 +126,58 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep, 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, +static int wsrep_write_cache_inc(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)) - { - WSREP_ERROR("failed to initialize io-cache"); - DBUG_RETURN(WSREP_TRX_ERROR); - } + DBUG_ENTER("wsrep_write_cache_inc"); + my_off_t const saved_pos(my_b_tell(cache)); - int err(WSREP_OK); + if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0)) + { + WSREP_ERROR("failed to initialize io-cache"); + DBUG_RETURN(1);; + } - size_t total_length(0); + int ret= 0; + size_t total_length(0); - uint length(my_b_bytes_in_cache(cache)); - if (unlikely(0 == length)) length = my_b_fill(cache); + uint length(my_b_bytes_in_cache(cache)); + if (unlikely(0 == length)) length = my_b_fill(cache); - if (likely(length > 0)) do + if (likely(length > 0)) + { + do { - total_length += length; - /* bail out if buffer grows too large - not a real limit on a writeset size which includes other things - like header and keys. - */ - if (unlikely(total_length > wsrep_max_ws_size)) - { - WSREP_WARN("transaction size limit (%lu) exceeded: %zu", - wsrep_max_ws_size, total_length); - err = WSREP_TRX_SIZE_EXCEEDED; - goto cleanup; - } - - if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle, - cache->read_pos, length))) - goto cleanup; - - if (cache->file < 0) - { - cache->read_pos= cache->read_end; - break; - } - } while ((length = my_b_fill(cache))); - - if (WSREP_OK == err) *len = total_length; + total_length += length; + /* bail out if buffer grows too large + not a real limit on a writeset size which includes other things + like header and keys. + */ + if (unlikely(total_length > wsrep_max_ws_size)) + { + WSREP_WARN("transaction size limit (%lu) exceeded: %zu", + wsrep_max_ws_size, total_length); + ret = 1; + goto cleanup; + } + if (thd->wsrep_cs().append_data(wsrep::const_buffer(cache->read_pos, length))) + goto cleanup; + cache->read_pos = cache->read_end; + } while ((cache->file >= 0) && (length = my_b_fill(cache))); + } + if (ret == 0) + { + assert(total_length + thd->wsrep_sr().bytes_certified() == saved_pos); + } cleanup: - if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) - { - WSREP_ERROR("failed to reinitialize io-cache"); - } - - DBUG_RETURN(err); + *len = total_length; + if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) + { + WSREP_ERROR("failed to reinitialize io-cache"); + } + DBUG_RETURN(ret); } /* @@ -307,17 +186,11 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep, 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, +int wsrep_write_cache(THD* const thd, IO_CACHE* const cache, size_t* const len) { - if (wsrep_incremental_data_collection) { - return wsrep_write_cache_inc(wsrep, thd, cache, len); - } - else { - return wsrep_write_cache_once(wsrep, thd, cache, len); - } + return wsrep_write_cache_inc(thd, cache, len); } void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) @@ -544,3 +417,123 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, 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_skip_event(THD* thd) +{ + DBUG_ENTER("wsrep_write_skip_event"); + Ignorable_log_event skip_event(thd); + int ret= mysql_bin_log.write_event(&skip_event); + if (ret) + { + WSREP_WARN("wsrep_write_skip_event: write to binlog failed: %d", ret); + } + if (!ret && (ret = trans_commit_stmt(thd))) + { + WSREP_WARN("wsrep_write_skip_event: statt commit failed"); + } + DBUG_RETURN(ret); +} + +int wsrep_write_dummy_event_low(THD *thd, const char *msg) +{ + ::abort(); + return 0; +#if 0 + 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; +#endif +} + +int wsrep_write_dummy_event(THD *orig_thd, const char *msg) +{ + return 0; +#if 0 + 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; +#endif +} diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h index 864813d5c98..2daa4c5db4d 100644 --- a/sql/wsrep_binlog.h +++ b/sql/wsrep_binlog.h @@ -16,6 +16,35 @@ #ifndef WSREP_BINLOG_H #define WSREP_BINLOG_H +#include "my_global.h" + +#define WSREP_FRAG_BYTES 0 +#define WSREP_FRAG_ROWS 1 +#define WSREP_FRAG_STATEMENTS 2 +#include "wsrep/streaming_context.hpp" +static inline enum wsrep::streaming_context::fragment_unit +wsrep_fragment_unit(ulong unit) +{ + switch (unit) + { + case WSREP_FRAG_BYTES: return wsrep::streaming_context::bytes; + case WSREP_FRAG_ROWS: return wsrep::streaming_context::row; + case WSREP_FRAG_STATEMENTS: return wsrep::streaming_context::statement; + default: + DBUG_ASSERT(0); + return wsrep::streaming_context::bytes; + } +} + +#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 */ @@ -38,23 +67,40 @@ 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); +int wsrep_write_cache(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 a skip event into binlog. + + @param thd Thread object pointer + @return Zero in case of success, non-zero on failure. +*/ +int wsrep_write_skip_event(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_client_service.cc b/sql/wsrep_client_service.cc new file mode 100644 index 00000000000..ee7a1b904c5 --- /dev/null +++ b/sql/wsrep_client_service.cc @@ -0,0 +1,300 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "wsrep_client_service.h" +#include "wsrep_high_priority_service.h" +#include "wsrep_applier.h" /* wsrep_apply_events() */ +#include "wsrep_binlog.h" /* wsrep_dump_rbr_buf() */ +#include "wsrep_schema.h" /* remove_fragments() */ +#include "wsrep_thd.h" +#include "wsrep_xid.h" +#include "wsrep_trans_observer.h" + +#include "sql_base.h" /* close_temporary_table() */ +#include "sql_class.h" /* THD */ +#include "sql_parse.h" /* stmt_causes_implicit_commit() */ +#include "rpl_filter.h" /* binlog_filter */ +#include "rpl_rli.h" /* Relay_log_info */ +#include "slave.h" /* opt_log_slave_updates */ +#include "transaction.h" /* trans_commit()... */ +#include "log.h" /* stmt_has_updated_trans_table() */ +//#include "debug_sync.h" +#include "mysql/service_debug_sync.h" +namespace +{ + +void debug_sync_caller(THD* thd, const char* sync_point) +{ +#ifdef ENABLED_DEBUG_SYNC_OUT + debug_sync_set_action(thd, sync_point, strlen(sync_point)); +#endif +#ifdef ENABLED_DEBUG_SYNC + debug_sync_service(thd, sync_point, strlen(sync_point)); +#endif + +} +} + +Wsrep_client_service::Wsrep_client_service(THD* thd, + Wsrep_client_state& client_state) + : wsrep::client_service() + , m_thd(thd) + , m_client_state(client_state) +{ } + +bool Wsrep_client_service::do_2pc() const +{ + DBUG_ASSERT(m_thd == current_thd); + THD_TRANS* trans= &m_thd->transaction.all.ha_list ? + &m_thd->transaction.all : + &m_thd->transaction.stmt; + return (!trans->no_2pc && trans->rw_ha_count > 1); + +} + +void Wsrep_client_service::store_globals() +{ + DBUG_ENTER("Wsrep_client_service::store_globals"); + m_thd->store_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_client_service::reset_globals() +{ + DBUG_ENTER("Wsrep_client_service::reset_globals"); + m_thd->reset_globals(); + DBUG_VOID_RETURN; +} + +bool Wsrep_client_service::interrupted() const +{ + DBUG_ASSERT(m_thd == current_thd); + mysql_mutex_lock(&m_thd->LOCK_thd_data); + bool ret= (m_thd->killed != NOT_KILLED); + mysql_mutex_unlock(&m_thd->LOCK_thd_data); + return ret; +} + +int Wsrep_client_service::prepare_data_for_replication() +{ + DBUG_ASSERT(m_thd == current_thd); + DBUG_ENTER("Wsrep_client_service::prepare_data_for_replication"); + size_t data_len= 0; + IO_CACHE* cache= wsrep_get_trans_cache(m_thd); + + if (cache) + { + m_thd->binlog_flush_pending_rows_event(true); + if (wsrep_write_cache(m_thd, cache, &data_len)) + { + WSREP_ERROR("rbr write fail, data_len: %zu", + data_len); + // wsrep_override_error(m_thd, ER_ERROR_DURING_COMMIT); + DBUG_RETURN(1); + } + } + + if (data_len == 0) + { + if (m_thd->get_stmt_da()->is_ok() && + m_thd->get_stmt_da()->affected_rows() > 0 && + !binlog_filter->is_on() && + !m_thd->wsrep_trx().is_streaming()) + { + WSREP_DEBUG("empty rbr buffer, query: %s, " + "affected rows: %llu, " + "changed tables: %d, " + "sql_log_bin: %d", + WSREP_QUERY(m_thd), + m_thd->get_stmt_da()->affected_rows(), + stmt_has_updated_trans_table(m_thd), + m_thd->variables.sql_log_bin); + } + else + { + WSREP_DEBUG("empty rbr buffer, query: %s", WSREP_QUERY(m_thd)); + } + } + DBUG_RETURN(0); +} + + +void Wsrep_client_service::cleanup_transaction() +{ + DBUG_ASSERT(m_thd == current_thd); + if (WSREP_EMULATE_BINLOG(m_thd)) wsrep_thd_binlog_trx_reset(m_thd); + m_thd->wsrep_affected_rows= 0; +} + + +int Wsrep_client_service::prepare_fragment_for_replication(wsrep::mutable_buffer& buffer) +{ + DBUG_ASSERT(m_thd == current_thd); + THD* thd= m_thd; + DBUG_ENTER("Wsrep_client_service::prepare_fragment_for_replication"); + IO_CACHE* cache= wsrep_get_trans_cache(thd); + thd->binlog_flush_pending_rows_event(true); + + const my_off_t saved_pos(my_b_tell(cache)); + if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0)) + { + DBUG_RETURN(1); + } + + int ret= 0; + size_t total_length= 0; + size_t length= my_b_bytes_in_cache(cache); + + if (!length) + { + length= my_b_fill(cache); + } + + if (length > 0) + { + do + { + total_length+= length; + if (total_length > wsrep_max_ws_size) + { + WSREP_WARN("transaction size limit (%lu) exceeded: %zu", + wsrep_max_ws_size, total_length); + ret= 1; + goto cleanup; + } + + buffer.push_back(reinterpret_cast<const char*>(cache->read_pos), + reinterpret_cast<const char*>(cache->read_pos + length)); + cache->read_pos= cache->read_end; + } + while (cache->file >= 0 && (length= my_b_fill(cache))); + } + DBUG_ASSERT(total_length == buffer.size()); +cleanup: + if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) + { + WSREP_WARN("Failed to reinitialize IO cache"); + ret= 1; + } + DBUG_RETURN(ret); +} + +int Wsrep_client_service::remove_fragments() +{ + DBUG_ENTER("Wsrep_client_service::remove_fragments"); + if (wsrep_schema->remove_fragments(m_thd, + Wsrep_server_state::instance().id(), + m_thd->wsrep_trx().id(), + m_thd->wsrep_sr().fragments())) + { + WSREP_DEBUG("Failed to remove fragments from SR storage for transaction " + "%lu, %llu", + m_thd->thread_id, m_thd->wsrep_trx().id().get()); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + +bool Wsrep_client_service::statement_allowed_for_streaming() const +{ + /* + Todo: Decide if implicit commit is allowed with streaming + replication. + !stmt_causes_implicit_commit(m_thd, CF_IMPLICIT_COMMIT_BEGIN); + */ + return true; +} + +size_t Wsrep_client_service::bytes_generated() const +{ + IO_CACHE* cache= wsrep_get_trans_cache(m_thd); + if (cache) + { + m_thd->binlog_flush_pending_rows_event(true); + return my_b_tell(cache); + } + return 0; +} + +void Wsrep_client_service::will_replay() +{ + DBUG_ASSERT(m_thd == current_thd); + mysql_mutex_lock(&LOCK_wsrep_replaying); + ++wsrep_replaying; + mysql_mutex_unlock(&LOCK_wsrep_replaying); +} + +enum wsrep::provider::status Wsrep_client_service::replay() +{ + DBUG_ASSERT(m_thd == current_thd); + Wsrep_replayer_service replayer_service(m_thd); + wsrep::provider& provider(m_thd->wsrep_cs().provider()); + mysql_mutex_lock(&m_thd->LOCK_thd_data); + m_thd->killed= NOT_KILLED; + mysql_mutex_unlock(&m_thd->LOCK_thd_data); + enum wsrep::provider::status ret= + provider.replay(m_thd->wsrep_trx().ws_handle(), &replayer_service); + replayer_service.replay_status(ret); + mysql_mutex_lock(&LOCK_wsrep_replaying); + --wsrep_replaying; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + return ret; +} + +void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock) +{ + DBUG_ASSERT(m_thd == current_thd); + lock.unlock(); + mysql_mutex_lock(&LOCK_wsrep_replaying); + while (wsrep_replaying > 0) + { + mysql_cond_wait(&COND_wsrep_replaying, &LOCK_wsrep_replaying); + } + mysql_mutex_unlock(&LOCK_wsrep_replaying); + lock.lock(); +} + +void Wsrep_client_service::debug_sync(const char* sync_point) +{ + DBUG_ASSERT(m_thd == current_thd); + debug_sync_caller(m_thd, sync_point); +} + +void Wsrep_client_service::debug_crash(const char* crash_point) +{ + // DBUG_ASSERT(m_thd == current_thd); + DBUG_EXECUTE_IF(crash_point, DBUG_SUICIDE(); ); +} + +int Wsrep_client_service::bf_rollback() +{ + DBUG_ASSERT(m_thd == current_thd); + DBUG_ENTER("Wsrep_client_service::rollback"); + + int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd)); + if (m_thd->locked_tables_mode && m_thd->lock) + { + m_thd->locked_tables_list.unlock_locked_tables(m_thd); + m_thd->variables.option_bits&= ~OPTION_TABLE_LOCK; + } + if (m_thd->global_read_lock.is_acquired()) + { + m_thd->global_read_lock.unlock_global_read_lock(m_thd); + } + m_thd->mdl_context.release_transactional_locks(); + m_thd->mdl_context.release_explicit_locks(); + + DBUG_RETURN(ret); +} diff --git a/sql/wsrep_client_service.h b/sql/wsrep_client_service.h new file mode 100644 index 00000000000..c2fe4e3985b --- /dev/null +++ b/sql/wsrep_client_service.h @@ -0,0 +1,64 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** @file wsrep_client_service.h + + This file provides declaratios for client service implementation. + See wsrep/client_service.hpp for interface documentation. +*/ + +#ifndef WSREP_CLIENT_SERVICE_H +#define WSREP_CLIENT_SERVICE_H + +/* wsrep-lib */ +#include "../wsrep-lib/include/wsrep/client_service.hpp" +#include "../wsrep-lib/include/wsrep/client_state.hpp" +#include "../wsrep-lib/include/wsrep/exception.hpp" /* not_implemented_error, remove when finished */ + +class THD; +class Wsrep_client_state; +class Wsrep_high_priority_context; + +class Wsrep_client_service : public wsrep::client_service +{ +public: + Wsrep_client_service(THD*, Wsrep_client_state&); + + bool do_2pc() const; + bool interrupted() const; + void reset_globals(); + void store_globals(); + int prepare_data_for_replication(); + void cleanup_transaction(); + bool statement_allowed_for_streaming() const; + size_t bytes_generated() const; + int prepare_fragment_for_replication(wsrep::mutable_buffer&); + int remove_fragments(); + void emergency_shutdown() + { throw wsrep::not_implemented_error(); } + void will_replay(); + enum wsrep::provider::status replay(); + void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&); + void debug_sync(const char*); + void debug_crash(const char*); + int bf_rollback(); +private: + friend class Wsrep_server_service; + THD* m_thd; + Wsrep_client_state& m_client_state; +}; + + +#endif /* WSREP_CLIENT_SERVICE_H */ diff --git a/sql/wsrep_client_state.h b/sql/wsrep_client_state.h new file mode 100644 index 00000000000..5d32e92eaa4 --- /dev/null +++ b/sql/wsrep_client_state.h @@ -0,0 +1,47 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_CLIENT_STATE_H +#define WSREP_CLIENT_STATE_H + +/* wsrep-lib */ +#include "../wsrep-lib/include/wsrep/client_state.hpp" +#include "my_global.h" + +class THD; + +class Wsrep_client_state : public wsrep::client_state +{ +public: + Wsrep_client_state(THD* thd, + wsrep::mutex& mutex, + wsrep::condition_variable& cond, + wsrep::server_state& server_state, + wsrep::client_service& client_service, + const wsrep::client_id& id) + : wsrep::client_state(mutex, + cond, + server_state, + client_service, + id, + wsrep::client_state::m_local) + , m_thd(thd) + { } + THD* thd() { return m_thd; } +private: + THD* m_thd; +}; + +#endif /* WSREP_CLIENT_STATE_H */ diff --git a/sql/wsrep_condition_variable.h b/sql/wsrep_condition_variable.h new file mode 100644 index 00000000000..fa22de4d845 --- /dev/null +++ b/sql/wsrep_condition_variable.h @@ -0,0 +1,54 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_CONDITION_VARIABLE_H +#define WSREP_CONDITION_VARIABLE_H + +/* wsrep-lib */ +#include "../wsrep-lib/include/wsrep/condition_variable.hpp" + +/* implementation */ +#include "my_pthread.h" + +class Wsrep_condition_variable : public wsrep::condition_variable +{ +public: + + Wsrep_condition_variable(mysql_cond_t& cond) + : m_cond(cond) + { } + ~Wsrep_condition_variable() + { } + + void notify_one() + { + mysql_cond_signal(&m_cond); + } + + void notify_all() + { + mysql_cond_broadcast(&m_cond); + } + + void wait(wsrep::unique_lock<wsrep::mutex>& lock) + { + mysql_mutex_t* mutex= static_cast<mysql_mutex_t*>(lock.mutex().native()); + mysql_cond_wait(&m_cond, mutex); + } +private: + mysql_cond_t& m_cond; +}; + +#endif /* WSREP_CONDITION_VARIABLE_H */ diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 9a4bbd01bcd..87ee0334ce0 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -17,7 +17,7 @@ #include <sql_class.h> #include <mysql/service_wsrep.h> -my_bool wsrep_thd_is_BF(THD *, my_bool) +my_bool wsrep_thd_is_BF(void *, my_bool) { return 0; } int wsrep_trx_order_before(THD *, THD *) @@ -26,7 +26,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,6 +39,10 @@ const unsigned char* wsrep_xid_uuid(const XID*) return uuid; } +#ifdef TODO +bool wsrep_prepare_key_for_innodb(THD* thd, const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*) +{ return -1; } +#endif bool wsrep_prepare_key(const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*) { return 0; } diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc new file mode 100644 index 00000000000..4408ee99f44 --- /dev/null +++ b/sql/wsrep_high_priority_service.cc @@ -0,0 +1,681 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "wsrep_high_priority_service.h" +#include "wsrep_applier.h" +#include "wsrep_binlog.h" +#include "wsrep_schema.h" +#include "wsrep_xid.h" +#include "wsrep_trans_observer.h" + +#include "sql_class.h" /* THD */ +#include "transaction.h" +#include "debug_sync.h" +/* RLI */ +#include "rpl_rli.h" +#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1 +#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2 +#include "slave.h" +#include "rpl_mi.h" + +namespace +{ +/* + Scoped mode for applying non-transactional write sets (TOI) + */ +class Wsrep_non_trans_mode +{ +public: + Wsrep_non_trans_mode(THD* thd, const wsrep::ws_meta& ws_meta) + : m_thd(thd) + , m_option_bits(thd->variables.option_bits) + , m_server_status(thd->server_status) + { + m_thd->variables.option_bits&= ~OPTION_BEGIN; + m_thd->server_status&= ~SERVER_STATUS_IN_TRANS; + m_thd->wsrep_cs().enter_toi(ws_meta); + } + ~Wsrep_non_trans_mode() + { + m_thd->variables.option_bits= m_option_bits; + m_thd->server_status= m_server_status; + m_thd->wsrep_cs().leave_toi(); + } +private: + Wsrep_non_trans_mode(const Wsrep_non_trans_mode&); + Wsrep_non_trans_mode& operator=(const Wsrep_non_trans_mode&); + THD* m_thd; + ulonglong m_option_bits; + uint m_server_status; +}; +} + +static rpl_group_info* wsrep_relay_group_init(const char* log_fname) +{ + Relay_log_info* rli= new Relay_log_info(false); + + if (!rli->relay_log.description_event_for_exec) + { + rli->relay_log.description_event_for_exec= + new Format_description_log_event(4); + } + + static LEX_CSTRING connection_name= { STRING_WITH_LEN("wsrep") }; + + /* + Master_info's constructor initializes rpl_filter by either an already + constructed Rpl_filter object from global 'rpl_filters' list if the + specified connection name is same, or it constructs a new Rpl_filter + object and adds it to rpl_filters. This object is later destructed by + Mater_info's destructor by looking it up based on connection name in + rpl_filters list. + + However, since all Master_info objects created here would share same + connection name ("wsrep"), destruction of any of the existing Master_info + objects (in wsrep_return_from_bf_mode()) would free rpl_filter referenced + by any/all existing Master_info objects. + + In order to avoid that, we have added a check in Master_info's destructor + to not free the "wsrep" rpl_filter. It will eventually be freed by + free_all_rpl_filters() when server terminates. + */ + rli->mi = new Master_info(&connection_name, false); + + struct rpl_group_info *rgi= new rpl_group_info(rli); + rgi->thd= rli->sql_driver_thd= current_thd; + + if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on())) + { + rgi->deferred_events= new Deferred_log_events(rli); + } + + return rgi; +} + +static void wsrep_setup_uk_and_fk_checks(THD* thd) +{ + /* Tune FK and UK checking policy. These are reset back to original + in Wsrep_high_priority_service destructor. */ + 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) + thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; + else + thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; +} + +/**************************************************************************** + High priority service +*****************************************************************************/ + +Wsrep_high_priority_service::Wsrep_high_priority_service(THD* thd) + : wsrep::high_priority_service(Wsrep_server_state::instance()) + , wsrep::high_priority_context(thd->wsrep_cs()) + , m_thd(thd) + , m_rli() +{ + LEX_CSTRING db_str= { NULL, 0 }; + m_shadow.option_bits = thd->variables.option_bits; + m_shadow.server_status = thd->server_status; + m_shadow.vio = thd->net.vio; + m_shadow.tx_isolation = thd->variables.tx_isolation; + m_shadow.db = (char *)thd->db.str; + m_shadow.db_length = thd->db.length; + //m_shadow.user_time = hrtime_to_my_time(thd->user_time); + m_shadow.user_time = thd->user_time; + m_shadow.row_count_func= thd->get_row_count_func(); + m_shadow.wsrep_applier = thd->wsrep_applier; + + /* Disable general logging on applier threads */ + thd->variables.option_bits |= OPTION_LOG_OFF; + /* Enable binlogging if opt_log_slave_updates is set */ + if (opt_log_slave_updates) + thd->variables.option_bits|= OPTION_BIN_LOG; + else + thd->variables.option_bits&= ~(OPTION_BIN_LOG); + + thd->net.vio= 0; + thd->reset_db(&db_str); + thd->clear_error(); + thd->variables.tx_isolation = ISO_READ_COMMITTED; + thd->tx_isolation = ISO_READ_COMMITTED; + + /* From trans_begin() */ + thd->variables.option_bits|= OPTION_BEGIN; + thd->server_status|= SERVER_STATUS_IN_TRANS; + + /* Make THD wsrep_applier so that it cannot be killed */ + thd->wsrep_applier= true; + + if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init("wsrep_relay"); + + m_rgi= thd->wsrep_rgi; + m_rgi->thd = thd; + m_rli= m_rgi->rli; + thd_proc_info(thd, "wsrep applier idle"); +} + +Wsrep_high_priority_service::~Wsrep_high_priority_service() +{ + THD* thd= m_thd; + thd->variables.option_bits = m_shadow.option_bits; + thd->server_status = m_shadow.server_status; + thd->net.vio = m_shadow.vio; + thd->variables.tx_isolation = m_shadow.tx_isolation; + LEX_CSTRING db_str= { m_shadow.db, m_shadow.db_length }; + thd->reset_db(&db_str); + thd->user_time = m_shadow.user_time; + + if (thd->wsrep_rgi && thd->wsrep_rgi->rli) + delete thd->wsrep_rgi->rli->mi; + if (thd->wsrep_rgi) + delete thd->wsrep_rgi->rli; + delete thd->wsrep_rgi; + thd->wsrep_rgi= NULL; + + thd->set_row_count_func(m_shadow.row_count_func); + thd->wsrep_applier = m_shadow.wsrep_applier; +} + +int Wsrep_high_priority_service::start_transaction( + const wsrep::ws_handle& ws_handle, const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER(" Wsrep_high_priority_service::start_transaction"); + DBUG_RETURN(m_thd->wsrep_cs().start_transaction(ws_handle, ws_meta)); +} + +const wsrep::transaction& Wsrep_high_priority_service::transaction() const +{ + DBUG_ENTER(" Wsrep_high_priority_service::transaction"); + DBUG_RETURN(m_thd->wsrep_trx()); +} + +void Wsrep_high_priority_service::adopt_transaction(const wsrep::transaction& transaction) +{ + DBUG_ENTER(" Wsrep_high_priority_service::adopt_transaction"); + m_thd->wsrep_cs().adopt_transaction(transaction); + DBUG_VOID_RETURN; +} + + +int Wsrep_high_priority_service::append_fragment_and_commit( + const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_high_priority_service::append_fragment"); + int ret= start_transaction(ws_handle, ws_meta); + ret= ret || wsrep_schema->append_fragment(m_thd, + ws_meta.server_id(), + ws_meta.transaction_id(), + ws_meta.seqno(), + ws_meta.flags(), + data); + + /* + Note: The commit code below seems to be identical to + Wsrep_storage_service::commit(). Consider implementing + common utility function to deal with commit. + */ + const bool do_binlog_commit= (opt_log_slave_updates && + wsrep_gtid_mode && + m_thd->variables.gtid_seq_no); + /* + Write skip event into binlog if gtid_mode is on. This is to + maintain gtid continuity. + */ + if (do_binlog_commit) + { + ret= wsrep_write_skip_event(m_thd); + } + + if (!ret) + { + ret= m_thd->wsrep_cs().prepare_for_ordering(ws_handle, + ws_meta, true); + } + + if (!ret) + { + DBUG_ASSERT(wsrep_thd_trx_seqno(m_thd) > 0); + if (!do_binlog_commit) + { + ret= wsrep_before_commit(m_thd, true); + } + ret= ret || trans_commit(m_thd); + if (!do_binlog_commit) + { + if (opt_log_slave_updates) + { + ret= ret || wsrep_ordered_commit(m_thd, true, wsrep_apply_error()); + } + ret= ret || wsrep_after_commit(m_thd, true); + } + } + m_thd->wsrep_cs().after_applying(); + m_thd->mdl_context.release_transactional_locks(); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::remove_fragments(const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::remove_fragments"); + int ret= wsrep_schema->remove_fragments(m_thd, + ws_meta.server_id(), + ws_meta.transaction_id(), + m_thd->wsrep_sr().fragments()); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::commit(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::commit"); + THD* thd= m_thd; + DBUG_ASSERT(thd->wsrep_trx().active()); + thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, true); + thd_proc_info(thd, "committing"); + + int ret= 0; + const bool is_ordered= !ws_meta.seqno().is_undefined(); + /* If opt_log_slave_updates is not on, applier does not write + anything to binlog cache and neither wsrep_before_commit() + nor wsrep_after_commit() we be reached from binlog code + path for applier. Therefore run wsrep_before_commit() + and wsrep_after_commit() here. wsrep_ordered_commit() + will be called from wsrep_ordered_commit_if_no_binlog(). */ + if (!opt_log_slave_updates && !opt_bin_log && is_ordered) + { + if (m_thd->transaction.all.no_2pc == false) + { + ret= wsrep_before_prepare(thd, true); + ret= ret || wsrep_after_prepare(thd, true); + } + ret= ret || wsrep_before_commit(thd, true); + } + ret= ret || trans_commit(thd); + + if (ret == 0) + { + m_rgi->cleanup_context(thd, 0); + } + + if (ret == 0 && !opt_log_slave_updates && !opt_bin_log && is_ordered) + { + ret= wsrep_after_commit(thd, true); + } + + m_thd->mdl_context.release_transactional_locks(); + + thd_proc_info(thd, "wsrep applier committed"); + + if (!is_ordered) + { + /* Wsrep commit was not ordered so it does not go through commit time + hooks and remains active. Roll it back to make cleanup happen + in after_applying() call. */ + m_thd->wsrep_cs().before_rollback(); + m_thd->wsrep_cs().after_rollback(); + } + + must_exit_ = check_exit_status(); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::rollback"); + m_thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, false); + int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd)); + m_thd->mdl_context.release_transactional_locks(); + m_thd->mdl_context.release_explicit_locks(); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_high_priority_service::apply_toi"); + THD* thd= m_thd; + Wsrep_non_trans_mode non_trans_mode(thd, ws_meta); + + wsrep::client_state& client_state(thd->wsrep_cs()); + DBUG_ASSERT(client_state.in_toi()); + + thd_proc_info(thd, "wsrep applier toi"); + + WSREP_DEBUG("Wsrep_high_priority_service::apply_toi: %lld", + client_state.toi_meta().seqno().get()); + + int ret= wsrep_apply_events(thd, m_rli, data.data(), data.size()); + if (ret != 0 || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); + thd->wsrep_has_ignored_error= false; + /* todo: error voting */ + } + trans_commit(thd); + + thd->close_temporary_tables(); +#ifdef OUT + bool locked; + TMP_TABLE_SHARE *share; + locked= lock_temporary_tables(); + All_tmp_tables_list::Iterator it(*thd->temporary_tables); + while ((share= it++)) + { + WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", + thd->thread_id, share->db.str, share->table_name.str); + close_temporary_table(thd, share, 1, 1); + } + if (locked) + { + unlock_temporary_tables(); + } +#endif + wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); + + must_exit_ = check_exit_status(); + + DBUG_RETURN(ret); +} + +void Wsrep_high_priority_service::store_globals() +{ + DBUG_ENTER("Wsrep_high_priority_service::store_globals"); + /* In addition to calling THD::store_globals(), call + wsrep::client_state::store_globals() to gain ownership of + the client state */ + m_thd->store_globals(); + m_thd->wsrep_cs().store_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_high_priority_service::reset_globals() +{ + DBUG_ENTER("Wsrep_high_priority_service::reset_globals"); + m_thd->reset_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_high_priority_service::switch_execution_context(wsrep::high_priority_service& orig_high_priority_service) +{ + DBUG_ENTER("Wsrep_high_priority_service::switch_execution_context"); + Wsrep_high_priority_service& + orig_hps= static_cast<Wsrep_high_priority_service&>(orig_high_priority_service); + m_thd->thread_stack= orig_hps.m_thd->thread_stack; + DBUG_VOID_RETURN; +} + +int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::log_dummy_write_set"); + int ret= 0; + DBUG_PRINT("info", + ("Wsrep_high_priority_service::log_dummy_write_set: seqno=%lld", + ws_meta.seqno().get())); + m_thd->wsrep_cs().start_transaction(ws_handle, ws_meta); + WSREP_DEBUG("Log dummy write set %lld", ws_meta.seqno().get()); + if (!(opt_log_slave_updates && wsrep_gtid_mode && m_thd->variables.gtid_seq_no)) + { + m_thd->wsrep_cs().before_rollback(); + m_thd->wsrep_cs().after_rollback(); + } + m_thd->wsrep_cs().after_applying(); + DBUG_RETURN(ret); +} + +void Wsrep_high_priority_service::debug_crash(const char* crash_point) +{ + DBUG_ASSERT(m_thd == current_thd); + DBUG_EXECUTE_IF(crash_point, DBUG_SUICIDE();); +} + +/**************************************************************************** + Applier service +*****************************************************************************/ + +Wsrep_applier_service::Wsrep_applier_service(THD* thd) + : Wsrep_high_priority_service(thd) +{ + thd->wsrep_applier_service= this; + thd->wsrep_cs().open(wsrep::client_id(thd->thread_id)); + thd->wsrep_cs().before_command(); + thd->wsrep_cs().debug_log_level(wsrep_debug); + +} + +Wsrep_applier_service::~Wsrep_applier_service() +{ + m_thd->wsrep_cs().after_command_before_result(); + m_thd->wsrep_cs().after_command_after_result(); + m_thd->wsrep_cs().close(); + m_thd->wsrep_cs().cleanup(); +} + +int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_applier_service::apply_write_set"); + THD* thd= m_thd; + + thd->variables.option_bits |= OPTION_BEGIN; + thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT; + DBUG_ASSERT(thd->wsrep_trx().active()); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_executing); + + thd_proc_info(thd, "applying write set"); + /* 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[]= + "now " + "SIGNAL sync.wsrep_apply_cb_reached " + "WAIT_FOR signal.wsrep_apply_cb"; + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act))); + };); + + wsrep_setup_uk_and_fk_checks(thd); + + int ret= wsrep_apply_events(thd, m_rli, data.data(), data.size()); + + if (ret || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); + } + + thd->close_temporary_tables(); +#ifdef OUT + TABLE *tmp; + while ((tmp = thd->temporary_tables)) + { + WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", + m_thd->thread_id, + (tmp->s) ? tmp->s->db.str : "void", + (tmp->s) ? tmp->s->table_name.str : "void"); + close_temporary_table(m_thd, tmp, 1, 1); + } +#endif + if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit)) + { + thd->wsrep_cs().fragment_applied(ws_meta.seqno()); + } + thd_proc_info(thd, "wsrep applied write set"); + DBUG_RETURN(ret); +} + +void Wsrep_applier_service::after_apply() +{ + DBUG_ENTER("Wsrep_applier_service::after_apply"); + wsrep_after_apply(m_thd); + // thd_proc_info(m_thd, "wsrep applier idle"); + DBUG_VOID_RETURN; +} + +bool Wsrep_applier_service::check_exit_status() const +{ + bool ret= false; + mysql_mutex_lock(&LOCK_wsrep_slave_threads); + if (wsrep_slave_count_change < 0) + { + ++wsrep_slave_count_change; + ret= true; + } + mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + return ret; +} + +/**************************************************************************** + Replayer service +*****************************************************************************/ + +Wsrep_replayer_service::Wsrep_replayer_service(THD* thd) + : Wsrep_high_priority_service(thd) + , m_da_shadow() + , m_replay_status() +{ + /* Response must not have been sent to client */ + DBUG_ASSERT(!thd->get_stmt_da()->is_sent()); + /* PS reprepare observer should have been removed already + open_table() will fail if we have dangling observer here */ + DBUG_ASSERT(!thd->m_reprepare_observer); + /* Replaying should happen always from after_statement() hook + after rollback, which should guarantee that there are no + transactional locks */ + DBUG_ASSERT(!thd->mdl_context.has_transactional_locks()); + + /* Make a shadow copy of diagnostics area and reset */ + m_da_shadow.status= thd->get_stmt_da()->status(); + if (m_da_shadow.status == Diagnostics_area::DA_OK) + { + m_da_shadow.affected_rows= thd->get_stmt_da()->affected_rows(); + m_da_shadow.last_insert_id= thd->get_stmt_da()->last_insert_id(); + strmake(m_da_shadow.message, thd->get_stmt_da()->message(), + sizeof(m_da_shadow.message) - 1); + } + thd->get_stmt_da()->reset_diagnostics_area(); + + /* Release explicit locks */ + if (thd->locked_tables_mode && thd->lock) + { + WSREP_WARN("releasing table lock for replaying (%ld)", + thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + + /* + Replaying will call MYSQL_START_STATEMENT when handling + BEGIN Query_log_event so end statement must be called before + replaying. + */ + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi= NULL; + thd->m_digest= NULL; + thd_proc_info(thd, "wsrep replaying trx"); +} + +Wsrep_replayer_service::~Wsrep_replayer_service() +{ + THD* thd= m_thd; + DBUG_ASSERT(!thd->get_stmt_da()->is_sent()); + DBUG_ASSERT(!thd->get_stmt_da()->is_set()); + if (m_replay_status == wsrep::provider::success) + { + DBUG_ASSERT(thd->wsrep_cs().current_error() == wsrep::e_success); + thd->killed= NOT_KILLED; + if (m_da_shadow.status == Diagnostics_area::DA_OK) + { + my_ok(thd, + m_da_shadow.affected_rows, + m_da_shadow.last_insert_id, + m_da_shadow.message); + } + else + { + my_ok(thd); + } + } + else if (m_replay_status == wsrep::provider::error_certification_failed) + { + DBUG_ASSERT(thd->wsrep_cs().current_error() == wsrep::e_deadlock_error); + } + else + { + DBUG_ASSERT(0); + WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s", + m_replay_status, + thd->db.str, WSREP_QUERY(thd)); + unireg_abort(1); + } +} + +int Wsrep_replayer_service::apply_write_set(const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_replayer_service::apply_write_set"); + THD* thd= m_thd; + + DBUG_ASSERT(thd->wsrep_trx().active()); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_replaying); + + wsrep_setup_uk_and_fk_checks(thd); + + int ret= 0; + if (!wsrep::starts_transaction(ws_meta.flags())) + { + DBUG_ASSERT(thd->wsrep_trx().is_streaming()); + ret= wsrep_schema->replay_transaction(thd, + m_rli, + ws_meta, + thd->wsrep_sr().fragments()); + } + + ret= ret || wsrep_apply_events(thd, m_rli, data.data(), data.size()); + + if (ret || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); + } + + thd->close_temporary_tables(); +#ifdef OUT + TABLE *tmp; + while ((tmp = thd->temporary_tables)) + { + WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", + m_thd->thread_id, + (tmp->s) ? tmp->s->db.str : "void", + (tmp->s) ? tmp->s->table_name.str : "void"); + close_temporary_table(m_thd, tmp, 1, 1); + } +#endif + if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit)) + { + thd->wsrep_cs().fragment_applied(ws_meta.seqno()); + } + + thd_proc_info(thd, "wsrep replayed write set"); + DBUG_RETURN(ret); +} diff --git a/sql/wsrep_high_priority_service.h b/sql/wsrep_high_priority_service.h new file mode 100644 index 00000000000..4012ca60a3e --- /dev/null +++ b/sql/wsrep_high_priority_service.h @@ -0,0 +1,118 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_HIGH_PRIORITY_SERVICE_H +#define WSREP_HIGH_PRIORITY_SERVICE_H + +#include "wsrep/high_priority_service.hpp" +#include "wsrep/client_state.hpp" +#include "my_global.h" +#include "sql_error.h" /* Diagnostics area */ +#include "sql_class.h" /* rpl_group_info */ + +class THD; +class Relay_log_info; +class Wsrep_server_service; + +class Wsrep_high_priority_service : + public wsrep::high_priority_service, + public wsrep::high_priority_context +{ +public: + Wsrep_high_priority_service(THD*); + ~Wsrep_high_priority_service(); + int start_transaction(const wsrep::ws_handle&, + const wsrep::ws_meta&); + const wsrep::transaction& transaction() const; + void adopt_transaction(const wsrep::transaction&); + int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&) = 0; + int append_fragment_and_commit(const wsrep::ws_handle&, + const wsrep::ws_meta&, + const wsrep::const_buffer&); + int remove_fragments(const wsrep::ws_meta&); + int commit(const wsrep::ws_handle&, const wsrep::ws_meta&); + int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&); + int apply_toi(const wsrep::ws_meta&, const wsrep::const_buffer&); + void store_globals(); + void reset_globals(); + void switch_execution_context(wsrep::high_priority_service&); + int log_dummy_write_set(const wsrep::ws_handle&, + const wsrep::ws_meta&); + + virtual bool check_exit_status() const = 0; + void debug_crash(const char*); +protected: + friend Wsrep_server_service; + THD* m_thd; + Relay_log_info* m_rli; + rpl_group_info* m_rgi; + struct shadow + { + ulonglong option_bits; + uint server_status; + struct st_vio* vio; + ulong tx_isolation; + char* db; + size_t db_length; + //struct timeval user_time; + my_hrtime_t user_time; + longlong row_count_func; + bool wsrep_applier; +} m_shadow; +}; + +class Wsrep_applier_service : public Wsrep_high_priority_service +{ +public: + Wsrep_applier_service(THD*); + ~Wsrep_applier_service(); + int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&); + void after_apply(); + bool is_replaying() const { return false; } + bool check_exit_status() const; +}; + +class Wsrep_replayer_service : public Wsrep_high_priority_service +{ +public: + Wsrep_replayer_service(THD*); + ~Wsrep_replayer_service(); + int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&); + void after_apply() { } + bool is_replaying() const { return true; } + void replay_status(enum wsrep::provider::status status) + { m_replay_status = status; } + enum wsrep::provider::status replay_status() const + { return m_replay_status; } + /* Replayer should never be forced to exit */ + bool check_exit_status() const { return false; } +private: + struct da_shadow + { + enum Diagnostics_area::enum_diagnostics_status status; + ulonglong affected_rows; + ulonglong last_insert_id; + char message[MYSQL_ERRMSG_SIZE]; + da_shadow() + : status() + , affected_rows() + , last_insert_id() + , message() + { } + } m_da_shadow; + enum wsrep::provider::status m_replay_status; +}; + +#endif /* WSREP_HIGH_PRIORITY_SERVICE_H */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 8110faf7d11..a78020a891c 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -345,6 +345,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_mutex.h b/sql/wsrep_mutex.h new file mode 100644 index 00000000000..03c9269119e --- /dev/null +++ b/sql/wsrep_mutex.h @@ -0,0 +1,50 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_MUTEX_H +#define WSREP_MUTEX_H + +/* wsrep-lib */ +#include "../wsrep-lib/include/wsrep/mutex.hpp" + +/* implementation */ +#include "my_pthread.h" + +class Wsrep_mutex : public wsrep::mutex +{ +public: + Wsrep_mutex(mysql_mutex_t& mutex) + : m_mutex(mutex) + { } + + void lock() + { + mysql_mutex_lock(&m_mutex); + } + + void unlock() + { + mysql_mutex_unlock(&m_mutex); + } + + void* native() + { + return &m_mutex; + } +private: + mysql_mutex_t& m_mutex; +}; + +#endif /* WSREP_MUTEX_H */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index d667d59b14f..c314fc65ce4 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -14,7 +14,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "sql_plugin.h" /* wsrep_plugins_pre_init() */ +#include "my_global.h" +#include "wsrep_server_state.h" + +#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,19 +38,22 @@ #include "wsrep_var.h" #include "wsrep_binlog.h" #include "wsrep_applier.h" +#include "wsrep_schema.h" +#include "wsrep_thd_pool.h" #include "wsrep_xid.h" +#include "wsrep_trans_observer.h" +#include "mysql/service_wsrep.h" #include <cstdio> #include <cstdlib> +#include <string> #include "log_event.h" #include <slave.h> -wsrep_t *wsrep = NULL; -/* - wsrep_emulate_bin_log is a flag to tell that binlog has not been configured. - wsrep needs to get binlog events from transaction cache even when binlog is - not enabled, wsrep_emulate_bin_log opens needed code paths to make this - possible -*/ +#include <sstream> + +/* wsrep-lib */ +Wsrep_server_state* Wsrep_server_state::m_instance; + my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface #ifdef GTID_SUPPORT /* Sidno in global_sid_map corresponding to group uuid */ @@ -82,7 +90,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_restart_slave; // Should mysql slave thread be @@ -107,7 +115,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 @@ -123,29 +139,37 @@ 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_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; @@ -156,11 +180,13 @@ 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_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[]= @@ -169,7 +195,7 @@ static PSI_cond_info wsrep_conds[]= { &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_thd, "THD::COND_wsrep_thd", 0}, { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL} }; @@ -181,47 +207,48 @@ 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] = -{ - "Primary", - "non-Primary", - "Disconnected" -}; static char provider_name[256]= { 0, }; static char provider_version[256]= { 0, }; static char provider_vendor[256]= { 0, }; /* - * wsrep status variables + * Wsrep status variables. LOCK_status must be locked When modifying + * these variables, */ my_bool wsrep_connected = FALSE; -my_bool wsrep_ready = FALSE; // node can accept queries +my_bool wsrep_ready = FALSE; const char* wsrep_cluster_state_uuid = cluster_uuid_str; long long wsrep_cluster_conf_id = WSREP_SEQNO_UNDEFINED; -const char* wsrep_cluster_status = cluster_status_str[WSREP_VIEW_DISCONNECTED]; +const char* wsrep_cluster_status = "Disconnected"; long wsrep_cluster_size = 0; long wsrep_local_index = -1; 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; - wsp::Config_state *wsrep_config_state; -// Boolean denoting if server is in initial startup phase. This is needed -// to make sure that main thread waiting in wsrep_sst_wait() is signaled -// if there was no state gap on receiving first view event. -static my_bool wsrep_startup = TRUE; + +wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; +wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; +wsp::node_status local_status; + +/* + */ +#define WSREP_THD_POOL_SIZE 16 +Wsrep_thd_pool* wsrep_thd_pool= 0; +Wsrep_schema *wsrep_schema= 0; +#if 0 static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { switch (level) { case WSREP_LOG_INFO: @@ -240,249 +267,163 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { break; } } +#endif -void wsrep_log(void (*fun)(const char *, ...), const char *format, ...) -{ - va_list args; - char msg[1024]; - va_start(args, format); - vsnprintf(msg, sizeof(msg) - 1, format, args); - va_end(args); - (fun)("WSREP: %s", msg); -} - - -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) -{ - char uuid_str[37]; - char msg[256]; - - wsrep_uuid_print (group_uuid, uuid_str, sizeof(uuid_str)); - snprintf (msg, 255, "WSREP: Group state: %s:%lld", - uuid_str, (long long)group_seqno); - wsrep_log_cb (level, msg); - - wsrep_uuid_print (node_uuid, uuid_str, sizeof(uuid_str)); - snprintf (msg, 255, "WSREP: Local state: %s:%lld", - uuid_str, (long long)node_seqno); - wsrep_log_cb (level, msg); -} - -#ifdef GTID_SUPPORT -void wsrep_init_sidno(const wsrep_uuid_t& wsrep_uuid) +//#ifdef GTID_SUPPORT +void wsrep_init_sidno(const wsrep::id& 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) + /* + Protocol versions starting from 4 use group gtid as it is. + For lesser protocol versions generate new Sid map entry from inverted + uuid. + */ + rpl_gtid sid; + if (wsrep_protocol_version >= 4) { - ltid_uuid.data[i] = ~wsrep_uuid.data[i]; + memcpy((void*)&sid, (const uchar*)uuid.data(),16); } - - sid.copy_from(ltid_uuid.data); + else + { + wsrep_uuid_t ltid_uuid; + for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i) + { + ltid_uuid.data[i] = ~((const uchar*)uuid.data())[i]; + } + memcpy((void*)&sid, (const uchar*)ltid_uuid.data,16); + } +#ifdef NOT_MERGED global_sid_lock->wrlock(); wsrep_sidno= global_sid_map->add_sid(sid); WSREP_INFO("Initialized wsrep sidno %d", wsrep_sidno); global_sid_lock->unlock(); +#endif } -#endif /* GTID_SUPPORT */ +//#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_member_status_t memb_status= wsrep_config_state->get_status(); - - if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t))) - { - memcpy(&cluster_uuid, &view->state_id.uuid, sizeof(cluster_uuid)); - - wsrep_uuid_print (&cluster_uuid, cluster_uuid_str, - sizeof(cluster_uuid_str)); - } - - wsrep_cluster_conf_id= view->view; - wsrep_cluster_status= cluster_status_str[view->status]; - 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); - - /* Proceed further only if view is PRIMARY */ - if (WSREP_VIEW_PRIMARY != view->status) - { -#ifdef HAVE_QUERY_CACHE - // query cache must be initialised by now - query_cache.flush(); -#endif /* HAVE_QUERY_CACHE */ - - wsrep_ready_set(FALSE); - memb_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 */ - // WRONG! local_uuid should be the last primary configuration uuid we were - // a member of. local_seqno should be updated in commit calls. - // local_uuid= cluster_uuid; - // local_seqno= view->first - 1; - goto out; - } + DBUG_ASSERT(!wsrep_schema); - switch (view->proto_ver) + WSREP_INFO("wsrep_init_schema_and_SR %p", wsrep_schema); + if (!wsrep_schema) { - case 0: - case 1: - case 2: - case 3: - // version change - if (view->proto_ver != wsrep_protocol_version) - { - my_bool wsrep_ready_saved= wsrep_ready_get(); - wsrep_ready_set(FALSE); - WSREP_INFO("closing client connections for " - "protocol change %ld -> %d", - wsrep_protocol_version, view->proto_ver); - wsrep_close_client_connections(TRUE); - wsrep_protocol_version= view->proto_ver; - wsrep_ready_set(wsrep_ready_saved); - } - break; - default: - WSREP_ERROR("Unsupported application protocol version: %d", - view->proto_ver); + // if (wsrep_before_SE()) { + DBUG_ASSERT(!wsrep_thd_pool); + wsrep_thd_pool= new Wsrep_thd_pool(WSREP_THD_POOL_SIZE); + //} + wsrep_schema= new Wsrep_schema(wsrep_thd_pool); + if (wsrep_schema->init()) + { + WSREP_ERROR("Failed to init wsrep schema"); unireg_abort(1); + } } +} - if (view->state_gap) +void wsrep_recover_sr_from_storage() +{ + switch (wsrep_SR_store_type) { - 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); - } - - 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 + case WSREP_SR_STORE_TABLE: + if (wsrep_schema->recover_sr_transactions()) { - assert(sst_req != NULL); - *sst_req_len= req_len; - memb_status= WSREP_MEMBER_JOINER; + WSREP_ERROR("Failed to recover SR transactions from schema"); + unireg_abort(1); } + break; + default: + /* */ + WSREP_ERROR("Unsupported wsrep SR store type: %lu", wsrep_SR_store_type); + unireg_abort(1); + break; } - 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) +} + +/** 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 (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(); - } - else + if (s.empty()) { - local_uuid= cluster_uuid; - local_seqno= view->state_id.seqno; + s = ":"; } - /* Init storage engine XIDs from first view */ - wsrep_set_SE_checkpoint(local_uuid, local_seqno); -#ifdef GTID_SUPPORT - wsrep_init_sidno(local_uuid); -#endif /* GTID_SUPPORT */ - memb_status= WSREP_MEMBER_JOINED; - } - - // 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); + s += names[i]; + s += ":"; } } - if (wsrep_auto_increment_control) - { - 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)); + /* 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. */ - 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; - } + char* const previous = *str; -out: - if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE; - wsrep_config_state->set(memb_status, view); + *str = strdup(s.c_str()); - return WSREP_CB_SUCCESS; + if (previous != NULL) + { + free(previous); + } } -my_bool wsrep_ready_set (my_bool x) +/* 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_DEBUG("Setting wsrep_ready to %d", x); - if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); - my_bool ret= (wsrep_ready != x); - if (ret) +#if 0 + wsrep_get_SE_checkpoint(local_uuid, local_seqno); + + if (memcmp(&local_uuid, &uuid, sizeof (wsrep_uuid_t)) || + local_seqno > seqno) { - wsrep_ready= x; - mysql_cond_signal (&COND_wsrep_ready); + 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); } - mysql_mutex_unlock (&LOCK_wsrep_ready); - return ret; +#endif + // wsrep_init_sidno(local_uuid); } +/* + Wsrep is considered ready if + 1) Provider is not loaded (native mode) + 2) Server has reached synced state + 3) Server is in joiner mode and mysqldump SST method has been + specified + See Wsrep_server_service::log_state_change() for further details. + */ my_bool wsrep_ready_get (void) { if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); @@ -499,63 +440,20 @@ int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff) return 0; } -// Wait until wsrep has reached ready state -void wsrep_ready_wait () -{ - if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); - while (!wsrep_ready) - { - WSREP_INFO("Waiting to reach ready state"); - mysql_cond_wait (&COND_wsrep_ready, &LOCK_wsrep_ready); - } - WSREP_INFO("ready state reached"); - mysql_mutex_unlock (&LOCK_wsrep_ready); -} - -static void wsrep_synced_cb(void* app_ctx) +void wsrep_update_cluster_state_uuid(const char* uuid) { - WSREP_INFO("Synchronized with group, ready for connections"); - my_bool signal_main= wsrep_ready_set(TRUE); - wsrep_config_state->set(WSREP_MEMBER_SYNCED); - - if (signal_main) - { - wsrep_SE_init_grab(); - // 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_restart_slave_activated) - { - int rcode; - WSREP_INFO("MariaDB slave restart"); - wsrep_restart_slave_activated= FALSE; - - mysql_mutex_lock(&LOCK_active_mi); - if ((rcode = start_slave_threads(0, - 1 /* need mutex */, - 0 /* no wait for start*/, - active_mi, - master_info_file, - relay_log_info_file, - SLAVE_SQL))) - { - WSREP_WARN("Failed to create slave threads: %d", rcode); - } - mysql_mutex_unlock(&LOCK_active_mi); - - } + strncpy(cluster_uuid_str, uuid, sizeof(cluster_uuid_str) - 1); } static void wsrep_init_position() { +#if 0 /* read XIDs from storage engines */ wsrep_uuid_t uuid; 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; @@ -563,9 +461,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 @@ -578,99 +477,70 @@ static void wsrep_init_position() WSREP_WARN("Initial position was provided by configuration or SST, " "avoiding override"); } +#endif } -extern char* my_bind_addr_str; - -int wsrep_init() +/**************************************************************************** + Helpers for wsrep_init() + ****************************************************************************/ +static std::string wsrep_server_name() { - int rcode= -1; - DBUG_ASSERT(wsrep_inited == 0); - - if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO) && - wsrep_start_position_init(wsrep_start_position)) - { - return 1; - } - - wsrep_sst_auth_init(); - - wsrep_ready_set(FALSE); - assert(wsrep_provider); + std::string ret(wsrep_node_name ? wsrep_node_name : ""); + return ret; +} - wsrep_init_position(); +static std::string wsrep_server_id() +{ +#ifdef WSREP_TODO + std::stringstream ss; + ss << server_id; + return(ss.str()); +#endif + /* using empty server_id, which enables view change handler to + set final server_id later on + */ + std::string ret(""); + return ret; +} - if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK) - { - if (strcasecmp(wsrep_provider, WSREP_NONE)) - { - WSREP_ERROR("wsrep_load(%s) failed: %s (%d). Reverting to no provider.", - wsrep_provider, strerror(rcode), rcode); - strcpy((char*)wsrep_provider, WSREP_NONE); // damn it's a dirty hack - return wsrep_init(); - } - else /* this is for recursive call above */ - { - WSREP_ERROR("Could not revert to no provider: %s (%d). Need to abort.", - strerror(rcode), rcode); - unireg_abort(1); - } - } +static std::string wsrep_server_node_address() +{ - if (!WSREP_PROVIDER_EXISTS) + std::string ret; + WSREP_INFO("node_address ptr %p", wsrep_node_address); + if (wsrep_node_address) { - // enable normal operation in case no provider is specified - wsrep_ready_set(TRUE); - wsrep_inited= 1; - global_system_variables.wsrep_on = 0; - wsrep_init_args args; - args.logger_cb = wsrep_log_cb; - args.options = (wsrep_provider_options) ? - wsrep_provider_options : ""; - rcode = wsrep->init(wsrep, &args); - if (rcode) - { - DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); - WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); - wsrep->free(wsrep); - free(wsrep); - wsrep = NULL; - } - return rcode; + WSREP_INFO("node_address %s", wsrep_node_address); } - else + if (!(wsrep_node_address && strlen(wsrep_node_address))) { - global_system_variables.wsrep_on = 1; - strncpy(provider_name, - wsrep->provider_name, sizeof(provider_name) - 1); - strncpy(provider_version, - wsrep->provider_version, sizeof(provider_version) - 1); - strncpy(provider_vendor, - wsrep->provider_vendor, sizeof(provider_vendor) - 1); - } - - if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) - wsrep_data_home_dir = mysql_real_data_home; + 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; - if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) - { - size_t const ret= wsrep_guess_ip(node_addr, node_addr_max); - if (!(ret > 0 && ret < node_addr_max)) + char node_addr[512] = {0, }; + const size_t node_addr_max= sizeof(node_addr) - 1; + size_t guess_ip_ret= wsrep_guess_ip(node_addr, node_addr_max); + if (!(guess_ip_ret > 0 && guess_ip_ret < node_addr_max)) { WSREP_WARN("Failed to guess base node address. Set it explicitly via " "wsrep_node_address."); - node_addr[0]= '\0'; + } + else + { + ret = node_addr; } } else { - strncpy(node_addr, wsrep_node_address, node_addr_max); + ret = wsrep_node_address; } + return ret; +} - /* Initialize node's incoming address */ +static std::string wsrep_server_incoming_address() +{ + std::string ret; + const std::string node_addr(wsrep_server_node_address()); char inc_addr[512]= { 0, }; size_t const inc_addr_max= sizeof (inc_addr); @@ -704,22 +574,28 @@ int wsrep_init() } else /* mysqld binds to 0.0.0.0, try taking IP from wsrep_node_address. */ { - size_t const node_addr_len= strlen(node_addr); - if (node_addr_len > 0) + if (node_addr.size()) { - wsp::Address addr(node_addr); - - if (!addr.is_valid()) + size_t const ip_len= wsrep_host_len(node_addr.c_str(), node_addr.size()); + if (ip_len + 7 /* :55555\0 */ < inc_addr_max) { - WSREP_DEBUG("Could not parse node address : %s", node_addr); - WSREP_WARN("Guessing address for incoming client connections failed. " - "Try setting wsrep_node_incoming_address explicitly."); - goto done; + memcpy (inc_addr, node_addr.c_str(), ip_len); + snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u", + (int)mysqld_port); } + else + { + WSREP_WARN("Guessing address for incoming client connections: " + "address too long."); + inc_addr[0]= '\0'; + } + } - const char *fmt= (addr.is_ipv6()) ? "[%s]:%u" : "%s:%u"; - snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), - (int) mysqld_port); + if (!strlen(inc_addr)) + { + WSREP_WARN("Guessing address for incoming client connections failed. " + "Try setting wsrep_node_incoming_address explicitly."); + WSREP_INFO("Node addr: %s", node_addr.c_str()); } } } @@ -743,46 +619,152 @@ int wsrep_init() snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), port); } + + done: + ret = wsrep_node_incoming_address; + return ret; +} + +static std::string wsrep_server_working_dir() +{ + std::string ret; + if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) + { + ret = mysql_real_data_home; + } + else + { + ret = wsrep_data_home_dir; + } + return ret; +} + +static wsrep::gtid wsrep_server_initial_position() +{ + wsrep::gtid ret; + WSREP_INFO("Server initial position: %s", wsrep_start_position); + std::istringstream is(wsrep_start_position); + is >> ret; + return ret; +} + +int wsrep_init_server() +{ + try + { + const std::string server_name= wsrep_server_name(); + const std::string server_id= wsrep_server_id(); + const std::string node_address= wsrep_server_node_address(); + const std::string incoming_address= wsrep_server_incoming_address(); + const std::string working_dir= wsrep_server_working_dir(); + const wsrep::gtid initial_position= wsrep_server_initial_position(); + + Wsrep_server_state::init_once(server_name, + server_id, + incoming_address, + node_address, + working_dir, + initial_position, + wsrep_max_protocol_version); + } + catch (const wsrep::runtime_error& e) + { + WSREP_ERROR("Failed to init wsrep server %s", e.what()); + return 1; + } + catch (const std::exception& e) + { + WSREP_ERROR("Failed to init wsrep server %s", e.what()); + } + return 0; +} + +void wsrep_init_globals() +{ + wsrep_init_sidno(Wsrep_server_state::instance().connected_gtid().id()); + wsrep_init_schema(); + wsrep_recover_sr_from_storage(); + if (WSREP_ON) + { + Wsrep_server_state::instance().initialized(); + } +} -done: - struct wsrep_init_args wsrep_args; +void wsrep_deinit_server() +{ + Wsrep_server_state::destroy(); +} - struct wsrep_gtid const state_id = { local_uuid, local_seqno }; +int wsrep_init() +{ + const std::string server_name= wsrep_server_name(); + const std::string server_id= wsrep_server_id(); + const std::string node_address= wsrep_server_node_address(); + const std::string incoming_address= wsrep_server_incoming_address(); + const std::string working_dir= wsrep_server_working_dir(); - wsrep_args.data_dir = wsrep_data_home_dir; - wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; - wsrep_args.node_address = node_addr; - wsrep_args.node_incoming = inc_addr; - wsrep_args.options = (wsrep_provider_options) ? - wsrep_provider_options : ""; - wsrep_args.proto_ver = wsrep_max_protocol_version; + assert(wsrep_provider); - wsrep_args.state_id = &state_id; + wsrep_init_position(); + wsrep_sst_auth_init(); - wsrep_args.logger_cb = wsrep_log_cb; - wsrep_args.view_handler_cb = wsrep_view_handler_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; + if (strlen(wsrep_provider)== 0 || + !strcmp(wsrep_provider, WSREP_NONE)) + { + // enable normal operation in case no provider is specified + global_system_variables.wsrep_on = 0; + int err= Wsrep_server_state::instance().load_provider(wsrep_provider, wsrep_provider_options ? wsrep_provider_options : ""); + if (err) + { + DBUG_PRINT("wsrep",("wsrep::init() failed: %d", err)); + WSREP_ERROR("wsrep::init() failed: %d, must shutdown", err); + } + return err; + } - rcode = wsrep->init(wsrep, &wsrep_args); + global_system_variables.wsrep_on = 1; - if (rcode) + if (wsrep_gtid_mode && opt_bin_log && !opt_log_slave_updates) { - DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); - WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); - wsrep->free(wsrep); - free(wsrep); - wsrep = NULL; - } else { - wsrep_inited= 1; + WSREP_ERROR("Option --log-slave-updates is required if " + "binlog is enabled, GTID mode is on and wsrep provider " + "is specified"); + return 1; } - return rcode; -} + if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) + wsrep_data_home_dir = mysql_real_data_home; + if (Wsrep_server_state::instance().load_provider(wsrep_provider, + wsrep_provider_options)) + { + WSREP_ERROR("Failed to load provider"); + return 1; + } + + 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_server_state::instance().unload_provider(); + return 1; + } + wsrep_inited= 1; + + wsrep_capabilities_export(Wsrep_server_state::instance().provider().capabilities(), + &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"); + + return 0; +} /* Initialize wsrep thread LOCKs and CONDs */ void wsrep_thr_init() @@ -801,25 +783,28 @@ 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; } -void wsrep_init_startup (bool first) +extern int wsrep_on(void *); + +void wsrep_init_startup (bool sst_first) { if (wsrep_init()) unireg_abort(1); - 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); + wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_thd_bf_abort, + wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); /* Pre-initialize global_system_variables.table_plugin with a dummy engine @@ -838,31 +823,56 @@ void wsrep_init_startup (bool first) /* Skip replication start if no cluster address */ if (!wsrep_cluster_address || wsrep_cluster_address[0] == 0) return; - if (first) wsrep_sst_grab(); // do it so we can wait for SST below - + /* + Read value of wsrep_new_cluster before wsrep_start_replication(), + the value is reset to FALSE inside wsrep_start_replication. + */ if (!wsrep_start_replication()) unireg_abort(1); wsrep_create_rollbacker(); wsrep_create_appliers(1); - if (first && !wsrep_sst_wait()) unireg_abort(1);// wait until SST is completed + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + /* + If the SST happens before server initialization, wait until the server + state reaches initializing. This indicates that + either SST was not necessary or SST has been delivered. + + With mysqldump SST (!sst_first) wait until the server reaches + joiner state and procedd to accepting connections. + */ + if (sst_first) + { + server_state.wait_until_state(Wsrep_server_state::s_initializing); + } + else + { + server_state.wait_until_state(Wsrep_server_state::s_joiner); + } } -void wsrep_deinit(bool free_options) +void wsrep_deinit() { DBUG_ASSERT(wsrep_inited == 1); - wsrep_unload(wsrep); - wsrep= 0; + delete wsrep_schema; + wsrep_schema= 0; + WSREP_DEBUG("wsrep_deinit"); + delete wsrep_thd_pool; + wsrep_thd_pool= 0; + + Wsrep_server_state::instance().unload_provider(); provider_name[0]= '\0'; provider_version[0]= '\0'; provider_vendor[0]= '\0'; 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); } } @@ -871,28 +881,38 @@ 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]; - 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)); @@ -900,43 +920,72 @@ 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); + wsrep::gtid gtid= wsrep_get_SE_checkpoint(); + std::ostringstream oss; + oss << gtid; + WSREP_INFO("Recovered position: %s", oss.str().c_str()); } void wsrep_stop_replication(THD *thd) { WSREP_INFO("Stop replication"); - if (!wsrep) + if (Wsrep_server_state::instance().state() != + Wsrep_server_state::s_disconnected) + { + WSREP_DEBUG("Provider disconnect"); + Wsrep_server_state::instance().disconnect(); + Wsrep_server_state::instance().wait_until_state(Wsrep_server_state::s_disconnected); + } + + /* 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_server_state::instance().state() == wsrep::server_state::s_disconnected) { - WSREP_INFO("Provider was not loaded, in stop replication"); + 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_server_state::instance().disconnect(); wsrep_close_client_connections(TRUE); + // wsrep_close_SR_transactions(NULL); /* wait until appliers have stopped */ - wsrep_wait_appliers_close(thd); + wsrep_wait_appliers_close(NULL); + node_uuid= WSREP_UUID_UNDEFINED; - return; + 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 provider must be loaded. */ - DBUG_ASSERT(wsrep); + int rcode; + WSREP_DEBUG("wsrep_start_replication"); /* if provider is trivial, don't even try to connect, @@ -945,34 +994,27 @@ bool wsrep_start_replication() if (!WSREP_PROVIDER_EXISTS) { // enable normal operation in case no provider is specified - wsrep_ready_set(TRUE); return true; } if (!wsrep_cluster_address || wsrep_cluster_address[0]== 0) { // if provider is non-trivial, but no address is specified, wait for address - wsrep_ready_set(FALSE); return true; } - bool const bootstrap= wsrep_new_cluster; + bool const bootstrap(TRUE == wsrep_new_cluster); + wsrep_new_cluster= FALSE; WSREP_INFO("Start replication"); - if (wsrep_new_cluster) + if ((rcode= Wsrep_server_state::instance().connect( + wsrep_cluster_name, + wsrep_cluster_address, + wsrep_sst_donor, + bootstrap))) { - WSREP_INFO("'wsrep-new-cluster' option used, bootstrapping the cluster"); - wsrep_new_cluster= false; - } - - if ((rcode = wsrep->connect(wsrep, - wsrep_cluster_name, - wsrep_cluster_address, - wsrep_sst_donor, - bootstrap))) - { - DBUG_PRINT("wsrep",("wsrep->connect(%s) failed: %d", + DBUG_PRINT("wsrep",("wsrep_ptr->connect(%s) failed: %d", wsrep_cluster_address, rcode)); WSREP_ERROR("wsrep::connect(%s) failed: %d", wsrep_cluster_address, rcode); @@ -980,15 +1022,12 @@ bool wsrep_start_replication() } else { - wsrep_connected= TRUE; - - char* opts= wsrep->options_get(wsrep); - if (opts) + try { - wsrep_provider_options_init(opts); - free(opts); + std::string opts= Wsrep_server_state::instance().provider().options(); + wsrep_provider_options_init(opts.c_str()); } - else + catch (const wsrep::runtime_error&) { WSREP_WARN("Failed to get wsrep options"); } @@ -999,13 +1038,19 @@ 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_thd_data); + 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_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; + thd->wsrep_trx().state() != + wsrep::transaction::s_replaying && + thd->wsrep_cs().sync_wait_gtid().is_undefined(); + // thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; + mysql_mutex_unlock(&thd->LOCK_thd_data); + return ret; } bool wsrep_sync_wait (THD* thd, uint mask) @@ -1016,9 +1061,8 @@ 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); - - if (unlikely(WSREP_OK != ret)) + // enum wsrep::provider::status ret = wsrep_sync_wait_upto(thd, NULL, -1); + if (thd->wsrep_cs().sync_wait(-1)) { const char* msg; int err; @@ -1028,11 +1072,11 @@ bool wsrep_sync_wait (THD* thd, uint mask) // ER_FUNCTION_NOT_DEFINED, ER_NOT_ALLOWED_COMMAND, ER_NOT_SUPPORTED_YET, // ER_FEATURE_DISABLED, ER_QUERY_INTERRUPTED - switch (ret) + switch (thd->wsrep_cs().current_error()) { - case WSREP_NOT_IMPLEMENTED: + case wsrep::e_not_supported_error: msg= "synchronous reads by wsrep backend. " - "Please unset wsrep_causal_reads variable."; + "Please unset wsrep_causal_reads variable."; err= ER_NOT_SUPPORTED_YET; break; default: @@ -1050,6 +1094,27 @@ bool wsrep_sync_wait (THD* thd, uint mask) return false; } +enum wsrep::provider::status +wsrep_sync_wait_upto (THD* thd, + wsrep_gtid_t* upto, + int timeout) +{ + DBUG_ASSERT(upto); + enum wsrep::provider::status ret; + if (upto) + { + wsrep::gtid upto_gtid(wsrep::id(upto->uuid.data, sizeof(upto->uuid.data)), + wsrep::seqno(upto->seqno)); + ret= Wsrep_server_state::instance().wait_for_gtid(upto_gtid, timeout); + } + else + { + ret= Wsrep_server_state::instance().causal_read(timeout).second; + } + WSREP_DEBUG("wsrep_sync_wait_upto: %d", ret); + return ret; +} + void wsrep_keys_free(wsrep_key_arr_t* key_arr) { for (size_t i= 0; i < key_arr->keys_len; ++i) @@ -1073,9 +1138,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; @@ -1087,6 +1152,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db, case 1: case 2: case 3: + case 4: { *key_len= 0; if (db) @@ -1105,6 +1171,9 @@ 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; @@ -1124,7 +1193,6 @@ static bool wsrep_prepare_key_for_isolation(const char* db, tmp= (wsrep_key_t*)my_realloc(ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0)); - if (!tmp) { WSREP_ERROR("Can't allocate memory for key_array"); @@ -1224,7 +1292,6 @@ bool wsrep_prepare_keys_for_isolation(THD* thd, return wsrep_prepare_keys_for_isolation(thd, db, table, table_list, NULL, ka); } - 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) @@ -1245,6 +1312,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 ); @@ -1266,7 +1334,79 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len, return true; } +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) +{ + + return wsrep_prepare_key(cache_key, cache_key_len, row_id, row_id_len, key, key_len); +} + +wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table, + enum wsrep::key::type type) +{ + wsrep::key ret(type); + DBUG_ASSERT(db); + ret.append_key_part(db, strlen(db)); + if (table) ret.append_key_part(table, strlen(table)); + return ret; +} + +wsrep::key_array +wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db, + Alter_info* alter_info) + +{ + wsrep::key_array ret; + Key *key; + List_iterator<Key> key_iterator(alter_info->key_list); + while ((key= key_iterator++)) + { + if (key->type == Key::FOREIGN_KEY) + { + Foreign_key *fk_key= (Foreign_key *)key; + const char *db_name= fk_key->ref_db.str; + const char *table_name= fk_key->ref_table.str; + if (!db_name) + { + db_name= child_table_db; + } + ret.push_back(wsrep_prepare_key_for_toi(db_name, table_name, + wsrep::key::exclusive)); + } + } + return ret; +} +wsrep::key_array wsrep_prepare_keys_for_toi(const char* db, + const char* table, + const TABLE_LIST* table_list, + Alter_info* alter_info) +{ + wsrep::key_array ret; + if (db || table) + { + ret.push_back(wsrep_prepare_key_for_toi(db, table, wsrep::key::exclusive)); + } + for (const TABLE_LIST* table= table_list; table; table= table->next_global) + { + ret.push_back(wsrep_prepare_key_for_toi(table->db.str, table->table_name.str, + wsrep::key::exclusive)); + } + if (alter_info && (alter_info->flags & ALTER_ADD_FOREIGN_KEY)) + { + wsrep::key_array fk(wsrep_prepare_keys_for_alter_add_fk(table_list->db.str, alter_info)); + if (!fk.empty()) + { + ret.insert(ret.end(), fk.begin(), fk.end()); + } + } + return ret; +} /* * Construct Query_log_Event from thd query and serialize it * into buffer. @@ -1277,7 +1417,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; @@ -1496,9 +1636,14 @@ static int wsrep_drop_table_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_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. + */ /* Decide if statement should run in TOI. @@ -1596,249 +1741,427 @@ static const char* wsrep_get_query_or_msg(const THD* thd) } } -/* - returns: - 0: statement was replicated as TOI - 1: TOI replication was skipped - -1: TOI replication failed - */ -static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_, - const TABLE_LIST* table_list, - Alter_info* alter_info) +static bool wsrep_can_run_in_nbo(THD *thd) { - wsrep_status_t ret(WSREP_WARNING); - uchar* buf(0); - size_t buf_len(0); - int buf_err; - int rc= 0; + 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 int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) +{ + String log_query; + sp_head *sp = thd->lex->sphead; + sql_mode_t saved_mode= thd->variables.sql_mode; + String retstr(64); + LEX_CSTRING returns= empty_clex_str; + retstr.set_charset(system_charset_info); + + log_query.set_charset(system_charset_info); - if (wsrep_can_run_in_toi(thd, db_, table_, table_list) == false) + if (sp->m_handler->type() == TYPE_ENUM_FUNCTION) { - WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd)); + sp_returns_type(thd, retstr, sp); + returns= retstr.lex_cstring(); + } + if (sp->m_handler-> + show_create_sp(thd, &log_query, + sp->m_explicit_name ? sp->m_db : null_clex_str, + sp->m_name, sp->m_params, returns, + sp->m_body, sp->chistics(), + thd->lex->definer[0], + thd->lex->create_info, + saved_mode)) + { + WSREP_WARN("SP create string failed: schema: %s, query: %s", + thd->get_db(), thd->query()); return 1; } - WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd)); + return wsrep_to_buf_helper(thd, log_query.ptr(), log_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: - buf_err= create_view_query(thd, &buf, &buf_len); + 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); + err= wsrep_create_sp(thd, buf, buf_len); break; case SQLCOM_CREATE_TRIGGER: - buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len); + err= wsrep_create_trigger_query(thd, buf, buf_len); break; case SQLCOM_CREATE_EVENT: - buf_err= wsrep_create_event_query(thd, &buf, &buf_len); + err= wsrep_create_event_query(thd, buf, buf_len); break; case SQLCOM_ALTER_EVENT: - buf_err= wsrep_alter_event_query(thd, &buf, &buf_len); + err= wsrep_alter_event_query(thd, buf, buf_len); break; case SQLCOM_DROP_TABLE: - buf_err= wsrep_drop_table_query(thd, &buf, &buf_len); + err= wsrep_drop_table_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); + err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), buf, + buf_len); break; } - 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, alter_info, &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); - rc= -1; - } - else { - /* 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"); - rc= 1; - } - if (buf) my_free(buf); - return rc; + return err; } -static void wsrep_TOI_end(THD *thd) { - wsrep_status_t ret; - wsrep_to_isolation--; - - WSREP_DEBUG("TO END: %lld, %d: %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, wsrep_get_query_or_msg(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)); - } - else { - WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", - ret, - thd->get_db(), - (thd->query()) ? thd->query() : "void"); +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; } +#if 0 + /* todo */ + 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); +#endif /* 0 */ + wsrep::client_state& cs(thd->wsrep_cs()); + int const ret= cs.leave_toi(); + if (ret) + { + WSREP_ERROR("Leaving critical section for failed TOI failed: thd: %lld, " + "schema: %s, SQL: %s, rcode: %d wsrep_error: %s", + (long long)thd->real_id, thd->db.str, + thd->query(), ret, wsrep::to_c_string(cs.current_error())); + goto fail; + } } + return; +fail: + WSREP_ERROR("Failed to release TOI resources. Need to abort."); + unireg_abort(1); } -static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_) + +/* + returns: + 0: statement was replicated as TOI + 1: TOI replication was skipped + -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, + Alter_info* alter_info) { - 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() ); + /* FIXME: NBO is broken in this codepath */ + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI); + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI || + thd->variables.wsrep_OSU_method == WSREP_OSU_NBO); - ret = wsrep->desync(wsrep); - if (ret != WSREP_OK) + WSREP_DEBUG("TOI Begin"); + if (wsrep_can_run_in_toi(thd, db, table, table_list) == false) { - WSREP_WARN("RSU desync failed %d for schema: %s, query: %s", - ret, thd->get_db(), thd->query()); - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(ret); + WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd)); + return 1; } - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying++; - mysql_mutex_unlock(&LOCK_wsrep_replaying); - - if (wsrep_wait_committing_connections_close(5000)) + if (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO && + Wsrep_server_state::has_capability(wsrep::provider::capability::nbo)) { - /* no can do, bail out from DDL */ - WSREP_WARN("RSU failed due to pending transactions, schema: %s, query %s", - thd->get_db(), thd->query()); - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - mysql_mutex_unlock(&LOCK_wsrep_replaying); - - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("resync failed %d for schema: %s, query: %s", - ret, thd->get_db(), thd->query()); - } - - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(1); + 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; } - wsrep_seqno_t seqno = wsrep->pause(wsrep); - if (seqno == WSREP_SEQNO_UNDEFINED) + 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_WARN("pause failed %lld for schema: %s, query: %s", (long long)seqno, - thd->get_db(), thd->query()); - return(1); + 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; } - WSREP_DEBUG("paused at %lld", (long long)seqno); - thd->variables.wsrep_on = 0; - return 0; -} -static void wsrep_RSU_end(THD *thd) -{ - wsrep_status_t ret(WSREP_WARNING); - WSREP_DEBUG("RSU END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, thd->query() ); + 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); + 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 }; - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - mysql_mutex_unlock(&LOCK_wsrep_replaying); + wsrep::key_array key_array= + wsrep_prepare_keys_for_toi(db, table, table_list, alter_info); - ret = wsrep->resume(wsrep); - if (ret != WSREP_OK) + /* wsrep_can_run_in_toi() should take care of checking that + DDLs with only temp tables should not be TOId at all */ + if (key_array.size() == 0) { - WSREP_WARN("resume failed %d for schema: %s, query: %s", ret, - thd->get_db(), thd->query()); + /* non replicated DDL, affecting temporary tables only */ + WSREP_DEBUG("TO isolation skipped, sql: %s." + "Only temporary tables affected.", + WSREP_QUERY(thd)); + if (buf) my_free(buf); + return -1; } - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) + thd_proc_info(thd, "acquiring total order isolation"); + wait_start= time(NULL); + wsrep::client_state& cs(thd->wsrep_cs()); + int ret; + do { - WSREP_WARN("resync failed %d for schema: %s, query: %s", ret, - thd->get_db(), thd->query()); - return; - } + ret= cs.enter_toi(key_array, + wsrep::const_buffer(buff.ptr, buff.len), + wsrep::provider::flag::start_transaction | + wsrep::provider::flag::commit); + if (thd->killed != NOT_KILLED) break; - thd->variables.wsrep_on = 1; -} + if (ret) + { + DBUG_ASSERT(cs.current_error()); + WSREP_DEBUG("to_execute_start() failed for %llu: %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 && cs.current_error() == wsrep::e_error_during_commit /* ? */ && run_in_nbo); -int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, - const TABLE_LIST* table_list, - Alter_info* alter_info) -{ - int ret= 0; + if (ret) { + /* jump to error handler in mysql_execute_command() */ + switch (cs.current_error()) + { + case wsrep::e_size_exceeded_error: + 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 { - /* - No isolation for applier or replaying threads. - */ - if (thd->wsrep_exec_mode == REPL_RECV) - return 0; + 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()); + ::abort(); + } - mysql_mutex_lock(&thd->LOCK_thd_data); + // thd->wsrep_exec_mode= TOTAL_ORDER; + ++wsrep_to_isolation; - 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()); - mysql_mutex_unlock(&thd->LOCK_thd_data); - return WSREP_TRX_FAIL; + // WSREP_DEBUG("TO BEGIN(%lu): %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; + } } - mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); + if (buf) my_free(buf); - if (thd->global_read_lock.can_acquire_protection()) + switch(rc) { - WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld", - thd->query(), (longlong) thd->thread_id); - return -1; - } - - if (wsrep_debug && thd->mdl_context.has_locks()) + case 0: + break; + case -2: { - WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lld", - thd->query(), (longlong) thd->thread_id); + 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); } - /* - It makes sense to set auto_increment_* to defaults in TOI operations. - Must be done before wsrep_TOI_begin() since Query_log_event encapsulating + return rc; +} + +static void wsrep_TOI_end(THD *thd) { + int ret; + wsrep_to_isolation--; + wsrep::client_state& client_state(thd->wsrep_cs()); + DBUG_ASSERT(wsrep_thd_is_local_toi(thd)); + WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(), + WSREP_QUERY(thd)); + + if (wsrep_thd_is_local_toi(thd)) + { + wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); + 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_ptr->to_execute_end(wsrep_ptr, thd->thread_id, &tmp); + client_state.leave_toi(); + } + else + { + ret= client_state.leave_toi(); + } + + if (ret == 0) + { + WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get()); + } + else + { + WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", + ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd)); + } + } + + if (thd->wsrep_nbo_ctx) + { + delete thd->wsrep_nbo_ctx; + thd->wsrep_nbo_ctx= NULL; + } +} + +static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_) +{ + WSREP_DEBUG("RSU BEGIN: %lld, : %s", wsrep_thd_trx_seqno(thd), + WSREP_QUERY(thd)); + if (thd->wsrep_cs().begin_rsu(5000)) + { + WSREP_WARN("RSU begin failed"); + } + else + { + thd->variables.wsrep_on = 0; + } + return 0; +} + +static void wsrep_RSU_end(THD *thd) +{ + WSREP_DEBUG("RSU END: %ld : %s", wsrep_thd_trx_seqno(thd), + WSREP_QUERY(thd)); + if (thd->wsrep_cs().end_rsu()) + { + WSREP_WARN("Failed to end RSU, server may need to be restarted"); + } + thd->variables.wsrep_on = 1; +} + +int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, + const TABLE_LIST* table_list, + Alter_info* alter_info) +{ + /* + No isolation for applier or replaying threads. + */ + if (!wsrep_thd_is_local(thd)) return 0; + + int ret= 0; + mysql_mutex_lock(&thd->LOCK_thd_data); + + if (thd->wsrep_trx().state() == wsrep::transaction::s_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()); + mysql_mutex_unlock(&thd->LOCK_thd_data); + return WSREP_TRX_FAIL; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); + + DBUG_ASSERT(wsrep_thd_is_local(thd)); + DBUG_ASSERT(thd->wsrep_trx().ws_meta().seqno().is_undefined()); + + if (thd->global_read_lock.can_acquire_protection()) + { + WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu", + 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 %llu", + WSREP_QUERY(thd), thd->thread_id); + } + + /* + It makes sense to set auto_increment_* to defaults in TOI operations. + Must be done before wsrep_TOI_begin() since Query_log_event encapsulating TOI statement and auto inc variables for wsrep replication is constructed there. Variables are reset back in THD::reset_for_next_command() before processing of next command. @@ -1849,14 +2172,15 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, thd->variables.auto_increment_increment = 1; } - if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) + if (thd->variables.wsrep_on && wsrep_thd_is_local(thd)) { switch (thd->variables.wsrep_OSU_method) { case WSREP_OSU_TOI: + case WSREP_OSU_NBO: ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info); 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", @@ -1865,7 +2189,7 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, break; } switch (ret) { - case 0: thd->wsrep_exec_mode= TOTAL_ORDER; break; + case 0: /* wsrep_TOI_begin sould set toi mode */ break; case 1: /* TOI replication skipped, treat as success */ ret = 0; @@ -1875,38 +2199,137 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, break; } } + return ret; } void wsrep_to_isolation_end(THD *thd) { - if (thd->wsrep_exec_mode == TOTAL_ORDER) + DBUG_ASSERT(wsrep_thd_is_local_toi(thd) || + wsrep_thd_is_in_rsu(thd)); + if (wsrep_thd_is_local_toi(thd)) + { + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI); + wsrep_TOI_end(thd); + } + else if (wsrep_thd_is_in_rsu(thd)) + { + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_RSU); + wsrep_RSU_end(thd); + } + else + { + DBUG_ASSERT(0); + } + if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd); +} + +void wsrep_begin_nbo_unlock(THD* thd) +{ + DBUG_ASSERT(0); +#if 0 + DBUG_ASSERT(thd->wsrep_nbo_ctx); + if (wsrep_thd_is_toi(thd)) + { + if (wsrep_ptr->to_execute_end(wsrep_ptr, thd->thread_id, NULL) != WSREP_OK) { + WSREP_ERROR("Non-blocking operation failed to release provider " + "resources, cannot continue"); + unireg_abort(1); + } + } + else if (wsrep_thd_is_applying(thd)) { - switch(thd->variables.wsrep_OSU_method) + thd->wsrep_nbo_ctx->signal(); + } + thd->wsrep_nbo_ctx->set_toi_released(true); +#endif +} + +void wsrep_end_nbo_lock(THD* thd, const TABLE_LIST *table_list) +{ + DBUG_ASSERT(0); +#if 0 + 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(wsrep_thd_is_toi(thd) || wsrep_thd_is_applying(thd)); + 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_ptr->to_execute_start(wsrep_ptr, 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) { - case WSREP_OSU_TOI: 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); + WSREP_ERROR("Lock wait timeout while waiting NBO end to replicate."); break; } - wsrep_cleanup_transaction(thd); } + + 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_ptr->free_connection(wsrep_ptr, thd->thread_id); + wsrep_ptr->disconnect(wsrep_ptr); + // 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); +#endif } #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: (%llu \tseqno %lld \twsrep (%s, %s, %s) cmd %d %d \t%s)\n" \ + "granted: (%llu \tseqno %lld \twsrep (%s, %s, %s) 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, \ + req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ + wsrep_thd_client_mode_str(req), wsrep_thd_client_state_str(req), wsrep_thd_transaction_state_str(req), \ 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, \ + gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ + wsrep_thd_client_mode_str(gra), wsrep_thd_client_state_str(gra), wsrep_thd_transaction_state_str(gra), \ gra->get_command(), gra->lex->sql_command, gra->query()); /** @@ -1934,43 +2357,35 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, int schema_len= key->db_name_length(); mysql_mutex_lock(&request_thd->LOCK_thd_data); + if (wsrep_thd_is_toi(request_thd) || + wsrep_thd_is_applying(request_thd)) { - /* - We consider granting MDL exceptions only for appliers (BF THD) and ones - executing under TOI mode. - - Rules: - 1. If granted/owner THD is also an applier (BF THD) or one executing - under TOI mode, then we grant the requested lock to the requester - THD. - @return true - - 2. If granted/owner THD is executing a FLUSH command or already has an - explicit lock, then do not grant the requested lock to the requester - THD and it has to wait. - @return false - - 3. In all other cases the granted/owner THD is aborted and the requested - lock is not granted to the requester THD, thus it has to wait. - @return false - */ - if (request_thd->wsrep_exec_mode == TOTAL_ORDER || - 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); ticket->wsrep_report(wsrep_debug); mysql_mutex_lock(&granted_thd->LOCK_thd_data); - if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || - granted_thd->wsrep_exec_mode == REPL_RECV) + if (wsrep_thd_is_toi(granted_thd) || + wsrep_thd_is_applying(granted_thd)) { - 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_thd_data); + 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_thd_data); + ret = TRUE; + } } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH || granted_thd->mdl_context.has_explicit_locks()) @@ -1978,173 +2393,60 @@ 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, conf %s", + wsrep_thd_transaction_state_str(granted_thd)); + ticket->wsrep_report(wsrep_debug); + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + 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_trx().active()) { - 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) + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + wsrep_abort_thd(request_thd, granted_thd, 1); + ret= FALSE; + } + else + { + /* + Granted_thd is likely executing with wsrep_on=0. If the requesting + thd is BF, BF abort and wait. + */ + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + if (wsrep_thd_is_BF(request_thd, FALSE)) { - WSREP_DEBUG("MDL granted, but committing thd abort scheduled"); + ha_abort_transaction(request_thd, granted_thd, TRUE); + ret= FALSE; } else { - WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len, - request_thd, granted_thd); + DBUG_ASSERT(0); + ret= TRUE; } - ticket->wsrep_report(true); } - - 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; } - -pthread_handler_t start_wsrep_THD(void *arg) -{ - THD *thd; - wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; - - if (my_thread_init() || (!(thd= new THD(next_thread_id(), true)))) - { - goto error; - } - - mysql_mutex_lock(&LOCK_thread_count); - - if (wsrep_gtid_mode) - { - /* Adjust domain_id. */ - thd->variables.gtid_domain_id= wsrep_gtid_domain_id; - } - - thd->real_id=pthread_self(); // Keep purify happy - thread_created++; - threads.append(thd); - - my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0)); - - DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); - thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); - (void) mysql_mutex_unlock(&LOCK_thread_count); - - /* from bootstrap()... */ - thd->bootstrap=1; - thd->max_client_packet_length= thd->net.max_packet; - thd->security_ctx->master_access= ~(ulong)0; - - /* from handle_one_connection... */ - pthread_detach_this_thread(); - - mysql_thread_set_psi_id(thd->thread_id); - thd->thr_create_utime= microsecond_interval_timer(); - if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); - goto error; - } - -// </5.1.17> - /* - handle_one_connection() is normally the only way a thread would - start and would always be on the very high end of the stack , - therefore, the thread stack always starts at the address of the - first local variable of handle_one_connection, which is thd. We - need to know the start of the stack so that we could check for - stack overruns. - */ - DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n", - (long long)thd->thread_id)); - /* now that we've called my_thread_init(), it is safe to call DBUG_* */ - - thd->thread_stack= (char*) &thd; - if (thd->store_globals()) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); - goto error; - } - - thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; - thd->security_ctx->skip_grants(); - - /* handle_one_connection() again... */ - //thd->version= refresh_version; - thd->proc_info= 0; - thd->set_command(COM_SLEEP); - thd->init_for_queries(); - - mysql_mutex_lock(&LOCK_thread_count); - wsrep_running_threads++; - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - - processor(thd); - - close_connection(thd, 0); - - mysql_mutex_lock(&LOCK_thread_count); - wsrep_running_threads--; - WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - - // Note: We can't call THD destructor without crashing - // if plugins have not been initialized. However, in most of the - // cases this means that pre SE initialization SST failed and - // we are going to exit anyway. - if (plugins_are_initialized) - { - net_end(&thd->net); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1)); - } - else - { - // TODO: lightweight cleanup to get rid of: - // 'Error in my_thread_global_end(): 2 threads didn't exit' - // at server shutdown - } - - unlink_not_visible_thd(thd); - delete thd; - my_thread_end(); - return(NULL); - -error: - WSREP_ERROR("Failed to create/initialize system thread"); - - /* Abort if its the first applier/rollbacker thread. */ - if (!mysqld_server_initialized) - unireg_abort(1); - else - return NULL; -} - - /**/ static bool abort_replicated(THD *thd) { bool ret_code= false; - if (thd->wsrep_query_state== QUERY_COMMITTING) + if (thd->wsrep_trx().state() == wsrep::transaction::s_committing) { WSREP_DEBUG("aborting replicated trx: %llu", (ulonglong)(thd->real_id)); @@ -2154,38 +2456,34 @@ static bool abort_replicated(THD *thd) return ret_code; } - /**/ static inline bool is_client_connection(THD *thd) { return (thd->wsrep_client_thread && thd->variables.wsrep_on); } - 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_trx().state() == wsrep::transaction::s_replaying) ? true : false; mysql_mutex_unlock(&thd->LOCK_thd_data); return ret; } - 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_trx().state() == wsrep::transaction::s_committing) ? true : false; mysql_mutex_unlock(&thd->LOCK_thd_data); return ret; } - static bool have_client_connections() { THD *tmp; @@ -2222,7 +2520,6 @@ static void wsrep_close_thread(THD *thd) } } - static my_bool have_committing_connections() { THD *tmp; @@ -2236,6 +2533,7 @@ static my_bool have_committing_connections() if (is_committing_connection(tmp)) { + mysql_mutex_unlock(&LOCK_thread_count); return TRUE; } } @@ -2243,7 +2541,6 @@ static my_bool have_committing_connections() return FALSE; } - int wsrep_wait_committing_connections_close(int wait_time) { int sleep_time= 100; @@ -2261,8 +2558,7 @@ 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 @@ -2284,6 +2580,12 @@ void wsrep_close_client_connections(my_bool wait_to_end) if (!is_client_connection(tmp)) continue; + if (tmp == except_caller_thd) + { + DBUG_ASSERT(is_client_connection(tmp)); + continue; + } + if (is_replaying_connection(tmp)) { tmp->set_killed(KILL_CONNECTION); @@ -2313,7 +2615,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); @@ -2344,7 +2647,6 @@ void wsrep_close_applier(THD *thd) wsrep_close_thread(thd); } - void wsrep_close_threads(THD *thd) { THD *tmp; @@ -2370,278 +2672,210 @@ 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) - // 1 is for rollbacker thread which needs to be killed explicitly. + while (wsrep_running_threads > 2) + // 2 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. { if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) { mysql_mutex_unlock(&LOCK_thread_count); - my_sleep(100); - mysql_mutex_lock(&LOCK_thread_count); - } - else - mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); - DBUG_PRINT("quit",("One applier died (count=%u)",thread_count)); - } - mysql_mutex_unlock(&LOCK_thread_count); - /* Now kill remaining wsrep threads: rollbacker */ - wsrep_close_threads (thd); - /* and wait for them to die */ - mysql_mutex_lock(&LOCK_thread_count); - while (wsrep_running_threads > 0) - { - if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) - { - mysql_mutex_unlock(&LOCK_thread_count); - my_sleep(100); - mysql_mutex_lock(&LOCK_thread_count); - } - else - mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); - DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); - } - mysql_mutex_unlock(&LOCK_thread_count); - - /* All wsrep applier threads have now been aborted. However, if this thread - is also applier, we are still running... - */ -} - - -void wsrep_kill_mysql(THD *thd) -{ - if (mysqld_server_started) - { - if (!shutdown_in_progress) - { - WSREP_INFO("starting shutdown"); - kill_mysql(); - } - } - else - { - unireg_abort(1); - } -} - - -static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) -{ - String log_query; - sp_head *sp = thd->lex->sphead; - sql_mode_t saved_mode= thd->variables.sql_mode; - String retstr(64); - LEX_CSTRING returns= empty_clex_str; - retstr.set_charset(system_charset_info); - - log_query.set_charset(system_charset_info); - - if (sp->m_handler->type() == TYPE_ENUM_FUNCTION) - { - sp_returns_type(thd, retstr, sp); - returns= retstr.lex_cstring(); - } - if (sp->m_handler-> - show_create_sp(thd, &log_query, - sp->m_explicit_name ? sp->m_db : null_clex_str, - sp->m_name, sp->m_params, returns, - sp->m_body, sp->chistics(), - thd->lex->definer[0], - thd->lex->create_info, - saved_mode)) - { - WSREP_WARN("SP create string failed: schema: %s, query: %s", - thd->get_db(), thd->query()); - return 1; - } - - return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); -} - - -extern int wsrep_on(THD *thd) -{ - return (int)(WSREP(thd)); -} - - -extern "C" bool wsrep_thd_is_wsrep_on(THD *thd) -{ - return thd->variables.wsrep_on; -} - - -bool wsrep_consistency_check(THD *thd) -{ - return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; -} - - -extern "C" 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; -} - - -enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd) -{ - return thd->wsrep_exec_mode; -} - + my_sleep(100); + mysql_mutex_lock(&LOCK_thread_count); + } + else + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + DBUG_PRINT("quit",("One applier died (count=%u)",thread_count)); + } + mysql_mutex_unlock(&LOCK_thread_count); + /* Now kill remaining wsrep threads: rollbacker */ + wsrep_close_threads (thd); + /* and wait for them to die */ + mysql_mutex_lock(&LOCK_thread_count); + while (wsrep_running_threads > 0) + { + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_unlock(&LOCK_thread_count); + my_sleep(100); + mysql_mutex_lock(&LOCK_thread_count); + } + else + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); + } + mysql_mutex_unlock(&LOCK_thread_count); -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"; + /* All wsrep applier threads have now been aborted. However, if this thread + is also applier, we are still running... + */ } - -enum wsrep_query_state wsrep_thd_query_state(THD *thd) +void wsrep_kill_mysql(THD *thd) { - return thd->wsrep_query_state; + if (mysqld_server_started) + { + if (!shutdown_in_progress) + { + WSREP_INFO("starting shutdown"); + kill_mysql(); + } + } + else + { + unireg_abort(1); + } } - -const char *wsrep_thd_query_state_str(THD *thd) +void +wsrep_last_committed_id(wsrep_gtid_t* gtid) { - 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"; + // wsrep_ptr->last_committed_id(wsrep_ptr, gtid); + wsrep::gtid ret= Wsrep_server_state::instance().last_committed_gtid(); + memcpy(gtid->uuid.data, ret.id().data(), sizeof(gtid->uuid.data)); + gtid->seqno= ret.seqno().get(); } - -enum wsrep_conflict_state wsrep_thd_get_conflict_state(THD *thd) +void +wsrep_node_uuid(wsrep_uuid_t& uuid) { - return thd->wsrep_conflict_state; + uuid = node_uuid; } - -const char *wsrep_thd_conflict_state_str(THD *thd) +int wsrep_must_ignore_error(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"; -} - + const int error= thd->get_stmt_da()->sql_errno(); + const uint flags= sql_command_flags[thd->lex->sql_command]; -wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd) -{ - return &thd->wsrep_ws_handle; -} + DBUG_ASSERT(error); + DBUG_ASSERT((wsrep_thd_is_toi(thd)) || + (wsrep_thd_is_applying(thd) && thd->wsrep_apply_toi)); + if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_DDL)) + goto ignore_error; -void wsrep_thd_LOCK(THD *thd) -{ - mysql_mutex_lock(&thd->LOCK_thd_data); -} + 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; -void wsrep_thd_UNLOCK(THD *thd) -{ - mysql_mutex_unlock(&thd->LOCK_thd_data); +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; } - -extern "C" time_t wsrep_thd_query_start(THD *thd) +int wsrep_ignored_error_code(Log_event* ev, int error) { - return thd->query_start(); -} + const THD* thd= ev->thd; + DBUG_ASSERT(error); + DBUG_ASSERT(wsrep_thd_is_applying(thd) && + !wsrep_thd_is_local_toi(thd)); -extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd) -{ - return thd->wsrep_rand; -} - -longlong wsrep_thd_trx_seqno(THD *thd) -{ - return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED; -} + 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; + } + return 0; -extern "C" query_id_t wsrep_thd_query_id(THD *thd) -{ - return thd->query_id; +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; } - -char *wsrep_thd_query(THD *thd) +bool wsrep_provider_is_SR_capable() { - return (thd) ? thd->query() : NULL; + return Wsrep_server_state::has_capability(wsrep::provider::capability::streaming); } -extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) +int wsrep_ordered_commit_if_no_binlog(THD* thd, bool all) { - return thd->wsrep_last_query_id; + if (((wsrep_thd_is_local(thd) && WSREP_EMULATE_BINLOG(thd)) || + (wsrep_thd_is_applying(thd) && !opt_log_slave_updates && !opt_bin_log)) + && wsrep_thd_trx_seqno(thd) > 0) + { + wsrep_apply_error unused; + return wsrep_ordered_commit(thd, all, unused); + } + return 0; } - -extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) +wsrep_status_t wsrep_tc_log_commit(THD* thd) { - thd->wsrep_last_query_id= id; -} + int cookie; + my_xid xid= thd->transaction.xid_state.xid.get_my_xid(); + DBUG_ASSERT(thd->lex->sql_command == SQLCOM_LOAD); + cookie= tc_log->log_and_order(thd, xid, 1, false, true); + if (!cookie) + { + WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie); + return WSREP_TRX_FAIL; + } + if (tc_log->unlog(cookie, xid)) + { + WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie); + return WSREP_TRX_FAIL; + } -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) -{ - if (signal) + if (wsrep_after_statement(thd)) { - thd->awake(KILL_QUERY); + return WSREP_TRX_FAIL; } - else + /* 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); + } + if (wsrep_start_transaction(thd, thd->wsrep_next_trx_id())) { - mysql_mutex_lock(&LOCK_wsrep_replaying); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); + return WSREP_TRX_FAIL; } + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + return WSREP_OK; } - int wsrep_thd_retry_counter(THD *thd) { return(thd->wsrep_retry_counter); } - -extern "C" bool wsrep_thd_ignore_table(THD *thd) +extern bool wsrep_thd_ignore_table(THD *thd) { return thd->wsrep_ignore_table; } - -extern int -wsrep_trx_order_before(THD *thd1, THD *thd2) +extern my_bool +wsrep_trx_order_before(const void* thd1_ptr, const void* thd2_ptr) { + THD *thd1= (THD*) thd1_ptr; + THD *thd2= (THD*) thd2_ptr; + if (wsrep_thd_trx_seqno(thd1) < wsrep_thd_trx_seqno(thd2)) { WSREP_DEBUG("BF conflict, order: %lld %lld\n", (long long)wsrep_thd_trx_seqno(thd1), @@ -2654,39 +2888,11 @@ wsrep_trx_order_before(THD *thd1, 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; -} - - -void wsrep_copy_query(THD *thd) -{ - thd->wsrep_retry_command = thd->get_command(); - thd->wsrep_retry_query_len = thd->query_length(); - if (thd->wsrep_retry_query) { - my_free(thd->wsrep_retry_query); - } - thd->wsrep_retry_query = (char *)my_malloc( - thd->wsrep_retry_query_len + 1, MYF(0)); - strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len); - thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0'; -} - - bool wsrep_is_show_query(enum enum_sql_command command) { DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0; } - bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, HA_CREATE_INFO *create_info) @@ -2736,8 +2942,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, return (true); } - -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; @@ -2792,6 +2997,142 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) buf, buf_len); } +void* start_wsrep_THD(void *arg) +{ + THD *thd; + //wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; + + Wsrep_thd_args* thd_args= (Wsrep_thd_args*) arg; + + if (my_thread_init() || (!(thd= new THD(next_thread_id(), true)))) + { + goto error; + } + + mysql_mutex_lock(&LOCK_thread_count); + + if (wsrep_gtid_mode) + { + /* Adjust domain_id. */ + thd->variables.gtid_domain_id= wsrep_gtid_domain_id; + } + + thd->real_id=pthread_self(); // Keep purify happy + thread_created++; + threads.append(thd); + + my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0)); + + DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); + thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); + (void) mysql_mutex_unlock(&LOCK_thread_count); + + /* from bootstrap()... */ + thd->bootstrap=1; + thd->max_client_packet_length= thd->net.max_packet; + thd->security_ctx->master_access= ~(ulong)0; + + /* from handle_one_connection... */ + pthread_detach_this_thread(); + + mysql_thread_set_psi_id(thd->thread_id); + thd->thr_create_utime= microsecond_interval_timer(); + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) + { + close_connection(thd, ER_OUT_OF_RESOURCES); + statistic_increment(aborted_connects,&LOCK_status); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + goto error; + } + +// </5.1.17> + /* + handle_one_connection() is normally the only way a thread would + start and would always be on the very high end of the stack , + therefore, the thread stack always starts at the address of the + first local variable of handle_one_connection, which is thd. We + need to know the start of the stack so that we could check for + stack overruns. + */ + DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n", + (long long)thd->thread_id)); + /* now that we've called my_thread_init(), it is safe to call DBUG_* */ + + thd->thread_stack= (char*) &thd; + if (thd->store_globals()) + { + 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; + } + + thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; + thd->security_ctx->skip_grants(); + + /* handle_one_connection() again... */ + //thd->version= refresh_version; + thd->proc_info= 0; + thd->set_command(COM_SLEEP); + thd->init_for_queries(); + + mysql_mutex_lock(&LOCK_thread_count); + wsrep_running_threads++; + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + WSREP_DEBUG("wsrep system thread %ld, %p starting", + thd->thread_id, thd); + thd_args->fun()(thd, thd_args->args()); + + WSREP_DEBUG("wsrep system thread: %ld, %p closing", + thd->thread_id, thd); + //processor(thd); + + 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); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + // Note: We can't call THD destructor without crashing + // if plugins have not been initialized. However, in most of the + // cases this means that pre SE initialization SST failed and + // we are going to exit anyway. + if (plugins_are_initialized) + { + net_end(&thd->net); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1)); + } + else + { + // TODO: lightweight cleanup to get rid of: + // 'Error in my_thread_global_end(): 2 threads didn't exit' + // at server shutdown + } + + unlink_not_visible_thd(thd); + delete thd; + my_thread_end(); + return(NULL); + +error: + WSREP_ERROR("Failed to create/initialize system thread"); + + /* Abort if its the first applier/rollbacker thread. */ + if (!mysqld_server_initialized) + unireg_abort(1); + else + return NULL; +} + + /***** callbacks for wsrep service ************/ my_bool get_wsrep_debug() @@ -2824,56 +3165,17 @@ my_bool get_wsrep_log_conflicts() return wsrep_log_conflicts; } -wsrep_t *get_wsrep() +bool wsrep_consistency_check(THD *thd) { - return wsrep; + return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; } +//wsrep_t *get_wsrep() +//{ +// return wsrep; +//} + my_bool get_wsrep_certify_nonPK() { return wsrep_certify_nonPK; } - -void wsrep_lock_rollback() -{ - mysql_mutex_lock(&LOCK_wsrep_rollback); -} - -void wsrep_unlock_rollback() -{ - mysql_cond_signal(&COND_wsrep_rollback); - mysql_mutex_unlock(&LOCK_wsrep_rollback); -} - -my_bool wsrep_aborting_thd_contains(THD *thd) -{ - mysql_mutex_assert_owner(&LOCK_wsrep_rollback); - wsrep_aborting_thd_t abortees = wsrep_aborting_thd; - while (abortees) - { - if (abortees->aborting_thd == thd) - return true; - abortees = abortees->next; - } - return false; -} - -void wsrep_aborting_thd_enqueue(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; -} - -bool wsrep_node_is_donor() -{ - return (WSREP_ON) ? (wsrep_config_state->get_status() == 2) : false; -} - -bool wsrep_node_is_synced() -{ - return (WSREP_ON) ? (wsrep_config_state->get_status() == 4) : false; -} diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 819a56b9f23..09f09d495e0 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 @@ -19,18 +19,23 @@ #define WSREP_MYSQLD_H #include <mysql/plugin.h> -#include <mysql/service_wsrep.h> +#include "mysql/service_wsrep.h" -#ifdef WITH_WSREP +#include <my_global.h> +#include <my_pthread.h> +#include "log.h" +#include "mysqld.h" 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 "../wsrep-lib/include/wsrep/provider.hpp" +#include "../wsrep-lib/wsrep/wsrep_api.h" +#include <vector> + #define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX class set_var; @@ -42,20 +47,8 @@ enum wsrep_consistency_check_mode { 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; +// extern wsrep_t* wsrep_ptr; // MySQL wsrep options extern const char* wsrep_provider; @@ -69,24 +62,34 @@ extern const char* wsrep_data_home_dir; extern const char* wsrep_dbug_option; extern long wsrep_slave_threads; extern int wsrep_slave_count_change; +extern MYSQL_PLUGIN_IMPORT my_bool wsrep_debug; extern my_bool wsrep_convert_LOCK_to_trx; extern ulong wsrep_retry_autocommit; extern my_bool wsrep_auto_increment_control; +extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_incremental_data_collection; 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 my_bool wsrep_certify_nonPK; +extern long int wsrep_protocol_version; extern ulong wsrep_forced_binlog_format; extern my_bool wsrep_desync; extern ulong wsrep_reject_queries; +extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; +extern my_bool wsrep_log_conflicts; extern ulong wsrep_mysql_replication_bundle; +extern my_bool wsrep_load_data_splitting; 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 +104,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 +118,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,11 +138,22 @@ 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); +void wsrep_update_cluster_state_uuid(const char* str); + +/* Filters out --wsrep-new-cluster oprtion from argv[] + * should be called in the very beginning of main() */ +void wsrep_filter_new_cluster (int* argc, char* argv[]); -int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); int wsrep_init(); -void wsrep_deinit(bool free_options); +void wsrep_deinit(); /* Initialize wsrep thread LOCKs and CONDs */ void wsrep_thr_init(); @@ -147,51 +170,60 @@ 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 void wsrep_close_client_connections(my_bool wait_to_end, + THD *except_caller_thd = NULL); +//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); -extern void wsrep_close_client_connections(my_bool wait_to_end); 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 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 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 enum wsrep::provider::status +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; - #define WSREP_ON \ - (global_system_variables.wsrep_on) - -#define WSREP_ON_NEW \ ((global_system_variables.wsrep_on) && \ wsrep_provider && \ strcmp(wsrep_provider, WSREP_NONE)) -#define WSREP(thd) \ +/* 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 && thd->variables.wsrep_on) +#define WSREP(thd) \ + (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) @@ -200,27 +232,42 @@ extern wsrep_seqno_t wsrep_locked_seqno; ? wsrep_forced_binlog_format : (ulong)(my_format)) // prefix all messages with "WSREP" -void wsrep_log(void (*fun)(const char *, ...), const char *format, ...); -#define WSREP_LOG(fun, ...) wsrep_log(fun, ## __VA_ARGS__) -#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 " \ - " SQL: %s", \ - role, thd_get_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) \ - ); - -#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \ - if (wsrep_debug || wsrep_log_conflicts) \ - { \ - WSREP_LOG(sql_print_information, "cluster conflict due to %s for threads:",\ - (bf_abort) ? "high priority abort" : "certification failure" \ - ); \ - if (bf_thd != NULL) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ - if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ +#define WSREP_LOG(fun, ...) \ + do { \ + char msg[1024] = {'\0'}; \ + snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \ + fun("WSREP: %s", msg); \ + } while(0) + +#define WSREP_DEBUG(...) \ + if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) +#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__) +#define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__) +#define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__) + +#define WSREP_LOG_CONFLICT_THD(thd, role) \ + WSREP_LOG(sql_print_information, \ + "%s: \n " \ + " THD: %llu, mode: %s, state: %s, conflict: %s, seqno: %ld\n " \ + " SQL: %s", \ + role, \ + wsrep_thd_thread_id(thd), \ + wsrep_thd_client_mode_str(thd), \ + wsrep_thd_client_state_str(thd), \ + wsrep_thd_transaction_state_str(thd), \ + wsrep_thd_trx_seqno(thd), \ + wsrep_thd_query(thd) \ + ); + +#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \ + if (wsrep_debug || wsrep_log_conflicts) \ + { \ + WSREP_LOG(sql_print_information, "cluster conflict due to %s for threads:", \ + (bf_abort) ? "high priority abort" : "certification failure" \ + ); \ + if (bf_thd) 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,17 +278,34 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...); extern my_bool wsrep_ready_get(); extern void wsrep_ready_wait(); +#ifdef OUT +enum wsrep_trx_status { + WSREP_TRX_OK, + WSREP_TRX_CERT_FAIL, /* certification failure, must abort */ + WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */ + WSREP_TRX_ERROR, /* native mysql error */ +}; +#endif +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_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 "C" bool wsrep_consistency_check(void *thd_ptr); extern mysql_mutex_t LOCK_wsrep_ready; extern mysql_cond_t COND_wsrep_ready; @@ -249,15 +313,15 @@ 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 +331,9 @@ extern my_bool wsrep_preordered_opt; extern handlerton *wsrep_hton; #ifdef HAVE_PSI_INTERFACE + +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,12 +342,18 @@ 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 */ @@ -289,12 +362,141 @@ class Alter_info; int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list, Alter_info* alter_info = NULL); + +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_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, @@ -305,16 +507,33 @@ 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); -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); -void wsrep_kill_mysql(THD *thd); +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*); + void wsrep_close_threads(THD *thd); -void wsrep_copy_query(THD *thd); +//void wsrep_copy_query(THD *thd); bool wsrep_is_show_query(enum enum_sql_command command); void wsrep_replay_transaction(THD *thd); bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, @@ -323,24 +542,11 @@ 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) -#else /* WITH_WSREP */ - +#ifdef WITH_WSREP_OUT #define WSREP(T) (0) #define WSREP_ON (0) #define WSREP_EMULATE_BINLOG(thd) (0) @@ -368,5 +574,55 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr); #define wsrep_thr_deinit() do {} while(0) #define wsrep_running_threads (0) #define WSREP_BINLOG_FORMAT(my_format) my_format -#endif /* WITH_WSREP */ +#endif +/** + * 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*, bool); + +/** + * 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); + +#include "wsrep_server_state.h" +// #include "mysql/service_wsrep.h" + +/** + * Initialize WSREP server instance. + * + * @return Zero on success, non-zero on error. + */ +int wsrep_init_server(); + +/** + * Initialize WSREP globals. This should be done after server initialization + * is complete and the server has joined to the cluster. + * + */ +void wsrep_init_globals(); + +/** + * Deinit and release WSREP resources. + */ +void wsrep_deinit_server(); #endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc index 92bcc8eda43..8a47597ae65 100644 --- a/sql/wsrep_notify.cc +++ b/sql/wsrep_notify.cc @@ -15,6 +15,7 @@ #include "mariadb.h" #include <mysqld.h> +#include "wsrep_api.h" #include "wsrep_priv.h" #include "wsrep_utils.h" diff --git a/sql/wsrep_plugin.cc b/sql/wsrep_plugin.cc new file mode 100644 index 00000000000..dd8095e3843 --- /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 0; +} + +static int wsrep_plugin_deinit(void *p) +{ + WSREP_INFO("wsrep_plugin_deinit()"); + return 0; +} + +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..65022396cd2 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,17 @@ 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, - const wsrep_uuid_t& uuid, - const wsrep_seqno_t seqno, - const void* const state, - const size_t state_len, - const bool implicit); +void wsrep_sst_received(THD*, const wsrep_uuid_t&, wsrep_seqno_t, + const void*, size_t); /*! 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..f209e1c8812 --- /dev/null +++ b/sql/wsrep_schema.cc @@ -0,0 +1,1319 @@ +/* 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 "mysql/service_wsrep.h" +#include "wsrep_thd_pool.h" +#include "wsrep_schema.h" +#include "wsrep_applier.h" +#include "wsrep_xid.h" +#include "wsrep_binlog.h" +#include "wsrep_high_priority_service.h" +#include "wsrep_storage_service.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 +{ + +class binlog_off +{ +public: + binlog_off(THD* thd) + : m_thd(thd) + , m_option_bits(thd->variables.option_bits) + , m_sql_log_bin(thd->variables.sql_log_bin) + { + thd->variables.option_bits&= ~OPTION_BIN_LOG; + thd->variables.sql_log_bin= 0; + } + ~binlog_off() + { + m_thd->variables.option_bits= m_option_bits; + m_thd->variables.sql_log_bin= m_sql_log_bin; + } +private: + THD* m_thd; + ulonglong m_option_bits; + my_bool m_sql_log_bin; +}; + +class wsrep_off +{ +public: + wsrep_off(THD* thd) + : m_thd(thd) + , m_wsrep_on(thd->variables.wsrep_on) + { + thd->variables.wsrep_on= 0; + } + ~wsrep_off() + { + m_thd->variables.wsrep_on= m_wsrep_on; + } +private: + THD* m_thd; + my_bool m_wsrep_on; +}; + +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); + + 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_id& id) { + assert(field < table->s->fields); + std::ostringstream os; + os << id; + table->field[field]->store(os.str().c_str(), + os.str().size(), + &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 void store(TABLE* table, uint field, const std::string& str) +{ + store(table, field, str.c_str(), str.size()); +} + +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; +} + +static int scan(TABLE* table, uint field, wsrep::id& id) +{ + assert(field < table->s->fields); + String uuid_str; + (void)table->field[field]->val_str(&uuid_str); + id = wsrep::id(std::string(uuid_str.c_ptr(), uuid_str.length())); + 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); +} +} /* 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(THD* thd, const Wsrep_view& 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_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + + /* + 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().id()); + Wsrep_schema_impl::store(cluster_table, 1, view.view_seqno().get()); + Wsrep_schema_impl::store(cluster_table, 2, view.state_id().seqno().get()); + Wsrep_schema_impl::store(cluster_table, 3, view.protocol_version()); + + 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 (size_t i= 0; i < view.members().size(); ++i) + { + Wsrep_schema_impl::store(members_table, 0, view.members()[i].id()); + Wsrep_schema_impl::store(members_table, 1, view.state_id().id()); + Wsrep_schema_impl::store(members_table, 2, + view.members()[i].name()); + Wsrep_schema_impl::store(members_table, 3, 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 */ + ret= 0; + out: + + 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_fragment(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + wsrep::seqno seqno, + int flags, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_schema::append_fragment"); + std::ostringstream os; + os << server_id; + WSREP_DEBUG("Append fragment(%llu) %s, %llu", + thd->thread_id, + os.str().c_str(), + transaction_id.get()); + Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::init_stmt(thd); + + TABLE* frag_table= 0; + if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)) + { + trans_rollback_stmt(thd); + DBUG_RETURN(1); + } + + Wsrep_schema_impl::store(frag_table, 0, server_id); + Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); + Wsrep_schema_impl::store(frag_table, 2, seqno.get()); + Wsrep_schema_impl::store(frag_table, 3, flags); + Wsrep_schema_impl::store(frag_table, 4, data.data(), data.size()); + + int error; + if ((error= Wsrep_schema_impl::insert(frag_table))) { + WSREP_ERROR("Failed to write to frag table: %d", error); + trans_rollback_stmt(thd); + DBUG_RETURN(1); + } + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(0); +} + +int Wsrep_schema::update_fragment_meta(THD* thd, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_schema::update_fragment_meta"); + std::ostringstream os; + os << ws_meta.server_id(); + WSREP_DEBUG("update_frag_seqno(%llu) %s, %llu, seqno %lld", + thd->thread_id, + os.str().c_str(), + ws_meta.transaction_id().get(), + ws_meta.seqno().get()); + DBUG_ASSERT(ws_meta.seqno().is_undefined() == false); + + Wsrep_schema_impl::binlog_off binlog_off(thd); + int error; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + TABLE* frag_table= 0; + + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)) + { + DBUG_RETURN(1); + } + + /* Find record with the given uuid, trx id, and seqno -1 */ + Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); + Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); + 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_WARN("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)); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + + /* 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, ws_meta.seqno().get()); + 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)); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + + int ret= Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(ret); +} + +static int remove_fragment(THD* thd, + TABLE* frag_table, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + wsrep::seqno seqno) +{ + WSREP_DEBUG("remove_fragment(%llu) trx %llu, seqno %lld", + thd->thread_id, + transaction_id.get(), + seqno.get()); + int ret= 0; + int error; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + + DBUG_ASSERT(server_id.is_undefined() == false); + DBUG_ASSERT(transaction_id.is_undefined() == false); + DBUG_ASSERT(seqno.is_undefined() == false); + + /* + 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, server_id); + Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); + Wsrep_schema_impl::store(frag_table, 2, seqno.get()); + 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_DEBUG("Record not found in %s.%s:trx %llu, seqno %lld, error %d", + frag_table->s->db.str, + frag_table->s->table_name.str, + transaction_id.get(), + seqno.get(), + error); + } + frag_table->file->print_error(error, MYF(0)); + ret= error; + } + else if (Wsrep_schema_impl::delete_row(frag_table)) + { + ret= 1; + } + + Wsrep_schema_impl::end_index_scan(frag_table); + return ret; +} + +int Wsrep_schema::remove_fragments(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + const std::vector<wsrep::seqno>& fragments) +{ + DBUG_ENTER("Wsrep_schema::remove_fragments"); + int ret= 0; + + Wsrep_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + + /* + Open SR table for write. + Adopted from Rpl_info_table_access::open_table() + */ + uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | + MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | + MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_LOCK_IGNORE_TIMEOUT); + Query_tables_list query_tables_list_backup; + Open_tables_backup open_tables_backup; + thd->lex->reset_n_backup_query_tables_list(&query_tables_list_backup); + thd->reset_n_backup_open_tables_state(&open_tables_backup); + TABLE_LIST tables; + LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() }; + LEX_CSTRING table_str= { "SR", strlen("SR") }; + tables.init_one_table(&schema_str, + &table_str, 0, TL_WRITE); + + if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) + { + WSREP_DEBUG("Failed to open SR table for access"); + ret= 1; + } + else + { + tables.table->use_all_columns(); + for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin(); + i != fragments.end(); ++i) + { + if (remove_fragment(thd, + tables.table, + server_id, + transaction_id, *i)) + { + ret= 1; + break; + } + } + } + close_thread_tables(thd); + thd->restore_backup_open_tables_state(&open_tables_backup); + thd->lex->restore_backup_query_tables_list(&query_tables_list_backup); + + if (thd->wsrep_cs().mode() == wsrep::client_state::m_local && + !thd->in_multi_stmt_transaction_mode()) + { + /* + The ugly part: Locally executing autocommit statement is + committing and it has removed a fragment from stable storage. + Now calling finish_stmt() will call trans_commit_stmt(), which will + actually commit the transaction, what we really don't want + to do at this point. + + Doing nothing at this point seems to work ok, this block is + intentionally no-op and for documentation purposes only. + */ + } + else + { + Wsrep_schema_impl::finish_stmt(thd); + } + + DBUG_RETURN(ret); +} + +int Wsrep_schema::replay_transaction(THD* thd, + Relay_log_info* rli, + const wsrep::ws_meta& ws_meta, + const std::vector<wsrep::seqno>& fragments) +{ + DBUG_ENTER("Wsrep_schema::replay_transaction"); + DBUG_ASSERT(!fragments.empty()); + + Wsrep_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + + int ret= 1; + int error; + TABLE* frag_table= 0; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + + for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin(); + i != fragments.end(); ++i) + { + Wsrep_schema_impl::init_stmt(thd); + if ((error= Wsrep_schema_impl::open_for_read(thd, "SR", &frag_table))) + { + WSREP_WARN("Could not open SR table for read: %d", error); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + + Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); + Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); + Wsrep_schema_impl::store(frag_table, 2, i->get()); + Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); + + int error= Wsrep_schema_impl::init_for_index_scan(frag_table, + key, + key_map); + if (error) + { + frag_table->file->print_error(error, MYF(0)); + Wsrep_schema_impl::end_index_scan(frag_table); + ret= 1; + break; + } + + int flags; + Wsrep_schema_impl::scan(frag_table, 3, flags); + WSREP_DEBUG("replay_fragment(%llu): seqno: %lld flags: %x", + ws_meta.transaction_id().get(), + i->get(), + flags); + String buf; + frag_table->field[4]->val_str(&buf); + + Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(thd); + ret= wsrep_apply_events(thd, rli, buf.c_ptr_safe(), buf.length()); + if (ret) + { + WSREP_WARN("Wsrep_schema::replay_transaction: failed to apply fragments"); + break; + } + Wsrep_schema_impl::init_stmt(thd); + + if ((error= Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table))) + { + WSREP_WARN("Could not open SR table for read: %d", error); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + error= Wsrep_schema_impl::init_for_index_scan(frag_table, + key, + key_map); + if (error) + { + frag_table->file->print_error(error, MYF(0)); + Wsrep_schema_impl::end_index_scan(frag_table); + ret= 1; + break; + } + + error= Wsrep_schema_impl::delete_row(frag_table); + if (error) + { + frag_table->file->print_error(error, MYF(0)); + Wsrep_schema_impl::end_index_scan(frag_table); + ret= 1; + break; + } + Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(thd); + } + + DBUG_RETURN(ret); +} + +int Wsrep_schema::recover_sr_transactions() +{ + DBUG_ENTER("Wsrep_schema::recover_sr_transactions"); + THD storage_thd(true, true); + storage_thd.thread_stack= (char*)&storage_thd; + TABLE* frag_table= 0; + TABLE* cluster_table= 0; + Wsrep_storage_service storage_service(&storage_thd); + Wsrep_schema_impl::binlog_off binlog_off(&storage_thd); + Wsrep_schema_impl::wsrep_off binglog_off(&storage_thd); + + Wsrep_server_state& server_state(Wsrep_server_state::instance()); + + int ret= 1; + int error; + wsrep::id cluster_id; + + storage_thd.store_globals(); + Wsrep_schema_impl::init_stmt(&storage_thd); + storage_thd.wsrep_skip_locking= FALSE; + if (Wsrep_schema_impl::open_for_read(&storage_thd, + "cluster", &cluster_table) || + Wsrep_schema_impl::init_for_scan(cluster_table)) + { + Wsrep_schema_impl::finish_stmt(&storage_thd); + DBUG_RETURN(1); + } + + if ((error= Wsrep_schema_impl::next_record(cluster_table))) + { + Wsrep_schema_impl::end_scan(cluster_table); + Wsrep_schema_impl::finish_stmt(&storage_thd); + trans_commit(&storage_thd); + if (error == HA_ERR_END_OF_FILE) + { + WSREP_INFO("Cluster table is empty, not recovering transactions"); + DBUG_RETURN(0); + } + else + { + WSREP_ERROR("Failed to read cluster table: %d", error); + DBUG_RETURN(1); + } + } + + Wsrep_schema_impl::scan(cluster_table, 0, cluster_id); + Wsrep_schema_impl::end_scan(cluster_table); + Wsrep_schema_impl::finish_stmt(&storage_thd); + + std::ostringstream os; + os << cluster_id; + WSREP_INFO("Recovered cluster id %s", os.str().c_str()); + + storage_thd.wsrep_skip_locking= TRUE; + Wsrep_schema_impl::init_stmt(&storage_thd); + if (Wsrep_schema_impl::open_for_read(&storage_thd, "SR", &frag_table) || + Wsrep_schema_impl::init_for_scan(frag_table)) + { + WSREP_ERROR("Failed to open SR table for read"); + goto out; + } + + while (true) + { + if ((error= Wsrep_schema_impl::next_record(frag_table)) == 0) + { + wsrep::id server_id; + Wsrep_schema_impl::scan(frag_table, 0, server_id); + wsrep::client_id client_id; + unsigned long long transaction_id_ull; + Wsrep_schema_impl::scan(frag_table, 1, transaction_id_ull); + wsrep::transaction_id transaction_id(transaction_id_ull); + long long seqno_ll; + Wsrep_schema_impl::scan(frag_table, 2, seqno_ll); + wsrep::seqno seqno(seqno_ll); + + if (seqno.is_undefined()) + { + Wsrep_schema_impl::delete_row(frag_table); + continue; + } + + wsrep::gtid gtid(cluster_id, seqno); + int flags; + Wsrep_schema_impl::scan(frag_table, 3, flags); + String data_str; + + (void)frag_table->field[4]->val_str(&data_str); + wsrep::const_buffer data(data_str.c_ptr(), data_str.length()); + wsrep::ws_meta ws_meta(gtid, + wsrep::stid(server_id, + transaction_id, + client_id), + wsrep::seqno::undefined(), + flags); + + wsrep::high_priority_service* applier; + if (!(applier = server_state.find_streaming_applier(server_id, + transaction_id))) + { + DBUG_ASSERT(wsrep::starts_transaction(flags)); + THD* thd= new THD(true, true); + thd->thread_stack= (char*)&storage_thd; + + mysql_mutex_lock(&LOCK_thread_count); + thd->thread_id= next_thread_id(); + thd->real_id= pthread_self(); + mysql_mutex_unlock(&LOCK_thread_count); + + applier= new Wsrep_applier_service(thd); + server_state.start_streaming_applier(server_id, transaction_id, + applier); + applier->start_transaction(wsrep::ws_handle(transaction_id, 0), + ws_meta); + } + applier->store_globals(); + applier->apply_write_set(ws_meta, data); + applier->after_apply(); + storage_service.store_globals(); + } + else if (error == HA_ERR_END_OF_FILE) + { + ret= 0; + break; + } + else + { + WSREP_ERROR("SR table scan returned error %d", error); + break; + } + } + Wsrep_schema_impl::end_scan(frag_table); + Wsrep_schema_impl::finish_stmt(&storage_thd); + trans_commit(&storage_thd); +out: + DBUG_RETURN(ret); +} diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h new file mode 100644 index 00000000000..af42db459f3 --- /dev/null +++ b/sql/wsrep_schema.h @@ -0,0 +1,167 @@ +/* Copyright (C) 2015-2018 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 + +/* wsrep-lib */ +#include "wsrep_types.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; +class Relay_log_info; +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(THD*, const Wsrep_view& view); + + /* + 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); + /** + Append transaction fragment to fragment storage. + Transaction must have been started for THD before this call. + In order to make changes durable, transaction must be committed + separately after this call. + + @param thd THD object + @param server_id Wsrep server identifier + @param transaction_id Transaction identifier + @param flags Flags for the fragment + @param data Fragment data buffer + + @return Zero in case of success, non-zero on failure. + */ + int append_fragment(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + wsrep::seqno seqno, + int flags, + const wsrep::const_buffer& data); + /** + Update existing fragment meta data. The fragment must have been + inserted before using append_fragment(). + + @param thd THD object + @param ws_meta Wsrep meta data + + @return Zero in case of success, non-zero on failure. + */ + int update_fragment_meta(THD* thd, + const wsrep::ws_meta& ws_meta); + + /** + Remove fragments from storage. This method must be called + inside active transaction. Fragment removal will be committed + once the transaction commits. + + @param thd Pointer to THD object + @param server_id Identifier of the running server + @param transaction_id Identifier of the current transaction + @param fragments Vector of fragment seqnos to be removed + */ + int remove_fragments(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + const std::vector<wsrep::seqno>& fragments); + + /** + Replay a transaction from stored fragments. The caller must have + started a transaction for a thd. + + @param thd Pointer to THD object + @param ws_meta Write set meta data for commit fragment. + @param fragments Vector of fragments to be replayed + + @return Zero on success, non-zero on failure. + */ + int replay_transaction(THD* thd, + Relay_log_info* rli, + const wsrep::ws_meta& ws_meta, + const std::vector<wsrep::seqno>& fragments); + + /** + Recover streaming transactions from SR table. + This method should be called after storage enignes are initialized. + It will scan SR table and replay found streaming transactions. + + @return Zero on success, non-zero on failure. + */ + int recover_sr_transactions(); + + /* + Close wsrep schema. + */ + void close(); + + private: + /* Non-copyable */ + Wsrep_schema(const Wsrep_schema&); + Wsrep_schema& operator=(const Wsrep_schema&); + + Wsrep_thd_pool* thd_pool_; +}; + +extern Wsrep_schema* wsrep_schema; + +#endif /* !WSREP_SCHEMA_H */ diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc new file mode 100644 index 00000000000..f22d3d1b1e5 --- /dev/null +++ b/sql/wsrep_server_service.cc @@ -0,0 +1,277 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_global.h" +//#include "mysql/service_wsrep.h" +#include "wsrep_server_service.h" +#include "wsrep_server_state.h" +#include "wsrep_client_state.h" +#include "wsrep_client_service.h" +#include "wsrep_storage_service.h" +#include "wsrep_high_priority_service.h" + +#include "wsrep_sst.h" +#include "wsrep_xid.h" +#include "wsrep_mysqld.h" +#include "wsrep_schema.h" + +#include "log.h" /* sql_print_xxx() */ +#include "sql_class.h" /* system variables */ +//#include "global_threads.h" /* LOCK_thread_count */ +#include "transaction.h" /* trans_xxx */ +#include "sql_base.h" /* close_thread_tables */ + +static void init_service_thd(THD* thd, char* thread_stack) +{ + thd->thread_stack= thread_stack; + //thd->thread_id= 0; + thd->real_id= pthread_self(); + thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); + thd->set_command(COM_SLEEP); + thd->reset_for_next_command(true); +} + +wsrep::storage_service* Wsrep_server_service::storage_service( + wsrep::client_service& client_service) +{ + Wsrep_client_service& cs= + static_cast<Wsrep_client_service&>(client_service); + THD* thd = new THD(next_thread_id(), true, true); + init_service_thd(thd, cs.m_thd->thread_stack); + WSREP_DEBUG("Created storage service with thread id %lu", + thd->thread_id); + return new Wsrep_storage_service(thd); +} + +wsrep::storage_service* Wsrep_server_service::storage_service( + wsrep::high_priority_service& high_priority_service) +{ + Wsrep_high_priority_service& hps= + static_cast<Wsrep_high_priority_service&>(high_priority_service); + THD* thd = new THD(next_thread_id(), true, true); + init_service_thd(thd, hps.m_thd->thread_stack); + WSREP_DEBUG("Created high priority storage service with thread id %lu", + thd->thread_id); + return new Wsrep_storage_service(thd); +} + +void Wsrep_server_service::release_storage_service( + wsrep::storage_service* storage_service) +{ + Wsrep_storage_service* ss= + static_cast<Wsrep_storage_service*>(storage_service); + THD* thd= ss->m_thd; + delete ss; + delete thd; +} + +wsrep::high_priority_service* +Wsrep_server_service::streaming_applier_service( + wsrep::client_service& orig_client_service) +{ + Wsrep_client_service& orig_cs= + static_cast<Wsrep_client_service&>(orig_client_service); + THD* thd= new THD(next_thread_id(), true, true); + init_service_thd(thd, orig_cs.m_thd->thread_stack); + WSREP_DEBUG("Created streaming applier service in local context with " + "thread id %lu", thd->thread_id); + return new Wsrep_applier_service(thd); +} + +wsrep::high_priority_service* +Wsrep_server_service::streaming_applier_service( + wsrep::high_priority_service& orig_high_priority_service) +{ + Wsrep_high_priority_service& + orig_hps(static_cast<Wsrep_high_priority_service&>(orig_high_priority_service)); + THD* thd= new THD(next_thread_id(), true, true); + init_service_thd(thd, orig_hps.m_thd->thread_stack); + WSREP_DEBUG("Created streaming applier service in high priority " + "context with thread id %lu", thd->thread_id); + return new Wsrep_applier_service(thd); +} + +void Wsrep_server_service::release_high_priority_service(wsrep::high_priority_service* high_priority_service) +{ + Wsrep_high_priority_service* hps= + static_cast<Wsrep_high_priority_service*>(high_priority_service); + THD* thd= hps->m_thd; + delete hps; + delete thd; +} + +void Wsrep_server_service::background_rollback(wsrep::client_state& client_state) +{ + Wsrep_client_state& cs= static_cast<Wsrep_client_state&>(client_state); + wsrep_fire_rollbacker(cs.thd()); +} + +void Wsrep_server_service::bootstrap() +{ + wsrep::log_info() + << "Bootstrapping a new cluster, setting initial position to " + << wsrep::gtid::undefined(); + wsrep_set_SE_checkpoint(wsrep::gtid::undefined()); +} + +void Wsrep_server_service::log_message(enum wsrep::log::level level, + const char* message) +{ + switch (level) + { + case wsrep::log::debug: + sql_print_information("debug: %s", message); + break; + case wsrep::log::info: + sql_print_information("%s", message); + break; + case wsrep::log::warning: + sql_print_warning("%s", message); + break; + case wsrep::log::error: + sql_print_error("%s", message); + break; + } +} + +void Wsrep_server_service::log_view( + wsrep::high_priority_service* high_priority_service, + const wsrep::view& view) +{ + Wsrep_high_priority_service* applier= + static_cast<Wsrep_high_priority_service*>(high_priority_service); + /* Update global system variables */ + mysql_mutex_lock(&LOCK_global_system_variables); + if (wsrep_auto_increment_control && view.own_index() >= 0) + { + global_system_variables.auto_increment_offset= view.own_index() + 1; + global_system_variables.auto_increment_increment= view.members().size(); + wsrep_protocol_version = view.protocol_version(); + } + mysql_mutex_unlock(&LOCK_global_system_variables); + + /* Update wsrep status variables */ + mysql_mutex_lock(&LOCK_status); + wsrep_cluster_size= view.members().size(); + wsrep_local_index= view.own_index(); + std::ostringstream os; + os << view.state_id().id(); + wsrep_update_cluster_state_uuid(os.str().c_str()); + mysql_mutex_unlock(&LOCK_status); + + if (view.status() == wsrep::view::primary) + { + if (applier) + { + if (trans_begin(applier->m_thd, MYSQL_START_TRANS_OPT_READ_WRITE)) + { + WSREP_WARN("Failed to start transaction for store view"); + } + else + { + if (wsrep_schema->store_view(applier->m_thd, view)) + { + WSREP_WARN("Failed to store view"); + trans_rollback_stmt(applier->m_thd); + if (!trans_rollback(applier->m_thd)) + { + close_thread_tables(applier->m_thd); + } + } + else + { + if (trans_commit(applier->m_thd)) + { + WSREP_WARN("Failed to commit transaction for store view"); + } + } + applier->m_thd->mdl_context.release_transactional_locks(); + } + } + else + { + WSREP_WARN("No applier in Wsrep_server_service::log_view(), " + "skipping write to wsrep_schema"); + } + } + + if (view.status() == wsrep::view::primary && + m_server_state.provider().last_committed_gtid().seqno() != + view.state_id().seqno()) + { + wsrep_set_SE_checkpoint(view.state_id()); + } +} + +void Wsrep_server_service::log_state_change( + enum Wsrep_server_state::state prev_state, + enum Wsrep_server_state::state current_state) +{ + WSREP_INFO("Server status change %s -> %s", + wsrep::to_c_string(prev_state), + wsrep::to_c_string(current_state)); + mysql_mutex_lock(&LOCK_status); + switch (current_state) + { + case Wsrep_server_state::s_synced: + wsrep_ready= TRUE; + /* fall through */ + case Wsrep_server_state::s_joined: + case Wsrep_server_state::s_donor: + wsrep_cluster_status= "Primary"; + break; + case Wsrep_server_state::s_connected: + wsrep_cluster_status= "non-Primary"; + wsrep_ready= FALSE; + wsrep_connected= TRUE; + break; + case Wsrep_server_state::s_disconnected: + wsrep_ready= FALSE; + wsrep_connected= FALSE; + wsrep_cluster_status= "Disconnected"; + break; + default: + wsrep_ready= FALSE; + wsrep_cluster_status= "non-Primary"; + break; + } + mysql_mutex_unlock(&LOCK_status); +} + +bool Wsrep_server_service::sst_before_init() const +{ + return wsrep_before_SE(); +} + +std::string Wsrep_server_service::sst_request() +{ + return wsrep_sst_prepare(); +} + +int Wsrep_server_service::start_sst(const std::string& sst_request, + const wsrep::gtid& gtid, + bool bypass) +{ + return wsrep_sst_donate(sst_request, gtid, bypass); +} + +int Wsrep_server_service::wait_committing_transactions(int timeout) +{ + return wsrep_wait_committing_connections_close(timeout); +} + +void Wsrep_server_service::debug_sync(const char*) +{ +} diff --git a/sql/wsrep_server_service.h b/sql/wsrep_server_service.h new file mode 100644 index 00000000000..c3a41829e67 --- /dev/null +++ b/sql/wsrep_server_service.h @@ -0,0 +1,75 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_SERVER_SERVICE_H +#define WSREP_SERVER_SERVICE_H + +/* wsrep-lib */ +#include "../wsrep-lib/include/wsrep/server_service.hpp" +#include "../wsrep-lib/include/wsrep/exception.hpp" // not_impemented_error(), remove when finished +#include "../wsrep-lib/include/wsrep/storage_service.hpp" + +class Wsrep_server_state; + + +/* wsrep::server_service interface implementation */ +class Wsrep_server_service : public wsrep::server_service +{ +public: + Wsrep_server_service(Wsrep_server_state& server_state) + : m_server_state(server_state) + { } + + wsrep::storage_service* storage_service(wsrep::client_service&); + + wsrep::storage_service* storage_service(wsrep::high_priority_service&); + + void release_storage_service(wsrep::storage_service*); + + wsrep::high_priority_service* + streaming_applier_service(wsrep::client_service&); + + wsrep::high_priority_service* + streaming_applier_service(wsrep::high_priority_service&); + + void release_high_priority_service(wsrep::high_priority_service*); + + void background_rollback(wsrep::client_state&); + + void bootstrap(); + void log_message(enum wsrep::log::level, const char*); + + void log_dummy_write_set(wsrep::client_state&, const wsrep::ws_meta&) + { throw wsrep::not_implemented_error(); } + + void log_view(wsrep::high_priority_service*, const wsrep::view&); + + void log_state_change(enum wsrep::server_state::state, + enum wsrep::server_state::state); + + bool sst_before_init() const; + + std::string sst_request(); + int start_sst(const std::string&, const wsrep::gtid&, bool); + + int wait_committing_transactions(int); + + void debug_sync(const char*); +private: + Wsrep_server_state& m_server_state; +}; + + +#endif /* WSREP_SERVER_SERVICE */ diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc new file mode 100644 index 00000000000..472be8b8169 --- /dev/null +++ b/sql/wsrep_server_state.cc @@ -0,0 +1,78 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_global.h" +#include "wsrep_api.h" +#include "wsrep_server_state.h" + +mysql_mutex_t LOCK_wsrep_server_state; +PSI_mutex_key key_LOCK_wsrep_server_state; +mysql_cond_t COND_wsrep_server_state; +PSI_cond_key key_COND_wsrep_server_state; + +Wsrep_server_state::Wsrep_server_state(const std::string& name, + const std::string& id, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version) + : wsrep::server_state(m_mutex, + m_cond, + m_service, + name, + id, + incoming_address, + address, + working_dir, + initial_position, + max_protocol_version, + wsrep::server_state::rm_sync) + , m_mutex(LOCK_wsrep_server_state) + , m_cond(COND_wsrep_server_state) + , m_service(*this) +{ + +} + +void Wsrep_server_state::init_once(const std::string& name, + const std::string& id, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version) +{ + if (m_instance == 0) + { + mysql_mutex_init(key_LOCK_wsrep_server_state, &LOCK_wsrep_server_state, + MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_server_state, &COND_wsrep_server_state, 0); + m_instance = new Wsrep_server_state(name, + id, + incoming_address, + address, + working_dir, + initial_position, + max_protocol_version); + } +} + +void Wsrep_server_state::destroy() +{ + delete m_instance; + mysql_mutex_destroy(&LOCK_wsrep_server_state); + mysql_cond_destroy(&COND_wsrep_server_state); +} diff --git a/sql/wsrep_server_state.h b/sql/wsrep_server_state.h new file mode 100644 index 00000000000..5f99259edc7 --- /dev/null +++ b/sql/wsrep_server_state.h @@ -0,0 +1,68 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_SERVER_STATE_H +#define WSREP_SERVER_STATE_H + +/* wsrep-lib */ +#include "../wsrep-lib/include/wsrep/server_state.hpp" +#include "../wsrep-lib/include/wsrep/provider.hpp" + +/* implementation */ +#include "wsrep_server_service.h" +#include "wsrep_mutex.h" +#include "wsrep_condition_variable.h" + +class Wsrep_server_state : public wsrep::server_state +{ +public: + static void init_once(const std::string& name, + const std::string& id, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version); + static void destroy(); + static Wsrep_server_state& instance() + { + return *m_instance; + } + + static wsrep::provider& get_provider() + { + return instance().provider(); + } + + static bool has_capability(int capability) + { + return (get_provider().capabilities() & capability); + } +private: + Wsrep_server_state(const std::string& name, + const std::string& id, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version); + Wsrep_mutex m_mutex; + Wsrep_condition_variable m_cond; + Wsrep_server_service m_service; + + static Wsrep_server_state* m_instance; +}; + +#endif // WSREP_SERVER_STATE_H diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index e648a7f4c69..63fa699f24c 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 @@ -30,6 +30,7 @@ #include <cstdio> #include <cstdlib> +const char wsrep_defaults_group_suffix[256] = {0}; #include <my_service_manager.h> static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 + @@ -180,6 +181,7 @@ bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) return 0; } + bool wsrep_before_SE() { return (wsrep_provider != NULL @@ -188,90 +190,17 @@ bool wsrep_before_SE() && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } -static bool sst_complete = false; -static bool sst_needed = false; - -#define WSREP_EXTEND_TIMEOUT_INTERVAL 30 -#define WSREP_TIMEDWAIT_SECONDS 10 - -void wsrep_sst_grab () -{ - WSREP_INFO("wsrep_sst_grab()"); - if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); - sst_complete = false; - mysql_mutex_unlock (&LOCK_wsrep_sst); -} - -// Wait for end of SST -bool wsrep_sst_wait () -{ - double total_wtime = 0; - - if (mysql_mutex_lock (&LOCK_wsrep_sst)) - abort(); - - WSREP_INFO("Waiting for SST to complete."); - - while (!sst_complete) - { - struct timespec wtime; - set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS); - time_t start_time = time(NULL); - mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime); - time_t end_time = time(NULL); - - if (!sst_complete) - { - total_wtime += difftime(end_time, start_time); - WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime); - service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL, - "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime); - } - } - - if (local_seqno >= 0) - { - WSREP_INFO("SST complete, seqno: %lld", (long long) local_seqno); - } - else - { - WSREP_ERROR("SST failed: %d (%s)", - int(-local_seqno), strerror(-local_seqno)); - } - - mysql_mutex_unlock (&LOCK_wsrep_sst); - - return (local_seqno >= 0); -} - // Signal end of SST void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, wsrep_seqno_t sst_seqno, bool needed) { - if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); - if (!sst_complete) - { - sst_complete = true; - sst_needed = needed; - local_uuid = *sst_uuid; - local_seqno = sst_seqno; - mysql_cond_signal (&COND_wsrep_sst); - } - else - { - /* This can happen when called from wsrep_synced_cb(). - At the moment there is no way to check there - if main thread is still waiting for signal, - so wsrep_sst_complete() is called from there - each time wsrep_ready changes from FALSE -> TRUE. - */ - WSREP_DEBUG("Nobody is waiting for SST."); - } - mysql_mutex_unlock (&LOCK_wsrep_sst); + wsrep::gtid gtid(wsrep::id(sst_uuid->data, sizeof(sst_uuid->data)), + wsrep::seqno(sst_seqno)); + Wsrep_server_state::instance().sst_received(gtid, 0); } -/* + /* If wsrep provider is loaded, inform that the new state snapshot has been received. Also update the local checkpoint. @@ -287,12 +216,11 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, true Error */ -bool wsrep_sst_received (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) +void wsrep_sst_received (THD* thd, + const wsrep_uuid_t& uuid, + wsrep_seqno_t const seqno, + const void* const state, + size_t const state_len) { /* To keep track of whether the local uuid:seqno should be updated. Also, note @@ -300,81 +228,50 @@ 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; - } - - if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) || - local_seqno < seqno || seqno < 0) - { - 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. + TODO: Handle backwards compatibility. WSREP API v25 does not have + wsrep schema. */ - if (implicit) - { - WSREP_WARN("Can't continue."); - unireg_abort(1); - } - else - { - return true; + /* + 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(wsrep::gtid::undefined()); + wsrep_set_SE_checkpoint(wsrep::gtid(wsrep::id(uuid.data, + sizeof(uuid.data)), + wsrep::seqno(seqno))); } - } - -#ifdef GTID_SUPPORT - wsrep_init_sidno(uuid); -#endif /* GTID_SUPPORT */ + wsrep_verify_SE_checkpoint(uuid, seqno); + // wsrep_init_SR(); + if (thd) mysql_mutex_lock(&LOCK_global_system_variables); - 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) - { - return true; + /* + Both wsrep_init_SR() and wsrep_recover_view() may use + wsrep thread pool. Restore original thd context before returning. + */ + if (thd) { + thd->store_globals(); } - } - - // Now is the good time to update the local state and checkpoint. - if (do_update) - { - if (wsrep_set_SE_checkpoint(uuid, seqno)) - { - return true; + else { + my_pthread_setspecific_ptr(THR_THD, NULL); } - local_uuid= uuid; - local_seqno= seqno; - } - - return false; -} - -// Let applier threads to continue -bool wsrep_sst_continue () -{ - if (sst_needed) - { - WSREP_INFO("Signalling provider to continue."); - return wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0, true); - } - return false; + int const rcode(seqno < 0 ? seqno : 0); + wsrep::gtid gtid(wsrep::id(uuid.data, sizeof(uuid.data)), + wsrep::seqno(seqno)); + Wsrep_server_state::instance().sst_received(gtid, rcode); } struct sst_thread_arg @@ -799,29 +696,21 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in, static bool SE_initialized = false; -ssize_t wsrep_sst_prepare (void** msg) +std::string wsrep_sst_prepare() { + const ssize_t ip_max= 256; + char ip_buf[ip_max]; const char* addr_in= NULL; const char* addr_out= NULL; if (!strcmp(wsrep_sst_method, WSREP_SST_SKIP)) { - ssize_t ret = strlen(WSREP_STATE_TRANSFER_TRIVIAL) + 1; - *msg = strdup(WSREP_STATE_TRANSFER_TRIVIAL); - if (!msg) - { - WSREP_ERROR("Could not allocate %zd bytes for state request", ret); - unireg_abort(1); - } - return ret; + return WSREP_STATE_TRANSFER_TRIVIAL; } /* Figure out SST receive address. Common for all SST methods. */ - char ip_buf[256]; - const ssize_t ip_max= sizeof(ip_buf); - // Attempt 1: wsrep_sst_receive_address if (wsrep_sst_receive_address && strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) @@ -838,7 +727,7 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Could not parse wsrep_node_address : %s", wsrep_node_address); - unireg_abort(1); + throw wsrep::runtime_error("Failed to prepare for SST. Unrecoverable"); } memcpy(ip_buf, addr.get_address(), addr.get_address_len()); addr_in= ip_buf; @@ -856,7 +745,7 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Failed to guess address to accept state transfer. " "wsrep_sst_receive_address must be set manually."); - unireg_abort(1); + throw wsrep::runtime_error("Could not prepare state transfer request"); } } @@ -864,12 +753,16 @@ 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) + { + throw wsrep::runtime_error("Could not prepare mysqldimp address"); + } } else { /*! A heuristic workaround until we learn how to stop and start engines */ - if (SE_initialized) + if (Wsrep_server_state::instance().is_initialized() && + Wsrep_server_state::instance().state() == Wsrep_server_state::s_joiner) { // we already did SST at initializaiton, now engines are running // sql_print_information() is here because the message is too long @@ -881,8 +774,7 @@ ssize_t wsrep_sst_prepare (void** msg) "if other means of state transfer are unavailable. " "In that case you will need to restart the server.", wsrep_sst_method); - *msg = 0; - return 0; + return ""; } addr_len = sst_prepare_other (wsrep_sst_method, sst_auth_real, @@ -891,31 +783,22 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", wsrep_sst_method); - unireg_abort(1); + throw wsrep::runtime_error("Failed to prepare for SST. Unrecoverable"); } } - size_t const method_len(strlen(wsrep_sst_method)); - size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); - - *msg = malloc (msg_len); - if (NULL != *msg) { - char* const method_ptr(reinterpret_cast<char*>(*msg)); - strcpy (method_ptr, wsrep_sst_method); - char* const addr_ptr(method_ptr + method_len + 1); - strcpy (addr_ptr, addr_out); + std::string ret; + ret += wsrep_sst_method; + ret.push_back('\0'); + ret += addr_out; - WSREP_INFO ("Prepared SST request: %s|%s", method_ptr, addr_ptr); - } - else { - WSREP_ERROR("Failed to allocate SST request of size %zu. Can't continue.", - msg_len); - unireg_abort(1); - } + const char* method_ptr(ret.data()); + const char* addr_ptr(ret.data() + strlen(method_ptr) + 1); + WSREP_INFO ("Prepared SST request: %s|%s", method_ptr, addr_ptr); if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out); - return msg_len; + return ret; } // helper method for donors @@ -950,15 +833,13 @@ static int sst_run_shell (const char* cmd_str, char** env, int max_tries) static void sst_reject_queries(my_bool close_conn) { - wsrep_ready_set (FALSE); // this will be resotred when donor becomes synced - WSREP_INFO("Rejecting client queries for the duration of SST."); - if (TRUE == close_conn) wsrep_close_client_connections(FALSE); + // wsrep_ready_set (FALSE); // this will be resotred when donor becomes synced + WSREP_INFO("Rejecting client queries for the duration of SST."); + if (TRUE == close_conn) wsrep_close_client_connections(FALSE); } static int sst_donate_mysqldump (const char* addr, - const wsrep_uuid_t* uuid, - const char* uuid_str, - wsrep_seqno_t seqno, + const wsrep::gtid& gtid, bool bypass, char** env) // carries auth info { @@ -981,10 +862,15 @@ 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(); - + std::ostringstream uuid_oss; + uuid_oss << gtid.id(); int ret= snprintf (cmd_str(), cmd_len, "wsrep_sst_mysqldump " WSREP_SST_OPT_ADDR " '%s' " @@ -995,10 +881,9 @@ static int sst_donate_mysqldump (const char* addr, WSREP_SST_OPT_GTID " '%s:%lld' " WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'" "%s", - addr, port, mysqld_port, mysqld_unix_port, - wsrep_defaults_file, uuid_str, - (long long)seqno, wsrep_gtid_domain_id, - bypass ? " " WSREP_SST_OPT_BYPASS : ""); + addr, mysqld_port, mysqld_unix_port, + wsrep_defaults_file, uuid_oss.str().c_str(), + gtid.seqno().get(), bypass ? " " WSREP_SST_OPT_BYPASS : ""); if (ret < 0 || ret >= cmd_len) { @@ -1010,16 +895,17 @@ static int sst_donate_mysqldump (const char* addr, ret= sst_run_shell (cmd_str(), env, 3); - wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)}; - - wsrep->sst_sent (wsrep, &state_id, ret); + wsrep::gtid sst_sent_gtid(ret == 0 ? + gtid : + wsrep::gtid(gtid.id(), + wsrep::seqno::undefined())); + Wsrep_server_state::instance().sst_sent(sst_sent_gtid, ret); return ret; } wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - /* Create a file under data directory. */ @@ -1068,7 +954,6 @@ static int sst_create_file(const char *name, const char *content) return err; } - static int run_sql_command(THD *thd, const char *query) { thd->set_query((char *)query, strlen(query)); @@ -1155,7 +1040,6 @@ static int sst_flush_tables(THD* thd) else { WSREP_INFO("Tables flushed."); - /* Tables have been flushed. Create a file with cluster state ID and wsrep_gtid_domain_id. @@ -1164,6 +1048,40 @@ static int sst_flush_tables(THD* thd) snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno, wsrep_gtid_domain_id); err= sst_create_file(flush_success, content); + + const char base_name[]= "tables_flushed"; + ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; + char *real_name = (char*) malloc(full_len); + sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); + char *tmp_name = (char*) malloc(full_len + 4); + sprintf(tmp_name, "%s.tmp", real_name); + + FILE* file= fopen(tmp_name, "w+"); + if (0 == file) + { + err= errno; + WSREP_ERROR("Failed to open '%s': %d (%s)", tmp_name, err,strerror(err)); + } + else + { + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + std::ostringstream uuid_oss; + + uuid_oss << server_state.current_view().state_id().id(); + + fprintf(file, "%s:%lld\n", + uuid_oss.str().c_str(), server_state.pause_seqno().get()); + fsync(fileno(file)); + fclose(file); + if (rename(tmp_name, real_name) == -1) + { + err= errno; + WSREP_ERROR("Failed to rename '%s' to '%s': %d (%s)", + tmp_name, real_name, err,strerror(err)); + } + } + free(real_name); + free(tmp_name); } return err; @@ -1306,24 +1224,20 @@ static void* sst_donor_thread (void* a) thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); } - // signal to donor that SST is over - struct wsrep_gtid const state_id = { - ret_uuid, err ? WSREP_SEQNO_UNDEFINED : ret_seqno - }; - wsrep->sst_sent (wsrep, &state_id, -err); + wsrep::gtid gtid(wsrep::id(ret_uuid.data, sizeof(ret_uuid.data)), + wsrep::seqno(err ? wsrep::seqno::undefined() : + wsrep::seqno(ret_seqno))); + Wsrep_server_state::instance().sst_sent(gtid, err); proc.wait(); return NULL; } - - -static int sst_donate_other (const char* method, - const char* addr, - const char* uuid, - wsrep_seqno_t seqno, - bool bypass, - char** env) // carries auth info +static int sst_donate_other (const char* method, + const char* addr, + const wsrep::gtid& gtid, + bool bypass, + char** env) // carries auth info { int const cmd_len= 4096; wsp::string cmd_str(cmd_len); @@ -1346,8 +1260,8 @@ static int sst_donate_other (const char* method, } if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; - make_wsrep_defaults_file(); - + std::ostringstream uuid_oss; + uuid_oss << gtid.id(); ret= snprintf (cmd_str(), cmd_len, "wsrep_sst_%s " WSREP_SST_OPT_ROLE " 'donor' " @@ -1362,7 +1276,7 @@ static int sst_donate_other (const char* method, method, addr, mysqld_unix_port, mysql_real_data_home, wsrep_defaults_file, binlog_opt, binlog_opt_val, - uuid, (long long) seqno, wsrep_gtid_domain_id, + uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_domain_id, bypass ? " " WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); @@ -1390,24 +1304,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) +int wsrep_sst_donate(const std::string& msg, + const wsrep::gtid& current_gtid, + const bool 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 = msg.data(); size_t method_len = strlen (method); const char* data = method + method_len + 1; - char uuid_str[37]; - wsrep_uuid_print (¤t_gtid->uuid, uuid_str, sizeof(uuid_str)); - wsp::env env(NULL); if (env.error()) { @@ -1434,54 +1344,13 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, if (!strcmp (WSREP_SST_MYSQLDUMP, method)) { - ret = sst_donate_mysqldump(data, ¤t_gtid->uuid, uuid_str, - current_gtid->seqno, bypass, env()); + ret = sst_donate_mysqldump(data, current_gtid, bypass, env()); } else { - ret = sst_donate_other(method, data, uuid_str, - current_gtid->seqno, bypass, env()); + ret = sst_donate_other(method, data, current_gtid, bypass, env()); } - return (ret >= 0 ? WSREP_CB_SUCCESS : WSREP_CB_FAILURE); -} - -void wsrep_SE_init_grab() -{ - if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort(); -} - -void wsrep_SE_init_wait() -{ - double total_wtime=0; - - while (SE_initialized == false) - { - struct timespec wtime; - set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS); - time_t start_time = time(NULL); - mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime); - time_t end_time = time(NULL); - - if (!SE_initialized) - { - total_wtime += difftime(end_time, start_time); - WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime); - service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL, - "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime); - } - } - - mysql_mutex_unlock (&LOCK_wsrep_sst_init); -} - -void wsrep_SE_init_done() -{ - mysql_cond_signal (&COND_wsrep_sst_init); - mysql_mutex_unlock (&LOCK_wsrep_sst_init); -} - -void wsrep_SE_initialized() -{ - SE_initialized = true; + return (ret >= 0 ? 0 : 1); } + diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index cc0f1f5389d..79d0d9e8a1e 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Codership Oy <info@codership.com> +/* Copyright (C) 2013-2018 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 @@ -18,9 +18,9 @@ #ifndef WSREP_SST_H #define WSREP_SST_H -#ifdef WITH_WSREP - -#include <mysql.h> // my_bool +#include "wsrep/gtid.hpp" +#include <my_global.h> +#include <string> #define WSREP_SST_OPT_ROLE "--role" #define WSREP_SST_OPT_ADDR "--address" @@ -74,11 +74,29 @@ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ extern void wsrep_SE_init_done(); /*! signal that SE init is complte */ extern void wsrep_SE_initialized(); /*! mark SE initialization complete */ +/** + Return a string containing the state transfer request string. + Note that the string may contain a '\0' in the middle. +*/ +std::string wsrep_sst_prepare(); + +/** + Donate a SST. + + @param request SST request string received from the joiner. Note that + the string may contain a '\0' in the middle. + @param gtid Current position of the donor + @param bypass If true, full SST is not needed. Joiner needs to be + notified that it can continue starting from gtid. + */ +int wsrep_sst_donate(const std::string& request, + const wsrep::gtid& gtid, + bool bypass); + #else #define wsrep_SE_initialized() do { } while(0) #define wsrep_SE_init_grab() do { } while(0) #define wsrep_SE_init_done() do { } while(0) #define wsrep_sst_continue() (0) -#endif /* WITH_WSREP */ #endif /* WSREP_SST_H */ diff --git a/sql/wsrep_storage_service.cc b/sql/wsrep_storage_service.cc new file mode 100644 index 00000000000..63c8771ea5c --- /dev/null +++ b/sql/wsrep_storage_service.cc @@ -0,0 +1,244 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_global.h" +#include "wsrep_storage_service.h" +#include "wsrep_trans_observer.h" /* wsrep_open() */ +#include "wsrep_schema.h" +#include "wsrep_binlog.h" + +#include "sql_class.h" +//#include "global_threads.h" /* LOCK_thread_count */ +#include "mysqld.h" /* next_query_id() */ +#include "slave.h" /* opt_log_slave_updates() */ +#include "transaction.h" /* trans_commit(), trans_rollback() */ + +/* + Temporarily enable wsrep on thd + */ +class Wsrep_on +{ +public: + Wsrep_on(THD* thd) + : m_thd(thd) + , m_wsrep_on(thd->variables.wsrep_on) + { + thd->variables.wsrep_on= TRUE; + } + ~Wsrep_on() + { + m_thd->variables.wsrep_on= m_wsrep_on; + } +private: + THD* m_thd; + my_bool m_wsrep_on; +}; + +Wsrep_storage_service::Wsrep_storage_service(THD* thd) + : wsrep::storage_service() + , wsrep::high_priority_context(thd->wsrep_cs()) + , m_thd(thd) +{ + thd->security_ctx->skip_grants(); + thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; + + /* No binlogging */ + // thd->variables.sql_log_bin = 0; + // thd->variables.option_bits &= ~OPTION_BIN_LOG; + + /* No general log */ + thd->variables.option_bits |= OPTION_LOG_OFF; + + /* Read committed isolation to avoid gap locking */ + thd->variables.tx_isolation = ISO_READ_COMMITTED; + + /* */ + // thd->variables.wsrep_on= 0; + /* Keep wsrep on to enter commit ordering hooks */ + thd->variables.wsrep_on= 1; + thd->wsrep_skip_locking= true; + + wsrep_open(thd); + wsrep_before_command(thd); +} + +Wsrep_storage_service::~Wsrep_storage_service() +{ + wsrep_after_command_ignore_result(m_thd); + wsrep_close(m_thd); + m_thd->wsrep_skip_locking= false; +} + +int Wsrep_storage_service::start_transaction(const wsrep::ws_handle& ws_handle) +{ + DBUG_ENTER("Wsrep_storage_service::start_transaction"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::start_transcation(%lu, %p)", + m_thd->thread_id, m_thd)); + m_thd->set_wsrep_next_trx_id(ws_handle.transaction_id().get()); + // DBUG_RETURN(wsrep_start_transaction(m_thd, m_thd->wsrep_next_trx_id())); + DBUG_RETURN(m_thd->wsrep_cs().start_transaction( + wsrep::transaction_id(m_thd->wsrep_next_trx_id())) || + trans_begin(m_thd, MYSQL_START_TRANS_OPT_READ_WRITE)); +} + +void Wsrep_storage_service::adopt_transaction(const wsrep::transaction& transaction) +{ + DBUG_ENTER("Wsrep_Storage_server::adopt_transaction"); + DBUG_ASSERT(m_thd == current_thd); + m_thd->wsrep_cs().adopt_transaction(transaction); + trans_begin(m_thd, MYSQL_START_TRANS_OPT_READ_WRITE); + DBUG_VOID_RETURN; +} + +int Wsrep_storage_service::append_fragment(const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + int flags, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_storage_service::append_fragment"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::append_fragment(%lu, %p)", + m_thd->thread_id, m_thd)); + int ret= wsrep_schema->append_fragment(m_thd, + server_id, + transaction_id, + wsrep::seqno(-1), + flags, + data); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::update_fragment_meta(const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_storage_service::update_fragment_meta"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::update_fragment_meta(%lu, %p)", + m_thd->thread_id, m_thd)); + int ret= wsrep_schema->update_fragment_meta(m_thd, ws_meta); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::remove_fragments() +{ + DBUG_ENTER("Wsrep_storage_service::remove_fragments"); + DBUG_ASSERT(m_thd == current_thd); + + int ret= wsrep_schema->remove_fragments(m_thd, + m_thd->wsrep_trx().server_id(), + m_thd->wsrep_trx().id(), + m_thd->wsrep_sr().fragments()); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::commit(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_storage_service::commit"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::commit(%lu, %p)", + m_thd->thread_id, m_thd)); + WSREP_DEBUG("Storage service commit: %llu, %lld", + ws_meta.transaction_id().get(), ws_meta.seqno().get()); + int ret= 0; + const bool do_binlog_commit= (opt_log_slave_updates && wsrep_gtid_mode); + const bool is_ordered= !ws_meta.seqno().is_undefined(); + /* + Write skip event into binlog if gtid_mode is on. This is to + maintain gtid continuity. + */ + if (do_binlog_commit && is_ordered) + { + ret= wsrep_write_skip_event(m_thd); + } + + if (!ret && is_ordered) + { + ret= m_thd->wsrep_cs().prepare_for_ordering(ws_handle, + ws_meta, true); + } + + if (!ret) + { + if (!do_binlog_commit && is_ordered) + { + ret= wsrep_before_commit(m_thd, true); + } + ret= ret || trans_commit(m_thd); + if (!do_binlog_commit && is_ordered) + { + if (opt_log_slave_updates) + { + ret= ret || wsrep_ordered_commit(m_thd, true, wsrep_apply_error()); + } + ret= ret || wsrep_after_commit(m_thd, true); + } + } + + if (!is_ordered) + { + /* Wsrep commit was not ordered so it does not go through commit time + hooks and remains active. Roll it back to make cleanup happen + in after_applying() call. */ + m_thd->wsrep_cs().before_rollback(); + m_thd->wsrep_cs().after_rollback(); + } + else if (ret) + { + /* Commit failed, this probably means that the parent SR transaction + was BF aborted. Roll back out of order, the parent + transaction will release commit order after it has rolled back. */ + m_thd->wsrep_cs().prepare_for_ordering(wsrep::ws_handle(), + wsrep::ws_meta(), + false); + trans_rollback(m_thd); + } + m_thd->wsrep_cs().after_applying(); + m_thd->mdl_context.release_transactional_locks(); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::rollback(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_storage_service::rollback"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::rollback(%lu, %p)", + m_thd->thread_id, m_thd)); + int ret= (m_thd->wsrep_cs().prepare_for_ordering( + ws_handle, ws_meta, false) || + trans_rollback(m_thd)); + m_thd->wsrep_cs().after_applying(); + m_thd->mdl_context.release_transactional_locks(); + DBUG_RETURN(ret); +} + +void Wsrep_storage_service::store_globals() +{ + DBUG_ENTER("Wsrep_storage_service::store_globals"); + DBUG_PRINT("info", ("Wsrep_storage_service::store_globals(%lu, %p)", + m_thd->thread_id, m_thd)); + m_thd->store_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_storage_service::reset_globals() +{ + DBUG_ENTER("Wsrep_storage_service::reset_globals"); + DBUG_PRINT("info", ("Wsrep_storage_service::reset_globals(%lu, %p)", + m_thd->thread_id, m_thd)); + m_thd->reset_globals(); + DBUG_VOID_RETURN; +} diff --git a/sql/wsrep_storage_service.h b/sql/wsrep_storage_service.h new file mode 100644 index 00000000000..6208300930f --- /dev/null +++ b/sql/wsrep_storage_service.h @@ -0,0 +1,48 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_STORAGE_SERVICE_H +#define WSREP_STORAGE_SERVICE_H + +#include "wsrep/storage_service.hpp" +#include "wsrep/client_state.hpp" + +class THD; +class Wsrep_server_service; +class Wsrep_storage_service : + public wsrep::storage_service, + public wsrep::high_priority_context +{ +public: + Wsrep_storage_service(THD*); + ~Wsrep_storage_service(); + int start_transaction(const wsrep::ws_handle&); + void adopt_transaction(const wsrep::transaction&); + int append_fragment(const wsrep::id&, + wsrep::transaction_id, + int flags, + const wsrep::const_buffer&); + int update_fragment_meta(const wsrep::ws_meta&); + int remove_fragments(); + int commit(const wsrep::ws_handle&, const wsrep::ws_meta&); + int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&); + void store_globals(); + void reset_globals(); +private: + friend class Wsrep_server_service; + THD* m_thd; +}; + +#endif /* WSREP_STORAGE_SERVICE_H */ diff --git a/sql/wsrep_tc.h b/sql/wsrep_tc.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index ce6d9688cb3..a96db7e6986 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -15,6 +15,8 @@ #include "mariadb.h" #include "wsrep_thd.h" +#include "wsrep_high_priority_service.h" +#include "wsrep_storage_service.h" #include "transaction.h" #include "rpl_rli.h" #include "log_event.h" @@ -22,12 +24,16 @@ //#include "global_threads.h" // LOCK_thread_count, etc. #include "sql_base.h" // close_thread_tables() #include "mysqld.h" // start_wsrep_THD(); - -#include "slave.h" // opt_log_slave_updates -#include "rpl_filter.h" +#include "wsrep_applier.h" // start_wsrep_THD(); +#include "mysql/service_wsrep.h" +#include "debug_sync.h" +#include "slave.h" #include "rpl_rli.h" #include "rpl_mi.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 @@ -47,52 +53,6 @@ int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, return 0; } -/* must have (&thd->LOCK_thd_data) */ -void wsrep_client_rollback(THD *thd) -{ - WSREP_DEBUG("client rollback due to BF abort for (%lld), query: %s", - (longlong) thd->thread_id, thd->query()); - - WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1); - - thd->wsrep_conflict_state= ABORTING; - mysql_mutex_unlock(&thd->LOCK_thd_data); - trans_rollback(thd); - - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("unlocking tables for BF abort (%lld)", - (longlong) 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); - thd->global_read_lock.unlock_global_read_lock(thd); - } - - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - - /* release explicit MDL locks */ - thd->mdl_context.release_explicit_locks(); - - if (thd->get_binlog_table_maps()) - { - WSREP_DEBUG("clearing binlog table map for BF abort (%lld)", - (longlong) thd->thread_id); - thd->clear_binlog_table_maps(); - } - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_conflict_state= ABORTED; -} - -#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1 -#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2 - static rpl_group_info* wsrep_relay_group_init(const char* log_fname) { Relay_log_info* rli= new Relay_log_info(false); @@ -135,292 +95,53 @@ 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) +static void wsrep_replication_process(THD *thd, + void* arg __attribute__((unused))) { - shadow->options = thd->variables.option_bits; - shadow->server_status = thd->server_status; - shadow->wsrep_exec_mode = thd->wsrep_exec_mode; - shadow->vio = thd->net.vio; - - // Disable general logging on applier threads - thd->variables.option_bits |= OPTION_LOG_OFF; - // Enable binlogging if opt_log_slave_updates is set - if (opt_log_slave_updates) - thd->variables.option_bits|= OPTION_BIN_LOG; - else - thd->variables.option_bits&= ~(OPTION_BIN_LOG); - + DBUG_ENTER("wsrep_replication_process"); if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init("wsrep_relay"); /* thd->system_thread_info.rpl_sql_info isn't initialized. */ thd->system_thread_info.rpl_sql_info= new rpl_sql_thread_info(thd->wsrep_rgi->rli->mi->rpl_filter); - thd->wsrep_exec_mode= REPL_RECV; - thd->net.vio= 0; - thd->clear_error(); - - shadow->tx_isolation = thd->variables.tx_isolation; - thd->variables.tx_isolation = ISO_READ_COMMITTED; - thd->tx_isolation = ISO_READ_COMMITTED; + Wsrep_applier_service applier_service(thd); - shadow->db = thd->db.str; - shadow->db_length = thd->db.length; - shadow->user_time = thd->user_time; - shadow->row_count_func= thd->get_row_count_func(); - thd->reset_db(&null_clex_str); -} + WSREP_INFO("Starting applier thread %llu", thd->thread_id); + enum wsrep::provider::status + ret= Wsrep_server_state::get_provider().run_applier(&applier_service); -static 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; - thd->server_status = shadow->server_status; - thd->wsrep_exec_mode = shadow->wsrep_exec_mode; - thd->net.vio = shadow->vio; - thd->variables.tx_isolation = shadow->tx_isolation; - thd->user_time = shadow->user_time; - thd->reset_db(&db); + WSREP_INFO("Applier thread exiting %d", ret); + mysql_mutex_lock(&LOCK_thread_count); + wsrep_close_applier(thd); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); delete thd->system_thread_info.rpl_sql_info; delete thd->wsrep_rgi->rli->mi; delete thd->wsrep_rgi->rli; - + thd->wsrep_rgi->cleanup_after_session(); delete thd->wsrep_rgi; thd->wsrep_rgi = NULL; - thd->set_row_count_func(shadow->row_count_func); -} -void wsrep_replay_transaction(THD *thd) -{ - DBUG_ENTER("wsrep_replay_transaction"); - /* checking if BF trx must be replayed */ - if (thd->wsrep_conflict_state== MUST_REPLAY) { - DBUG_ASSERT(wsrep_thd_trx_seqno(thd)); - if (thd->wsrep_exec_mode!= REPL_RECV) { - if (thd->get_stmt_da()->is_sent()) - { - WSREP_ERROR("replay issue, thd has reported status already"); - } - - - /* - PS reprepare observer should have been removed already. - open_table() will fail if we have dangling observer here. - */ - DBUG_ASSERT(thd->m_reprepare_observer == NULL); - - struct da_shadow - { - enum Diagnostics_area::enum_diagnostics_status status; - ulonglong affected_rows; - ulonglong last_insert_id; - char message[MYSQL_ERRMSG_SIZE]; - }; - struct da_shadow da_status; - da_status.status= thd->get_stmt_da()->status(); - if (da_status.status == Diagnostics_area::DA_OK) - { - da_status.affected_rows= thd->get_stmt_da()->affected_rows(); - da_status.last_insert_id= thd->get_stmt_da()->last_insert_id(); - strmake(da_status.message, - thd->get_stmt_da()->message(), - sizeof(da_status.message)-1); - } - - thd->get_stmt_da()->reset_diagnostics_area(); - - thd->wsrep_conflict_state= REPLAYING; - mysql_mutex_unlock(&thd->LOCK_thd_data); - - thd->reset_for_next_command(); - thd->reset_killed(); - close_thread_tables(thd); - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("releasing table lock for replaying (%lld)", - (longlong) thd->thread_id); - thd->locked_tables_list.unlock_locked_tables(thd); - thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); - } - thd->mdl_context.release_transactional_locks(); - /* - Replaying will call MYSQL_START_STATEMENT when handling - BEGIN Query_log_event so end statement must be called before - replaying. - */ - MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); - thd->m_statement_psi= NULL; - thd->m_digest= NULL; - thd_proc_info(thd, "WSREP replaying trx"); - WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)wsrep_thd_trx_seqno(thd)); - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - - /* From trans_begin() */ - thd->variables.option_bits|= OPTION_BEGIN; - thd->server_status|= SERVER_STATUS_IN_TRANS; - - int rcode = wsrep->replay_trx(wsrep, - &thd->wsrep_ws_handle, - (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 ); - - mysql_mutex_lock(&thd->LOCK_thd_data); - - switch (rcode) - { - case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(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()) - { - WSREP_WARN("replay ok, thd has reported status"); - } - else if (thd->get_stmt_da()->is_set()) - { - if (thd->get_stmt_da()->status() != Diagnostics_area::DA_OK && - thd->get_stmt_da()->status() != Diagnostics_area::DA_OK_BULK) - { - WSREP_WARN("replay ok, thd has error status %d", - thd->get_stmt_da()->status()); - } - } - else - { - if (da_status.status == Diagnostics_area::DA_OK) - { - my_ok(thd, - da_status.affected_rows, - da_status.last_insert_id, - da_status.message); - } - else - { - my_ok(thd); - } - } - break; - case WSREP_TRX_FAIL: - if (thd->get_stmt_da()->is_sent()) - { - WSREP_ERROR("replay failed, thd has reported status"); - } - else - { - WSREP_DEBUG("replay failed, rolling back"); - } - thd->wsrep_conflict_state= ABORTED; - wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle); - break; - default: - WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s", - rcode, thd->get_db(), - thd->query() ? thd->query() : "void"); - /* we're now in inconsistent state, must abort */ - - /* http://bazaar.launchpad.net/~codership/codership-mysql/5.6/revision/3962#sql... */ - mysql_mutex_unlock(&thd->LOCK_thd_data); - - unireg_abort(1); - break; - } - - wsrep_cleanup_transaction(thd); - - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lld", - wsrep_replaying, (longlong) thd->thread_id); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } - } - DBUG_VOID_RETURN; -} - -static void wsrep_replication_process(THD *thd) -{ - int rcode; - DBUG_ENTER("wsrep_replication_process"); - - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - - /* From trans_begin() */ - thd->variables.option_bits|= OPTION_BEGIN; - thd->server_status|= SERVER_STATUS_IN_TRANS; - - rcode = wsrep->recv(wsrep, (void *)thd); - DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode)); - - WSREP_INFO("applier thread exiting (code:%d)", rcode); - - switch (rcode) { - case WSREP_OK: - case WSREP_NOT_IMPLEMENTED: - case WSREP_CONN_FAIL: - /* provider does not support slave operations / disconnected from group, - * just close applier thread */ - break; - case WSREP_NODE_FAIL: - /* data inconsistency => SST is needed */ - /* Note: we cannot just blindly restart replication here, - * SST might require server restart if storage engines must be - * initialized after SST */ - WSREP_ERROR("node consistency compromised, aborting"); - wsrep_kill_mysql(thd); - break; - case WSREP_WARNING: - case WSREP_TRX_FAIL: - case WSREP_TRX_MISSING: - /* these suggests a bug in provider code */ - WSREP_WARN("bad return from recv() call: %d", rcode); - /* Shut down this node. */ - /* fall through */ - case WSREP_FATAL: - /* Cluster connectivity is lost. - * - * If applier was killed on purpose (KILL_CONNECTION), we - * avoid mysql shutdown. This is because the killer will then handle - * shutdown processing (or replication restarting) - */ - if (thd->killed != KILL_CONNECTION) - { - wsrep_kill_mysql(thd); - } - break; - } - - mysql_mutex_lock(&LOCK_thread_count); - wsrep_close_applier(thd); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); if(thd->has_thd_temporary_tables()) { WSREP_WARN("Applier %lld has temporary tables at exit.", thd->thread_id); } - wsrep_return_from_bf_mode(thd, &shadow); 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 @@ -435,7 +156,16 @@ static bool create_wsrep_THD(wsrep_thd_processor_fun processor) void wsrep_create_appliers(long threads) { - if (!wsrep_connected) + /* + Todo: We should somehow verify here that the provider has been + connected. However, currently the wsrep_connected status variable + is updated in Wsrep_server_service::log_state_change() after the + Wsrep_server_state reaches connected state. Due to the differences + in Wsrep_server_state state machine with different SST methods, + it is not straightforward to wait for certain state. Perhaps + connecting state needs to be implemented separately. + */ + if (false) { /* see wsrep_replication_start() for the logic */ if (wsrep_cluster_address && strlen(wsrep_cluster_address) && @@ -449,88 +179,188 @@ 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; - - while (thd->killed == NOT_KILLED) { - thd_proc_info(thd, "WSREP aborter idle"); - thd->mysys_var->current_mutex= &LOCK_wsrep_rollback; - thd->mysys_var->current_cond= &COND_wsrep_rollback; + THD* thd= NULL; + DBUG_ASSERT(!wsrep_rollback_queue); + wsrep_rollback_queue= new Wsrep_thd_queue(rollbacker); - mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback); + thd_proc_info(rollbacker, "wsrep aborter idle"); + while ((thd= wsrep_rollback_queue->pop_front()) != NULL) + { + mysql_mutex_lock(&thd->LOCK_thd_data); + wsrep::client_state& cs(thd->wsrep_cs()); + const wsrep::transaction& tx(cs.transaction()); + if (tx.state() == wsrep::transaction::s_aborted) + { + WSREP_DEBUG("rollbacker thd already aborted: %llu state: %d", + (long long)thd->real_id, + tx.state()); - WSREP_DEBUG("WSREP rollback thread wakes for signal"); + mysql_mutex_unlock(&thd->LOCK_thd_data); + continue; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); - mysql_mutex_lock(&thd->mysys_var->mutex); - thd_proc_info(thd, "WSREP aborter active"); - thd->mysys_var->current_mutex= 0; - thd->mysys_var->current_cond= 0; - mysql_mutex_unlock(&thd->mysys_var->mutex); + thd_proc_info(rollbacker, "wsrep aborter active"); - /* check for false alarms */ - if (!wsrep_aborting_thd) + wsrep::transaction_id transaction_id(thd->wsrep_trx().id()); + if (thd->wsrep_trx().is_streaming() && + thd->wsrep_trx().bf_aborted_in_total_order()) { - WSREP_DEBUG("WSREP rollback thread has empty abort queue"); - } - /* process all entries in the queue */ - while (wsrep_aborting_thd) { - THD *aborting; - wsrep_aborting_thd_t next = wsrep_aborting_thd->next; - aborting = wsrep_aborting_thd->aborting_thd; - my_free(wsrep_aborting_thd); - wsrep_aborting_thd= next; - /* - * must release mutex, appliers my want to add more - * aborting thds in our work queue, while we rollback - */ - mysql_mutex_unlock(&LOCK_wsrep_rollback); - - mysql_mutex_lock(&aborting->LOCK_thd_data); - if (aborting->wsrep_conflict_state== ABORTED) + thd->store_globals(); + thd->wsrep_cs().store_globals(); + if (thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority) + { + DBUG_ASSERT(thd->wsrep_applier_service); + thd->wsrep_applier_service->rollback(wsrep::ws_handle(), + wsrep::ws_meta()); + thd->wsrep_applier_service->after_apply(); + /* Will free THD */ + Wsrep_server_state::instance().server_service(). + release_high_priority_service(thd->wsrep_applier_service); + } + else { - WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", - (long long)aborting->real_id, - aborting->wsrep_conflict_state); + mysql_mutex_lock(&thd->LOCK_thd_data); + /* prepare THD for rollback processing */ + thd->reset_for_next_command(true); + thd->lex->sql_command= SQLCOM_ROLLBACK; + mysql_mutex_unlock(&thd->LOCK_thd_data); + /* Perform a client rollback, restore globals and signal + the victim only when all the resources have been + released */ + thd->wsrep_cs().client_service().bf_rollback(); + thd->reset_globals(); + thd->wsrep_cs().sync_rollback_complete(); + } + } + else if (wsrep_thd_is_applying(thd)) + { + WSREP_DEBUG("rollbacker aborting SR thd: (%lld %llu)", + thd->thread_id, (long long)thd->real_id); + DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_high_priority); + /* Must be streaming and must have been removed from the + server state streaming appliers map. */ + DBUG_ASSERT(thd->wsrep_trx().is_streaming()); + DBUG_ASSERT(!Wsrep_server_state::instance().find_streaming_applier( + thd->wsrep_trx().server_id(), + thd->wsrep_trx().id())); + DBUG_ASSERT(thd->wsrep_applier_service); + + /* Fragment removal should happen before rollback to make + the transaction non-observable in SR table after the rollback + completes. For correctness the order does not matter here, + but currently it is mandated by checks in some MTR tests. */ + Wsrep_storage_service* storage_service= + static_cast<Wsrep_storage_service*>( + Wsrep_server_state::instance().server_service().storage_service( + *thd->wsrep_applier_service)); + storage_service->store_globals(); + storage_service->adopt_transaction(thd->wsrep_trx()); + storage_service->remove_fragments(); + storage_service->commit(wsrep::ws_handle(transaction_id, 0), + wsrep::ws_meta()); + Wsrep_server_state::instance().server_service().release_storage_service(storage_service); + thd->store_globals(); + thd->wsrep_cs().store_globals(); + thd->wsrep_applier_service->rollback(wsrep::ws_handle(), + wsrep::ws_meta()); + thd->wsrep_applier_service->after_apply(); + /* Will free THD */ + Wsrep_server_state::instance().server_service() + .release_high_priority_service(thd->wsrep_applier_service); - mysql_mutex_unlock(&aborting->LOCK_thd_data); - mysql_mutex_lock(&LOCK_wsrep_rollback); - continue; + } + else + { + if (thd->wsrep_trx().is_streaming()) + { + Wsrep_storage_service* storage_service= + static_cast<Wsrep_storage_service*>( + Wsrep_server_state::instance().server_service(). + storage_service(thd->wsrep_cs().client_service())); + + storage_service->store_globals(); + storage_service->adopt_transaction(thd->wsrep_trx()); + storage_service->remove_fragments(); + storage_service->commit(wsrep::ws_handle(transaction_id, 0), + wsrep::ws_meta()); + Wsrep_server_state::instance().server_service(). + release_storage_service(storage_service); } - aborting->wsrep_conflict_state= ABORTING; + thd->store_globals(); + thd->wsrep_cs().store_globals(); + mysql_mutex_lock(&thd->LOCK_thd_data); + /* prepare THD for rollback processing */ + thd->reset_for_next_command(); + thd->lex->sql_command= SQLCOM_ROLLBACK; + mysql_mutex_unlock(&thd->LOCK_thd_data); + /* Perform a client rollback, restore globals and signal + the victim only when all the resources have been + released */ + thd->wsrep_cs().client_service().bf_rollback(); + thd->reset_globals(); + thd->wsrep_cs().sync_rollback_complete(); + WSREP_DEBUG("rollbacker aborted thd: (%llu %llu)", + thd->thread_id, (long long)thd->real_id); + } - mysql_mutex_unlock(&aborting->LOCK_thd_data); + thd_proc_info(rollbacker, "wsrep aborter idle"); + } + + delete wsrep_rollback_queue; + wsrep_rollback_queue= NULL; - set_current_thd(aborting); - aborting->store_globals(); + sql_print_information("WSREP: rollbacker thread exiting"); - 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); + DBUG_ASSERT(rollbacker->killed != NOT_KILLED); + DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); + DBUG_VOID_RETURN; +} - set_current_thd(thd); - thd->store_globals(); +static void wsrep_post_rollback_process(THD *post_rollbacker, + void *arg __attribute__((unused))) +{ + DBUG_ENTER("wsrep_post_rollback_process"); + THD* thd= NULL; - mysql_mutex_lock(&LOCK_wsrep_rollback); - } + DBUG_ASSERT(!wsrep_post_rollback_queue); + wsrep_post_rollback_queue= new Wsrep_thd_queue(post_rollbacker); + + while ((thd= wsrep_post_rollback_queue->pop_front()) != NULL) + { + thd->store_globals(); + wsrep::client_state& cs(thd->wsrep_cs()); + mysql_mutex_lock(&thd->LOCK_thd_data); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborting); + WSREP_DEBUG("post rollbacker calling post rollback for thd %llu, conf %s", + thd->thread_id, wsrep_thd_transaction_state_str(thd)); + + cs.after_rollback(); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborted); + mysql_mutex_unlock(&thd->LOCK_thd_data); } - mysql_mutex_unlock(&LOCK_wsrep_rollback); - sql_print_information("WSREP: rollbacker thread exiting"); + delete wsrep_post_rollback_queue; + wsrep_post_rollback_queue= NULL; - DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); + DBUG_ASSERT(post_rollbacker->killed != NOT_KILLED); + DBUG_PRINT("wsrep",("wsrep post rollbacker thread exiting")); DBUG_VOID_RETURN; } @@ -538,12 +368,19 @@ 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"); + } +} +#if 0 void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe) { if (thd_ptr) @@ -553,116 +390,51 @@ void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe) } } -enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd, my_bool sync) -{ - enum wsrep_conflict_state state = NO_CONFLICT; - if (thd) - { - if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - - state = thd->wsrep_conflict_state; - if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); - } - return state; -} - -my_bool wsrep_thd_is_wsrep(THD *thd) -{ - my_bool status = FALSE; - if (thd) - { - status = (WSREP(thd) && WSREP_PROVIDER_EXISTS); - } - return status; -} - -my_bool wsrep_thd_is_BF(THD *thd, my_bool sync) -{ - my_bool status = FALSE; - if (thd) - { - // THD can be BF only if provider exists - if (wsrep_thd_is_wsrep(thd)) - { - if (sync) - mysql_mutex_lock(&thd->LOCK_thd_data); - - status = ((thd->wsrep_exec_mode == REPL_RECV) || - (thd->wsrep_exec_mode == TOTAL_ORDER)); - if (sync) - mysql_mutex_unlock(&thd->LOCK_thd_data); - } - } - return status; -} +#endif +/* + Start async rollback process -extern "C" -my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync) + Asserts thd->LOCK_thd_data ownership + */ +void wsrep_fire_rollbacker(THD *thd) { - bool status = FALSE; - if (thd_ptr) + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborting); + DBUG_PRINT("wsrep",("enqueuing trx abort for %llu", thd->thread_id)); + WSREP_DEBUG("enqueuing trx abort for (%llu)", thd->thread_id); + if (wsrep_rollback_queue->push_back(thd)) { - THD* thd = (THD*)thd_ptr; - if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - - status = ((thd->wsrep_exec_mode == REPL_RECV) || - (thd->wsrep_exec_mode == TOTAL_ORDER) || - (thd->wsrep_exec_mode == LOCAL_COMMIT)); - if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); + WSREP_WARN("duplicate thd %llu for rollbacker", + thd->thread_id); } - return status; } -extern "C" -my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync) -{ - bool status = FALSE; - if (thd_ptr) - { - THD* thd = (THD*)thd_ptr; - if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - - status = (thd->wsrep_exec_mode == LOCAL_STATE); - if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); - } - return status; -} int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) { + DBUG_ENTER("wsrep_abort_thd"); 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_thd_data); if ( (WSREP(bf_thd) || ( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) && - bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && - victim_thd) + wsrep_thd_is_toi(bf_thd)) ) && + victim_thd && + !wsrep_thd_is_aborting(victim_thd)) { - if ((victim_thd->wsrep_conflict_state == MUST_ABORT) || - (victim_thd->wsrep_conflict_state == ABORTED) || - (victim_thd->wsrep_conflict_state == ABORTING)) - { - 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); - ha_abort_transaction(bf_thd, victim_thd, signal); + 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_thd_data); + ha_abort_transaction(bf_thd, victim_thd, signal); + mysql_mutex_lock(&victim_thd->LOCK_thd_data); } else { WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd); } - + mysql_mutex_unlock(&victim_thd->LOCK_thd_data); DBUG_RETURN(1); } - -extern "C" +#if 0 int wsrep_thd_in_locking_session(void *thd_ptr) { if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { @@ -676,3 +448,27 @@ bool wsrep_thd_has_explicit_locks(THD *thd) assert(thd); return thd->mdl_context.has_explicit_locks(); } + +#endif + +bool wsrep_bf_abort(const THD* bf_thd, THD* victim_thd) +{ + WSREP_LOG_THD((THD*)bf_thd, "BF aborter before"); + WSREP_LOG_THD(victim_thd, "victim before"); + wsrep::seqno bf_seqno(bf_thd->wsrep_trx().ws_meta().seqno()); + bool ret; + if (wsrep_thd_is_toi(bf_thd)) + { + ret= victim_thd->wsrep_cs().total_order_bf_abort(bf_seqno); + } + else + { + ret= victim_thd->wsrep_cs().bf_abort(bf_seqno); + } + if (ret) + { + my_atomic_add64(&wsrep_bf_aborts_counter, 1); + } + return ret; +} + diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 5900668f3fb..a2fdd7d1a36 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -18,37 +18,220 @@ #ifndef WSREP_THD_H #define WSREP_THD_H -#ifdef WITH_WSREP - +#include "mysql/service_wsrep.h" #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(); +bool wsrep_bf_abort(const THD*, THD*); int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal); - -/* - 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_wsrep(void *thd_ptr); +THD* wsrep_start_SR_THD(char *thread_stack); +void wsrep_end_SR_THD(THD* thd); + +/** + 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) +{ + DBUG_ASSERT(error != ER_ERROR_DURING_COMMIT); + 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, + enum wsrep::provider::status 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); + } +} + +static inline void wsrep_override_error(THD* thd, + wsrep::client_error ce, + enum wsrep::provider::status status) +{ + DBUG_ASSERT(ce != wsrep::e_success); + switch (ce) + { + case wsrep::e_error_during_commit: + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status); + break; + case wsrep::e_deadlock_error: + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + break; + case wsrep::e_interrupted_error: + wsrep_override_error(thd, ER_QUERY_INTERRUPTED); + break; + case wsrep::e_size_exceeded_error: + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status); + break; + case wsrep::e_append_fragment_error: + /* TODO: Figure out better error number */ + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status); + break; + case wsrep::e_not_supported_error: + wsrep_override_error(thd, ER_NOT_SUPPORTED_YET); + break; + case wsrep::e_timeout_error: + wsrep_override_error(thd, ER_LOCK_WAIT_TIMEOUT); + break; + default: + wsrep_override_error(thd, ER_UNKNOWN_ERROR); + break; + } +} + +/** + 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 client_mode: %s client_state: %s trx_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_client_mode_str(thd), + wsrep_thd_client_state_str(thd), + wsrep_thd_transaction_state_str(thd), + (long long)thd->wsrep_next_trx_id(), + (long long)thd->wsrep_trx_id(), + wsrep_thd_trx_seqno(thd), + thd->wsrep_trx().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 */ + ); +} -enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); -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); +#define WSREP_LOG_THD(thd_, message_) wsrep_log_thd(thd_, message_, __FUNCTION__) #else /* WITH_WSREP */ -#define wsrep_thd_is_BF(T, S) (0) -#define wsrep_abort_thd(X,Y,Z) do { } while(0) -#define wsrep_create_appliers(T) do { } while(0) +//#define wsrep_thd_is_BF(T, S) (0) +//#define wsrep_abort_thd(X,Y,Z) do { } while(0) +//#define wsrep_create_appliers(T) do { } while(0) -#endif #endif /* WSREP_THD_H */ diff --git a/sql/wsrep_thd_pool.cc b/sql/wsrep_thd_pool.cc new file mode 100644 index 00000000000..4a1ff7fde5f --- /dev/null +++ b/sql/wsrep_thd_pool.cc @@ -0,0 +1,125 @@ +/* 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 "wsrep_api.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; + /* No binlogging */ + thd->variables.sql_log_bin = 0; + thd->variables.option_bits &= ~OPTION_BIN_LOG; + /* No general log */ + thd->variables.option_bits |= OPTION_LOG_OFF; + /* Read committed isolation to avoid gap locking */ + thd->variables.tx_isolation = ISO_READ_COMMITTED; + + 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.h b/sql/wsrep_trans_observer.h new file mode 100644 index 00000000000..cf78912195a --- /dev/null +++ b/sql/wsrep_trans_observer.h @@ -0,0 +1,369 @@ +/* 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 "mysql/service_wsrep.h" +#include "wsrep_applier.h" /* wsrep_apply_error */ +#include "wsrep_xid.h" +#include "wsrep_thd.h" + +#include "my_dbug.h" + +class THD; + +/* + Return true if THD has active wsrep transaction. + */ +static inline bool wsrep_is_active(THD* thd) +{ + return (wsrep_on(thd) && thd->wsrep_cs().transaction().active()); +} + +/* + Return true if THD is either committing a transaction or statement + is autocommit. + */ +static inline bool wsrep_is_real(THD* thd, bool all) +{ + return (all || thd->transaction.all.ha_list == 0); +} + +static inline int wsrep_check_pk(THD* thd) +{ + 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); + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + return 1; + } + } + } + return 0; +} + +static inline bool wsrep_streaming_enabled(THD* thd) +{ + return (thd->wsrep_sr().fragment_size() > 0); +} + + +static inline int wsrep_start_transaction(THD* thd, wsrep_trx_id_t trx_id) +{ + return (wsrep_on(thd) ? + thd->wsrep_cs().start_transaction(wsrep::transaction_id(trx_id)) : + 0); +} + +/**/ +static inline int wsrep_start_trx_if_not_started(THD* thd) +{ + int ret= 0; + DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID); + DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_local); + if (thd->wsrep_trx().active() == false) + { + ret= wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); + } + return ret; +} + +/* + Called after each row operation. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_row(THD* thd, bool) +{ + if (wsrep_on(thd) && wsrep_thd_is_local(thd)) + { + if (wsrep_check_pk(thd)) + { + return 1; + } + else if (wsrep_streaming_enabled(thd)) + { + return thd->wsrep_cs().after_row(); + } + } + return 0; +} + +/* + Called before the transaction is prepared. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_before_prepare(THD* thd, bool all) +{ + WSREP_DEBUG("wsrep_before_prepare: %d", wsrep_is_real(thd, all)); + int ret= ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ? + thd->wsrep_cs().before_prepare() : 0); + DBUG_ASSERT(ret == 0 || thd->wsrep_cs().current_error()); + return ret; +} + +/* + Called after the transaction has been prepared. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_prepare(THD* thd, bool all) +{ + WSREP_DEBUG("wsrep_after_prepare: %d", wsrep_is_real(thd, all)); + int ret= ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ? + thd->wsrep_cs().after_prepare() : 0); + DBUG_ASSERT(ret == 0 || thd->wsrep_cs().current_error() || + thd->wsrep_cs().transaction().state() == wsrep::transaction::s_must_replay); + return ret; +} + + +/* + 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. + */ +static inline int wsrep_before_commit(THD* thd, bool all) +{ + WSREP_DEBUG("wsrep_before_commit: %d, %lld", + wsrep_is_real(thd, all), + wsrep_thd_trx_seqno(thd)); + return ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ? + wsrep_xid_init(&thd->wsrep_xid, + thd->wsrep_cs().transaction().ws_meta().gtid()), + thd->wsrep_cs().before_commit() : 0); +} + +/* + 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. + */ +static inline int wsrep_ordered_commit(THD* thd, + bool all, + const wsrep_apply_error&) +{ + WSREP_DEBUG("wsrep_ordered_commit: %d", wsrep_is_real(thd, all)); + return ((wsrep_is_real(thd, all) && wsrep_is_active(thd)) ? + thd->wsrep_cs().ordered_commit() : 0); +} + +/* + Called after the transaction has been committed. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_commit(THD* thd, bool all) +{ + WSREP_DEBUG("wsrep_after_commit: %d, %d, %lu", wsrep_is_real(thd, all), + wsrep_is_active(thd), wsrep_thd_trx_seqno(thd)); + bool run_after_commit= (wsrep_is_real(thd, all) && wsrep_is_active(thd)); + if (run_after_commit) + { + return (wsrep_ordered_commit_if_no_binlog(thd, all) || + (wsrep_xid_init(&thd->wsrep_xid, wsrep::gtid::undefined()), + thd->wsrep_cs().after_commit())); + } + else + { + return 0; + } +} + +/* + Called before the transaction is rolled back. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_before_rollback(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_rollback"); + int ret= 0; + if (wsrep_is_active(thd)) + { + if (!all && thd->in_active_multi_stmt_transaction() && + thd->wsrep_trx().is_streaming() && + !wsrep_stmt_rollback_is_safe(thd)) + { + /* Non-safe statement rollback during SR multi statement + transasction. Self abort the transaction, the actual rollback + and error handling will be done in after statement phase. */ + wsrep_thd_self_abort(thd); + ret= 0; + } + else if (wsrep_is_real(thd, all) && + thd->wsrep_trx().state() != wsrep::transaction::s_aborted) + { + /* Real transaction rolling back and wsrep abort not completed + yet */ + /* Reset XID so that it does not trigger writing serialization + history in InnoDB. This needs to be avoided because rollback + may happen out of order and replay may follow. */ + wsrep_xid_init(&thd->wsrep_xid, wsrep::gtid::undefined()); + ret= thd->wsrep_cs().before_rollback(); + } + } + DBUG_RETURN(ret); +} + +/* + Called after the transaction has been rolled back. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_rollback(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_rollback"); + DBUG_RETURN((wsrep_is_real(thd, all) && wsrep_is_active(thd) && + thd->wsrep_cs().transaction().state() != + wsrep::transaction::s_aborted) ? + thd->wsrep_cs().after_rollback() : 0); +} + +static inline int wsrep_before_statement(THD* thd) +{ + return (wsrep_on(thd) ? thd->wsrep_cs().before_statement() : 0); +} + +static inline +// enum wsrep::client_state::after_statement_result +int wsrep_after_statement(THD* thd) +{ + return (wsrep_on((const void*)thd) ? + thd->wsrep_cs().after_statement() : 0); +} + +static inline void wsrep_after_apply(THD* thd) +{ + DBUG_ASSERT(wsrep_thd_is_applying(thd)); + WSREP_DEBUG("wsrep_after_apply %lld", thd->thread_id); + thd->wsrep_cs().after_applying(); +} + +static inline void wsrep_open(THD* thd) +{ + DBUG_ENTER("wsrep_open"); + if (wsrep_global_on()) + { + thd->wsrep_cs().open(wsrep::client_id(thd->thread_id)); + thd->wsrep_cs().debug_log_level(wsrep_debug); + } + DBUG_VOID_RETURN; +} + +static inline void wsrep_close(THD* thd) +{ + DBUG_ENTER("wsrep_close"); + if (wsrep_global_on()) + { + thd->wsrep_cs().close(); + } + DBUG_VOID_RETURN; +} + +static inline int wsrep_before_command(THD* thd) +{ + return (wsrep_global_on() ? thd->wsrep_cs().before_command() : 0); +} +/* + Called after each command. + + Return zero on success, non-zero on failure. +*/ +static inline void wsrep_after_command_before_result(THD* thd) +{ + if (wsrep_global_on()) + { + thd->wsrep_cs().after_command_before_result(); + } +} + +static inline void wsrep_after_command_after_result(THD* thd) +{ + if (wsrep_global_on()) + { + thd->wsrep_cs().after_command_after_result(); + } +} + +static inline void wsrep_after_command_ignore_result(THD* thd) +{ + wsrep_after_command_before_result(thd); + DBUG_ASSERT(!thd->wsrep_cs().current_error()); + wsrep_after_command_after_result(thd); +} + +static inline enum wsrep::client_error wsrep_current_error(THD* thd) +{ + return thd->wsrep_cs().current_error(); +} + +static inline enum wsrep::provider::status +wsrep_current_error_status(THD* thd) +{ + return thd->wsrep_cs().current_error_status(); +} + + +/* + Commit an empty transaction. + + If the transaction is real and the wsrep transaction is still active, + the transaction did not generate any rows or keys and is committed + as empty. Here the wsrep transaction is rolled back and after statement + step is performed to leave the wsrep transaction in the state as it + never existed. +*/ +static inline void wsrep_commit_empty(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_commit_empty"); + WSREP_DEBUG("wsrep_commit_empty(%llu)", thd->thread_id); + if (wsrep_is_real(thd, all) && + wsrep_thd_is_local(thd) && + thd->wsrep_trx().active()) + { + bool have_error= wsrep_current_error(thd); + int ret= wsrep_before_rollback(thd, all) || + wsrep_after_rollback(thd, all) || + wsrep_after_statement(thd); + DBUG_ASSERT(!ret); + DBUG_ASSERT(have_error || !wsrep_current_error(thd)); + if (ret) + { + WSREP_WARN("wsrep_commit_empty failed: %d", wsrep_current_error(thd)); + } + } + DBUG_VOID_RETURN; +} + +#endif /* WSREP_TRANS_OBSERVER */ diff --git a/sql/wsrep_types.h b/sql/wsrep_types.h new file mode 100644 index 00000000000..9da00e305a7 --- /dev/null +++ b/sql/wsrep_types.h @@ -0,0 +1,29 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* + Wsrep typedefs to better conform to coding style. + */ +#ifndef WSREP_TYPES_H +#define WSREP_TYPES_H + +#include "wsrep/seqno.hpp" +#include "wsrep/view.hpp" + +typedef wsrep::id Wsrep_id; +typedef wsrep::seqno Wsrep_seqno; +typedef wsrep::view Wsrep_view; + +#endif /* WSREP_TYPES_H */ diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 3c341e222b3..f0f82ac41b9 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -21,6 +21,8 @@ #endif #include "mariadb.h" +#include "my_global.h" +#include "wsrep_api.h" #include "wsrep_utils.h" #include "wsrep_mysqld.h" diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 277cea9dc31..f6520dda86e 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); @@ -314,6 +335,17 @@ class string 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 f8a494416e2..791bd1c2b2a 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, uuid, seqno, NULL, 0); } 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; @@ -263,25 +261,23 @@ static int get_provider_option_value(const char* opts, static bool refresh_provider_options() { - DBUG_ASSERT(wsrep); - WSREP_DEBUG("refresh_provider_options: %s", (wsrep_provider_options) ? wsrep_provider_options : "null"); - char* opts= wsrep->options_get(wsrep); - if (opts) + + try { - wsrep_provider_options_init(opts); + std::string opts= Wsrep_server_state::instance().provider().options(); + wsrep_provider_options_init(opts.c_str()); get_provider_option_value(wsrep_provider_options, (char*)"repl.max_ws_size", &wsrep_max_ws_size); - free(opts); + return false; } - else + catch (...) { WSREP_ERROR("Failed to get provider options"); return true; } - return false; } static int wsrep_provider_verify (const char* provider_str) @@ -332,8 +328,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,12 +338,18 @@ 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); + wsrep_deinit(); char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider //when fails @@ -364,10 +364,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; } @@ -390,19 +390,14 @@ void wsrep_provider_init (const char* value) bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) { - if (wsrep == NULL) - { - my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0)); - return true; - } return false; } bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) { - DBUG_ASSERT(wsrep); - wsrep_status_t ret= wsrep->options_set(wsrep, wsrep_provider_options); - if (ret != WSREP_OK) + enum wsrep::provider::status ret= + Wsrep_server_state::instance().provider().options(wsrep_provider_options); + if (ret) { WSREP_ERROR("Set options returned %d", ret); refresh_provider_options(); @@ -468,18 +463,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) - { - WSREP_INFO("wsrep provider is not loaded, can't re(start) replication."); - 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 +470,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 +481,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,10 +577,10 @@ 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_DEBUG("Change on slave threads: New %lu old %lu difference %d", - wsrep_slave_threads, wsrep_prev_slave_threads, wsrep_slave_count_change); - 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); + WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %lu", + wsrep_slave_threads, wsrep_running_threads, wsrep_slave_count_change); } bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) @@ -613,7 +596,7 @@ bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) { - if (wsrep == NULL) + if (!WSREP_ON) { my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0)); return true; @@ -638,17 +621,17 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) } return false; } - wsrep_status_t ret(WSREP_WARNING); + int ret= 1; if (new_wsrep_desync) { - ret = wsrep->desync (wsrep); - if (ret != WSREP_OK) { - WSREP_WARN ("SET desync failed %d for schema: %s, query: %s", - ret, thd->get_db(), thd->query()); + ret= Wsrep_server_state::instance().provider().desync(); + if (ret) { + WSREP_WARN ("SET desync failed %d for schema: %s, query: %s", ret, + thd->db.str, WSREP_QUERY(thd)); my_error (ER_CANNOT_USER, MYF(0), "'desync'", thd->query()); return true; } } else { - ret = wsrep->resync (wsrep); + ret= Wsrep_server_state::instance().provider().resync(); if (ret != WSREP_OK) { WSREP_WARN ("SET resync failed %d for schema: %s, query: %s", ret, thd->get_db(), thd->query()); @@ -661,32 +644,67 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) bool wsrep_desync_update (sys_var *self, THD* thd, enum_var_type type) { - DBUG_ASSERT(wsrep); return false; } bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var) { - if (wsrep == NULL) - { - my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0)); + 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) +bool wsrep_trx_fragment_size_update(sys_var* self, THD *thd, enum_var_type) { - DBUG_ASSERT(wsrep); + WSREP_INFO("wsrep_trx_fragment_size_update: %lu", thd->variables.wsrep_trx_fragment_size); + if (thd->variables.wsrep_trx_fragment_size) + { + return thd->wsrep_cs().enable_streaming( + thd->wsrep_sr().fragment_unit(), + thd->variables.wsrep_trx_fragment_size); + } + else + { + thd->wsrep_cs().disable_streaming(); + return false; + } +} +bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type) +{ char max_ws_size_opt[128]; my_snprintf(max_ws_size_opt, sizeof(max_ws_size_opt), - "repl.max_ws_size=%lu", wsrep_max_ws_size); - wsrep_status_t ret= wsrep->options_set(wsrep, max_ws_size_opt); - if (ret != WSREP_OK) + "repl.max_ws_size=%d", wsrep_max_ws_size); + enum wsrep::provider::status ret= Wsrep_server_state::instance().provider().options(max_ws_size_opt); + if (ret) { WSREP_ERROR("Set options returned %d", ret); - refresh_provider_options(); return true; } return refresh_provider_options(); @@ -695,16 +713,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} }; @@ -713,6 +732,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_var) +{ + mysql->name = wsrep_var->name; + switch (wsrep_var->type) { + case WSREP_VAR_INT64: + mysql->value = (char*) &wsrep_var->value._int64; + mysql->type = SHOW_LONGLONG; + break; + case WSREP_VAR_STRING: + mysql->value = (char*) &wsrep_var->value._string; + mysql->type = SHOW_CHAR_PTR; + break; + case WSREP_VAR_DOUBLE: + mysql->value = (char*) &wsrep_var->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) { @@ -758,3 +801,67 @@ 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; + + thd->wsrep_status_vars = Wsrep_server_state::instance().status(); + + wsrep_status_len= thd->wsrep_status_vars.size(); + +#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++) + { + mysql_status_vars[i].name= (char*)thd->wsrep_status_vars[i].name().c_str(); + mysql_status_vars[i].value= (char*)thd->wsrep_status_vars[i].value().c_str(); + mysql_status_vars[i].type= SHOW_CHAR; + } + + 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) +{ + thd->wsrep_status_vars.clear(); +} diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 7d3ff50f1d2..15187a542dc 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -90,10 +90,14 @@ 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_trx_fragment_size_update UPDATE_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 2834100568a..a77d884a5a0 100644 --- a/sql/wsrep_xid.cc +++ b/sql/wsrep_xid.cc @@ -21,6 +21,7 @@ #include "sql_class.h" #include "wsrep_mysqld.h" // for logging macros +#include <sstream> /* * WSREPXid */ @@ -34,20 +35,23 @@ #define WSREP_XID_SEQNO_OFFSET (WSREP_XID_UUID_OFFSET + sizeof(wsrep_uuid_t)) #define WSREP_XID_GTRID_LEN (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t)) -void wsrep_xid_init(XID* xid, const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) +void wsrep_xid_init(XID* xid, const wsrep::gtid& gtid) { xid->formatID= 1; xid->gtrid_length= WSREP_XID_GTRID_LEN; xid->bqual_length= 0; memset(xid->data, 0, sizeof(xid->data)); memcpy(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN); - xid->data[WSREP_XID_VERSION_OFFSET] = WSREP_XID_VERSION_2; - memcpy(xid->data + WSREP_XID_UUID_OFFSET, &uuid, sizeof(wsrep_uuid_t)); - int8store(xid->data + WSREP_XID_SEQNO_OFFSET,seqno); + memcpy(xid->data + WSREP_XID_UUID_OFFSET, + gtid.id().data(), gtid.id().size()); + long long seqno= gtid.seqno().get(); + memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(seqno)); } -int wsrep_is_wsrep_xid(const XID* xid) +//extern "C" +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 && @@ -56,45 +60,27 @@ int wsrep_is_wsrep_xid(const XID* xid) xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_2)); } -const wsrep_uuid_t* wsrep_xid_uuid(const XID& xid) +wsrep::id wsrep_xid_uuid(const XID& xid) { + wsrep::id ret(xid.data + WSREP_XID_UUID_OFFSET, 16); if (wsrep_is_wsrep_xid(&xid)) - return reinterpret_cast<const wsrep_uuid_t*>(xid.data - + WSREP_XID_UUID_OFFSET); + return wsrep::id(xid.data + WSREP_XID_UUID_OFFSET, 16); else - return &WSREP_UUID_UNDEFINED; + return wsrep::id::undefined(); } -const unsigned char* wsrep_xid_uuid(const xid_t* xid) +wsrep::seqno wsrep_xid_seqno(const XID& xid) { - DBUG_ASSERT(xid); - return wsrep_xid_uuid(*xid)->data; -} - -wsrep_seqno_t wsrep_xid_seqno(const XID& xid) -{ - wsrep_seqno_t ret= WSREP_SEQNO_UNDEFINED; if (wsrep_is_wsrep_xid(&xid)) { - switch (xid.data[WSREP_XID_VERSION_OFFSET]) - { - case WSREP_XID_VERSION_1: - memcpy(&ret, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof ret); - break; - case WSREP_XID_VERSION_2: - ret= sint8korr(xid.data + WSREP_XID_SEQNO_OFFSET); - break; - default: - break; - } + wsrep_seqno_t seqno; + memcpy(&seqno, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t)); + return wsrep::seqno(seqno); + } + else + { + return wsrep::seqno::undefined(); } - return ret; -} - -long long wsrep_xid_seqno(const xid_t* xid) -{ - DBUG_ASSERT(xid); - return wsrep_xid_seqno(*xid); } static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) @@ -102,29 +88,29 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) XID* xid= static_cast<XID*>(arg); handlerton* hton= plugin_data(plugin, handlerton *); - if (hton->set_checkpoint) + if (hton->db_type == DB_TYPE_INNODB) { - const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid)); - char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + const wsrep::id uuid(wsrep_xid_uuid(*xid)); + std::ostringstream oss; + oss << uuid; WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(*xid)); + oss.str().c_str(), get_wsrep_xid_seqno(xid)); hton->set_checkpoint(hton, xid); } + 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::gtid& gtid) { XID xid; - wsrep_xid_init(&xid, uuid, seqno); - return wsrep_set_SE_checkpoint(xid); + wsrep_xid_init(&xid, gtid); + wsrep_set_SE_checkpoint(xid); } static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) @@ -135,47 +121,39 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) if (hton->get_checkpoint) { hton->get_checkpoint(hton, xid); - const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid)); - char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); - WSREP_DEBUG("Read WSREPXid from InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(*xid)); + std::ostringstream oss; + oss << wsrep_xid_uuid(*xid); + oss << ":"; + oss << wsrep_xid_seqno(*xid); + WSREP_DEBUG("Read WSREPXid from InnoDB: %s", oss.str().c_str()); } 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) +wsrep::gtid wsrep_get_SE_checkpoint() { - uuid= WSREP_UUID_UNDEFINED; - seqno= WSREP_SEQNO_UNDEFINED; - XID xid; xid.null(); - if (wsrep_get_SE_checkpoint(xid)) - { - return true; - } + wsrep_get_SE_checkpoint(xid); if (xid.is_null()) { - return false; + return wsrep::gtid(); } if (!wsrep_is_wsrep_xid(&xid)) { WSREP_WARN("Read non-wsrep XID from storage engines."); - return false; + return wsrep::gtid::undefined(); } + return wsrep::gtid(wsrep_xid_uuid(xid), wsrep_xid_seqno(xid)); +} - uuid= *wsrep_xid_uuid(xid); - seqno= wsrep_xid_seqno(xid); - return false; -} diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h index 5b33a904de1..92ea6618f81 100644 --- a/sql/wsrep_xid.h +++ b/sql/wsrep_xid.h @@ -15,22 +15,20 @@ #ifndef WSREP_XID_H #define WSREP_XID_H - #include <my_config.h> - + #ifdef WITH_WSREP -#include "../wsrep/wsrep_api.h" +#include "wsrep/gtid.hpp" #include "handler.h" // XID typedef +#include "wsrep_api.h" -void wsrep_xid_init(xid_t*, const wsrep_uuid_t&, wsrep_seqno_t); -const wsrep_uuid_t* wsrep_xid_uuid(const XID&); -wsrep_seqno_t wsrep_xid_seqno(const XID&); +void wsrep_xid_init(xid_t*, const wsrep::gtid&); +wsrep::id wsrep_xid_uuid(const XID&); +wsrep::seqno 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); +wsrep::gtid wsrep_get_SE_checkpoint(); +void wsrep_set_SE_checkpoint(const wsrep::gtid& gtid); #endif /* WITH_WSREP */ #endif /* WSREP_UTILS_H */ diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 088741e8ce8..34462873b57 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -43,6 +43,9 @@ Created April 08, 2011 Vasil Dimov #include "ut0byte.h" #include <algorithm> +#ifdef WITH_WSREP_OUT +extern my_bool wsrep_recovery; +#endif /* WITH_WSREP */ #include "mysql/service_wsrep.h" /* wsrep_recovery */ #include <my_service_manager.h> @@ -824,7 +827,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 diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b2df3983831..0f703c53dca 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -151,21 +151,14 @@ 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) { - return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), - (wsrep_trx_id_t)trx->id); -} - -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); -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 force correct commit order in binlog */ @@ -1851,6 +1844,13 @@ thd_to_trx_id( } #endif /* WITH_WSREP */ +#ifdef WITH_WSREP +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal); +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); +#endif /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -4160,10 +4160,10 @@ static int innodb_init(void* p) | HTON_NATIVE_SYS_VERSIONING; #ifdef WITH_WSREP - innobase_hton->abort_transaction=wsrep_abort_transaction; - innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint; - innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint; - innobase_hton->fake_trx_id=wsrep_fake_trx_id; + innobase_hton->abort_transaction=wsrep_abort_transaction; + innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint; + innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint; + innobase_hton->fake_trx_id=NULL; #endif /* WITH_WSREP */ innobase_hton->tablefile_extensions = ha_innobase_exts; @@ -4630,6 +4630,16 @@ 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. + This seems to be problematic with load data splitting. + Commented out for now. */ + // 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); @@ -5109,7 +5119,7 @@ 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_is_aborting(thd)) { /* if victim has been signaled by BF thread and/or aborting is already progressing, following query aborting is not necessary any more. @@ -5121,9 +5131,22 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) #endif /* WITH_WSREP */ if (trx_t* trx = thd_to_trx(thd)) { +#ifdef WITH_WSREP + bool locked= trx->lock.was_chosen_as_deadlock_victim; + if (locked) { + lock_mutex_exit(); + trx_mutex_exit(trx); + } +#endif /* WITH_WSREP */ ut_ad(trx->mysql_thd == thd); /* Cancel a pending lock request if there are any */ lock_trx_handle_wait(trx); +#ifdef WITH_WSREP + if (locked) { + lock_mutex_enter(); + trx_mutex_enter(trx); + } +#endif /* WITH_WSREP */ } DBUG_VOID_RETURN; @@ -6501,7 +6524,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 */ @@ -6925,7 +6947,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 */ @@ -6937,7 +6958,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; @@ -8097,9 +8119,9 @@ ha_innobase::write_row( wsrep_thd_query(m_user_thd) : (char *)"void"); error= DB_SUCCESS; - wsrep_thd_set_conflict_state( - m_user_thd, MUST_ABORT); - innobase_srv_conc_exit_innodb(m_prebuilt); + wsrep_thd_self_abort(current_thd); + innobase_srv_conc_exit_innodb( + m_prebuilt); /* jump straight to func exit over * later wsrep hooks */ goto func_exit; @@ -8167,14 +8189,15 @@ ha_innobase::write_row( error, m_prebuilt->table->flags, m_user_thd); #ifdef WITH_WSREP - if (!error_result - && wsrep_on(m_user_thd) - && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE - && !wsrep_consistency_check(m_user_thd) - && !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) { - DBUG_PRINT("wsrep", ("row key failed")); - error_result = HA_ERR_INTERNAL_ERROR; + if (!error_result && wsrep_thd_is_local(m_user_thd) && + wsrep_on(m_user_thd) && !wsrep_consistency_check(m_user_thd) && + (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) && + (thd_sql_command(m_user_thd) != SQLCOM_LOAD || + thd_binlog_format(m_user_thd) == BINLOG_FORMAT_ROW)) { + if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, record, + NULL)) { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; goto wsrep_error; } } @@ -8645,7 +8668,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 @@ -8868,13 +8890,13 @@ ha_innobase::update_row( innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && - !wsrep_thd_ignore_table(m_user_thd)) { + if (error == DB_SUCCESS && wsrep_thd_is_local(m_user_thd) && + wsrep_on(m_user_thd)) { + DBUG_PRINT("wsrep", ("update row key")); - if (wsrep_append_keys(m_user_thd, false, old_row, new_row)) { + if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, old_row, + new_row)) { WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); DBUG_PRINT("wsrep", ("row key failed")); err = HA_ERR_INTERNAL_ERROR; @@ -8934,11 +8956,12 @@ ha_innobase::delete_row( innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && + if (error == DB_SUCCESS && wsrep_thd_is_local(m_user_thd) && + wsrep_on(m_user_thd) && !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) { + + if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, record, + NULL)) { DBUG_PRINT("wsrep", ("delete fail")); error = (dberr_t) HA_ERR_INTERNAL_ERROR; goto wsrep_error; @@ -10130,16 +10153,30 @@ wsrep_dict_foreign_find_index( ibool check_charsets, ulint check_null); +inline +const char* +wsrep_key_type_to_str(wsrep_key_type type) +{ + switch (type) { + case WSREP_KEY_SHARED: + return "shared"; + case WSREP_KEY_SEMI: + return "semi"; + case WSREP_KEY_EXCLUSIVE: + return "exclusive"; + }; + return "unknown"; +} 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 */ dict_index_t* index, /*!<in: clustered index */ ibool referenced, /*!<in: is check for referenced table */ - ibool shared) /*!<in: is shared access */ + wsrep_key_type key_type) /*!< in: access type of this key + (shared, exclusive, semi...) */ { ut_a(trx); THD* thd = (THD*)trx->mysql_thd; @@ -10149,7 +10186,7 @@ wsrep_append_foreign_key( bool const copy = true; if (!wsrep_on(trx->mysql_thd) || - wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + wsrep_thd_is_local(trx->mysql_thd) == false) { return DB_SUCCESS; } @@ -10238,11 +10275,11 @@ wsrep_append_foreign_key( if (rcode != DB_SUCCESS) { WSREP_ERROR( - "FK key set failed: " ULINTPF - " (" ULINTPF " " ULINTPF "), index: %s %s, %s", - rcode, referenced, shared, - (index) ? index->name() : "void index", - (index && index->table) ? index->table->name.m_name : + "FK key set failed: %lu (%lu %s), index: %s %s, %s", + rcode, referenced, wsrep_key_type_to_str(key_type), + (index && index->name) ? index->name : + "void index", + (index) ? index->table->name.m_name : "void table", wsrep_thd_query(thd)); return DB_ERROR; @@ -10278,7 +10315,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, @@ -10289,17 +10327,10 @@ wsrep_append_foreign_key( wsrep_thd_query(thd) : "void"); return DB_ERROR; } - - wsrep_t *wsrep= get_wsrep(); - - rcode = (int)wsrep->append_key( - wsrep, - wsrep_ws_handle(thd, trx), - &wkey, - 1, - shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, - copy); - + rcode = wsrep_thd_append_key( + thd, &wkey, 1, + (key_type == WSREP_KEY_SHARED) ? wsrep_key_shared : + wsrep_key_exclusive); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: " ULINTPF, rcode)); WSREP_ERROR("Appending cascaded fk row key failed: %s, " @@ -10314,20 +10345,22 @@ wsrep_append_foreign_key( static int wsrep_append_key( -/*=============*/ THD *thd, trx_t *trx, TABLE_SHARE *table_share, const char* key, uint16_t key_len, - bool shared + wsrep_key_type key_type /*!< in: access type of this key + (shared, exclusive, semi...) */ ) { DBUG_ENTER("wsrep_append_key"); - bool const copy = true; + DBUG_PRINT("enter", + ("thd: %lld trx: %lld", thd_get_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", + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n SQL: %s ", + wsrep_key_type_to_str(key_type), thd_get_thread_id(thd), (long long)trx->id, key_len, table_share->table_name.str, wsrep_thd_query(thd)); for (int i=0; i<key_len; i++) { @@ -10338,7 +10371,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, @@ -10350,15 +10384,11 @@ wsrep_append_key( DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } - wsrep_t *wsrep= get_wsrep(); - - int rcode = (int)wsrep->append_key( - wsrep, - wsrep_ws_handle(thd, trx), - &wkey, - 1, - shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, - copy); + int rcode = wsrep_thd_append_key( + thd, + &wkey, + 1, + (key_type == WSREP_KEY_SHARED) ? wsrep_key_shared : wsrep_key_exclusive); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); WSREP_WARN("Appending row key failed: %s, %d", @@ -10397,9 +10427,9 @@ referenced_by_foreign_key2( int ha_innobase::wsrep_append_keys( -/*===========================*/ THD *thd, - bool shared, + wsrep_key_type key_type, /*!< in: access type of this key + (shared, exclusive, semi...) */ const uchar* record0, /* in: row in MySQL format */ const uchar* record1) /* in: row in MySQL format */ { @@ -10431,7 +10461,7 @@ ha_innobase::wsrep_append_keys( if (!is_null) { rcode = wsrep_append_key( thd, trx, table_share, keyval, - len, shared); + len, key_type); if (rcode) { DBUG_RETURN(rcode); @@ -10485,14 +10515,13 @@ ha_innobase::wsrep_append_keys( if (!is_null) { rcode = wsrep_append_key( thd, trx, table_share, - keyval0, len+1, shared); + keyval0, len+1, key_type); - 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 || + key_type == WSREP_KEY_SHARED) + key_appended = true; } else { WSREP_DEBUG("NULL key skipped: %s", wsrep_thd_query(thd)); @@ -10507,7 +10536,7 @@ ha_innobase::wsrep_append_keys( if (!is_null && memcmp(key0, key1, len)) { rcode = wsrep_append_key( thd, trx, table_share, - keyval1, len+1, shared); + keyval1, len+1, key_type); if (rcode) DBUG_RETURN(rcode); } } @@ -10524,7 +10553,7 @@ ha_innobase::wsrep_append_keys( if ((rcode = wsrep_append_key(thd, trx, table_share, (const char*) digest, 16, - shared))) { + key_type))) { DBUG_RETURN(rcode); } @@ -10533,7 +10562,7 @@ ha_innobase::wsrep_append_keys( digest, record1, table, m_prebuilt); if ((rcode = wsrep_append_key(thd, trx, table_share, (const char*) digest, - 16, shared))) { + 16, key_type))) { DBUG_RETURN(rcode); } } @@ -15379,8 +15408,7 @@ ha_innobase::external_lock( if (!skip) { #ifdef WITH_WSREP - if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) - { + if (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd)) { #endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when" @@ -18496,118 +18524,22 @@ wsrep_innobase_kill_one_trx( bf_trx ? bf_trx->id : 0); DBUG_RETURN(1); } - - WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); - - WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF - "), victim: (%lu) trx: " TRX_ID_FMT, - signal, bf_seqno, - thd_get_thread_id(thd), - victim_trx->id); - - WSREP_DEBUG("Aborting query: %s conf %d trx: %" PRId64, - (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", - wsrep_thd_conflict_state(thd, FALSE), - wsrep_thd_ws_handle(thd)->trx_id); + WSREP_LOG_CONFLICT((const void*)bf_thd, (const void*)thd, TRUE); 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; - } + WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%llu) trx: %llu", + signal, (long long)bf_seqno, + (long long)thd_get_thread_id(thd), + (long long)victim_trx->id); - 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); + WSREP_DEBUG("Aborting query: %s conf %s trx: %lld", + (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", + wsrep_thd_transaction_state_str(thd), + wsrep_thd_transaction_id(thd)); + wsrep_thd_UNLOCK(thd); + if (wsrep_thd_bf_abort(bf_thd, thd, signal)) + { victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; if (victim_trx->lock.wait_lock) { @@ -18620,9 +18552,7 @@ 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((const void*)thd, signal); } else { /* abort currently executing query */ DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu", @@ -18631,56 +18561,8 @@ wsrep_innobase_kill_one_trx( thd_get_thread_id(thd)); /* Note that innobase_kill_query will take lock_mutex and trx_mutex */ - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - - /* for BF thd, we need to prevent him from committing */ - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - wsrep_abort_slave_trx(bf_seqno, - 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)); + wsrep_thd_awake((const void*)thd, signal); } - - 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)); - wsrep_thd_UNLOCK(thd); - break; } DBUG_RETURN(0); @@ -18700,26 +18582,24 @@ wsrep_abort_transaction( trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; - WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d", + WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s", wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd), - wsrep_thd_conflict_state(victim_thd, FALSE)); + wsrep_thd_transaction_state_str(victim_thd)); if (victim_trx) { lock_mutex_enter(); trx_mutex_enter(victim_trx); - int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, - victim_trx, signal); - lock_mutex_exit(); + int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx, + victim_trx, signal); trx_mutex_exit(victim_trx); + lock_mutex_exit(); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); - } else { - WSREP_DEBUG("victim does not have transaction"); - wsrep_thd_LOCK(victim_thd); - wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT); - wsrep_thd_UNLOCK(victim_thd); - wsrep_thd_awake(victim_thd, signal); + } + else + { + wsrep_thd_bf_abort(bf_thd, victim_thd, signal); } DBUG_RETURN(-1); @@ -18761,6 +18641,7 @@ static void wsrep_fake_trx_id(handlerton *, THD *thd) trx_id_t trx_id = trx_sys.get_new_trx_id(); WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s", trx_id, wsrep_thd_query(thd)); + wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id); } diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index e65e7a57c99..7d1a9680010 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -16,6 +16,10 @@ this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ +#ifdef WITH_WSREP +#include "wsrep_api.h" +#include <mysql/service_wsrep.h> +#endif /* WITH_WSREP */ /* The InnoDB handler: the interface between MySQL and InnoDB. */ @@ -450,8 +454,11 @@ class ha_innobase: public handler dict_index_t* innobase_get_index(uint keynr); #ifdef WITH_WSREP - int wsrep_append_keys(THD *thd, bool shared, - const uchar* record0, const uchar* record1); + int wsrep_append_keys( + THD *thd, + wsrep_key_type key_type, + const uchar* record0, + const uchar* record1); #endif /** Builds a 'template' to the prebuilt struct. @@ -577,23 +584,7 @@ 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); - -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); - -extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); - -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" 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 /* WITH_WSREP */ extern const struct _ft_vft ft_vft_result; @@ -627,10 +618,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..4ce29521b55 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -233,13 +233,11 @@ innobase_casedn_str( #ifdef WITH_WSREP UNIV_INTERN int -wsrep_innobase_kill_one_trx(void * const thd_ptr, - const trx_t * const bf_trx, - trx_t *victim_trx, - ibool signal); +wsrep_innobase_kill_one_trx(void *thd_ptr, + const trx_t *bf_trx, trx_t *victim_trx, ibool signal); ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, - unsigned char* str, unsigned int str_length, - unsigned int buf_length); + unsigned char* str, unsigned int str_length, + unsigned int buf_length); #endif /* WITH_WSREP */ /**********************************************************************//** diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index cb878fa5b19..d60ab6826ef 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 c19797ab9da..edeb9e5a871 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -766,9 +766,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 @@ -778,12 +776,11 @@ lock_rec_has_to_wait( << type_mode << " supremum: " << lock_is_on_supremum << "conflicts states: my " - << wsrep_thd_conflict_state( - trx->mysql_thd, FALSE) + << wsrep_thd_transaction_state_str( + trx->mysql_thd) << " locked " - << wsrep_thd_conflict_state( - lock2->trx->mysql_thd, - FALSE); + << wsrep_thd_transaction_state_str( + lock2->trx->mysql_thd); lock_rec_print(stderr, lock2); ib::info() << " SQL1: " << wsrep_thd_query(trx->mysql_thd) @@ -1103,11 +1100,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( + if ((!bf_other) || + (bf_other && wsrep_thd_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { + ut_ad(bf_this); if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { if (wsrep_debug) { @@ -1429,9 +1429,11 @@ lock_rec_create_low( lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; - while (hash && wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) - && wsrep_trx_order_before(hash->trx->mysql_thd, - trx->mysql_thd)) { + while (hash && + wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) && + wsrep_thd_order_before( + ((lock_t *)hash)->trx->mysql_thd, + trx->mysql_thd)) { prev = hash; hash = (lock_t *)hash->hash; } @@ -1844,15 +1846,15 @@ lock_rec_add_to_queue( ib::info() << "WSREP BF lock conflict for my lock:\n BF:" << ((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(trx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(trx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(trx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " << wsrep_thd_query(trx->mysql_thd); trx_t* otrx = other_lock->trx; ib::info() << "WSREP other lock:\n BF:" << ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << wsrep_thd_query(otrx->mysql_thd); } @@ -4944,8 +4946,8 @@ lock_rec_queue_validate( if (!lock_get_wait(other_lock) ) { ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" << ((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(impl_trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(impl_trx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(impl_trx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " << wsrep_thd_query(impl_trx->mysql_thd); @@ -4953,8 +4955,8 @@ lock_rec_queue_validate( ib::info() << "WSREP other lock:\n BF:" << ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << wsrep_thd_query(otrx->mysql_thd); } @@ -6986,6 +6988,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..c84dd9e512e 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -36,7 +36,9 @@ Created 25/5/2010 Sunny Bains #include "row0mysql.h" #include "srv0start.h" #include "lock0priv.h" - +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif /* WITH_WSREP */ /*********************************************************************//** Print the contents of the lock_sys_t::waiting_threads array. */ static @@ -195,8 +197,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 +216,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 cfc7c20b8cb..39ee2dd8ae1 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -50,6 +50,10 @@ Created 4/20/1996 Heikki Tuuri #include "fts0types.h" #include "m_string.h" #include "gis0geo.h" +#include "wsrep_api.h" +#include "mysql/service_wsrep.h" +#include "wsrep_mysqld.h" +#include "mysql/service_wsrep.h" /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -1049,7 +1053,7 @@ dberr_t wsrep_append_foreign_key(trx_t *trx, const rec_t* clust_rec, dict_index_t* clust_index, ibool referenced, - ibool shared); + wsrep_key_type key_type); #endif /* WITH_WSREP */ /*********************************************************************//** @@ -1434,7 +1438,7 @@ row_ins_foreign_check_on_constraint( #ifdef WITH_WSREP err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index, - FALSE, FALSE); + FALSE, WSREP_KEY_EXCLUSIVE); if (err != DB_SUCCESS) { fprintf(stderr, "WSREP: foreign key append failed: %d\n", err); @@ -1809,13 +1813,19 @@ row_ins_check_foreign_constraint( if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP + wsrep_key_type key_type; + if (upd_node != NULL) { + key_type = WSREP_KEY_SHARED; + } else { + key_type = WSREP_KEY_SEMI; + } err = wsrep_append_foreign_key( thr_get_trx(thr), foreign, rec, check_index, check_ref, - (upd_node) ? TRUE : FALSE); + key_type); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { @@ -1913,6 +1923,23 @@ row_ins_check_foreign_constraint( check_table->inc_fk_checks(); lock_wait_suspend_thread(thr); +#ifdef WITH_WSREP + ut_ad(!trx_mutex_own(trx)); + switch (trx->error_state) { + case DB_DEADLOCK: + if (wsrep_debug) { + ib::info() << + "WSREP: innodb trx state changed during wait " + << " trx: " << trx->id << " with error_state: " + << trx->error_state << " err: " << err; + } + err = trx->error_state; + break; + default: + break; + } + +#endif /* WITH_WSREP */ thr->lock_state = QUE_THR_LOCK_NOLOCK; @@ -3231,9 +3258,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 1531fb38b7f..079573e0417 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -56,6 +56,13 @@ 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 */ + +#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 +4510,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 5279d21b452..3caca05c89a 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -51,6 +51,10 @@ Created 12/27/1996 Heikki Tuuri #include "trx0rec.h" #include "fts0fts.h" #include "fts0types.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#include "mysql/service_wsrep.h" +#endif #include <algorithm> #include <mysql/plugin.h> #include <mysql/service_wsrep.h> @@ -2451,6 +2455,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) { @@ -2458,8 +2466,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, @@ -2791,8 +2802,8 @@ row_upd_clust_rec_by_insert( << " table " << index->table->name; goto err_exit; } -#endif /* WITH_WSREP */ } +#endif /* WITH_WSREP */ } mtr_commit(mtr); @@ -2998,7 +3009,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/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index d26e61253cd..65c5c47d35e 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -122,12 +122,11 @@ srv_conc_enter_innodb_with_atomics( for (;;) { ulint sleep_in_us; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { - if (wsrep_debug) { + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_aborting(trx->mysql_thd)) { + if (wsrep_debug) ib::info() << "srv_conc_enter due to MUST_ABORT"; - } srv_conc_force_enter_innodb(trx); return; } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 94e5954c884..dd855c63599 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -80,8 +80,8 @@ Created 10/8/1995 Heikki Tuuri #include <my_service_manager.h> #ifdef WITH_WSREP -extern int wsrep_debug; -extern int wsrep_trx_is_aborting(void *thd_ptr); +extern my_bool wsrep_debug; +#include "mysql/service_wsrep.h" #endif /* The following is the maximum allowed duration of a lock wait. */ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT; diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index f7f6dff4380..bb63ca509ab 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 bfa49b88d1d..2a3e908c115 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -58,10 +58,11 @@ trx_rseg_update_wsrep_checkpoint( #ifdef UNIV_DEBUG /* Check that seqno is monotonically increasing */ - long long xid_seqno = wsrep_xid_seqno(xid); - const byte* xid_uuid = wsrep_xid_uuid(xid); + long long xid_seqno = get_wsrep_xid_seqno(xid); + const byte* xid_uuid = get_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); @@ -108,7 +109,7 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); - const byte* xid_uuid = wsrep_xid_uuid(xid); + const byte* xid_uuid = get_wsrep_xid_uuid(xid); if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) { memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); @@ -206,8 +207,8 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid) found = trx_rseg_init_wsrep_xid(sys->frame, xid); ut_ad(!found || xid.formatID == 1); if (found) { - max_xid_seqno = wsrep_xid_seqno(&xid); - memcpy(wsrep_uuid, wsrep_xid_uuid(&xid), + max_xid_seqno = get_wsrep_xid_seqno(&xid); + memcpy(wsrep_uuid, get_wsrep_xid_uuid(&xid), sizeof wsrep_uuid); } } @@ -229,12 +230,12 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid) XID tmp_xid; long long tmp_seqno = 0; if (trx_rseg_read_wsrep_checkpoint(rseg_header, tmp_xid) - && (tmp_seqno = wsrep_xid_seqno(&tmp_xid)) + && (tmp_seqno = get_wsrep_xid_seqno(&tmp_xid)) > max_xid_seqno) { found = true; max_xid_seqno = tmp_seqno; xid = tmp_xid; - memcpy(wsrep_uuid, wsrep_xid_uuid(&tmp_xid), + memcpy(wsrep_uuid, get_wsrep_xid_uuid(&tmp_xid), sizeof wsrep_uuid); } } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 600a6eb6229..388cd3c8174 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -55,6 +55,9 @@ Created 3/26/1996 Heikki Tuuri #include <set> #include <new> +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" +#endif /* WITH_WSREP */ /** The bit pattern corresponding to TRX_ID_MAX */ const byte trx_id_max_bytes[8] = { diff --git a/wsrep-lib b/wsrep-lib new file mode 160000 index 00000000000..94174b06e65 --- /dev/null +++ b/wsrep-lib @@ -0,0 +1 @@ +Subproject commit 94174b06e653dcf92a940dfb009e525ca62b5204 diff --git a/wsrep/CMakeLists.txt b/wsrep/CMakeLists.txt deleted file mode 100644 index ff2bdec4def..00000000000 --- a/wsrep/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2012, Codership Oy. 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 - -SET(WSREP_SOURCES wsrep_gtid.c wsrep_uuid.c wsrep_loader.c wsrep_dummy.c) - -IF(NOT WITH_INNOBASE_STORAGE_ENGINE) - MESSAGE(WARNING "WSRep is enabled, but innodb is not. This configuration is not supported") -ENDIF() - -ADD_CONVENIENCE_LIBRARY(wsrep ${WSREP_SOURCES}) -DTRACE_INSTRUMENT(wsrep) - -#ADD_EXECUTABLE(listener wsrep_listener.c ${WSREP_SOURCES}) -#TARGET_LINK_LIBRARIES(listener ${LIBDL}) diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h index 1d6bc059d3d..ecbf08fbc34 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 @@ -738,29 +834,49 @@ struct wsrep { * @retval WSREP_CONN_FAIL must close client connection * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*replay_trx)(wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle, - void* trx_ctx); + wsrep_status_t (*replay_trx)(wsrep_t* wsrep, + const wsrep_ws_handle_t* ws_handle, + 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 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_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 abort secceded - * @retval WSREP_WARNING abort failed + * @retval WSREP_OK rollback fragment sent successfully */ - wsrep_status_t (*abort_pre_commit)(wsrep_t* wsrep, - wsrep_seqno_t bf_seqno, - wsrep_trx_id_t victim_trx); + 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..8c39ca5ace0 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,24 @@ 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))) { 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_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 +167,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 +192,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 +204,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 +243,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 +252,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 +294,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 +303,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 +357,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 +374,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 +392,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 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) 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)); +}
participants (1)
-
jan