Merge lp:maria/maria-10.0-galera revisions 3867..3869 and

3871..3879.
This commit is contained in:
Jan Lindström 2014-08-26 12:32:21 +03:00
parent 62f40f49ca
commit fe4f467276
37 changed files with 931 additions and 347 deletions

View file

@ -92,9 +92,7 @@ enum options_client
OPT_REPORT_PROGRESS,
OPT_SKIP_ANNOTATE_ROWS_EVENTS,
OPT_SSL_CRL, OPT_SSL_CRLPATH,
#ifdef WITH_WSREP
OPT_GALERA_SST_MODE,
#endif
OPT_MAX_CLIENT_OPTION /* should be always the last */
};

View file

@ -111,9 +111,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_slave_apply= 0,
opt_include_master_host_port= 0,
opt_events= 0, opt_comments_used= 0,
#ifdef WITH_WSREP
opt_galera_sst_mode= 0,
#endif
opt_alltspcs=0, opt_notspcs= 0;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
@ -349,14 +347,14 @@ static struct my_option my_long_options[] =
{"force", 'f', "Continue even if we get an SQL error.",
&ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
#ifdef WITH_WSREP
{"galera-sst-mode", OPT_GALERA_SST_MODE, "This mode is normally used "
"in mysqldump snapshot-state transfer in a Galera cluster. If enabled, "
"mysqldump additionally emits statements to turn off binary logging and "
"set global gtid_binlog_state with the current value.",
{"galera-sst-mode", OPT_GALERA_SST_MODE,
"This mode should normally be used in mysqldump snapshot state transfer "
"(SST) in a Galera cluster. If enabled, mysqldump additionally dumps "
"commands to turn off binary logging and SET global gtid_binlog_state "
"with the current value. Note: RESET MASTER needs to be executed on the "
"server receiving the resulting dump.",
&opt_galera_sst_mode, &opt_galera_sst_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
#endif
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
@ -4810,13 +4808,12 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
} /* dump_selected_tables */
#ifdef WITH_WSREP
/**
Additionally emit the following statements :
Add the following statements to the generated dump:
a) SET @@session.sql_log_bin=OFF;
b) SET @@global.gtid_binlog_state='[N-N-N,...]'
*/
static int wsrep_add_sst_mode_cmds(MYSQL *mysql) {
static int wsrep_set_sst_cmds(MYSQL *mysql) {
MYSQL_RES *res;
MYSQL_ROW row;
@ -4846,7 +4843,6 @@ static int wsrep_add_sst_mode_cmds(MYSQL *mysql) {
mysql_free_result(res);
return 0;
}
#endif
static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
{
@ -5793,10 +5789,8 @@ int main(int argc, char **argv)
if (opt_slave_apply && add_stop_slave())
goto err;
#ifdef WITH_WSREP
if (opt_galera_sst_mode && wsrep_add_sst_mode_cmds(mysql))
if (opt_galera_sst_mode && wsrep_set_sst_cmds(mysql))
goto err;
#endif
if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos))
goto err;

View file

@ -22,8 +22,8 @@ SET(WSREP_PATCH_VERSION "10")
# MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment.
# Branch : codership-mysql/5.5
SET(WSREP_PATCH_REVNO "4002") # Should be updated on every merge.
# Branch : codership-mysql/5.6
SET(WSREP_PATCH_REVNO "4123") # Should be updated on every merge.
# MariaDB addition: Revision number of the last revision merged from
# Branch : lp:maria/maria-10.0-galera

View file

@ -0,0 +1,6 @@
--source include/have_innodb.inc
if (`SELECT COUNT(*) = 0 from INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME = 'INNODB_DISALLOW_WRITES'`) {
--skip Test requires 'innodb_disallow_writes'
}

View file

@ -3,6 +3,6 @@
if (`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`)
{
--skip Test required wsrep plugin.
--skip Test requires wsrep plugin.
}

View file

@ -33,7 +33,8 @@
--let _WRTF_SERVER_NUMBER= $server_number
if (!$server_number)
{
--let _WRTF_SERVER_NUMBER= `SELECT 1 + @@PORT - $MASTER_MYPORT`
# Note: 2 extra ports are reserved per server for galera use.
--let _WRTF_SERVER_NUMBER= `SELECT 1 + FLOOR((@@PORT - $MASTER_MYPORT) / 3)`
}
--let $_write_result_msg= [server=$_WRTF_SERVER_NUMBER]

View file

@ -1072,8 +1072,8 @@ The following options may be given as the first argument:
variables
(Defaults to on; use --skip-wsrep-auto-increment-control to disable.)
--wsrep-causal-reads
Enable "strictly synchronous" semantics for read
operations
(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.)
@ -1147,6 +1147,11 @@ The following options may be given as the first argument:
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
Variables (--variable-name=value)
allow-suspicious-udfs FALSE
@ -1483,6 +1488,7 @@ 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
To see what values a running MySQL server is using, type
'mysqladmin variables' instead of 'mysqld --verbose --help'.

View file

@ -0,0 +1,24 @@
#
# Test for mysqldump's galera-sst-mode option
#
#
# MDEV-6490: mysqldump unknown option --galera-sst-mode
#
CREATE DATABASE bug6490;
USE bug6490;
CREATE TABLE t1(c1 INT);
INSERT INTO t1 values (1);
INSERT INTO t1 values (2);
# Save the current gtid_binlog_state.
# Take a dump of bug6490 database
DROP TABLE t1;
# Load the dump
RESET MASTER;
SELECT * from t1;
c1
1
2
# Compare the two gtid_binlog_state's
# Cleanup
DROP DATABASE bug6490;
# End of test

View file

@ -0,0 +1,43 @@
# Embedded server doesn't support external clients
--source include/not_embedded.inc
# Binlog is required
--source include/have_log_bin.inc
--echo #
--echo # Test for mysqldump's galera-sst-mode option
--echo #
--echo #
--echo # MDEV-6490: mysqldump unknown option --galera-sst-mode
--echo #
CREATE DATABASE bug6490;
USE bug6490;
CREATE TABLE t1(c1 INT);
INSERT INTO t1 values (1);
INSERT INTO t1 values (2);
--echo # Save the current gtid_binlog_state.
--let $before= `SELECT @@global.gtid_binlog_state`
--echo # Take a dump of bug6490 database
--exec $MYSQL_DUMP --galera-sst-mode bug6490 > $MYSQLTEST_VARDIR/tmp/bug6490.sql
DROP TABLE t1;
--echo # Load the dump
RESET MASTER;
--exec $MYSQL -uroot bug6490 < $MYSQLTEST_VARDIR/tmp/bug6490.sql
SELECT * from t1;
--echo # Compare the two gtid_binlog_state's
--let $after= `SELECT @@global.gtid_binlog_state`
if (`SELECT STRCMP($before, $after)`)
{
--die ERROR: The two gtid_binlog_state's did not match.
}
--echo # Cleanup
--remove_file $MYSQLTEST_VARDIR/tmp/bug6490.sql
DROP DATABASE bug6490;
--echo # End of test

View file

@ -0,0 +1,56 @@
#
# wsrep_sync_wait
#
# save the initial values
SET @wsrep_sync_wait_global_saved = @@global.wsrep_sync_wait;
SET @wsrep_sync_wait_session_saved = @@session.wsrep_sync_wait;
# default
SELECT @@global.wsrep_sync_wait;
@@global.wsrep_sync_wait
0
SELECT @@session.wsrep_sync_wait;
@@session.wsrep_sync_wait
0
# scope and valid values
SET @@global.wsrep_sync_wait=0;
SELECT @@global.wsrep_sync_wait;
@@global.wsrep_sync_wait
0
SET @@global.wsrep_sync_wait=7;
SELECT @@global.wsrep_sync_wait;
@@global.wsrep_sync_wait
7
SET @@session.wsrep_sync_wait=0;
SELECT @@session.wsrep_sync_wait;
@@session.wsrep_sync_wait
0
SET @@session.wsrep_sync_wait=7;
SELECT @@session.wsrep_sync_wait;
@@session.wsrep_sync_wait
7
SET @@session.wsrep_sync_wait=default;
SELECT @@session.wsrep_sync_wait;
@@session.wsrep_sync_wait
7
SET @@session.wsrep_sync_wait=8;
Warnings:
Warning 1292 Truncated incorrect wsrep_sync_wait value: '8'
SELECT @@session.wsrep_sync_wait;
@@session.wsrep_sync_wait
7
# invalid values
SET @@global.wsrep_sync_wait=NULL;
ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait'
SET @@global.wsrep_sync_wait='junk';
ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait'
SET @@session.wsrep_sync_wait=NULL;
ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait'
SET @@session.wsrep_sync_wait='junk';
ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait'
# restore the initial values
SET @@global.wsrep_sync_wait = @wsrep_sync_wait_global_saved;
SET @@session.wsrep_sync_wait = @wsrep_sync_wait_session_saved;
# End of test

View file

@ -0,0 +1,47 @@
--source include/have_wsrep.inc
--echo #
--echo # wsrep_sync_wait
--echo #
--echo # save the initial values
SET @wsrep_sync_wait_global_saved = @@global.wsrep_sync_wait;
SET @wsrep_sync_wait_session_saved = @@session.wsrep_sync_wait;
--echo # default
SELECT @@global.wsrep_sync_wait;
SELECT @@session.wsrep_sync_wait;
--echo
--echo # scope and valid values
SET @@global.wsrep_sync_wait=0;
SELECT @@global.wsrep_sync_wait;
SET @@global.wsrep_sync_wait=7;
SELECT @@global.wsrep_sync_wait;
SET @@session.wsrep_sync_wait=0;
SELECT @@session.wsrep_sync_wait;
SET @@session.wsrep_sync_wait=7;
SELECT @@session.wsrep_sync_wait;
SET @@session.wsrep_sync_wait=default;
SELECT @@session.wsrep_sync_wait;
SET @@session.wsrep_sync_wait=8;
SELECT @@session.wsrep_sync_wait;
--echo
--echo # invalid values
--error ER_WRONG_TYPE_FOR_VAR
SET @@global.wsrep_sync_wait=NULL;
--error ER_WRONG_TYPE_FOR_VAR
SET @@global.wsrep_sync_wait='junk';
--error ER_WRONG_TYPE_FOR_VAR
SET @@session.wsrep_sync_wait=NULL;
--error ER_WRONG_TYPE_FOR_VAR
SET @@session.wsrep_sync_wait='junk';
--echo
--echo # restore the initial values
SET @@global.wsrep_sync_wait = @wsrep_sync_wait_global_saved;
SET @@session.wsrep_sync_wait = @wsrep_sync_wait_session_saved;
--echo # End of test

View file

@ -0,0 +1,19 @@
install plugin innodb soname 'ha_innodb';
select engine,support,transactions,xa from information_schema.engines where engine='innodb';
engine support transactions xa
InnoDB YES YES YES
create table t1 (a int) engine=innodb;
start transaction;
insert t1 values (1);
insert t1 values (2);
commit;
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
mysqld-bin.000001 # Gtid # # GTID #-#-#
mysqld-bin.000001 # Query # # use `test`; create table t1 (a int) engine=innodb
mysqld-bin.000001 # Gtid # # BEGIN GTID #-#-#
mysqld-bin.000001 # Query # # use `test`; insert t1 values (1)
mysqld-bin.000001 # Query # # use `test`; insert t1 values (2)
mysqld-bin.000001 # Xid # # COMMIT /* XID */
drop table t1;
uninstall plugin innodb;

View file

@ -0,0 +1 @@
--ignore-builtin-innodb --loose-innodb --log-bin

View file

@ -0,0 +1,19 @@
#
# MDEV-6082 Assertion `0' fails in TC_LOG_DUMMY::log_and_order on DML after installing TokuDB at runtime on server with disabled InnoDB
#
--source include/not_embedded.inc
--source include/have_wsrep.inc
if (!$HA_INNODB_SO) {
--skip Need InnoDB plugin
}
install plugin innodb soname 'ha_innodb';
select engine,support,transactions,xa from information_schema.engines where engine='innodb';
create table t1 (a int) engine=innodb;
start transaction;
insert t1 values (1);
insert t1 values (2);
commit;
--source include/show_binlog_events.inc
drop table t1;
uninstall plugin innodb;

View file

@ -1477,11 +1477,12 @@ end:
{
// sql_print_information("sizeof(LEX) = %d", sizeof(struct LEX));
// sizeof(LEX) = 4512, so it's relatively safe to allocate it on stack.
LEX *old_lex= thd->lex, new_lex;
new_lex.sql_command= SQLCOM_DROP_EVENT;
thd->lex= &new_lex;
LEX lex;
LEX* saved = thd->lex;
lex.sql_command = SQLCOM_DROP_EVENT;
thd->lex = &lex;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
thd->lex= old_lex;
thd->lex = saved;
}
#endif

View file

@ -1199,6 +1199,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL)
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table, true) :

View file

@ -642,6 +642,7 @@ typedef struct system_variables
#ifdef WITH_WSREP
my_bool wsrep_on;
my_bool wsrep_causal_reads;
uint wsrep_sync_wait;
ulong wsrep_retry_autocommit;
#endif
double long_query_time_double;

View file

@ -2719,7 +2719,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STATUS:
{
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
goto error;
#endif /* WITH_WSREP */
execute_show_status(thd, all_tables);
@ -2755,7 +2755,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
goto error;
#endif /* WITH_WSREP */
@ -2780,7 +2780,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_INDEX_STATS:
case SQLCOM_SELECT:
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
goto error;
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_CHARSETS:
@ -2788,7 +2788,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STORAGE_ENGINES:
case SQLCOM_SHOW_PROFILE:
#endif /* WITH_WSREP */
{
{
thd->status_var.last_query_cost= 0.0;
/*
@ -2811,7 +2811,7 @@ mysql_execute_command(THD *thd)
res= execute_sqlcom_select(thd, all_tables);
break;
}
case SQLCOM_PREPARE:
case SQLCOM_PREPARE:
{
mysql_sql_stmt_prepare(thd);
break;
@ -3460,15 +3460,16 @@ end_with_restore_list:
#endif
#endif /* EMBEDDED_LIBRARY */
case SQLCOM_SHOW_CREATE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef DONT_ALLOW_SHOW_COMMANDS
my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
MYF(0)); /* purecov: inspected */
goto error;
#else
{
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
goto error;
#endif /* WITH_WSREP */
@ -3529,13 +3530,13 @@ end_with_restore_list:
/* Access is granted. Execute the command. */
res= mysqld_show_create(thd, first_table);
break;
}
#endif
}
case SQLCOM_CHECKSUM:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
goto error;
#endif /* WITH_WSREP */
@ -3550,6 +3551,12 @@ end_with_restore_list:
{
ha_rows found= 0, updated= 0;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
goto error;
#endif /* WITH_WSREP */
if (update_precheck(thd, all_tables))
break;
@ -3586,6 +3593,11 @@ end_with_restore_list:
/* if we switched from normal update, rights are checked */
if (up_result != 2)
{
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
goto error;
#endif /* WITH_WSREP */
if ((res= multi_update_precheck(thd, all_tables)))
break;
}
@ -3655,6 +3667,12 @@ end_with_restore_list:
break;
}
case SQLCOM_REPLACE:
{
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
goto error;
#endif /* WITH_WSREP */
#ifndef DBUG_OFF
if (mysql_bin_log.is_open())
{
@ -3689,10 +3707,17 @@ end_with_restore_list:
DBUG_PRINT("debug", ("Just after generate_incident()"));
}
#endif
}
case SQLCOM_INSERT:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
goto error;
#endif /* WITH_WSREP */
/*
Since INSERT DELAYED doesn't support temporary tables, we could
not pre-open temporary tables for SQLCOM_INSERT / SQLCOM_REPLACE.
@ -3747,11 +3772,16 @@ end_with_restore_list:
select_result *sel_result;
bool explain= MY_TEST(lex->describe);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE))
goto error;
#endif /* WITH_WSREP */
if ((res= insert_precheck(thd, all_tables)))
break;
#ifdef WITH_WSREP
if (WSREP_ON && lex->sql_command == SQLCOM_INSERT_SELECT &&
thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED)
if (WSREP(thd) && thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED)
{
thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING;
WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL);
@ -3848,6 +3878,12 @@ end_with_restore_list:
{
select_result *sel_result=lex->result;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
goto error;
#endif /* WITH_WSREP */
if ((res= delete_precheck(thd, all_tables)))
break;
DBUG_ASSERT(select_lex->offset_limit == 0);
@ -3904,6 +3940,11 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
multi_delete *result;
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) &&
wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE))
goto error;
#endif /* WITH_WSREP */
if ((res= multi_delete_precheck(thd, all_tables)))
break;
@ -3975,7 +4016,7 @@ end_with_restore_list:
thd->variables.option_bits|= OPTION_KEEP_LOG;
}
#ifdef WITH_WSREP
if (WSREP_ON)
if (WSREP(thd))
{
for (TABLE_LIST *table= all_tables; table; table= table->next_global)
{
@ -4002,8 +4043,8 @@ end_with_restore_list:
/* DDL and binlog write order are protected by metadata locks. */
res= mysql_rm_table(thd, first_table, lex->check_exists,
lex->drop_temporary);
break;
}
break;
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_ctx->priv_user[0] &&
check_global_access(thd,PROCESS_ACL))

View file

@ -4615,9 +4615,22 @@ static Sys_var_mybool Sys_wsrep_certify_nonPK(
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
static Sys_var_mybool Sys_wsrep_causal_reads(
"wsrep_causal_reads", "Enable \"strictly synchronous\" semantics for read operations",
SESSION_VAR(wsrep_causal_reads),
CMD_LINE(OPT_ARG), DEFAULT(FALSE));
"wsrep_causal_reads", "(DEPRECATED) Setting this variable is equivalent "
"to setting wsrep_sync_wait READ flag",
SESSION_VAR(wsrep_causal_reads), CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(wsrep_causal_reads_update));
static Sys_var_uint Sys_wsrep_sync_wait(
"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",
SESSION_VAR(wsrep_sync_wait), CMD_LINE(OPT_ARG),
VALID_RANGE(WSREP_SYNC_WAIT_NONE, WSREP_SYNC_WAIT_MAX),
DEFAULT(WSREP_SYNC_WAIT_NONE), BLOCK_SIZE(1),
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 Sys_var_enum Sys_wsrep_OSU_method(

View file

@ -195,7 +195,7 @@ bool trans_begin(THD *thd, uint flags)
#ifdef WITH_WSREP
thd->wsrep_PA_safe= true;
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */

View file

@ -146,7 +146,7 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) {
sql_print_error("WSREP: %s", msg);
break;
case WSREP_LOG_DEBUG:
sql_print_information ("[Debug] WSREP: %s", msg);
if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg);
default:
break;
}
@ -808,10 +808,10 @@ void wsrep_filter_new_cluster (int* argc, char* argv[])
{
/* make a copy of the argument to convert possible underscores to hyphens.
* the copy need not to be longer than WSREP_NEW_CLUSTER option */
char arg[sizeof(WSREP_NEW_CLUSTER) + 2]= { 0, };
char arg[sizeof(WSREP_NEW_CLUSTER) + 1]= { 0, };
strncpy(arg, argv[i], sizeof(arg) - 1);
char* underscore;
while (NULL != (underscore= strchr(arg, '_'))) *underscore= '-';
char* underscore(arg);
while (NULL != (underscore= strchr(underscore, '_'))) *underscore= '-';
if (!strcmp(arg, WSREP_NEW_CLUSTER))
{
@ -893,13 +893,15 @@ bool wsrep_start_replication()
return true;
}
bool
wsrep_causal_wait (THD* thd)
bool wsrep_sync_wait (THD* thd, uint mask)
{
if (thd->variables.wsrep_causal_reads && thd->variables.wsrep_on &&
if ((thd->variables.wsrep_sync_wait & mask) &&
thd->variables.wsrep_on &&
!thd->in_active_multi_stmt_transaction() &&
thd->wsrep_conflict_state != REPLAYING)
{
WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u",
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_gtid_t gtid;
@ -918,12 +920,12 @@ wsrep_causal_wait (THD* thd)
switch (ret)
{
case WSREP_NOT_IMPLEMENTED:
msg= "consistent reads by wsrep backend. "
msg= "synchronous reads by wsrep backend. "
"Please unset wsrep_causal_reads variable.";
err= ER_NOT_SUPPORTED_YET;
break;
default:
msg= "Causal wait failed.";
msg= "Synchronous wait failed.";
err= ER_LOCK_WAIT_TIMEOUT; // NOTE: the above msg won't be displayed
// with ER_LOCK_WAIT_TIMEOUT
}
@ -1818,7 +1820,6 @@ static my_bool have_committing_connections()
if (is_committing_connection(tmp))
{
mysql_mutex_unlock(&LOCK_thread_count);
return TRUE;
}
}
@ -2302,6 +2303,9 @@ 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);

View file

@ -115,6 +115,14 @@ extern my_bool wsrep_slave_FK_checks;
extern my_bool wsrep_slave_UK_checks;
enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU };
enum enum_wsrep_sync_wait {
WSREP_SYNC_WAIT_NONE = 0x0,
// show, select, begin
WSREP_SYNC_WAIT_BEFORE_READ = 0x1,
WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE = 0x2,
WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE = 0x4,
WSREP_SYNC_WAIT_MAX = 0x7
};
// MySQL status variables
extern my_bool wsrep_connected;
@ -188,9 +196,10 @@ extern void wsrep_kill_mysql(THD *thd);
/* new defines */
extern void wsrep_stop_replication(THD *thd);
extern bool wsrep_start_replication();
extern bool wsrep_causal_wait(THD* thd);
extern bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ);
extern int wsrep_check_opts (int argc, char* const* argv);
extern void wsrep_prepend_PATH (const char* path);
/* some inline functions are defined in wsrep_mysqld_inl.h */
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;

