mirror of
https://github.com/MariaDB/server.git
synced 2025-04-12 02:05:34 +02:00
Merge lp:maria/maria-10.0-galera revisions 3867..3869 and
3871..3879.
This commit is contained in:
parent
62f40f49ca
commit
fe4f467276
37 changed files with 931 additions and 347 deletions
client
cmake
mysql-test
include
r
suite
sql
event_data_objects.ccsql_admin.ccsql_class.hsql_parse.ccsys_vars.cctransaction.ccwsrep_mysqld.ccwsrep_mysqld.hwsrep_thd.ccwsrep_thd.hwsrep_var.ccwsrep_var.h
storage
innobase
xtradb
support-files
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
6
mysql-test/include/have_innodb_disallow_writes.inc
Normal file
6
mysql-test/include/have_innodb_disallow_writes.inc
Normal 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'
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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'.
|
||||
|
|
24
mysql-test/suite/galera/r/galera_sst_mode.result
Normal file
24
mysql-test/suite/galera/r/galera_sst_mode.result
Normal 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
|
43
mysql-test/suite/galera/t/galera_sst_mode.test
Normal file
43
mysql-test/suite/galera/t/galera_sst_mode.test
Normal 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
|
56
mysql-test/suite/sys_vars/r/wsrep_sync_wait_basic.result
Normal file
56
mysql-test/suite/sys_vars/r/wsrep_sync_wait_basic.result
Normal 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
|
47
mysql-test/suite/sys_vars/t/wsrep_sync_wait_basic.test
Normal file
47
mysql-test/suite/sys_vars/t/wsrep_sync_wait_basic.test
Normal 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
|
19
mysql-test/suite/wsrep/r/innodb_load_xa_with_wsrep.result
Normal file
19
mysql-test/suite/wsrep/r/innodb_load_xa_with_wsrep.result
Normal 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;
|
1
mysql-test/suite/wsrep/t/innodb_load_xa_with_wsrep.opt
Normal file
1
mysql-test/suite/wsrep/t/innodb_load_xa_with_wsrep.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--ignore-builtin-innodb --loose-innodb --log-bin
|
19
mysql-test/suite/wsrep/t/innodb_load_xa_with_wsrep.test
Normal file
19
mysql-test/suite/wsrep/t/innodb_load_xa_with_wsrep.test
Normal 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;
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) :
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue