mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.1 into 10.2
This commit is contained in:
@@ -166,8 +166,8 @@ static struct my_option my_long_options[]=
|
|||||||
"server with which it was built/distributed.",
|
"server with which it was built/distributed.",
|
||||||
&opt_version_check, &opt_version_check, 0,
|
&opt_version_check, &opt_version_check, 0,
|
||||||
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
|
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
|
||||||
{"write-binlog", OPT_WRITE_BINLOG, "All commands including those, "
|
{"write-binlog", OPT_WRITE_BINLOG, "All commands including those "
|
||||||
"issued by mysqlcheck, are written to the binary log.",
|
"issued by mysqlcheck are written to the binary log.",
|
||||||
&opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG,
|
&opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG,
|
||||||
0, 0, 0, 0, 0, 0},
|
0, 0, 0, 0, 0, 0},
|
||||||
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||||
|
@@ -63,6 +63,12 @@ typedef struct st_mysql_lex_string LEX_STRING;
|
|||||||
/* NO and OK is the same used just to show semantics */
|
/* NO and OK is the same used just to show semantics */
|
||||||
#define ER_DYNCOL_NO ER_DYNCOL_OK
|
#define ER_DYNCOL_NO ER_DYNCOL_OK
|
||||||
|
|
||||||
|
#ifdef HAVE_CHARSET_utf8mb4
|
||||||
|
#define DYNCOL_UTF (&my_charset_utf8mb4_general_ci)
|
||||||
|
#else
|
||||||
|
#define DYNCOL_UTF (&my_charset_utf8_general_ci)
|
||||||
|
#endif
|
||||||
|
|
||||||
enum enum_dyncol_func_result
|
enum enum_dyncol_func_result
|
||||||
{
|
{
|
||||||
ER_DYNCOL_OK= 0,
|
ER_DYNCOL_OK= 0,
|
||||||
|
@@ -691,8 +691,7 @@ it was built/distributed. Defaults to on; use \fB\-\-skip\-version\-check\fR to
|
|||||||
.sp
|
.sp
|
||||||
Cause binary logging to be enabled while
|
Cause binary logging to be enabled while
|
||||||
\fBmysql_upgrade\fR
|
\fBmysql_upgrade\fR
|
||||||
runs\&. This is the default behavior; to disable binary logging during the upgrade, use the inverse of this option (that is, start the program with
|
runs\&.
|
||||||
\fB\-\-skip\-write\-binlog\fR)\&.
|
|
||||||
.RE
|
.RE
|
||||||
.SH "COPYRIGHT"
|
.SH "COPYRIGHT"
|
||||||
.br
|
.br
|
||||||
|
@@ -10272,6 +10272,21 @@ DROP TABLE allbytes;
|
|||||||
SET sql_mode = DEFAULT;
|
SET sql_mode = DEFAULT;
|
||||||
# End of ctype_backslash.inc
|
# End of ctype_backslash.inc
|
||||||
#
|
#
|
||||||
|
# MDEV-12681 Wrong VIEW results for CHAR(0xDF USING latin1)
|
||||||
|
#
|
||||||
|
SET NAMES utf8;
|
||||||
|
SELECT CHAR(0xDF USING latin1);
|
||||||
|
CHAR(0xDF USING latin1)
|
||||||
|
ß
|
||||||
|
CREATE OR REPLACE VIEW v1 AS SELECT CHAR(0xDF USING latin1) AS c;
|
||||||
|
SHOW CREATE VIEW v1;
|
||||||
|
View Create View character_set_client collation_connection
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select char(0xdf using latin1) AS `c` utf8 utf8_general_ci
|
||||||
|
SELECT * FROM v1;
|
||||||
|
c
|
||||||
|
ß
|
||||||
|
DROP VIEW v1;
|
||||||
|
#
|
||||||
# End of 10.0 tests
|
# End of 10.0 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@@ -3430,6 +3430,32 @@ a b
|
|||||||
a 😁 b a ? b
|
a 😁 b a ? b
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-8949: COLUMN_CREATE unicode name breakage
|
||||||
|
#
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SELECT COLUMN_JSON(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1));
|
||||||
|
COLUMN_JSON(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1))
|
||||||
|
{"😎":1}
|
||||||
|
SELECT COLUMN_LIST(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1));
|
||||||
|
COLUMN_LIST(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1))
|
||||||
|
`😎`
|
||||||
|
SELECT COLUMN_GET(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1), _utf8mb4 0xF09F988E
|
||||||
|
as int);
|
||||||
|
COLUMN_GET(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1), _utf8mb4 0xF09F988E
|
||||||
|
as int)
|
||||||
|
1
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
COLUMN_LIST(COLUMN_CREATE('a',1)),
|
||||||
|
COLUMN_JSON(COLUMN_CREATE('b',1));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`COLUMN_LIST(COLUMN_CREATE('a',1))` longtext CHARACTER SET utf8mb4 DEFAULT NULL,
|
||||||
|
`COLUMN_JSON(COLUMN_CREATE('b',1))` longtext CHARACTER SET utf8mb4 DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET NAMES default;
|
||||||
|
#
|
||||||
# End of 10.0 tests
|
# End of 10.0 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@@ -4556,6 +4556,27 @@ set global max_allowed_packet=default;
|
|||||||
# End of 5.6 tests
|
# End of 5.6 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
# Start of 10.0 tests
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# MDEV-12681 Wrong VIEW results for CHAR(0xDF USING latin1)
|
||||||
|
#
|
||||||
|
EXPLAIN EXTENDED SELECT CHAR(0xDF USING latin1);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select char(0xdf using latin1) AS `CHAR(0xDF USING latin1)`
|
||||||
|
EXPLAIN EXTENDED SELECT CHAR(0xDF USING `binary`);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select char(0xdf) AS `CHAR(0xDF USING ``binary``)`
|
||||||
|
EXPLAIN EXTENDED SELECT CHAR(0xDF);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select char(0xdf) AS `CHAR(0xDF)`
|
||||||
|
#
|
||||||
# Start of 10.1 tests
|
# Start of 10.1 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
64
mysql-test/suite/innodb/r/recovery_shutdown.result
Normal file
64
mysql-test/suite/innodb/r/recovery_shutdown.result
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#
|
||||||
|
# MDEV-13797 InnoDB may hang if shutdown is initiated soon after startup
|
||||||
|
# while rolling back recovered incomplete transactions
|
||||||
|
#
|
||||||
|
CREATE TABLE t (a INT) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
COMMIT;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t8 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t8 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t8 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t8;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t7 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t7 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t7 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t7;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t6 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t6 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t6 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t6;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t5 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t5 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t5 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t5;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t4 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t4 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t4 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t4;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t3 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t3 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t3 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t3;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t2 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t2 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t2;
|
||||||
|
connect con$c,localhost,root,,;
|
||||||
|
CREATE TABLE t1 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 (a) SELECT NULL FROM t;
|
||||||
|
UPDATE t1 SET a=a+100, b=a;
|
||||||
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
connection default;
|
||||||
|
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||||
|
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
|
||||||
|
DROP TABLE t,u;
|
59
mysql-test/suite/innodb/t/recovery_shutdown.test
Normal file
59
mysql-test/suite/innodb/t/recovery_shutdown.test
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-13797 InnoDB may hang if shutdown is initiated soon after startup
|
||||||
|
--echo # while rolling back recovered incomplete transactions
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t (a INT) ENGINE=InnoDB;
|
||||||
|
let $size = 100;
|
||||||
|
let $trx = 8;
|
||||||
|
let $c = $size;
|
||||||
|
BEGIN;
|
||||||
|
--disable_query_log
|
||||||
|
while ($c) {
|
||||||
|
INSERT INTO t VALUES();
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
let $c = $trx;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
connect (con$c,localhost,root,,);
|
||||||
|
eval CREATE TABLE t$c (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
eval INSERT INTO t$c (a) SELECT NULL FROM t;
|
||||||
|
eval UPDATE t$c SET a=a+$size, b=a;
|
||||||
|
eval DELETE FROM t$c;
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
|
||||||
|
--connection default
|
||||||
|
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||||
|
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
|
||||||
|
|
||||||
|
--let $shutdown_timeout=0
|
||||||
|
--source include/restart_mysqld.inc
|
||||||
|
--let $shutdown_timeout=60
|
||||||
|
--source include/restart_mysqld.inc
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
let $c = $trx;
|
||||||
|
while ($c)
|
||||||
|
{
|
||||||
|
disconnect con$c;
|
||||||
|
eval DROP TABLE t$c;
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
DROP TABLE t,u;
|
@@ -1 +1 @@
|
|||||||
--innodb-open-files=13
|
--innodb-open-files=20
|
||||||
|
@@ -1878,6 +1878,18 @@ SELECT _utf8 0x7E, _utf8 X'7E', _utf8 B'01111110';
|
|||||||
let $ctype_unescape_combinations=selected;
|
let $ctype_unescape_combinations=selected;
|
||||||
--source include/ctype_unescape.inc
|
--source include/ctype_unescape.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-12681 Wrong VIEW results for CHAR(0xDF USING latin1)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET NAMES utf8;
|
||||||
|
SELECT CHAR(0xDF USING latin1);
|
||||||
|
CREATE OR REPLACE VIEW v1 AS SELECT CHAR(0xDF USING latin1) AS c;
|
||||||
|
SHOW CREATE VIEW v1;
|
||||||
|
SELECT * FROM v1;
|
||||||
|
DROP VIEW v1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.0 tests
|
--echo # End of 10.0 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -1922,6 +1922,24 @@ INSERT IGNORE INTO t1 SELECT 'a 😁 b', 'a 😁 b';
|
|||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-8949: COLUMN_CREATE unicode name breakage
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SELECT COLUMN_JSON(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1));
|
||||||
|
SELECT COLUMN_LIST(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1));
|
||||||
|
SELECT COLUMN_GET(COLUMN_CREATE(_utf8mb4 0xF09F988E, 1), _utf8mb4 0xF09F988E
|
||||||
|
as int);
|
||||||
|
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
COLUMN_LIST(COLUMN_CREATE('a',1)),
|
||||||
|
COLUMN_JSON(COLUMN_CREATE('b',1));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
SET NAMES default;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.0 tests
|
--echo # End of 10.0 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -1756,6 +1756,18 @@ set global max_allowed_packet=default;
|
|||||||
--echo # End of 5.6 tests
|
--echo # End of 5.6 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Start of 10.0 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-12681 Wrong VIEW results for CHAR(0xDF USING latin1)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
EXPLAIN EXTENDED SELECT CHAR(0xDF USING latin1);
|
||||||
|
EXPLAIN EXTENDED SELECT CHAR(0xDF USING `binary`);
|
||||||
|
EXPLAIN EXTENDED SELECT CHAR(0xDF);
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # Start of 10.1 tests
|
--echo # Start of 10.1 tests
|
||||||
--echo #
|
--echo #
|
||||||
@@ -1800,7 +1812,6 @@ SELECT f1,HEX(f2) FROM t1 WHERE f1='YQ==' AND (f2= from_base64(
|
|||||||
SELECT f1,HEX(f2) FROM t1 WHERE f1='YQ==' AND (f2= from_base64("Yq==") OR f2= from_base64("YQ=="));
|
SELECT f1,HEX(f2) FROM t1 WHERE f1='YQ==' AND (f2= from_base64("Yq==") OR f2= from_base64("YQ=="));
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.1 tests
|
--echo # End of 10.1 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -4183,8 +4183,7 @@ mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((rc= mariadb_dyncol_val_str(json, &val,
|
if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, '"')) < 0)
|
||||||
&my_charset_utf8_general_ci, '"')) < 0)
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -273,7 +273,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
|
|||||||
/*
|
/*
|
||||||
Come here when some alarm in queue is due.
|
Come here when some alarm in queue is due.
|
||||||
Mark all alarms with are finnished in list.
|
Mark all alarms with are finnished in list.
|
||||||
Shedule alarms to be sent again after 1-10 sec (many alarms at once)
|
Schedule alarms to be sent again after 1-10 sec (many alarms at once)
|
||||||
If alarm_aborted is set then all alarms are given and resent
|
If alarm_aborted is set then all alarms are given and resent
|
||||||
every second.
|
every second.
|
||||||
*/
|
*/
|
||||||
@@ -425,7 +425,7 @@ void end_thr_alarm(my_bool free_structures)
|
|||||||
if (alarm_aborted != 1) /* If memory not freed */
|
if (alarm_aborted != 1) /* If memory not freed */
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_alarm);
|
mysql_mutex_lock(&LOCK_alarm);
|
||||||
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
|
DBUG_PRINT("info",("Rescheduling %d waiting alarms",alarm_queue.elements));
|
||||||
alarm_aborted= -1; /* mark aborted */
|
alarm_aborted= -1; /* mark aborted */
|
||||||
if (alarm_queue.elements || (alarm_thread_running && free_structures))
|
if (alarm_queue.elements || (alarm_thread_running && free_structures))
|
||||||
{
|
{
|
||||||
|
@@ -6976,20 +6976,20 @@ longlong Item_func_dyncol_exists::val_int()
|
|||||||
null_value= 1;
|
null_value= 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (my_charset_same(nm->charset(), &my_charset_utf8_general_ci))
|
if (my_charset_same(nm->charset(), DYNCOL_UTF))
|
||||||
{
|
{
|
||||||
buf.str= (char *) nm->ptr();
|
buf.str= (char *) nm->ptr();
|
||||||
buf.length= nm->length();
|
buf.length= nm->length();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint strlen= nm->length() * my_charset_utf8_general_ci.mbmaxlen + 1;
|
uint strlen= nm->length() * DYNCOL_UTF->mbmaxlen + 1;
|
||||||
uint dummy_errors;
|
uint dummy_errors;
|
||||||
buf.str= (char *) current_thd->alloc(strlen);
|
buf.str= (char *) current_thd->alloc(strlen);
|
||||||
if (buf.str)
|
if (buf.str)
|
||||||
{
|
{
|
||||||
buf.length=
|
buf.length=
|
||||||
copy_and_convert(buf.str, strlen, &my_charset_utf8_general_ci,
|
copy_and_convert(buf.str, strlen, DYNCOL_UTF,
|
||||||
nm->ptr(), nm->length(), nm->charset(),
|
nm->ptr(), nm->length(), nm->charset(),
|
||||||
&dummy_errors);
|
&dummy_errors);
|
||||||
}
|
}
|
||||||
|
@@ -2834,6 +2834,20 @@ String *Item_func_make_set::val_str(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_char::print(String *str, enum_query_type query_type)
|
||||||
|
{
|
||||||
|
str->append(Item_func_char::func_name());
|
||||||
|
str->append('(');
|
||||||
|
print_args(str, 0, query_type);
|
||||||
|
if (collation.collation != &my_charset_bin)
|
||||||
|
{
|
||||||
|
str->append(C_STRING_WITH_LEN(" using "));
|
||||||
|
str->append(collation.collation->csname);
|
||||||
|
}
|
||||||
|
str->append(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String *Item_func_char::val_str(String *str)
|
String *Item_func_char::val_str(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
@@ -4412,20 +4426,19 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg)
|
|||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
// guaranty UTF-8 string for names
|
// guaranty UTF-8 string for names
|
||||||
if (my_charset_same(res->charset(), &my_charset_utf8_general_ci))
|
if (my_charset_same(res->charset(), DYNCOL_UTF))
|
||||||
{
|
{
|
||||||
keys_str[i].length= res->length();
|
keys_str[i].length= res->length();
|
||||||
keys_str[i].str= thd->strmake(res->ptr(), res->length());
|
keys_str[i].str= thd->strmake(res->ptr(), res->length());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint strlen= res->length() * my_charset_utf8_general_ci.mbmaxlen + 1;
|
uint strlen= res->length() * DYNCOL_UTF->mbmaxlen + 1;
|
||||||
uint dummy_errors;
|
uint dummy_errors;
|
||||||
char *str= (char *) thd->alloc(strlen);
|
if (char *str= (char *) thd->alloc(strlen))
|
||||||
if (str)
|
|
||||||
{
|
{
|
||||||
keys_str[i].length=
|
keys_str[i].length=
|
||||||
copy_and_convert(str, strlen, &my_charset_utf8_general_ci,
|
copy_and_convert(str, strlen, DYNCOL_UTF,
|
||||||
res->ptr(), res->length(), res->charset(),
|
res->ptr(), res->length(), res->charset(),
|
||||||
&dummy_errors);
|
&dummy_errors);
|
||||||
keys_str[i].str= str;
|
keys_str[i].str= str;
|
||||||
@@ -4645,9 +4658,10 @@ String *Item_func_dyncol_json::val_str(String *str)
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
size_t length, alloc_length;
|
size_t length, alloc_length;
|
||||||
dynstr_reassociate(&json, &ptr, &length, &alloc_length);
|
dynstr_reassociate(&json, &ptr, &length, &alloc_length);
|
||||||
str->reset(ptr, length, alloc_length, &my_charset_utf8_general_ci);
|
str->reset(ptr, length, alloc_length, DYNCOL_UTF);
|
||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
}
|
}
|
||||||
|
str->set_charset(DYNCOL_UTF);
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
null:
|
null:
|
||||||
@@ -4747,20 +4761,20 @@ bool Item_dyncol_get::get_dyn_value(THD *thd, DYNAMIC_COLUMN_VALUE *val,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (my_charset_same(nm->charset(), &my_charset_utf8_general_ci))
|
if (my_charset_same(nm->charset(), DYNCOL_UTF))
|
||||||
{
|
{
|
||||||
buf.str= (char *) nm->ptr();
|
buf.str= (char *) nm->ptr();
|
||||||
buf.length= nm->length();
|
buf.length= nm->length();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint strlen= nm->length() * my_charset_utf8_general_ci.mbmaxlen + 1;
|
uint strlen= nm->length() * DYNCOL_UTF->mbmaxlen + 1;
|
||||||
uint dummy_errors;
|
uint dummy_errors;
|
||||||
buf.str= (char *) thd->alloc(strlen);
|
buf.str= (char *) thd->alloc(strlen);
|
||||||
if (buf.str)
|
if (buf.str)
|
||||||
{
|
{
|
||||||
buf.length=
|
buf.length=
|
||||||
copy_and_convert(buf.str, strlen, &my_charset_utf8_general_ci,
|
copy_and_convert(buf.str, strlen, DYNCOL_UTF,
|
||||||
nm->ptr(), nm->length(), nm->charset(),
|
nm->ptr(), nm->length(), nm->charset(),
|
||||||
&dummy_errors);
|
&dummy_errors);
|
||||||
}
|
}
|
||||||
@@ -5184,7 +5198,6 @@ String *Item_func_dyncol_list::val_str(String *str)
|
|||||||
goto null;
|
goto null;
|
||||||
|
|
||||||
str->length(0);
|
str->length(0);
|
||||||
str->set_charset(&my_charset_utf8_general_ci);
|
|
||||||
for (i= 0; i < count; i++)
|
for (i= 0; i < count; i++)
|
||||||
{
|
{
|
||||||
append_identifier(current_thd, str, names[i].str, names[i].length);
|
append_identifier(current_thd, str, names[i].str, names[i].length);
|
||||||
@@ -5194,6 +5207,7 @@ String *Item_func_dyncol_list::val_str(String *str)
|
|||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
if (names)
|
if (names)
|
||||||
my_free(names);
|
my_free(names);
|
||||||
|
str->set_charset(DYNCOL_UTF);
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
null:
|
null:
|
||||||
|
@@ -870,6 +870,7 @@ public:
|
|||||||
max_length= arg_count * 4;
|
max_length= arg_count * 4;
|
||||||
}
|
}
|
||||||
const char *func_name() const { return "char"; }
|
const char *func_name() const { return "char"; }
|
||||||
|
void print(String *str, enum_query_type query_type);
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_func_char>(thd, mem_root, this); }
|
{ return get_item_copy<Item_func_char>(thd, mem_root, this); }
|
||||||
};
|
};
|
||||||
@@ -1431,14 +1432,14 @@ public:
|
|||||||
class Item_func_dyncol_json: public Item_str_func
|
class Item_func_dyncol_json: public Item_str_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_dyncol_json(THD *thd, Item *str): Item_str_func(thd, str) {}
|
Item_func_dyncol_json(THD *thd, Item *str): Item_str_func(thd, str)
|
||||||
|
{collation.set(DYNCOL_UTF);}
|
||||||
const char *func_name() const{ return "column_json"; }
|
const char *func_name() const{ return "column_json"; }
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec()
|
||||||
{
|
{
|
||||||
max_length= MAX_BLOB_WIDTH;
|
max_length= MAX_BLOB_WIDTH;
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
collation.set(&my_charset_bin);
|
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
}
|
}
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
@@ -1491,7 +1492,8 @@ public:
|
|||||||
class Item_func_dyncol_list: public Item_str_func
|
class Item_func_dyncol_list: public Item_str_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_dyncol_list(THD *thd, Item *str): Item_str_func(thd, str) {};
|
Item_func_dyncol_list(THD *thd, Item *str): Item_str_func(thd, str)
|
||||||
|
{collation.set(DYNCOL_UTF);}
|
||||||
void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; };
|
void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; };
|
||||||
const char *func_name() const{ return "column_list"; }
|
const char *func_name() const{ return "column_list"; }
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
|
@@ -3866,8 +3866,7 @@ innobase_init(
|
|||||||
/* Currently, Galera does not support VATS lock schedule algorithm. */
|
/* Currently, Galera does not support VATS lock schedule algorithm. */
|
||||||
if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
|
if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
|
||||||
&& global_system_variables.wsrep_on) {
|
&& global_system_variables.wsrep_on) {
|
||||||
ib::info() << "In Galera environment Variance-Aware-Transaction-Sheduling Algorithm"
|
ib::info() << "For Galera, using innodb_lock_schedule_algorithm=fcfs";
|
||||||
" is not supported. Falling back to First-Come-First-Served order. ";
|
|
||||||
innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS;
|
innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS;
|
||||||
}
|
}
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
@@ -380,9 +380,6 @@ struct que_thr_t{
|
|||||||
UT_LIST_NODE_T(que_thr_t)
|
UT_LIST_NODE_T(que_thr_t)
|
||||||
thrs; /*!< list of thread nodes of the fork
|
thrs; /*!< list of thread nodes of the fork
|
||||||
node */
|
node */
|
||||||
UT_LIST_NODE_T(que_thr_t)
|
|
||||||
trx_thrs; /*!< lists of threads in wait list of
|
|
||||||
the trx */
|
|
||||||
UT_LIST_NODE_T(que_thr_t)
|
UT_LIST_NODE_T(que_thr_t)
|
||||||
queue; /*!< list of runnable thread nodes in
|
queue; /*!< list of runnable thread nodes in
|
||||||
the server task queue */
|
the server task queue */
|
||||||
|
@@ -33,7 +33,8 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
#include "mtr0mtr.h"
|
#include "mtr0mtr.h"
|
||||||
#include "trx0sys.h"
|
#include "trx0sys.h"
|
||||||
|
|
||||||
extern bool trx_rollback_or_clean_is_active;
|
extern bool trx_rollback_or_clean_is_active;
|
||||||
|
extern const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Determines if this transaction is rolling back an incomplete transaction
|
Determines if this transaction is rolling back an incomplete transaction
|
||||||
@@ -62,6 +63,10 @@ trx_undo_rec_t*
|
|||||||
trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap)
|
trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap)
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
|
|
||||||
|
/** Report progress when rolling back a row of a recovered transaction.
|
||||||
|
@return whether the rollback should be aborted due to pending shutdown */
|
||||||
|
bool
|
||||||
|
trx_roll_must_shutdown();
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Rollback or clean up any incomplete transactions which were
|
Rollback or clean up any incomplete transactions which were
|
||||||
encountered in crash recovery. If the transaction already was
|
encountered in crash recovery. If the transaction already was
|
||||||
|
@@ -1178,7 +1178,16 @@ close_table:
|
|||||||
if (!row_undo_search_clust_to_pcur(node)) {
|
if (!row_undo_search_clust_to_pcur(node)) {
|
||||||
/* As long as this rolling-back transaction exists,
|
/* As long as this rolling-back transaction exists,
|
||||||
the PRIMARY KEY value pointed to by the undo log
|
the PRIMARY KEY value pointed to by the undo log
|
||||||
record must exist. But, it is possible that the record
|
record should exist.
|
||||||
|
|
||||||
|
However, if InnoDB is killed during a rollback, or
|
||||||
|
shut down during the rollback of recovered
|
||||||
|
transactions, then after restart we may try to roll
|
||||||
|
back some of the same undo log records again, because
|
||||||
|
trx_roll_try_truncate() is not being invoked after
|
||||||
|
every undo log record.
|
||||||
|
|
||||||
|
It is also possible that the record
|
||||||
was not modified yet (the DB_ROLL_PTR does not match
|
was not modified yet (the DB_ROLL_PTR does not match
|
||||||
node->roll_ptr) and thus there is nothing to roll back.
|
node->roll_ptr) and thus there is nothing to roll back.
|
||||||
|
|
||||||
@@ -1186,8 +1195,11 @@ close_table:
|
|||||||
record after successfully acquiring an exclusive lock
|
record after successfully acquiring an exclusive lock
|
||||||
on the the clustered index record. That lock will not
|
on the the clustered index record. That lock will not
|
||||||
be released before the transaction is committed or
|
be released before the transaction is committed or
|
||||||
fully rolled back. */
|
fully rolled back. (Exception: if the server was
|
||||||
ut_ad(node->pcur.btr_cur.low_match == node->ref->n_fields);
|
killed, restarted, and shut down again before the
|
||||||
|
rollback of the recovered transaction was completed,
|
||||||
|
it is possible that the transaction was partially
|
||||||
|
rolled back and locks released.) */
|
||||||
goto close_table;
|
goto close_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@@ -339,6 +340,13 @@ row_undo_step(
|
|||||||
|
|
||||||
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(trx == trx_roll_crash_recv_trx)
|
||||||
|
&& trx_roll_must_shutdown()) {
|
||||||
|
/* Shutdown has been initiated. */
|
||||||
|
trx->error_state = DB_INTERRUPTED;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
err = row_undo(node, thr);
|
err = row_undo(node, thr);
|
||||||
|
|
||||||
trx->error_state = err;
|
trx->error_state = err;
|
||||||
|
@@ -2633,8 +2633,6 @@ files_checked:
|
|||||||
trx_temp_rseg_create();
|
trx_temp_rseg_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_is_being_started = false;
|
|
||||||
|
|
||||||
ut_a(trx_purge_state() == PURGE_STATE_INIT);
|
ut_a(trx_purge_state() == PURGE_STATE_INIT);
|
||||||
|
|
||||||
/* Create the master thread which does purge and other utility
|
/* Create the master thread which does purge and other utility
|
||||||
@@ -2683,6 +2681,8 @@ files_checked:
|
|||||||
purge_sys->state = PURGE_STATE_DISABLED;
|
purge_sys->state = PURGE_STATE_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srv_is_being_started = false;
|
||||||
|
|
||||||
if (!srv_read_only_mode) {
|
if (!srv_read_only_mode) {
|
||||||
/* wake main loop of page cleaner up */
|
/* wake main loop of page cleaner up */
|
||||||
os_event_set(buf_flush_event);
|
os_event_set(buf_flush_event);
|
||||||
|
@@ -24,8 +24,10 @@ Transaction rollback
|
|||||||
Created 3/26/1996 Heikki Tuuri
|
Created 3/26/1996 Heikki Tuuri
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
#include "ha_prototypes.h"
|
#include "my_config.h"
|
||||||
|
#include <my_systemd.h>
|
||||||
|
|
||||||
|
#include "ha_prototypes.h"
|
||||||
#include "trx0roll.h"
|
#include "trx0roll.h"
|
||||||
|
|
||||||
#include <mysql/service_wsrep.h>
|
#include <mysql/service_wsrep.h>
|
||||||
@@ -56,14 +58,7 @@ static const ulint TRX_ROLL_TRUNC_THRESHOLD = 1;
|
|||||||
bool trx_rollback_or_clean_is_active;
|
bool trx_rollback_or_clean_is_active;
|
||||||
|
|
||||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/** In crash recovery we set this to the undo n:o of the current trx to be
|
|
||||||
rolled back. Then we can print how many % the rollback has progressed. */
|
|
||||||
static undo_no_t trx_roll_max_undo_no;
|
|
||||||
|
|
||||||
/** Auxiliary variable which tells the previous progress % we printed */
|
|
||||||
static ulint trx_roll_progress_printed_pct;
|
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
Finishes a transaction rollback. */
|
Finishes a transaction rollback. */
|
||||||
@@ -631,8 +626,6 @@ trx_rollback_active(
|
|||||||
que_thr_t* thr;
|
que_thr_t* thr;
|
||||||
roll_node_t* roll_node;
|
roll_node_t* roll_node;
|
||||||
dict_table_t* table;
|
dict_table_t* table;
|
||||||
int64_t rows_to_undo;
|
|
||||||
const char* unit = "";
|
|
||||||
ibool dictionary_locked = FALSE;
|
ibool dictionary_locked = FALSE;
|
||||||
|
|
||||||
heap = mem_heap_create(512);
|
heap = mem_heap_create(512);
|
||||||
@@ -651,28 +644,8 @@ trx_rollback_active(
|
|||||||
|
|
||||||
ut_a(thr == que_fork_start_command(fork));
|
ut_a(thr == que_fork_start_command(fork));
|
||||||
|
|
||||||
trx_sys_mutex_enter();
|
|
||||||
|
|
||||||
trx_roll_crash_recv_trx = trx;
|
trx_roll_crash_recv_trx = trx;
|
||||||
|
|
||||||
trx_roll_max_undo_no = trx->undo_no;
|
|
||||||
|
|
||||||
trx_roll_progress_printed_pct = 0;
|
|
||||||
|
|
||||||
rows_to_undo = trx_roll_max_undo_no;
|
|
||||||
|
|
||||||
trx_sys_mutex_exit();
|
|
||||||
|
|
||||||
if (rows_to_undo > 1000000000) {
|
|
||||||
rows_to_undo = rows_to_undo / 1000000;
|
|
||||||
unit = "M";
|
|
||||||
}
|
|
||||||
|
|
||||||
const trx_id_t trx_id = trx_get_id_for_print(trx);
|
|
||||||
|
|
||||||
ib::info() << "Rolling back trx with id " << trx_id << ", "
|
|
||||||
<< rows_to_undo << unit << " rows to undo";
|
|
||||||
|
|
||||||
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
||||||
row_mysql_lock_data_dictionary(trx);
|
row_mysql_lock_data_dictionary(trx);
|
||||||
dictionary_locked = TRUE;
|
dictionary_locked = TRUE;
|
||||||
@@ -683,6 +656,17 @@ trx_rollback_active(
|
|||||||
|
|
||||||
que_run_threads(roll_node->undo_thr);
|
que_run_threads(roll_node->undo_thr);
|
||||||
|
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_is_being_started);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
ut_ad(!dictionary_locked);
|
||||||
|
que_graph_free(static_cast<que_t*>(
|
||||||
|
roll_node->undo_thr->common.parent));
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
||||||
|
|
||||||
/* Free the memory reserved by the undo graph */
|
/* Free the memory reserved by the undo graph */
|
||||||
@@ -714,11 +698,13 @@ trx_rollback_active(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func_exit:
|
||||||
if (dictionary_locked) {
|
if (dictionary_locked) {
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ib::info() << "Rollback of trx with id " << trx_id << " completed";
|
ib::info() << "Rollback of trx with id " << ib::hex(trx->id)
|
||||||
|
<< " completed";
|
||||||
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
@@ -736,7 +722,7 @@ ibool
|
|||||||
trx_rollback_resurrected(
|
trx_rollback_resurrected(
|
||||||
/*=====================*/
|
/*=====================*/
|
||||||
trx_t* trx, /*!< in: transaction to rollback or clean */
|
trx_t* trx, /*!< in: transaction to rollback or clean */
|
||||||
ibool all) /*!< in: FALSE=roll back dictionary transactions;
|
ibool* all) /*!< in/out: FALSE=roll back dictionary transactions;
|
||||||
TRUE=roll back all non-PREPARED transactions */
|
TRUE=roll back all non-PREPARED transactions */
|
||||||
{
|
{
|
||||||
ut_ad(trx_sys_mutex_own());
|
ut_ad(trx_sys_mutex_own());
|
||||||
@@ -747,40 +733,102 @@ trx_rollback_resurrected(
|
|||||||
to accidentally clean up a non-recovered transaction here. */
|
to accidentally clean up a non-recovered transaction here. */
|
||||||
|
|
||||||
trx_mutex_enter(trx);
|
trx_mutex_enter(trx);
|
||||||
bool is_recovered = trx->is_recovered;
|
if (!trx->is_recovered) {
|
||||||
trx_state_t state = trx->state;
|
func_exit:
|
||||||
trx_mutex_exit(trx);
|
trx_mutex_exit(trx);
|
||||||
|
|
||||||
if (!is_recovered) {
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (trx->state) {
|
||||||
case TRX_STATE_COMMITTED_IN_MEMORY:
|
case TRX_STATE_COMMITTED_IN_MEMORY:
|
||||||
|
trx_mutex_exit(trx);
|
||||||
trx_sys_mutex_exit();
|
trx_sys_mutex_exit();
|
||||||
ib::info() << "Cleaning up trx with id "
|
ib::info() << "Cleaning up trx with id " << ib::hex(trx->id);
|
||||||
<< trx_get_id_for_print(trx);
|
|
||||||
|
|
||||||
trx_cleanup_at_db_startup(trx);
|
trx_cleanup_at_db_startup(trx);
|
||||||
trx_free_resurrected(trx);
|
trx_free_resurrected(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
case TRX_STATE_ACTIVE:
|
case TRX_STATE_ACTIVE:
|
||||||
if (all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
if (!srv_is_being_started
|
||||||
|
&& !srv_undo_sources && srv_fast_shutdown) {
|
||||||
|
fake_prepared:
|
||||||
|
trx->state = TRX_STATE_PREPARED;
|
||||||
|
trx_sys->n_prepared_trx++;
|
||||||
|
trx_sys->n_prepared_recovered_trx++;
|
||||||
|
*all = FALSE;
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
trx_mutex_exit(trx);
|
||||||
|
|
||||||
|
if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
||||||
trx_sys_mutex_exit();
|
trx_sys_mutex_exit();
|
||||||
trx_rollback_active(trx);
|
trx_rollback_active(trx);
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
trx->error_state = DB_SUCCESS;
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
trx_mutex_enter(trx);
|
||||||
|
goto fake_prepared;
|
||||||
|
}
|
||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
case TRX_STATE_PREPARED:
|
case TRX_STATE_PREPARED:
|
||||||
return(FALSE);
|
goto func_exit;
|
||||||
case TRX_STATE_NOT_STARTED:
|
case TRX_STATE_NOT_STARTED:
|
||||||
case TRX_STATE_FORCED_ROLLBACK:
|
case TRX_STATE_FORCED_ROLLBACK:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_error;
|
ut_error;
|
||||||
return(FALSE);
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Report progress when rolling back a row of a recovered transaction.
|
||||||
|
@return whether the rollback should be aborted due to pending shutdown */
|
||||||
|
bool
|
||||||
|
trx_roll_must_shutdown()
|
||||||
|
{
|
||||||
|
const trx_t* trx = trx_roll_crash_recv_trx;
|
||||||
|
ut_ad(trx);
|
||||||
|
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
|
||||||
|
ut_ad(trx->in_rollback);
|
||||||
|
|
||||||
|
if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE
|
||||||
|
&& !srv_is_being_started
|
||||||
|
&& !srv_undo_sources && srv_fast_shutdown) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ib_time_t time = ut_time();
|
||||||
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
mutex_enter(&recv_sys->mutex);
|
||||||
|
|
||||||
|
if (recv_sys->report(time)) {
|
||||||
|
ulint n_trx = 0, n_rows = 0;
|
||||||
|
for (const trx_t* t = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
|
||||||
|
t != NULL;
|
||||||
|
t = UT_LIST_GET_NEXT(trx_list, t)) {
|
||||||
|
|
||||||
|
assert_trx_in_rw_list(t);
|
||||||
|
if (t->is_recovered
|
||||||
|
&& trx_state_eq(t, TRX_STATE_ACTIVE)) {
|
||||||
|
n_trx++;
|
||||||
|
n_rows += t->undo_no;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ib::info() << "To roll back: " << n_trx << " transactions, "
|
||||||
|
<< n_rows << " rows";
|
||||||
|
sd_notifyf(0, "STATUS=To roll back: " ULINTPF " transactions, "
|
||||||
|
ULINTPF " rows", n_trx, n_rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_exit(&recv_sys->mutex);
|
||||||
|
mutex_exit(&trx_sys->mutex);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
@@ -825,17 +873,11 @@ trx_rollback_or_clean_recovered(
|
|||||||
|
|
||||||
assert_trx_in_rw_list(trx);
|
assert_trx_in_rw_list(trx);
|
||||||
|
|
||||||
if (srv_shutdown_state != SRV_SHUTDOWN_NONE
|
|
||||||
&& srv_fast_shutdown != 0) {
|
|
||||||
all = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this function does a cleanup or rollback
|
/* If this function does a cleanup or rollback
|
||||||
then it will release the trx_sys->mutex, therefore
|
then it will release the trx_sys->mutex, therefore
|
||||||
we need to reacquire it before retrying the loop. */
|
we need to reacquire it before retrying the loop. */
|
||||||
|
|
||||||
if (trx_rollback_resurrected(trx, all)) {
|
if (trx_rollback_resurrected(trx, &all)) {
|
||||||
|
|
||||||
trx_sys_mutex_enter();
|
trx_sys_mutex_enter();
|
||||||
|
|
||||||
@@ -1042,27 +1084,6 @@ trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap)
|
|||||||
ut_ad(trx_roll_check_undo_rec_ordering(
|
ut_ad(trx_roll_check_undo_rec_ordering(
|
||||||
undo_no, undo->rseg->space, trx));
|
undo_no, undo->rseg->space, trx));
|
||||||
|
|
||||||
/* We print rollback progress info if we are in a crash recovery
|
|
||||||
and the transaction has at least 1000 row operations to undo. */
|
|
||||||
|
|
||||||
if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
|
|
||||||
|
|
||||||
ulint progress_pct = 100 - (ulint)
|
|
||||||
((undo_no * 100) / trx_roll_max_undo_no);
|
|
||||||
if (progress_pct != trx_roll_progress_printed_pct) {
|
|
||||||
if (trx_roll_progress_printed_pct == 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"\nInnoDB: Progress in percents:"
|
|
||||||
" %lu", (ulong) progress_pct);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
" %lu", (ulong) progress_pct);
|
|
||||||
}
|
|
||||||
fflush(stderr);
|
|
||||||
trx_roll_progress_printed_pct = progress_pct;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trx->undo_no = undo_no;
|
trx->undo_no = undo_no;
|
||||||
trx->undo_rseg_space = undo->rseg->space;
|
trx->undo_rseg_space = undo->rseg->space;
|
||||||
mutex_exit(&trx->undo_mutex);
|
mutex_exit(&trx->undo_mutex);
|
||||||
|
@@ -1826,10 +1826,14 @@ trx_undo_free_prepared(
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case TRX_UNDO_ACTIVE:
|
case TRX_UNDO_ACTIVE:
|
||||||
/* lock_trx_release_locks() assigns
|
/* lock_trx_release_locks() assigns
|
||||||
trx->is_recovered=false */
|
trx->is_recovered=false and
|
||||||
|
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
|
||||||
|
also for transactions that we faked
|
||||||
|
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
|
||||||
ut_a(!srv_was_started
|
ut_a(!srv_was_started
|
||||||
|| srv_read_only_mode
|
|| srv_read_only_mode
|
||||||
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
|
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
|
||||||
|
|| srv_fast_shutdown);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ut_error;
|
ut_error;
|
||||||
@@ -1854,10 +1858,14 @@ trx_undo_free_prepared(
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case TRX_UNDO_ACTIVE:
|
case TRX_UNDO_ACTIVE:
|
||||||
/* lock_trx_release_locks() assigns
|
/* lock_trx_release_locks() assigns
|
||||||
trx->is_recovered=false */
|
trx->is_recovered=false and
|
||||||
|
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
|
||||||
|
also for transactions that we faked
|
||||||
|
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
|
||||||
ut_a(!srv_was_started
|
ut_a(!srv_was_started
|
||||||
|| srv_read_only_mode
|
|| srv_read_only_mode
|
||||||
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
|
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
|
||||||
|
|| srv_fast_shutdown);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ut_error;
|
ut_error;
|
||||||
|
@@ -6342,7 +6342,6 @@ my_bool translog_write_record(LSN *lsn,
|
|||||||
short_trid, &parts, trn, hook_arg);
|
short_trid, &parts, trn, hook_arg);
|
||||||
break;
|
break;
|
||||||
case LOGRECTYPE_NOT_ALLOWED:
|
case LOGRECTYPE_NOT_ALLOWED:
|
||||||
DBUG_ASSERT(0);
|
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
rc= 1;
|
rc= 1;
|
||||||
|
@@ -226,7 +226,6 @@ master-bin.000001 # Xid # # COMMIT /* XID */
|
|||||||
master-bin.000001 # Rotate # # master-bin.000002;pos=POS
|
master-bin.000001 # Rotate # # master-bin.000002;pos=POS
|
||||||
include/show_binlog_events.inc
|
include/show_binlog_events.inc
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000002 # Binlog_checkpoint # # master-bin.000002
|
|
||||||
master-bin.000002 # Gtid # # GTID #-#-#
|
master-bin.000002 # Gtid # # GTID #-#-#
|
||||||
master-bin.000002 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
|
master-bin.000002 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
|
||||||
master-bin.000002 # Gtid # # GTID #-#-#
|
master-bin.000002 # Gtid # # GTID #-#-#
|
||||||
@@ -268,7 +267,6 @@ slave-bin.000001 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
|
|||||||
slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS
|
slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS
|
||||||
include/show_binlog_events.inc
|
include/show_binlog_events.inc
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
|
|
||||||
slave-bin.000002 # Gtid # # GTID #-#-#
|
slave-bin.000002 # Gtid # # GTID #-#-#
|
||||||
slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
|
slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
|
||||||
slave-bin.000002 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000002 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
@@ -222,7 +222,6 @@ master-bin.000001 # Xid # # COMMIT /* XID */
|
|||||||
master-bin.000001 # Rotate # # master-bin.000002;pos=POS
|
master-bin.000001 # Rotate # # master-bin.000002;pos=POS
|
||||||
include/show_binlog_events.inc
|
include/show_binlog_events.inc
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000002 # Binlog_checkpoint # # master-bin.000002
|
|
||||||
master-bin.000002 # Gtid # # GTID #-#-#
|
master-bin.000002 # Gtid # # GTID #-#-#
|
||||||
master-bin.000002 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
|
master-bin.000002 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
|
||||||
master-bin.000002 # Gtid # # GTID #-#-#
|
master-bin.000002 # Gtid # # GTID #-#-#
|
||||||
@@ -260,7 +259,6 @@ slave-bin.000001 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
|
|||||||
slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS
|
slave-bin.000001 # Rotate # # slave-bin.000002;pos=POS
|
||||||
include/show_binlog_events.inc
|
include/show_binlog_events.inc
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
|
|
||||||
slave-bin.000002 # Gtid # # GTID #-#-#
|
slave-bin.000002 # Gtid # # GTID #-#-#
|
||||||
slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
|
slave-bin.000002 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
|
||||||
slave-bin.000002 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000002 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
@@ -3903,6 +3903,17 @@ innobase_init(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/* Currently, Galera does not support VATS lock schedule algorithm. */
|
||||||
|
if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
|
||||||
|
&& global_system_variables.wsrep_on) {
|
||||||
|
/* Do not allow InnoDB startup with VATS and Galera */
|
||||||
|
sql_print_error("In Galera, innodb_lock_schedule_algorithm=vats"
|
||||||
|
" is not supported.");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
#ifndef HAVE_LZ4
|
#ifndef HAVE_LZ4
|
||||||
if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) {
|
if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) {
|
||||||
sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n"
|
sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n"
|
||||||
@@ -5454,8 +5465,8 @@ innobase_kill_connection(
|
|||||||
wsrep_thd_is_BF(current_thd, FALSE),
|
wsrep_thd_is_BF(current_thd, FALSE),
|
||||||
lock_get_info(trx->lock.wait_lock).c_str());
|
lock_get_info(trx->lock.wait_lock).c_str());
|
||||||
|
|
||||||
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
|
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)
|
||||||
trx->abort_type == TRX_SERVER_ABORT) {
|
&& trx->abort_type == TRX_SERVER_ABORT) {
|
||||||
ut_ad(!lock_mutex_own());
|
ut_ad(!lock_mutex_own());
|
||||||
lock_mutex_enter();
|
lock_mutex_enter();
|
||||||
}
|
}
|
||||||
@@ -20463,7 +20474,7 @@ static MYSQL_SYSVAR_ENUM(empty_free_list_algorithm,
|
|||||||
&innodb_empty_free_list_algorithm_typelib);
|
&innodb_empty_free_list_algorithm_typelib);
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm,
|
static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm,
|
||||||
PLUGIN_VAR_RQCMDARG,
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
"The algorithm Innodb uses for deciding which locks to grant next when"
|
"The algorithm Innodb uses for deciding which locks to grant next when"
|
||||||
" a lock is released. Possible values are"
|
" a lock is released. Possible values are"
|
||||||
" FCFS"
|
" FCFS"
|
||||||
|
@@ -384,9 +384,6 @@ struct que_thr_t{
|
|||||||
UT_LIST_NODE_T(que_thr_t)
|
UT_LIST_NODE_T(que_thr_t)
|
||||||
thrs; /*!< list of thread nodes of the fork
|
thrs; /*!< list of thread nodes of the fork
|
||||||
node */
|
node */
|
||||||
UT_LIST_NODE_T(que_thr_t)
|
|
||||||
trx_thrs; /*!< lists of threads in wait list of
|
|
||||||
the trx */
|
|
||||||
UT_LIST_NODE_T(que_thr_t)
|
UT_LIST_NODE_T(que_thr_t)
|
||||||
queue; /*!< list of runnable thread nodes in
|
queue; /*!< list of runnable thread nodes in
|
||||||
the server task queue */
|
the server task queue */
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@@ -33,7 +34,8 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
#include "mtr0mtr.h"
|
#include "mtr0mtr.h"
|
||||||
#include "trx0sys.h"
|
#include "trx0sys.h"
|
||||||
|
|
||||||
extern bool trx_rollback_or_clean_is_active;
|
extern bool trx_rollback_or_clean_is_active;
|
||||||
|
extern const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Determines if this transaction is rolling back an incomplete transaction
|
Determines if this transaction is rolling back an incomplete transaction
|
||||||
@@ -104,6 +106,11 @@ trx_undo_rec_release(
|
|||||||
/*=================*/
|
/*=================*/
|
||||||
trx_t* trx, /*!< in/out: transaction */
|
trx_t* trx, /*!< in/out: transaction */
|
||||||
undo_no_t undo_no);/*!< in: undo number */
|
undo_no_t undo_no);/*!< in: undo number */
|
||||||
|
/** Report progress when rolling back a row of a recovered transaction.
|
||||||
|
@return whether the rollback should be aborted due to pending shutdown */
|
||||||
|
UNIV_INTERN
|
||||||
|
bool
|
||||||
|
trx_roll_must_shutdown();
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Rollback or clean up any incomplete transactions which were
|
Rollback or clean up any incomplete transactions which were
|
||||||
encountered in crash recovery. If the transaction already was
|
encountered in crash recovery. If the transaction already was
|
||||||
|
@@ -937,14 +937,21 @@ lock_reset_lock_and_trx_wait(
|
|||||||
|
|
||||||
ib_logf(IB_LOG_LEVEL_INFO,
|
ib_logf(IB_LOG_LEVEL_INFO,
|
||||||
"Trx id " TRX_ID_FMT
|
"Trx id " TRX_ID_FMT
|
||||||
" is waiting a lock in statement %s"
|
" is waiting a lock "
|
||||||
" for this trx id " TRX_ID_FMT
|
" for this trx id " TRX_ID_FMT
|
||||||
" and statement %s wait_lock %p",
|
" wait_lock %p",
|
||||||
lock->trx->id,
|
lock->trx->id,
|
||||||
stmt ? stmt : "NULL",
|
|
||||||
trx_id,
|
trx_id,
|
||||||
stmt2 ? stmt2 : "NULL",
|
|
||||||
lock->trx->lock.wait_lock);
|
lock->trx->lock.wait_lock);
|
||||||
|
|
||||||
|
if (stmt) {
|
||||||
|
ib_logf(IB_LOG_LEVEL_INFO, " SQL1: %s\n", stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stmt2) {
|
||||||
|
ib_logf(IB_LOG_LEVEL_INFO, " SQL2: %s\n", stmt2);
|
||||||
|
}
|
||||||
|
|
||||||
ut_ad(lock->trx->lock.wait_lock == lock);
|
ut_ad(lock->trx->lock.wait_lock == lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1162,7 +1169,7 @@ lock_rec_has_to_wait(
|
|||||||
type_mode, lock_is_on_supremum);
|
type_mode, lock_is_on_supremum);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"conflicts states: my %d locked %d\n",
|
"conflicts states: my %d locked %d\n",
|
||||||
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
|
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
|
||||||
wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) );
|
wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) );
|
||||||
lock_rec_print(stderr, lock2);
|
lock_rec_print(stderr, lock2);
|
||||||
if (for_locking) return FALSE;
|
if (for_locking) return FALSE;
|
||||||
@@ -1714,7 +1721,7 @@ lock_rec_other_has_expl_req(
|
|||||||
ulint heap_no,/*!< in: heap number of the record */
|
ulint heap_no,/*!< in: heap number of the record */
|
||||||
trx_id_t trx_id) /*!< in: transaction */
|
trx_id_t trx_id) /*!< in: transaction */
|
||||||
{
|
{
|
||||||
const lock_t* lock;
|
lock_t* lock;
|
||||||
|
|
||||||
ut_ad(lock_mutex_own());
|
ut_ad(lock_mutex_own());
|
||||||
ut_ad(mode == LOCK_X || mode == LOCK_S);
|
ut_ad(mode == LOCK_X || mode == LOCK_S);
|
||||||
@@ -1723,7 +1730,7 @@ lock_rec_other_has_expl_req(
|
|||||||
|
|
||||||
for (lock = lock_rec_get_first(block, heap_no);
|
for (lock = lock_rec_get_first(block, heap_no);
|
||||||
lock != NULL;
|
lock != NULL;
|
||||||
lock = lock_rec_get_next_const(heap_no, lock)) {
|
lock = lock_rec_get_next(heap_no, lock)) {
|
||||||
|
|
||||||
if (lock->trx->id != trx_id
|
if (lock->trx->id != trx_id
|
||||||
&& (gap
|
&& (gap
|
||||||
@@ -1810,7 +1817,7 @@ Checks if some other transaction has a conflicting explicit lock request
|
|||||||
in the queue, so that we have to wait.
|
in the queue, so that we have to wait.
|
||||||
@return lock or NULL */
|
@return lock or NULL */
|
||||||
static
|
static
|
||||||
const lock_t*
|
lock_t*
|
||||||
lock_rec_other_has_conflicting(
|
lock_rec_other_has_conflicting(
|
||||||
/*===========================*/
|
/*===========================*/
|
||||||
enum lock_mode mode, /*!< in: LOCK_S or LOCK_X,
|
enum lock_mode mode, /*!< in: LOCK_S or LOCK_X,
|
||||||
@@ -1822,7 +1829,7 @@ lock_rec_other_has_conflicting(
|
|||||||
ulint heap_no,/*!< in: heap number of the record */
|
ulint heap_no,/*!< in: heap number of the record */
|
||||||
const trx_t* trx) /*!< in: our transaction */
|
const trx_t* trx) /*!< in: our transaction */
|
||||||
{
|
{
|
||||||
const lock_t* lock;
|
lock_t* lock;
|
||||||
ibool is_supremum;
|
ibool is_supremum;
|
||||||
|
|
||||||
ut_ad(lock_mutex_own());
|
ut_ad(lock_mutex_own());
|
||||||
@@ -1831,13 +1838,16 @@ lock_rec_other_has_conflicting(
|
|||||||
|
|
||||||
for (lock = lock_rec_get_first(block, heap_no);
|
for (lock = lock_rec_get_first(block, heap_no);
|
||||||
lock != NULL;
|
lock != NULL;
|
||||||
lock = lock_rec_get_next_const(heap_no, lock)) {
|
lock = lock_rec_get_next(heap_no, lock)) {
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (lock_rec_has_to_wait(TRUE, trx, mode, lock, is_supremum)) {
|
if (lock_rec_has_to_wait(TRUE, trx, mode, lock, is_supremum)) {
|
||||||
if (wsrep_on_trx(trx)) {
|
if (wsrep_on_trx(trx)) {
|
||||||
trx_mutex_enter(lock->trx);
|
trx_mutex_enter(lock->trx);
|
||||||
wsrep_kill_victim(trx, lock);
|
/* Below function will roll back either trx
|
||||||
|
or lock->trx depending on priority of the
|
||||||
|
transaction. */
|
||||||
|
wsrep_kill_victim(const_cast<trx_t*>(trx), lock);
|
||||||
trx_mutex_exit(lock->trx);
|
trx_mutex_exit(lock->trx);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -2045,15 +2055,17 @@ wsrep_print_wait_locks(
|
|||||||
{
|
{
|
||||||
if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) {
|
if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) {
|
||||||
fprintf(stderr, "WSREP: c_lock != wait lock\n");
|
fprintf(stderr, "WSREP: c_lock != wait lock\n");
|
||||||
if (lock_get_type_low(c_lock) & LOCK_TABLE)
|
if (lock_get_type_low(c_lock) & LOCK_TABLE) {
|
||||||
lock_table_print(stderr, c_lock);
|
lock_table_print(stderr, c_lock);
|
||||||
else
|
} else {
|
||||||
lock_rec_print(stderr, c_lock);
|
lock_rec_print(stderr, c_lock);
|
||||||
|
}
|
||||||
|
|
||||||
if (lock_get_type_low(c_lock->trx->lock.wait_lock) & LOCK_TABLE)
|
if (lock_get_type_low(c_lock->trx->lock.wait_lock) & LOCK_TABLE) {
|
||||||
lock_table_print(stderr, c_lock->trx->lock.wait_lock);
|
lock_table_print(stderr, c_lock->trx->lock.wait_lock);
|
||||||
else
|
} else {
|
||||||
lock_rec_print(stderr, c_lock->trx->lock.wait_lock);
|
lock_rec_print(stderr, c_lock->trx->lock.wait_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
@@ -2358,8 +2370,8 @@ lock_rec_create(
|
|||||||
if (wsrep_debug) {
|
if (wsrep_debug) {
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
"WSREP: c_lock canceled %llu\n",
|
"WSREP: c_lock canceled " TRX_ID_FMT "\n",
|
||||||
(ulonglong) c_lock->trx->id);
|
c_lock->trx->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* have to bail out here to avoid lock_set_lock... */
|
/* have to bail out here to avoid lock_set_lock... */
|
||||||
@@ -2551,6 +2563,16 @@ lock_rec_enqueue_waiting(
|
|||||||
err = DB_LOCK_WAIT;
|
err = DB_LOCK_WAIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
if (!lock_get_wait(lock) && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
|
||||||
|
if (wsrep_debug) {
|
||||||
|
fprintf(stderr, "WSREP: BF thread got lock granted early, ID " TRX_ID_FMT
|
||||||
|
"\n",
|
||||||
|
lock->trx->id);
|
||||||
|
}
|
||||||
|
return(DB_SUCCESS);
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
// Move it only when it does not cause a deadlock.
|
// Move it only when it does not cause a deadlock.
|
||||||
if (err != DB_DEADLOCK
|
if (err != DB_DEADLOCK
|
||||||
&& innodb_lock_schedule_algorithm
|
&& innodb_lock_schedule_algorithm
|
||||||
@@ -2981,6 +3003,15 @@ lock_rec_has_to_wait_in_queue(
|
|||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) &&
|
if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) &&
|
||||||
wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) {
|
wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) {
|
||||||
|
if (wsrep_debug) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"BF-BF lock conflict " TRX_ID_FMT
|
||||||
|
" : " TRX_ID_FMT "\n",
|
||||||
|
wait_lock->trx->id,
|
||||||
|
lock->trx->id);
|
||||||
|
lock_rec_print(stderr, wait_lock);
|
||||||
|
lock_rec_print(stderr, lock);
|
||||||
|
}
|
||||||
/* don't wait for another BF lock */
|
/* don't wait for another BF lock */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3139,7 +3170,7 @@ lock_grant_and_move_on_page(
|
|||||||
&& !lock_rec_has_to_wait_in_queue(lock)) {
|
&& !lock_rec_has_to_wait_in_queue(lock)) {
|
||||||
|
|
||||||
lock_grant(lock, false);
|
lock_grant(lock, false);
|
||||||
|
|
||||||
if (previous != NULL) {
|
if (previous != NULL) {
|
||||||
/* Move the lock to the head of the list. */
|
/* Move the lock to the head of the list. */
|
||||||
HASH_GET_NEXT(hash, previous) = HASH_GET_NEXT(hash, lock);
|
HASH_GET_NEXT(hash, previous) = HASH_GET_NEXT(hash, lock);
|
||||||
@@ -5017,8 +5048,8 @@ lock_table_create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wsrep_debug) {
|
if (wsrep_debug) {
|
||||||
fprintf(stderr, "WSREP: c_lock canceled %llu\n",
|
fprintf(stderr, "WSREP: c_lock canceled " TRX_ID_FMT "\n",
|
||||||
(ulonglong) c_lock->trx->id);
|
c_lock->trx->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c_lock) {
|
if (c_lock) {
|
||||||
@@ -5297,7 +5328,7 @@ Checks if other transactions have an incompatible mode lock request in
|
|||||||
the lock queue.
|
the lock queue.
|
||||||
@return lock or NULL */
|
@return lock or NULL */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
const lock_t*
|
lock_t*
|
||||||
lock_table_other_has_incompatible(
|
lock_table_other_has_incompatible(
|
||||||
/*==============================*/
|
/*==============================*/
|
||||||
const trx_t* trx, /*!< in: transaction, or NULL if all
|
const trx_t* trx, /*!< in: transaction, or NULL if all
|
||||||
@@ -5308,7 +5339,7 @@ lock_table_other_has_incompatible(
|
|||||||
const dict_table_t* table, /*!< in: table */
|
const dict_table_t* table, /*!< in: table */
|
||||||
enum lock_mode mode) /*!< in: lock mode */
|
enum lock_mode mode) /*!< in: lock mode */
|
||||||
{
|
{
|
||||||
const lock_t* lock;
|
lock_t* lock;
|
||||||
|
|
||||||
ut_ad(lock_mutex_own());
|
ut_ad(lock_mutex_own());
|
||||||
|
|
||||||
@@ -5361,7 +5392,7 @@ lock_table(
|
|||||||
#endif
|
#endif
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
const lock_t* wait_for;
|
lock_t* wait_for;
|
||||||
|
|
||||||
ut_ad(table != NULL);
|
ut_ad(table != NULL);
|
||||||
ut_ad(thr != NULL);
|
ut_ad(thr != NULL);
|
||||||
@@ -5412,13 +5443,13 @@ lock_table(
|
|||||||
|
|
||||||
if (wait_for != NULL) {
|
if (wait_for != NULL) {
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
err = lock_table_enqueue_waiting((ib_lock_t*)wait_for, mode | flags, table, thr);
|
err = lock_table_enqueue_waiting(wait_for, mode | flags, table, thr);
|
||||||
#else
|
#else
|
||||||
err = lock_table_enqueue_waiting(mode | flags, table, thr);
|
err = lock_table_enqueue_waiting(mode | flags, table, thr);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
lock_table_create(c_lock, table, mode | flags, trx);
|
lock_table_create(c_lock, table, mode | flags, trx);
|
||||||
#else
|
#else
|
||||||
lock_table_create(table, mode | flags, trx);
|
lock_table_create(table, mode | flags, trx);
|
||||||
#endif
|
#endif
|
||||||
@@ -7101,10 +7132,10 @@ lock_rec_insert_check_and_lock(
|
|||||||
on the successor, which produced an unnecessary deadlock. */
|
on the successor, which produced an unnecessary deadlock. */
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if ((c_lock = (ib_lock_t*)lock_rec_other_has_conflicting(
|
if ((c_lock = lock_rec_other_has_conflicting(
|
||||||
static_cast<enum lock_mode>(
|
static_cast<enum lock_mode>(
|
||||||
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
|
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
|
||||||
block, next_rec_heap_no, trx))) {
|
block, next_rec_heap_no, trx))) {
|
||||||
#else
|
#else
|
||||||
if (lock_rec_other_has_conflicting(
|
if (lock_rec_other_has_conflicting(
|
||||||
static_cast<enum lock_mode>(
|
static_cast<enum lock_mode>(
|
||||||
@@ -7117,7 +7148,7 @@ lock_rec_insert_check_and_lock(
|
|||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
err = lock_rec_enqueue_waiting(c_lock,
|
err = lock_rec_enqueue_waiting(c_lock,
|
||||||
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
|
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
|
||||||
block, next_rec_heap_no, index, thr);
|
block, next_rec_heap_no, index, thr);
|
||||||
#else
|
#else
|
||||||
err = lock_rec_enqueue_waiting(
|
err = lock_rec_enqueue_waiting(
|
||||||
|
@@ -191,22 +191,25 @@ lock_wait_table_reserve_slot(
|
|||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
check if lock timeout was for priority thread,
|
check if lock timeout was for priority thread,
|
||||||
as a side effect trigger lock monitor
|
as a side effect trigger lock monitor
|
||||||
|
@param[in] trx transaction owning the lock
|
||||||
|
@param[in] locked true if trx and lock_sys_mutex is ownd
|
||||||
@return false for regular lock timeout */
|
@return false for regular lock timeout */
|
||||||
static ibool
|
static
|
||||||
|
bool
|
||||||
wsrep_is_BF_lock_timeout(
|
wsrep_is_BF_lock_timeout(
|
||||||
/*====================*/
|
const trx_t* trx,
|
||||||
trx_t* trx) /* in: trx to check for lock priority */
|
bool locked = true)
|
||||||
{
|
{
|
||||||
if (wsrep_on_trx(trx) &&
|
if (wsrep_on_trx(trx)
|
||||||
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
|
&& wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
|
||||||
fprintf(stderr, "WSREP: BF lock wait long\n");
|
fprintf(stderr, "WSREP: BF lock wait long for trx " TRX_ID_FMT "\n", trx->id);
|
||||||
srv_print_innodb_monitor = TRUE;
|
srv_print_innodb_monitor = TRUE;
|
||||||
srv_print_innodb_lock_monitor = TRUE;
|
srv_print_innodb_lock_monitor = TRUE;
|
||||||
os_event_set(srv_monitor_event);
|
os_event_set(srv_monitor_event);
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
@@ -402,15 +405,15 @@ lock_wait_suspend_thread(
|
|||||||
if (lock_wait_timeout < 100000000
|
if (lock_wait_timeout < 100000000
|
||||||
&& wait_time > (double) lock_wait_timeout) {
|
&& wait_time > (double) lock_wait_timeout) {
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (!wsrep_on_trx(trx) ||
|
if (!wsrep_on_trx(trx) ||
|
||||||
(!wsrep_is_BF_lock_timeout(trx) &&
|
(!wsrep_is_BF_lock_timeout(trx) &&
|
||||||
trx->error_state != DB_DEADLOCK)) {
|
trx->error_state != DB_DEADLOCK)) {
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
|
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
}
|
}
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
MONITOR_INC(MONITOR_TIMEOUT);
|
MONITOR_INC(MONITOR_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@@ -348,6 +349,13 @@ row_undo_step(
|
|||||||
|
|
||||||
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(trx == trx_roll_crash_recv_trx)
|
||||||
|
&& trx_roll_must_shutdown()) {
|
||||||
|
/* Shutdown has been initiated. */
|
||||||
|
trx->error_state = DB_INTERRUPTED;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
err = row_undo(node, thr);
|
err = row_undo(node, thr);
|
||||||
|
|
||||||
trx->error_state = err;
|
trx->error_state = err;
|
||||||
|
@@ -24,6 +24,9 @@ Transaction rollback
|
|||||||
Created 3/26/1996 Heikki Tuuri
|
Created 3/26/1996 Heikki Tuuri
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
|
#include "my_config.h"
|
||||||
|
#include <my_systemd.h>
|
||||||
|
|
||||||
#include "trx0roll.h"
|
#include "trx0roll.h"
|
||||||
|
|
||||||
#ifdef UNIV_NONINL
|
#ifdef UNIV_NONINL
|
||||||
@@ -60,14 +63,7 @@ rollback */
|
|||||||
bool trx_rollback_or_clean_is_active;
|
bool trx_rollback_or_clean_is_active;
|
||||||
|
|
||||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/** In crash recovery we set this to the undo n:o of the current trx to be
|
|
||||||
rolled back. Then we can print how many % the rollback has progressed. */
|
|
||||||
static undo_no_t trx_roll_max_undo_no;
|
|
||||||
|
|
||||||
/** Auxiliary variable which tells the previous progress % we printed */
|
|
||||||
static ulint trx_roll_progress_printed_pct;
|
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
Finishes a transaction rollback. */
|
Finishes a transaction rollback. */
|
||||||
@@ -564,8 +560,6 @@ trx_rollback_active(
|
|||||||
que_thr_t* thr;
|
que_thr_t* thr;
|
||||||
roll_node_t* roll_node;
|
roll_node_t* roll_node;
|
||||||
dict_table_t* table;
|
dict_table_t* table;
|
||||||
ib_int64_t rows_to_undo;
|
|
||||||
const char* unit = "";
|
|
||||||
ibool dictionary_locked = FALSE;
|
ibool dictionary_locked = FALSE;
|
||||||
|
|
||||||
heap = mem_heap_create(512);
|
heap = mem_heap_create(512);
|
||||||
@@ -584,30 +578,8 @@ trx_rollback_active(
|
|||||||
|
|
||||||
ut_a(thr == que_fork_start_command(fork));
|
ut_a(thr == que_fork_start_command(fork));
|
||||||
|
|
||||||
mutex_enter(&trx_sys->mutex);
|
|
||||||
|
|
||||||
trx_roll_crash_recv_trx = trx;
|
trx_roll_crash_recv_trx = trx;
|
||||||
|
|
||||||
trx_roll_max_undo_no = trx->undo_no;
|
|
||||||
|
|
||||||
trx_roll_progress_printed_pct = 0;
|
|
||||||
|
|
||||||
rows_to_undo = trx_roll_max_undo_no;
|
|
||||||
|
|
||||||
mutex_exit(&trx_sys->mutex);
|
|
||||||
|
|
||||||
if (rows_to_undo > 1000000000) {
|
|
||||||
rows_to_undo = rows_to_undo / 1000000;
|
|
||||||
unit = "M";
|
|
||||||
}
|
|
||||||
|
|
||||||
ut_print_timestamp(stderr);
|
|
||||||
fprintf(stderr,
|
|
||||||
" InnoDB: Rolling back trx with id " TRX_ID_FMT ", %lu%s"
|
|
||||||
" rows to undo\n",
|
|
||||||
trx->id,
|
|
||||||
(ulong) rows_to_undo, unit);
|
|
||||||
|
|
||||||
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
||||||
row_mysql_lock_data_dictionary(trx);
|
row_mysql_lock_data_dictionary(trx);
|
||||||
dictionary_locked = TRUE;
|
dictionary_locked = TRUE;
|
||||||
@@ -618,6 +590,16 @@ trx_rollback_active(
|
|||||||
|
|
||||||
que_run_threads(roll_node->undo_thr);
|
que_run_threads(roll_node->undo_thr);
|
||||||
|
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
ut_ad(!dictionary_locked);
|
||||||
|
que_graph_free(static_cast<que_t*>(
|
||||||
|
roll_node->undo_thr->common.parent));
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
||||||
|
|
||||||
/* Free the memory reserved by the undo graph */
|
/* Free the memory reserved by the undo graph */
|
||||||
@@ -662,13 +644,14 @@ trx_rollback_active(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ib_logf(IB_LOG_LEVEL_INFO,
|
||||||
|
"Rollback of trx with id " TRX_ID_FMT " completed", trx->id);
|
||||||
|
|
||||||
|
func_exit:
|
||||||
if (dictionary_locked) {
|
if (dictionary_locked) {
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ib_logf(IB_LOG_LEVEL_INFO,
|
|
||||||
"Rollback of trx with id " TRX_ID_FMT " completed", trx->id);
|
|
||||||
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
trx_roll_crash_recv_trx = NULL;
|
trx_roll_crash_recv_trx = NULL;
|
||||||
@@ -685,7 +668,7 @@ ibool
|
|||||||
trx_rollback_resurrected(
|
trx_rollback_resurrected(
|
||||||
/*=====================*/
|
/*=====================*/
|
||||||
trx_t* trx, /*!< in: transaction to rollback or clean */
|
trx_t* trx, /*!< in: transaction to rollback or clean */
|
||||||
ibool all) /*!< in: FALSE=roll back dictionary transactions;
|
ibool* all) /*!< in/out: FALSE=roll back dictionary transactions;
|
||||||
TRUE=roll back all non-PREPARED transactions */
|
TRUE=roll back all non-PREPARED transactions */
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&trx_sys->mutex));
|
ut_ad(mutex_own(&trx_sys->mutex));
|
||||||
@@ -696,16 +679,15 @@ trx_rollback_resurrected(
|
|||||||
to accidentally clean up a non-recovered transaction here. */
|
to accidentally clean up a non-recovered transaction here. */
|
||||||
|
|
||||||
trx_mutex_enter(trx);
|
trx_mutex_enter(trx);
|
||||||
bool is_recovered = trx->is_recovered;
|
if (!trx->is_recovered) {
|
||||||
trx_state_t state = trx->state;
|
func_exit:
|
||||||
trx_mutex_exit(trx);
|
trx_mutex_exit(trx);
|
||||||
|
|
||||||
if (!is_recovered) {
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (trx->state) {
|
||||||
case TRX_STATE_COMMITTED_IN_MEMORY:
|
case TRX_STATE_COMMITTED_IN_MEMORY:
|
||||||
|
trx_mutex_exit(trx);
|
||||||
mutex_exit(&trx_sys->mutex);
|
mutex_exit(&trx_sys->mutex);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Cleaning up trx with id " TRX_ID_FMT "\n",
|
"InnoDB: Cleaning up trx with id " TRX_ID_FMT "\n",
|
||||||
@@ -714,21 +696,83 @@ trx_rollback_resurrected(
|
|||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
case TRX_STATE_ACTIVE:
|
case TRX_STATE_ACTIVE:
|
||||||
if (all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
if (!srv_undo_sources && srv_fast_shutdown) {
|
||||||
|
fake_prepared:
|
||||||
|
trx->state = TRX_STATE_PREPARED;
|
||||||
|
trx_sys->n_prepared_trx++;
|
||||||
|
trx_sys->n_prepared_recovered_trx++;
|
||||||
|
*all = FALSE;
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
trx_mutex_exit(trx);
|
||||||
|
|
||||||
|
if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
||||||
mutex_exit(&trx_sys->mutex);
|
mutex_exit(&trx_sys->mutex);
|
||||||
trx_rollback_active(trx);
|
trx_rollback_active(trx);
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
trx_mutex_enter(trx);
|
||||||
|
goto fake_prepared;
|
||||||
|
}
|
||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
case TRX_STATE_PREPARED:
|
case TRX_STATE_PREPARED:
|
||||||
return(FALSE);
|
goto func_exit;
|
||||||
case TRX_STATE_NOT_STARTED:
|
case TRX_STATE_NOT_STARTED:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_error;
|
ut_error;
|
||||||
return(FALSE);
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Report progress when rolling back a row of a recovered transaction.
|
||||||
|
@return whether the rollback should be aborted due to pending shutdown */
|
||||||
|
UNIV_INTERN
|
||||||
|
bool
|
||||||
|
trx_roll_must_shutdown()
|
||||||
|
{
|
||||||
|
const trx_t* trx = trx_roll_crash_recv_trx;
|
||||||
|
ut_ad(trx);
|
||||||
|
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
|
||||||
|
|
||||||
|
if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE
|
||||||
|
&& !srv_undo_sources && srv_fast_shutdown) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ib_time_t time = ut_time();
|
||||||
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
mutex_enter(&recv_sys->mutex);
|
||||||
|
|
||||||
|
if (recv_sys->report(time)) {
|
||||||
|
ulint n_trx = 0, n_rows = 0;
|
||||||
|
for (const trx_t* t = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
|
||||||
|
t != NULL;
|
||||||
|
t = UT_LIST_GET_NEXT(trx_list, t)) {
|
||||||
|
|
||||||
|
assert_trx_in_rw_list(t);
|
||||||
|
if (t->is_recovered
|
||||||
|
&& trx_state_eq(t, TRX_STATE_ACTIVE)) {
|
||||||
|
n_trx++;
|
||||||
|
n_rows += t->undo_no;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ib_logf(IB_LOG_LEVEL_INFO,
|
||||||
|
"To roll back: " ULINTPF " transactions, "
|
||||||
|
ULINTPF " rows", n_trx, n_rows);
|
||||||
|
sd_notifyf(0, "STATUS=To roll back: " ULINTPF " transactions, "
|
||||||
|
ULINTPF " rows", n_trx, n_rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_exit(&recv_sys->mutex);
|
||||||
|
mutex_exit(&trx_sys->mutex);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
@@ -775,17 +819,11 @@ trx_rollback_or_clean_recovered(
|
|||||||
|
|
||||||
assert_trx_in_rw_list(trx);
|
assert_trx_in_rw_list(trx);
|
||||||
|
|
||||||
if (srv_shutdown_state != SRV_SHUTDOWN_NONE
|
|
||||||
&& srv_fast_shutdown != 0) {
|
|
||||||
all = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this function does a cleanup or rollback
|
/* If this function does a cleanup or rollback
|
||||||
then it will release the trx_sys->mutex, therefore
|
then it will release the trx_sys->mutex, therefore
|
||||||
we need to reacquire it before retrying the loop. */
|
we need to reacquire it before retrying the loop. */
|
||||||
|
|
||||||
if (trx_rollback_resurrected(trx, all)) {
|
if (trx_rollback_resurrected(trx, &all)) {
|
||||||
|
|
||||||
mutex_enter(&trx_sys->mutex);
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
|
||||||
@@ -1118,7 +1156,6 @@ trx_roll_pop_top_rec_of_trx(
|
|||||||
undo_no_t undo_no;
|
undo_no_t undo_no;
|
||||||
ibool is_insert;
|
ibool is_insert;
|
||||||
trx_rseg_t* rseg;
|
trx_rseg_t* rseg;
|
||||||
ulint progress_pct;
|
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
rseg = trx->rseg;
|
rseg = trx->rseg;
|
||||||
@@ -1176,27 +1213,6 @@ try_again:
|
|||||||
|
|
||||||
ut_ad(undo_no + 1 == trx->undo_no);
|
ut_ad(undo_no + 1 == trx->undo_no);
|
||||||
|
|
||||||
/* We print rollback progress info if we are in a crash recovery
|
|
||||||
and the transaction has at least 1000 row operations to undo. */
|
|
||||||
|
|
||||||
if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
|
|
||||||
|
|
||||||
progress_pct = 100 - (ulint)
|
|
||||||
((undo_no * 100) / trx_roll_max_undo_no);
|
|
||||||
if (progress_pct != trx_roll_progress_printed_pct) {
|
|
||||||
if (trx_roll_progress_printed_pct == 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"\nInnoDB: Progress in percents:"
|
|
||||||
" %lu", (ulong) progress_pct);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
" %lu", (ulong) progress_pct);
|
|
||||||
}
|
|
||||||
fflush(stderr);
|
|
||||||
trx_roll_progress_printed_pct = progress_pct;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trx->undo_no = undo_no;
|
trx->undo_no = undo_no;
|
||||||
|
|
||||||
if (!trx_undo_arr_store_info(trx, undo_no)) {
|
if (!trx_undo_arr_store_info(trx, undo_no)) {
|
||||||
|
@@ -2023,10 +2023,14 @@ trx_undo_free_prepared(
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case TRX_UNDO_ACTIVE:
|
case TRX_UNDO_ACTIVE:
|
||||||
/* lock_trx_release_locks() assigns
|
/* lock_trx_release_locks() assigns
|
||||||
trx->is_recovered=false */
|
trx->is_recovered=false and
|
||||||
|
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
|
||||||
|
also for transactions that we faked
|
||||||
|
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
|
||||||
ut_a(srv_read_only_mode
|
ut_a(srv_read_only_mode
|
||||||
|| srv_apply_log_only
|
|| srv_apply_log_only
|
||||||
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
|
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
|
||||||
|
|| srv_fast_shutdown);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ut_error;
|
ut_error;
|
||||||
@@ -2048,10 +2052,14 @@ trx_undo_free_prepared(
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case TRX_UNDO_ACTIVE:
|
case TRX_UNDO_ACTIVE:
|
||||||
/* lock_trx_release_locks() assigns
|
/* lock_trx_release_locks() assigns
|
||||||
trx->is_recovered=false */
|
trx->is_recovered=false and
|
||||||
|
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
|
||||||
|
also for transactions that we faked
|
||||||
|
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
|
||||||
ut_a(srv_read_only_mode
|
ut_a(srv_read_only_mode
|
||||||
|| srv_apply_log_only
|
|| srv_apply_log_only
|
||||||
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
|
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
|
||||||
|
|| srv_fast_shutdown);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ut_error;
|
ut_error;
|
||||||
|
Reference in New Issue
Block a user