View file

@ -503,17 +503,35 @@ int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync)
return state;
}
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
{
my_bool wsrep_thd_is_wsrep(void *thd_ptr)
{
my_bool status = FALSE;
if (thd_ptr)
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
status = (WSREP(thd) && WSREP_PROVIDER_EXISTS);
}
return status;
}
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
{
my_bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
// THD can be BF only if provider exists
if (wsrep_thd_is_wsrep(thd_ptr))
{
if (sync)
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER));
if (sync)
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
}
return status;
}

View file

@ -29,6 +29,8 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern my_bool wsrep_thd_is_wsrep(void *thd_ptr);
extern int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
//extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync);

View file

@ -60,11 +60,29 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
return false;
}
void wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type)
bool wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type)
{
if (var_type == OPT_GLOBAL) {
thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads;
// global setting should not affect session setting.
// if (var_type == OPT_GLOBAL) {
// thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads;
// }
if (thd->variables.wsrep_causal_reads) {
thd->variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ;
} else {
thd->variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ;
}
return false;
}
bool wsrep_sync_wait_update (sys_var* self, THD* thd, enum_var_type var_type)
{
// global setting should not affect session setting.
// if (var_type == OPT_GLOBAL) {
// thd->variables.wsrep_sync_wait = global_system_variables.wsrep_sync_wait;
// }
thd->variables.wsrep_causal_reads = thd->variables.wsrep_sync_wait &
WSREP_SYNC_WAIT_BEFORE_READ;
return false;
}
static int wsrep_start_position_verify (const char* start_str)

View file

@ -35,7 +35,8 @@ int wsrep_init_vars();
#define INIT_ARGS (const char* opt)
extern bool wsrep_on_update UPDATE_ARGS;
extern void wsrep_causal_reads_update UPDATE_ARGS;
extern bool wsrep_causal_reads_update UPDATE_ARGS;
extern bool wsrep_sync_wait_update UPDATE_ARGS;
extern bool wsrep_start_position_check CHECK_ARGS;
extern bool wsrep_start_position_update UPDATE_ARGS;
extern void wsrep_start_position_init INIT_ARGS;

View file

@ -5757,7 +5757,7 @@ wsrep_innobase_mysql_sort(
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_VARCHAR:
{
uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN];
uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN;
/* Use the charset number to pick the right charset struct for
@ -5796,11 +5796,11 @@ wsrep_innobase_mysql_sort(
} else {
/* strnxfrm will expand the destination string,
protocols < 3 truncated the sorted sring
protocols > 3 gets full sorted sring
protocols >= 3 gets full sorted sring
*/
tmp_length = charset->coll->strnxfrm(
charset, str, buf_length,
str_length, tmp_str, tmp_length, 0);
str_length, tmp_str, str_length, 0);
DBUG_ASSERT(tmp_length <= buf_length);
ret_length = tmp_length;
}
@ -6343,6 +6343,7 @@ UNIV_INTERN
uint
wsrep_store_key_val_for_row(
/*===============================*/
THD* thd,
TABLE* table,
uint keynr, /*!< in: key number */
char* buff, /*!< in/out: buffer for the key value (in MySQL
@ -6357,25 +6358,33 @@ wsrep_store_key_val_for_row(
char* buff_start = buff;
enum_field_types mysql_type;
Field* field;
uint buff_space = buff_len;
DBUG_ENTER("wsrep_store_key_val_for_row");
memset(buff, 0, buff_len);
*key_is_null = TRUE;
for (; key_part != end; key_part++) {
uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
ibool part_is_null = FALSE;
if (key_part->null_bit) {
if (record[key_part->null_offset] &
key_part->null_bit) {
*buff = 1;
part_is_null = TRUE;
if (buff_space > 0) {
if (record[key_part->null_offset]
& key_part->null_bit) {
*buff = 1;
part_is_null = TRUE;
} else {
*buff = 0;
}
buff++;
buff_space--;
} else {
*buff = 0;
fprintf (stderr, "WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
}
buff++;
}
if (!part_is_null) *key_is_null = FALSE;
@ -6395,8 +6404,15 @@ wsrep_store_key_val_for_row(
key_len = key_part->length;
if (part_is_null) {
buff += key_len + 2;
true_len = key_len + 2;
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
continue;
}
cs = field->charset();
@ -6436,13 +6452,20 @@ wsrep_store_key_val_for_row(
REC_VERSION_56_MAX_INDEX_COL_LEN);
if (wsrep_protocol_version > 1) {
memcpy(buff, sorted, true_len);
/* Note that we always reserve the maximum possible
length of the true VARCHAR in the key value, though
only len first bytes after the 2 length bytes contain
actual data. The rest of the space was reset to zero
in the bzero() call above. */
buff += true_len;
/* Note that we always reserve the maximum possible
length of the true VARCHAR in the key value, though
only len first bytes after the 2 length bytes contain
actual data. The rest of the space was reset to zero
in the bzero() call above. */
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
memcpy(buff, sorted, true_len);
buff += true_len;
buff_space -= true_len;
} else {
buff += key_len;
}
@ -6466,7 +6489,15 @@ wsrep_store_key_val_for_row(
key_len = key_part->length;
if (part_is_null) {
buff += key_len + 2;
true_len = key_len + 2;
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
continue;
}
@ -6509,15 +6540,22 @@ wsrep_store_key_val_for_row(
mysql_type, cs->number, sorted, true_len,
REC_VERSION_56_MAX_INDEX_COL_LEN);
memcpy(buff, sorted, true_len);
/* Note that we always reserve the maximum possible
length of the BLOB prefix in the key value. */
if (wsrep_protocol_version > 1) {
buff += true_len;
} else {
buff += key_len;
}
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
} else {
buff += key_len;
}
memcpy(buff, sorted, true_len);
} else {
/* Here we handle all other data types except the
true VARCHAR, BLOB and TEXT. Note that the column
@ -6534,9 +6572,17 @@ wsrep_store_key_val_for_row(
key_len = key_part->length;
if (part_is_null) {
buff += key_len;
true_len = key_len;
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
continue;
continue;
}
src_start = record + key_part->offset;
@ -6574,12 +6620,18 @@ wsrep_store_key_val_for_row(
mysql_type, cs->number, sorted, true_len,
REC_VERSION_56_MAX_INDEX_COL_LEN);
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
memcpy(buff, sorted, true_len);
} else {
memcpy(buff, src_start, true_len);
}
buff += true_len;
buff += true_len;
buff_space -= true_len;
}
}
@ -9782,7 +9834,8 @@ ha_innobase::wsrep_append_keys(
ibool is_null;
len = wsrep_store_key_val_for_row(
table, 0, key, key_info->key_length, record0, &is_null);
thd, table, 0, key, WSREP_MAX_SUPPORTED_KEY_LENGTH,
record0, &is_null);
if (!is_null) {
rcode = wsrep_append_key(
@ -9804,9 +9857,6 @@ ha_innobase::wsrep_append_keys(
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) {
hasPK = true;
if (i != table->s->primary_key) {
wsrep_thd_set_PA_safe(thd, FALSE);
}
}
}
@ -9837,7 +9887,8 @@ ha_innobase::wsrep_append_keys(
(!tab && referenced_by_foreign_key()))) {
len = wsrep_store_key_val_for_row(
table, i, key0, key_info->key_length,
thd, table, i, key0,
WSREP_MAX_SUPPORTED_KEY_LENGTH,
record0, &is_null);
if (!is_null) {
rcode = wsrep_append_key(
@ -9847,7 +9898,6 @@ ha_innobase::wsrep_append_keys(
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
}
else
{
@ -9856,7 +9906,8 @@ ha_innobase::wsrep_append_keys(
}
if (record1) {
len = wsrep_store_key_val_for_row(
table, i, key1, key_info->key_length,
thd, table, i, key1,
WSREP_MAX_SUPPORTED_KEY_LENGTH,
record1, &is_null);
if (!is_null && memcmp(key0, key1, len)) {
rcode = wsrep_append_key(

View file

@ -294,6 +294,7 @@ wsrep_innobase_kill_one_trx(void *thd_ptr,
my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_wsrep(void *thd_ptr);
int wsrep_trx_order_before(void *thd1, void *thd2);
int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length,

View file

@ -144,6 +144,33 @@ do {\
}\
} while (0)
#ifdef WITH_WSREP
/*******************************************************************//**
Inserts a struct to the head of hash table. */
#define HASH_PREPEND(TYPE, NAME, TABLE, FOLD, DATA) \
do { \
hash_cell_t* cell3333; \
TYPE* struct3333; \
\
HASH_ASSERT_OWN(TABLE, FOLD) \
\
(DATA)->NAME = NULL; \
\
cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
\
if (cell3333->node == NULL) { \
cell3333->node = DATA; \
DATA->NAME = NULL; \
} else { \
struct3333 = (TYPE*) cell3333->node; \
\
DATA->NAME = struct3333; \
\
cell3333->node = DATA; \
} \
} while (0)
#endif /*WITH_WSREP */
#ifdef UNIV_HASH_DEBUG
# define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1)
# define HASH_INVALIDATE(DATA, NAME) *(void**) (&DATA->NAME) = (void*) -1

View file

@ -1035,22 +1035,23 @@ lock_rec_has_to_wait(
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict,"
"type_mode: %lu supremum: %lu\n",
fprintf(stderr, "BF-BF X lock conflict,"
"type_mode: %lu supremum: %lu\n",
type_mode, lock_is_on_supremum);
fprintf(stderr, "conflicts states: my %d locked %d\n",
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
fprintf(stderr, "conflicts states: my %d locked %d\n",
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) );
lock_rec_print(stderr, lock2);
abort();
return FALSE;
//abort();
} else {
/* if lock2->index->n_uniq <=
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
@ -1060,7 +1061,7 @@ lock_rec_has_to_wait(
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
@ -1623,8 +1624,12 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
static void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
static
void
wsrep_kill_victim(
const trx_t * const trx,
const lock_t *lock)
{
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
@ -1633,32 +1638,38 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug)
if (wsrep_debug) {
fprintf(stderr, "WSREP: BF victim waiting\n");
}
/* cannot release lock, until our lock
is in the queue*/
} else if (lock->trx != trx) {
if (wsrep_log_conflicts) {
mutex_enter(&trx_sys->mutex);
if (bf_this)
fputs("\n*** Priority TRANSACTION:\n",
if (bf_this) {
fputs("\n*** Priority TRANSACTION:\n",
stderr);
else
fputs("\n*** Victim TRANSACTION:\n",
} else {
fputs("\n*** Victim TRANSACTION:\n",
stderr);
}
trx_print_latched(stderr, trx, 3000);
if (bf_other)
fputs("\n*** Priority TRANSACTION:\n",
if (bf_other) {
fputs("\n*** Priority TRANSACTION:\n",
stderr);
else
fputs("\n*** Victim TRANSACTION:\n",
} else {
fputs("\n*** Victim TRANSACTION:\n",
stderr);
}
trx_print_latched(stderr, lock->trx, 3000);
mutex_exit(&trx_sys->mutex);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
stderr);
@ -1668,6 +1679,7 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
lock_table_print(stderr, lock);
}
}
wsrep_innobase_kill_one_trx(trx->mysql_thd,
(const trx_t*) trx, lock->trx, TRUE);
}
@ -1997,7 +2009,7 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL;
@ -2024,7 +2036,9 @@ lock_rec_create(
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock);
if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
}
trx->lock.que_state = TRX_QUE_LOCK_WAIT;
lock_set_lock_and_trx_wait(lock, trx);
@ -2038,10 +2052,15 @@ lock_rec_create(
victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again
*/
if (caller_owns_trx_mutex) trx_mutex_exit(trx);
if (caller_owns_trx_mutex) {
trx_mutex_exit(trx);
}
lock_cancel_waiting_and_release(
c_lock->trx->lock.wait_lock);
if (caller_owns_trx_mutex) trx_mutex_enter(trx);
if (caller_owns_trx_mutex) {
trx_mutex_enter(trx);
}
/* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above
@ -2049,17 +2068,23 @@ lock_rec_create(
if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock);
}
trx_mutex_exit(c_lock->trx);
if (wsrep_debug) fprintf(
stderr,
"WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
if (wsrep_debug) {
fprintf(
stderr,
"WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
}
/* have to bail out here to avoid lock_set_lock... */
return(lock);
}
trx_mutex_exit(c_lock->trx);
} else if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
HASH_PREPEND(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
} else {
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
@ -2075,7 +2100,6 @@ lock_rec_create(
ut_ad(trx_mutex_own(trx));
if (type_mode & LOCK_WAIT) {
lock_set_lock_and_trx_wait(lock, trx);
}
@ -2087,7 +2111,6 @@ lock_rec_create(
MONITOR_INC(MONITOR_RECLOCK_CREATED);
MONITOR_INC(MONITOR_NUM_RECLOCK);
return(lock);
}
@ -2267,7 +2290,7 @@ lock_rec_add_to_queue(
block, heap_no, trx);
#ifdef WITH_WSREP
/* this can potentionally assert with wsrep */
if (wsrep_on(trx->mysql_thd)) {
if (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (wsrep_debug && other_lock) {
fprintf(stderr,
"WSREP: InnoDB assert ignored\n");
@ -2305,7 +2328,16 @@ lock_rec_add_to_queue(
if (lock_get_wait(lock)
&& lock_rec_get_nth_bit(lock, heap_no)) {
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (wsrep_debug) {
fprintf(stderr,
"BF skipping wait: %lu\n",
trx->id);
lock_rec_print(stderr, lock);
}
} else
#endif
goto somebody_waits;
}
}
@ -2503,8 +2535,8 @@ lock_rec_lock_slow(
/* c_lock is NULL here if jump to enqueue_waiting happened
but it's ok because lock is not NULL in that case and c_lock
is not used. */
err=
lock_rec_enqueue_waiting(c_lock, mode, block, heap_no, index, thr);
err = lock_rec_enqueue_waiting(c_lock,
mode, block, heap_no, index, thr);
#else
err = lock_rec_enqueue_waiting(
mode, block, heap_no, index, thr);
@ -2614,7 +2646,13 @@ lock_rec_has_to_wait_in_queue(
if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask)
&& lock_has_to_wait(wait_lock, lock)) {
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) {
/* don't wait for another BF lock */
continue;
}
#endif
return(lock);
}
}
@ -3999,19 +4037,21 @@ lock_deadlock_select_victim(
choose it as the victim and roll it back. */
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx);
else
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx);
}
else
#endif /* WITH_WSREP */
return(ctx->start);
return(ctx->start);
}
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE))
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) {
return(ctx->start);
}
else
#endif /* WITH_WSREP */
return(ctx->wait_lock->trx);
return(ctx->wait_lock->trx);
}
/********************************************************************//**
@ -4141,12 +4181,13 @@ lock_deadlock_search(
ctx->too_deep = TRUE;
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx->id);
}
else
#endif /* WITH_WSREP */
/* Select the joining transaction as the victim. */
return(ctx->start->id);
return(ctx->start->id);
} else if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
@ -4383,42 +4424,54 @@ lock_table_create(
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
if (c_lock) trx_mutex_enter(c_lock->trx);
if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock);
/* have to release trx mutex for the duration of
victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again
*/
/* caller has trx_mutex, have to release for lock cancel */
trx_mutex_exit(trx);
lock_cancel_waiting_and_release(c_lock->trx->lock.wait_lock);
trx_mutex_enter(trx);
/* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above
*/
if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock);
if (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
if (wsrep_debug) {
fprintf(stderr, "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
if (c_lock) {
trx_mutex_enter(c_lock->trx);
}
if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
wsrep_print_wait_locks(c_lock->trx->lock.wait_lock);
}
/* have to release trx mutex for the duration of
victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again
*/
/* caller has trx_mutex, have to release for lock cancel */
trx_mutex_exit(trx);
lock_cancel_waiting_and_release(c_lock->trx->lock.wait_lock);
trx_mutex_enter(trx);
/* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above
*/
if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock);
}
if (wsrep_debug) {
fprintf(stderr, "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
}
}
if (c_lock) {
trx_mutex_exit(c_lock->trx);
}
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
if (c_lock) trx_mutex_exit(c_lock->trx);
#else
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
#endif /* WITH_WSREP */
@ -4705,11 +4758,15 @@ lock_table_other_has_incompatible(
&& (wait || !lock_get_wait(lock))) {
#ifdef WITH_WSREP
if (wsrep_debug)
fprintf(stderr, "WSREP: table lock abort");
trx_mutex_enter(lock->trx);
wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
trx_mutex_exit(lock->trx);
if(wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (wsrep_debug) {
fprintf(stderr, "WSREP: trx %ld table lock abort\n",
trx->id);
}
trx_mutex_enter(lock->trx);
wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
trx_mutex_exit(lock->trx);
}
#endif
return(lock);
@ -5965,15 +6022,17 @@ lock_rec_queue_validate(
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
#ifndef WITH_WSREP
enum lock_mode mode;
if (wsrep_thd_is_wsrep(lock->trx->mysql_thd)) {
enum lock_mode mode;
if (lock_get_mode(lock) == LOCK_S) {
mode = LOCK_X;
} else {
mode = LOCK_S;
if (lock_get_mode(lock) == LOCK_S) {
mode = LOCK_X;
} else {
mode = LOCK_S;
}
ut_a(!lock_rec_other_has_expl_req(
mode, 0, 0, block, heap_no, lock->trx));
}
ut_a(!lock_rec_other_has_expl_req(
mode, 0, 0, block, heap_no, lock->trx));
#endif /* WITH_WSREP */
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {

View file

@ -417,12 +417,9 @@ wsrep_row_upd_check_foreign_constraints(
}
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
(foreign->referenced_table
->n_foreign_key_checks_running)++;
mutex_exit(&(dict_sys->mutex));
os_inc_counter(dict_sys->mutex,
foreign->referenced_table
->n_foreign_key_checks_running);
}
/* NOTE that if the thread ends up waiting for a lock
@ -434,20 +431,14 @@ wsrep_row_upd_check_foreign_constraints(
TRUE, foreign, table, entry, thr);
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
ut_a(foreign->referenced_table
->n_foreign_key_checks_running > 0);
(foreign->referenced_table
->n_foreign_key_checks_running)--;
os_dec_counter(dict_sys->mutex,
foreign->referenced_table
->n_foreign_key_checks_running);
if (opened == TRUE) {
dict_table_close(foreign->referenced_table, TRUE, FALSE);
opened = FALSE;
}
mutex_exit(&(dict_sys->mutex));
}
if (err != DB_SUCCESS) {

View file

@ -6204,7 +6204,7 @@ wsrep_innobase_mysql_sort(
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_VARCHAR:
{
uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN];
uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN;
/* Use the charset number to pick the right charset struct for
@ -6243,11 +6243,11 @@ wsrep_innobase_mysql_sort(
} else {
/* strnxfrm will expand the destination string,
protocols < 3 truncated the sorted sring
protocols > 3 gets full sorted sring
protocols >= 3 gets full sorted sring
*/
tmp_length = charset->coll->strnxfrm(
charset, str, buf_length,
str_length, tmp_str, tmp_length, 0);
str_length, tmp_str, str_length, 0);
DBUG_ASSERT(tmp_length <= buf_length);
ret_length = tmp_length;
}
@ -6790,6 +6790,7 @@ UNIV_INTERN
uint
wsrep_store_key_val_for_row(
/*===============================*/
THD* thd,
TABLE* table,
uint keynr, /*!< in: key number */
char* buff, /*!< in/out: buffer for the key value (in MySQL
@ -6804,25 +6805,33 @@ wsrep_store_key_val_for_row(
char* buff_start = buff;
enum_field_types mysql_type;
Field* field;
uint buff_space = buff_len;
DBUG_ENTER("wsrep_store_key_val_for_row");
memset(buff, 0, buff_len);
*key_is_null = TRUE;
for (; key_part != end; key_part++) {
uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
ibool part_is_null = FALSE;
if (key_part->null_bit) {
if (record[key_part->null_offset] &
key_part->null_bit) {
*buff = 1;
part_is_null = TRUE;
if (buff_space > 0) {
if (record[key_part->null_offset]
& key_part->null_bit) {
*buff = 1;
part_is_null = TRUE;
} else {
*buff = 0;
}
buff++;
buff_space--;
} else {
*buff = 0;
fprintf (stderr, "WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
}
buff++;
}
if (!part_is_null) *key_is_null = FALSE;
@ -6842,8 +6851,15 @@ wsrep_store_key_val_for_row(
key_len = key_part->length;
if (part_is_null) {
buff += key_len + 2;
true_len = key_len + 2;
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
continue;
}
cs = field->charset();
@ -6883,13 +6899,20 @@ wsrep_store_key_val_for_row(
REC_VERSION_56_MAX_INDEX_COL_LEN);
if (wsrep_protocol_version > 1) {
memcpy(buff, sorted, true_len);
/* Note that we always reserve the maximum possible
length of the true VARCHAR in the key value, though
only len first bytes after the 2 length bytes contain
actual data. The rest of the space was reset to zero
in the bzero() call above. */
buff += true_len;
/* Note that we always reserve the maximum possible
length of the true VARCHAR in the key value, though
only len first bytes after the 2 length bytes contain
actual data. The rest of the space was reset to zero
in the bzero() call above. */
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
memcpy(buff, sorted, true_len);
buff += true_len;
buff_space -= true_len;
} else {
buff += key_len;
}
@ -6913,7 +6936,15 @@ wsrep_store_key_val_for_row(
key_len = key_part->length;
if (part_is_null) {
buff += key_len + 2;
true_len = key_len + 2;
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
continue;
}
@ -6956,15 +6987,22 @@ wsrep_store_key_val_for_row(
mysql_type, cs->number, sorted, true_len,
REC_VERSION_56_MAX_INDEX_COL_LEN);
memcpy(buff, sorted, true_len);
/* Note that we always reserve the maximum possible
length of the BLOB prefix in the key value. */
if (wsrep_protocol_version > 1) {
buff += true_len;
} else {
buff += key_len;
}
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
} else {
buff += key_len;
}
memcpy(buff, sorted, true_len);
} else {
/* Here we handle all other data types except the
true VARCHAR, BLOB and TEXT. Note that the column
@ -6981,9 +7019,17 @@ wsrep_store_key_val_for_row(
key_len = key_part->length;
if (part_is_null) {
buff += key_len;
true_len = key_len;
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
buff += true_len;
buff_space -= true_len;
continue;
continue;
}
src_start = record + key_part->offset;
@ -7021,12 +7067,18 @@ wsrep_store_key_val_for_row(
mysql_type, cs->number, sorted, true_len,
REC_VERSION_56_MAX_INDEX_COL_LEN);
if (true_len > buff_space) {
fprintf (stderr,
"WSREP: key truncated: %s\n",
wsrep_thd_query(thd));
true_len = buff_space;
}
memcpy(buff, sorted, true_len);
} else {
memcpy(buff, src_start, true_len);
}
buff += true_len;
buff += true_len;
buff_space -= true_len;
}
}
@ -10223,7 +10275,7 @@ wsrep_append_key(
DBUG_ENTER("wsrep_append_key");
bool const copy = true;
#ifdef WSREP_DEBUG_PRINT
fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ",
fprintf(stderr, "%s conn %ld, trx %lu, keylen %d, table %s ",
(shared) ? "Shared" : "Exclusive",
wsrep_thd_thread_id(thd), (long long)trx->id, key_len,
table_share->table_name.str);
@ -10293,11 +10345,11 @@ ha_innobase::wsrep_append_keys(
uint len;
char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
char *key = &keyval[0];
KEY *key_info = table->key_info;
ibool is_null;
len = wsrep_store_key_val_for_row(
table, 0, key, key_info->key_length, record0, &is_null);
thd, table, 0, key, WSREP_MAX_SUPPORTED_KEY_LENGTH,
record0, &is_null);
if (!is_null) {
rcode = wsrep_append_key(
@ -10319,9 +10371,6 @@ ha_innobase::wsrep_append_keys(
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) {
hasPK = true;
if (i != table->s->primary_key) {
wsrep_thd_set_PA_safe(thd, FALSE);
}
}
}
@ -10352,7 +10401,8 @@ ha_innobase::wsrep_append_keys(
(!tab && referenced_by_foreign_key()))) {
len = wsrep_store_key_val_for_row(
table, i, key0, key_info->key_length,
thd, table, i, key0,
WSREP_MAX_SUPPORTED_KEY_LENGTH,
record0, &is_null);
if (!is_null) {
rcode = wsrep_append_key(
@ -10362,7 +10412,6 @@ ha_innobase::wsrep_append_keys(
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
}
else
{
@ -10371,7 +10420,8 @@ ha_innobase::wsrep_append_keys(
}
if (record1) {
len = wsrep_store_key_val_for_row(
table, i, key1, key_info->key_length,
thd, table, i, key1,
WSREP_MAX_SUPPORTED_KEY_LENGTH,
record1, &is_null);
if (!is_null && memcmp(key0, key1, len)) {
rcode = wsrep_append_key(
@ -18472,7 +18522,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
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);
wsrep_thd_awake(victim_thd, signal);
}
DBUG_RETURN(-1);
}

View file

@ -293,6 +293,7 @@ wsrep_innobase_kill_one_trx(void *thd_ptr,
my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_wsrep(void *thd_ptr);
int wsrep_trx_order_before(void *thd1, void *thd2);
int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length,

View file

@ -144,6 +144,33 @@ do {\
}\
} while (0)
#ifdef WITH_WSREP
/*******************************************************************//**
Inserts a struct to the head of hash table. */
#define HASH_PREPEND(TYPE, NAME, TABLE, FOLD, DATA) \
do { \
hash_cell_t* cell3333; \
TYPE* struct3333; \
\
HASH_ASSERT_OWN(TABLE, FOLD) \
\
(DATA)->NAME = NULL; \
\
cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
\
if (cell3333->node == NULL) { \
cell3333->node = DATA; \
DATA->NAME = NULL; \
} else { \
struct3333 = (TYPE*) cell3333->node; \
\
DATA->NAME = struct3333; \
\
cell3333->node = DATA; \
} \
} while (0)
#endif /*WITH_WSREP */
#ifdef UNIV_HASH_DEBUG
# define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1)
# define HASH_INVALIDATE(DATA, NAME) *(void**) (&DATA->NAME) = (void*) -1

View file

@ -1036,22 +1036,23 @@ lock_rec_has_to_wait(
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict,"
"type_mode: %lu supremum: %lu\n",
fprintf(stderr, "BF-BF X lock conflict,"
"type_mode: %lu supremum: %lu\n",
type_mode, lock_is_on_supremum);
fprintf(stderr, "conflicts states: my %d locked %d\n",
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
fprintf(stderr, "conflicts states: my %d locked %d\n",
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) );
lock_rec_print(stderr, lock2);
abort();
return FALSE;
//abort();
} else {
/* if lock2->index->n_uniq <=
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
@ -1061,7 +1062,7 @@ lock_rec_has_to_wait(
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
@ -1622,8 +1623,12 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
static void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
static
void
wsrep_kill_victim(
const trx_t * const trx,
const lock_t *lock)
{
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
@ -1632,32 +1637,38 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug)
if (wsrep_debug) {
fprintf(stderr, "WSREP: BF victim waiting\n");
}
/* cannot release lock, until our lock
is in the queue*/
} else if (lock->trx != trx) {
if (wsrep_log_conflicts) {
mutex_enter(&trx_sys->mutex);
if (bf_this)
fputs("\n*** Priority TRANSACTION:\n",
if (bf_this) {
fputs("\n*** Priority TRANSACTION:\n",
stderr);
else
fputs("\n*** Victim TRANSACTION:\n",
} else {
fputs("\n*** Victim TRANSACTION:\n",
stderr);
}
trx_print_latched(stderr, trx, 3000);
if (bf_other)
fputs("\n*** Priority TRANSACTION:\n",
if (bf_other) {
fputs("\n*** Priority TRANSACTION:\n",
stderr);
else
fputs("\n*** Victim TRANSACTION:\n",
} else {
fputs("\n*** Victim TRANSACTION:\n",
stderr);
}
trx_print_latched(stderr, lock->trx, 3000);
mutex_exit(&trx_sys->mutex);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
stderr);
@ -1667,6 +1678,7 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
lock_table_print(stderr, lock);
}
}
wsrep_innobase_kill_one_trx(trx->mysql_thd,
(const trx_t*) trx, lock->trx, TRUE);
}
@ -2008,7 +2020,7 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL;
@ -2035,7 +2047,9 @@ lock_rec_create(
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock);
if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
}
trx->lock.que_state = TRX_QUE_LOCK_WAIT;
lock_set_lock_and_trx_wait(lock, trx);
@ -2049,10 +2063,15 @@ lock_rec_create(
victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again
*/
if (caller_owns_trx_mutex) trx_mutex_exit(trx);
if (caller_owns_trx_mutex) {
trx_mutex_exit(trx);
}
lock_cancel_waiting_and_release(
c_lock->trx->lock.wait_lock);
if (caller_owns_trx_mutex) trx_mutex_enter(trx);
if (caller_owns_trx_mutex) {
trx_mutex_enter(trx);
}
/* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above
@ -2060,17 +2079,23 @@ lock_rec_create(
if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock);
}
trx_mutex_exit(c_lock->trx);
if (wsrep_debug) fprintf(
stderr,
"WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
if (wsrep_debug) {
fprintf(
stderr,
"WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
}
/* have to bail out here to avoid lock_set_lock... */
return(lock);
}
trx_mutex_exit(c_lock->trx);
} else if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
HASH_PREPEND(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
} else {
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
@ -2088,7 +2113,6 @@ lock_rec_create(
ut_ad(trx_mutex_own(trx));
if (type_mode & LOCK_WAIT) {
lock_set_lock_and_trx_wait(lock, trx);
}
@ -2100,7 +2124,6 @@ lock_rec_create(
MONITOR_INC(MONITOR_RECLOCK_CREATED);
MONITOR_INC(MONITOR_NUM_RECLOCK);
return(lock);
}
@ -2288,7 +2311,7 @@ lock_rec_add_to_queue(
block, heap_no, trx->id);
#ifdef WITH_WSREP
/* this can potentionally assert with wsrep */
if (wsrep_on(trx->mysql_thd)) {
if (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (wsrep_debug && other_lock) {
fprintf(stderr,
"WSREP: InnoDB assert ignored\n");
@ -2326,7 +2349,16 @@ lock_rec_add_to_queue(
if (lock_get_wait(lock)
&& lock_rec_get_nth_bit(lock, heap_no)) {
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (wsrep_debug) {
fprintf(stderr,
"BF skipping wait: %lu\n",
trx->id);
lock_rec_print(stderr, lock);
}
} else
#endif
goto somebody_waits;
}
}
@ -2526,8 +2558,8 @@ lock_rec_lock_slow(
/* c_lock is NULL here if jump to enqueue_waiting happened
but it's ok because lock is not NULL in that case and c_lock
is not used. */
err=
lock_rec_enqueue_waiting(c_lock, mode, block, heap_no, index, thr);
err = lock_rec_enqueue_waiting(c_lock,
mode, block, heap_no, index, thr);
#else
err = lock_rec_enqueue_waiting(
mode, block, heap_no, index, thr);
@ -2638,7 +2670,13 @@ lock_rec_has_to_wait_in_queue(
if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask)
&& lock_has_to_wait(wait_lock, lock)) {
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) {
/* don't wait for another BF lock */
continue;
}
#endif
return(lock);
}
}
@ -4025,19 +4063,21 @@ lock_deadlock_select_victim(
choose it as the victim and roll it back. */
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx);
else
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx);
}
else
#endif /* WITH_WSREP */
return(ctx->start);
return(ctx->start);
}
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE))
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) {
return(ctx->start);
}
else
#endif /* WITH_WSREP */
return(ctx->wait_lock->trx);
return(ctx->wait_lock->trx);
}
/********************************************************************//**
@ -4167,12 +4207,13 @@ lock_deadlock_search(
ctx->too_deep = TRUE;
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx->id);
}
else
#endif /* WITH_WSREP */
/* Select the joining transaction as the victim. */
return(ctx->start->id);
return(ctx->start->id);
} else if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
@ -4411,42 +4452,54 @@ lock_table_create(
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
if (c_lock) trx_mutex_enter(c_lock->trx);
if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock);
/* have to release trx mutex for the duration of
victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again
*/
/* caller has trx_mutex, have to release for lock cancel */
trx_mutex_exit(trx);
lock_cancel_waiting_and_release(c_lock->trx->lock.wait_lock);
trx_mutex_enter(trx);
/* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above
*/
if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock);
if (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
if (wsrep_debug) {
fprintf(stderr, "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
if (c_lock) {
trx_mutex_enter(c_lock->trx);
}
if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
wsrep_print_wait_locks(c_lock->trx->lock.wait_lock);
}
/* have to release trx mutex for the duration of
victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again
*/
/* caller has trx_mutex, have to release for lock cancel */
trx_mutex_exit(trx);
lock_cancel_waiting_and_release(c_lock->trx->lock.wait_lock);
trx_mutex_enter(trx);
/* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above
*/
if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock);
}
if (wsrep_debug) {
fprintf(stderr, "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
}
}
if (c_lock) {
trx_mutex_exit(c_lock->trx);
}
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
if (c_lock) trx_mutex_exit(c_lock->trx);
#else
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
#endif /* WITH_WSREP */
@ -4740,11 +4793,15 @@ lock_table_other_has_incompatible(
&& (wait || !lock_get_wait(lock))) {
#ifdef WITH_WSREP
if (wsrep_debug)
fprintf(stderr, "WSREP: table lock abort");
trx_mutex_enter(lock->trx);
wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
trx_mutex_exit(lock->trx);
if(wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (wsrep_debug) {
fprintf(stderr, "WSREP: trx %ld table lock abort\n",
trx->id);
}
trx_mutex_enter(lock->trx);
wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
trx_mutex_exit(lock->trx);
}
#endif
return(lock);
@ -6014,15 +6071,18 @@ lock_rec_queue_validate(
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
#ifndef WITH_WSREP
enum lock_mode mode;
if (wsrep_thd_is_wsrep(lock->trx->mysql_thd)) {
enum lock_mode mode;
if (lock_get_mode(lock) == LOCK_S) {
mode = LOCK_X;
} else {
mode = LOCK_S;
}
ut_a(!lock_rec_other_has_expl_req(
if (lock_get_mode(lock) == LOCK_S) {
mode = LOCK_X;
} else {
mode = LOCK_S;
}
ut_a(!lock_rec_other_has_expl_req(
mode, 0, 0, block, heap_no, lock->trx->id));
}
#endif /* WITH_WSREP */
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {

View file

@ -419,12 +419,9 @@ wsrep_row_upd_check_foreign_constraints(
}
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
(foreign->referenced_table
->n_foreign_key_checks_running)++;
mutex_exit(&(dict_sys->mutex));
os_inc_counter(dict_sys->mutex,
foreign->referenced_table
->n_foreign_key_checks_running);
}
/* NOTE that if the thread ends up waiting for a lock
@ -436,20 +433,14 @@ wsrep_row_upd_check_foreign_constraints(
TRUE, foreign, table, entry, thr);
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
ut_a(foreign->referenced_table
->n_foreign_key_checks_running > 0);
(foreign->referenced_table
->n_foreign_key_checks_running)--;
os_dec_counter(dict_sys->mutex,
foreign->referenced_table
->n_foreign_key_checks_running);
if (opened == TRUE) {
dict_table_close(foreign->referenced_table, TRUE, FALSE);
opened = FALSE;
}
mutex_exit(&(dict_sys->mutex));
}
if (err != DB_SUCCESS) {

View file

@ -356,7 +356,10 @@ case "$mode" in
# Stop the service and regardless of whether it was
# running or not, start it again.
if $0 stop $other_args; then
$0 start $other_args
if ! $0 start $other_args; then
log_failure_msg "Failed to restart server."
exit 1
fi
else
log_failure_msg "Failed to stop running server, so refusing to try to start."
exit 1