summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/mysql_upgrade.c4
-rw-r--r--include/ma_dyncol.h6
-rw-r--r--man/mysql_upgrade.13
-rw-r--r--mysql-test/include/kill_and_restart_mysqld.inc15
-rw-r--r--mysql-test/r/ctype_utf8.result15
-rw-r--r--mysql-test/r/ctype_utf8mb4.result26
-rw-r--r--mysql-test/r/func_str.result33
-rw-r--r--mysql-test/suite/innodb/r/recovery_shutdown.result64
-rw-r--r--mysql-test/suite/innodb/r/update_time.result1
-rw-r--r--mysql-test/suite/innodb/t/recovery_shutdown.test59
-rw-r--r--mysql-test/suite/innodb/t/table_definition_cache_debug.opt2
-rw-r--r--mysql-test/suite/innodb/t/update_time.test3
-rw-r--r--mysql-test/suite/innodb_gis/r/kill_server.result1
-rw-r--r--mysql-test/suite/innodb_gis/r/rtree_compress2.result1
-rw-r--r--mysql-test/suite/innodb_gis/r/rtree_crash.result41
-rw-r--r--mysql-test/suite/innodb_gis/r/rtree_recovery.result2
-rw-r--r--mysql-test/suite/innodb_gis/r/types.result1
-rw-r--r--mysql-test/suite/innodb_gis/t/kill_server.test3
-rw-r--r--mysql-test/suite/innodb_gis/t/rtree_compress2.test3
-rw-r--r--mysql-test/suite/innodb_gis/t/rtree_recovery.test5
-rw-r--r--mysql-test/suite/innodb_gis/t/types.test3
-rw-r--r--mysql-test/suite/storage_engine/type_bit_indexes.result4
-rw-r--r--mysql-test/t/ctype_utf8.test12
-rw-r--r--mysql-test/t/ctype_utf8mb4.test18
-rw-r--r--mysql-test/t/func_str.test30
-rw-r--r--mysys/ma_dyncol.c3
-rw-r--r--mysys/thr_alarm.c4
-rw-r--r--sql/item_cmpfunc.cc6
-rw-r--r--sql/item_strfunc.cc34
-rw-r--r--sql/item_strfunc.h8
-rw-r--r--storage/innobase/ha/ha0ha.cc58
-rw-r--r--storage/innobase/handler/ha_innodb.cc3
-rw-r--r--storage/innobase/include/ha0ha.h7
-rw-r--r--storage/innobase/include/que0que.h3
-rw-r--r--storage/innobase/include/trx0roll.h7
-rw-r--r--storage/innobase/row/row0quiesce.cc4
-rw-r--r--storage/innobase/row/row0umod.cc18
-rw-r--r--storage/innobase/row/row0undo.cc8
-rw-r--r--storage/innobase/srv/srv0srv.cc28
-rw-r--r--storage/innobase/srv/srv0start.cc4
-rw-r--r--storage/innobase/trx/trx0purge.cc70
-rw-r--r--storage/innobase/trx/trx0roll.cc165
-rw-r--r--storage/innobase/trx/trx0undo.cc16
-rw-r--r--storage/maria/ma_loghandler.c1
-rw-r--r--storage/rocksdb/mysql-test/storage_engine/disabled.def1
-rw-r--r--storage/rocksdb/mysql-test/storage_engine/type_bit_indexes.rdiff20
-rw-r--r--storage/rocksdb/mysql-test/storage_engine/type_enum_indexes.rdiff11
-rw-r--r--storage/rocksdb/mysql-test/storage_engine/type_set_indexes.rdiff20
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result2
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result2
-rw-r--r--storage/xtradb/handler/ha_innodb.cc17
-rw-r--r--storage/xtradb/include/que0que.h3
-rw-r--r--storage/xtradb/include/trx0roll.h9
-rw-r--r--storage/xtradb/lock/lock0lock.cc91
-rw-r--r--storage/xtradb/lock/lock0wait.cc39
-rw-r--r--storage/xtradb/row/row0undo.cc8
-rw-r--r--storage/xtradb/trx/trx0roll.cc164
-rw-r--r--storage/xtradb/trx/trx0undo.cc16
58 files changed, 765 insertions, 440 deletions
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 7ba15b772b5..14a47bce352 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -166,8 +166,8 @@ static struct my_option my_long_options[]=
"server with which it was built/distributed.",
&opt_version_check, &opt_version_check, 0,
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
- {"write-binlog", OPT_WRITE_BINLOG, "All commands including those, "
- "issued by mysqlcheck, are written to the binary log.",
+ {"write-binlog", OPT_WRITE_BINLOG, "All commands including those "
+ "issued by mysqlcheck are written to the binary log.",
&opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, 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}
diff --git a/include/ma_dyncol.h b/include/ma_dyncol.h
index cb03ccb5382..300474e061e 100644
--- a/include/ma_dyncol.h
+++ b/include/ma_dyncol.h
@@ -63,6 +63,12 @@ typedef struct st_mysql_lex_string LEX_STRING;
/* NO and OK is the same used just to show semantics */
#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
{
ER_DYNCOL_OK= 0,
diff --git a/man/mysql_upgrade.1 b/man/mysql_upgrade.1
index 876e224aa83..13b2a07cecb 100644
--- a/man/mysql_upgrade.1
+++ b/man/mysql_upgrade.1
@@ -691,8 +691,7 @@ it was built/distributed. Defaults to on; use \fB\-\-skip\-version\-check\fR to
.sp
Cause binary logging to be enabled while
\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
-\fB\-\-skip\-write\-binlog\fR)\&.
+runs\&.
.RE
.SH "COPYRIGHT"
.br
diff --git a/mysql-test/include/kill_and_restart_mysqld.inc b/mysql-test/include/kill_and_restart_mysqld.inc
deleted file mode 100644
index b67fb7350b4..00000000000
--- a/mysql-test/include/kill_and_restart_mysqld.inc
+++ /dev/null
@@ -1,15 +0,0 @@
-if (!$restart_parameters)
-{
- let $restart_parameters = restart;
-}
-
---let $_server_id= `SELECT @@server_id`
---let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
-
---echo # Kill and $restart_parameters
---exec echo "$restart_parameters" > $_expect_file_name
---shutdown_server 0
---source include/wait_until_disconnected.inc
---enable_reconnect
---source include/wait_until_connected_again.inc
---disable_reconnect
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 7381c1c4004..dfe96d1a904 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -10272,6 +10272,21 @@ DROP TABLE allbytes;
SET sql_mode = DEFAULT;
# 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
#
#
diff --git a/mysql-test/r/ctype_utf8mb4.result b/mysql-test/r/ctype_utf8mb4.result
index cf3000baf6a..fbe95d9f44b 100644
--- a/mysql-test/r/ctype_utf8mb4.result
+++ b/mysql-test/r/ctype_utf8mb4.result
@@ -3430,6 +3430,32 @@ a b
a 😁 b a ? b
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
#
#
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index b1862d46613..da03ae6a18e 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -4734,6 +4734,27 @@ set global max_allowed_packet=default;
# 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
#
#
@@ -4843,6 +4864,12 @@ YQ== 61
Yq== 62
DROP TABLE t1;
#
+# End of 10.1 tests
+#
+#
+# Start of 10.3 tests
+#
+#
# MDEV-12685 Oracle-compatible function CHR()
#
select chr(65);
@@ -4859,12 +4886,6 @@ utf8 3 1
drop database mysqltest1;
use test;
#
-# End of 10.1 tests
-#
-#
-# Start of 10.3 tests
-#
-#
# MDEV-12592 Illegal mix of collations with the HEX function
#
SET NAMES utf8;
diff --git a/mysql-test/suite/innodb/r/recovery_shutdown.result b/mysql-test/suite/innodb/r/recovery_shutdown.result
new file mode 100644
index 00000000000..7b6c9863b59
--- /dev/null
+++ b/mysql-test/suite/innodb/r/recovery_shutdown.result
@@ -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;
diff --git a/mysql-test/suite/innodb/r/update_time.result b/mysql-test/suite/innodb/r/update_time.result
index ab3eeb08dc7..d8b9069b1ae 100644
--- a/mysql-test/suite/innodb/r/update_time.result
+++ b/mysql-test/suite/innodb/r/update_time.result
@@ -43,7 +43,6 @@ XA PREPARE 'xatrx';
CONNECT con1,localhost,root,,;
call mtr.add_suppression("Found 1 prepared XA transactions");
FLUSH TABLES;
-# Kill and restart
SELECT update_time FROM information_schema.tables WHERE table_name = 't';
update_time
NULL
diff --git a/mysql-test/suite/innodb/t/recovery_shutdown.test b/mysql-test/suite/innodb/t/recovery_shutdown.test
new file mode 100644
index 00000000000..fbe26368e1b
--- /dev/null
+++ b/mysql-test/suite/innodb/t/recovery_shutdown.test
@@ -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;
diff --git a/mysql-test/suite/innodb/t/table_definition_cache_debug.opt b/mysql-test/suite/innodb/t/table_definition_cache_debug.opt
index 6195e055dc8..6d341857397 100644
--- a/mysql-test/suite/innodb/t/table_definition_cache_debug.opt
+++ b/mysql-test/suite/innodb/t/table_definition_cache_debug.opt
@@ -1 +1 @@
---innodb-open-files=13
+--innodb-open-files=20
diff --git a/mysql-test/suite/innodb/t/update_time.test b/mysql-test/suite/innodb/t/update_time.test
index e2213c5d9b7..1a00e3b9f73 100644
--- a/mysql-test/suite/innodb/t/update_time.test
+++ b/mysql-test/suite/innodb/t/update_time.test
@@ -67,7 +67,8 @@ CONNECT (con1,localhost,root,,);
call mtr.add_suppression("Found 1 prepared XA transactions");
FLUSH TABLES;
---source include/kill_and_restart_mysqld.inc
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
SELECT update_time FROM information_schema.tables WHERE table_name = 't';
diff --git a/mysql-test/suite/innodb_gis/r/kill_server.result b/mysql-test/suite/innodb_gis/r/kill_server.result
index 579317872b4..eac4feb442f 100644
--- a/mysql-test/suite/innodb_gis/r/kill_server.result
+++ b/mysql-test/suite/innodb_gis/r/kill_server.result
@@ -36,6 +36,5 @@ call mtr.add_suppression("InnoDB: A copy of page \[page id: space=[0-9]+, page n
START TRANSACTION;
CALL insert_t1(5000);
COMMIT;
-# Kill and restart
drop procedure insert_t1;
drop table t1;
diff --git a/mysql-test/suite/innodb_gis/r/rtree_compress2.result b/mysql-test/suite/innodb_gis/r/rtree_compress2.result
index 3522a1097aa..04940f2b3b1 100644
--- a/mysql-test/suite/innodb_gis/r/rtree_compress2.result
+++ b/mysql-test/suite/innodb_gis/r/rtree_compress2.result
@@ -20,6 +20,5 @@ call mtr.add_suppression("InnoDB: A copy of page \[page id: space=[0-9]+, page n
START TRANSACTION;
CALL insert_t1(5000);
COMMIT;
-# Kill and restart
drop procedure insert_t1;
drop table t1;
diff --git a/mysql-test/suite/innodb_gis/r/rtree_crash.result b/mysql-test/suite/innodb_gis/r/rtree_crash.result
deleted file mode 100644
index 12ca15a420d..00000000000
--- a/mysql-test/suite/innodb_gis/r/rtree_crash.result
+++ /dev/null
@@ -1,41 +0,0 @@
-create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb;
-create procedure insert_t1(IN total int)
-begin
-declare i int default 1;
-while (i <= total) DO
-insert into t1 values (i, Point(i, i));
-set i = i + 1;
-end while;
-end|
-CALL insert_t1(5000);
-select count(*) from t1;
-count(*)
-5000
-check table t1;
-Table Op Msg_type Msg_text
-test.t1 check status OK
-truncate table t1;
-CALL insert_t1(10000);
-select count(*) from t1;
-count(*)
-10000
-drop index c2 on t1;
-create spatial index idx on t1(c2);
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `c1` int(11) DEFAULT NULL,
- `c2` geometry NOT NULL,
- SPATIAL KEY `idx` (`c2`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
-check table t1;
-Table Op Msg_type Msg_text
-test.t1 check status OK
-truncate table t1;
-call mtr.add_suppression("InnoDB: page [0-9]+ in the doublewrite buffer is not within space bounds.*");
-START TRANSACTION;
-CALL insert_t1(5000);
-COMMIT;
-# Kill and restart
-drop procedure insert_t1;
-drop table t1;
diff --git a/mysql-test/suite/innodb_gis/r/rtree_recovery.result b/mysql-test/suite/innodb_gis/r/rtree_recovery.result
index d2f4409f38c..3572e3e0bed 100644
--- a/mysql-test/suite/innodb_gis/r/rtree_recovery.result
+++ b/mysql-test/suite/innodb_gis/r/rtree_recovery.result
@@ -18,7 +18,6 @@ end while;
end|
CALL insert_t1(367);
COMMIT;
-# Kill and restart
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
@@ -29,7 +28,6 @@ CALL update_t1(367);
SET @poly1 = ST_GeomFromText('POLYGON((10000 10000, 10000 10350, 10350 10350, 10350 10000, 10000 10000))');
delete from t1 where ST_Contains(@poly1, c2);
COMMIT;
-# Kill and restart
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
diff --git a/mysql-test/suite/innodb_gis/r/types.result b/mysql-test/suite/innodb_gis/r/types.result
index ac1802085d6..7d823927df1 100644
--- a/mysql-test/suite/innodb_gis/r/types.result
+++ b/mysql-test/suite/innodb_gis/r/types.result
@@ -53,7 +53,6 @@ COMMIT;
INSERT INTO t_wl6455 VALUES(11, POINT(11,11));
BEGIN;
INSERT INTO t_wl6455 VALUES(1, POINT(1,1));
-# Kill and restart
CHECK TABLE t_wl6455;
Table Op Msg_type Msg_text
test.t_wl6455 check status OK
diff --git a/mysql-test/suite/innodb_gis/t/kill_server.test b/mysql-test/suite/innodb_gis/t/kill_server.test
index 9b6469606ca..028bbbdd40d 100644
--- a/mysql-test/suite/innodb_gis/t/kill_server.test
+++ b/mysql-test/suite/innodb_gis/t/kill_server.test
@@ -58,7 +58,8 @@ CALL insert_t1(5000);
COMMIT;
---source include/kill_and_restart_mysqld.inc
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
# Clean up.
drop procedure insert_t1;
diff --git a/mysql-test/suite/innodb_gis/t/rtree_compress2.test b/mysql-test/suite/innodb_gis/t/rtree_compress2.test
index 5956fc9a774..86ef1171833 100644
--- a/mysql-test/suite/innodb_gis/t/rtree_compress2.test
+++ b/mysql-test/suite/innodb_gis/t/rtree_compress2.test
@@ -51,7 +51,8 @@ CALL insert_t1(5000);
COMMIT;
---source include/kill_and_restart_mysqld.inc
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
# Clean up.
drop procedure insert_t1;
diff --git a/mysql-test/suite/innodb_gis/t/rtree_recovery.test b/mysql-test/suite/innodb_gis/t/rtree_recovery.test
index 9e332c089f2..d995048ceac 100644
--- a/mysql-test/suite/innodb_gis/t/rtree_recovery.test
+++ b/mysql-test/suite/innodb_gis/t/rtree_recovery.test
@@ -44,7 +44,8 @@ delimiter ;|
CALL insert_t1(367);
COMMIT;
---source include/kill_and_restart_mysqld.inc
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
# Check table.
check table t1;
@@ -63,7 +64,7 @@ SET @poly1 = ST_GeomFromText('POLYGON((10000 10000, 10000 10350, 10350 10350, 10
delete from t1 where ST_Contains(@poly1, c2);
COMMIT;
---source include/kill_and_restart_mysqld.inc
+--source include/restart_mysqld.inc
# Check table.
check table t1;
diff --git a/mysql-test/suite/innodb_gis/t/types.test b/mysql-test/suite/innodb_gis/t/types.test
index bd03e7b1dbe..65f65e5ae1f 100644
--- a/mysql-test/suite/innodb_gis/t/types.test
+++ b/mysql-test/suite/innodb_gis/t/types.test
@@ -73,7 +73,8 @@ INSERT INTO t_wl6455 VALUES(11, POINT(11,11));
BEGIN;
INSERT INTO t_wl6455 VALUES(1, POINT(1,1));
---source include/kill_and_restart_mysqld.inc
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
CHECK TABLE t_wl6455;
SELECT ST_AsText(g) FROM t_wl6455;
diff --git a/mysql-test/suite/storage_engine/type_bit_indexes.result b/mysql-test/suite/storage_engine/type_bit_indexes.result
index e7c0cf656c5..af8ddf7d6c9 100644
--- a/mysql-test/suite/storage_engine/type_bit_indexes.result
+++ b/mysql-test/suite/storage_engine/type_bit_indexes.result
@@ -69,7 +69,7 @@ INSERT INTO t1 (a,b,c,d) VALUES
(1,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF);
EXPLAIN SELECT HEX(b+c) FROM t1 WHERE c > 1 OR HEX(b) < 0xFFFFFF;
id select_type table type possible_keys key key_len ref rows Extra
-# # # # # NULL # # # #
+# # # # # b_c # # # #
SELECT HEX(b+c) FROM t1 WHERE c > 1 OR HEX(b) < 0xFFFFFF;
HEX(b+c)
10
@@ -98,7 +98,7 @@ INSERT INTO t1 (a,b,c,d) VALUES
(1,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF);
EXPLAIN SELECT DISTINCT a+0 FROM t1 ORDER BY a;
id select_type table type possible_keys key key_len ref rows Extra
-# # # # # NULL # # # #
+# # # # # a # # # #
SELECT DISTINCT a+0 FROM t1 ORDER BY a;
a+0
0
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index adb846a0df2..b839042b91e 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1879,6 +1879,18 @@ let $ctype_unescape_combinations=selected;
--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 # End of 10.0 tests
--echo #
diff --git a/mysql-test/t/ctype_utf8mb4.test b/mysql-test/t/ctype_utf8mb4.test
index 94b5d77ad90..7aa644fe8a9 100644
--- a/mysql-test/t/ctype_utf8mb4.test
+++ b/mysql-test/t/ctype_utf8mb4.test
@@ -1923,6 +1923,24 @@ SELECT * FROM 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 # End of 10.0 tests
--echo #
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index a75330ab981..dbb7502a3ec 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -1810,6 +1810,18 @@ set global max_allowed_packet=default;
--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 # Start of 10.1 tests
--echo #
@@ -1854,6 +1866,15 @@ SELECT f1,HEX(f2) FROM t1 WHERE f1='YQ==' AND (f2= from_base64(
DROP TABLE t1;
--echo #
+--echo # End of 10.1 tests
+--echo #
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
--echo # MDEV-12685 Oracle-compatible function CHR()
--echo #
select chr(65);
@@ -1865,15 +1886,6 @@ drop database mysqltest1;
use test;
--echo #
---echo # End of 10.1 tests
---echo #
-
-
---echo #
---echo # Start of 10.3 tests
---echo #
-
---echo #
--echo # MDEV-12592 Illegal mix of collations with the HEX function
--echo #
diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c
index 125b3a4632d..3c15e373182 100644
--- a/mysys/ma_dyncol.c
+++ b/mysys/ma_dyncol.c
@@ -4183,8 +4183,7 @@ mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json,
}
else
{
- if ((rc= mariadb_dyncol_val_str(json, &val,
- &my_charset_utf8_general_ci, '"')) < 0)
+ if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, '"')) < 0)
goto err;
}
}
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 9d917d3dd59..61ef3657161 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -273,7 +273,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
/*
Come here when some alarm in queue is due.
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
every second.
*/
@@ -425,7 +425,7 @@ void end_thr_alarm(my_bool free_structures)
if (alarm_aborted != 1) /* If memory not freed */
{
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 */
if (alarm_queue.elements || (alarm_thread_running && free_structures))
{
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 587dc14c529..d7429af76f7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -6940,20 +6940,20 @@ longlong Item_func_dyncol_exists::val_int()
null_value= 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.length= nm->length();
}
else
{
- uint strlen= nm->length() * my_charset_utf8_general_ci.mbmaxlen + 1;
+ uint strlen= nm->length() * DYNCOL_UTF->mbmaxlen + 1;
uint dummy_errors;
buf.str= (char *) current_thd->alloc(strlen);
if (buf.str)
{
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(),
&dummy_errors);
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index d7e526906c6..b39fcb78fe9 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2918,6 +2918,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)
{
DBUG_ASSERT(fixed == 1);
@@ -4514,20 +4528,19 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg)
if (res)
{
// 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].str= thd->strmake(res->ptr(), res->length());
}
else
{
- uint strlen= res->length() * my_charset_utf8_general_ci.mbmaxlen + 1;
+ uint strlen= res->length() * DYNCOL_UTF->mbmaxlen + 1;
uint dummy_errors;
- char *str= (char *) thd->alloc(strlen);
- if (str)
+ if (char *str= (char *) thd->alloc(strlen))
{
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(),
&dummy_errors);
keys_str[i].str= str;
@@ -4747,9 +4760,10 @@ String *Item_func_dyncol_json::val_str(String *str)
char *ptr;
size_t 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;
}
+ str->set_charset(DYNCOL_UTF);
return str;
null:
@@ -4849,20 +4863,20 @@ bool Item_dyncol_get::get_dyn_value(THD *thd, DYNAMIC_COLUMN_VALUE *val,
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.length= nm->length();
}
else
{
- uint strlen= nm->length() * my_charset_utf8_general_ci.mbmaxlen + 1;
+ uint strlen= nm->length() * DYNCOL_UTF->mbmaxlen + 1;
uint dummy_errors;
buf.str= (char *) thd->alloc(strlen);
if (buf.str)
{
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(),
&dummy_errors);
}
@@ -5286,7 +5300,6 @@ String *Item_func_dyncol_list::val_str(String *str)
goto null;
str->length(0);
- str->set_charset(&my_charset_utf8_general_ci);
for (i= 0; i < count; i++)
{
append_identifier(current_thd, str, names[i].str, names[i].length);
@@ -5296,6 +5309,7 @@ String *Item_func_dyncol_list::val_str(String *str)
null_value= FALSE;
if (names)
my_free(names);
+ str->set_charset(DYNCOL_UTF);
return str;
null:
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index fbcf69d00ce..49f82f7028c 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -978,6 +978,7 @@ public:
max_length= arg_count * 4;
}
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)
{ return get_item_copy<Item_func_char>(thd, mem_root, this); }
};
@@ -1585,14 +1586,14 @@ public:
class Item_func_dyncol_json: public Item_str_func
{
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"; }
String *val_str(String *);
void fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
- collation.set(&my_charset_bin);
decimals= 0;
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1645,7 +1646,8 @@ public:
class Item_func_dyncol_list: public Item_str_func
{
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; };
const char *func_name() const{ return "column_list"; }
String *val_str(String *);
diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc
index f620db6f62e..da542d4f742 100644
--- a/storage/innobase/ha/ha0ha.cc
+++ b/storage/innobase/ha/ha0ha.cc
@@ -489,62 +489,4 @@ ha_validate(
return(ok);
}
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
-
-/*************************************************************//**
-Prints info of a hash table. */
-void
-ha_print_info(
-/*==========*/
- FILE* file, /*!< in: file where to print */
- hash_table_t* table) /*!< in: hash table */
-{
-#ifdef UNIV_DEBUG
-/* Some of the code here is disabled for performance reasons in production
-builds, see http://bugs.mysql.com/36941 */
-#define PRINT_USED_CELLS
-#endif /* UNIV_DEBUG */
-
-#ifdef PRINT_USED_CELLS
- hash_cell_t* cell;
- ulint cells = 0;
- ulint i;
-#endif /* PRINT_USED_CELLS */
- ulint n_bufs;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-#ifdef PRINT_USED_CELLS
- for (i = 0; i < hash_get_n_cells(table); i++) {
-
- cell = hash_get_nth_cell(table, i);
-
- if (cell->node) {
-
- cells++;
- }
- }
-#endif /* PRINT_USED_CELLS */
-
- fprintf(file, "Hash table size %lu",
- (ulong) hash_get_n_cells(table));
-
-#ifdef PRINT_USED_CELLS
- fprintf(file, ", used cells %lu", (ulong) cells);
-#endif /* PRINT_USED_CELLS */
-
- if (table->heaps == NULL && table->heap != NULL) {
-
- /* This calculation is intended for the adaptive hash
- index: how many buffer frames we have reserved? */
-
- n_bufs = UT_LIST_GET_LEN(table->heap->base) - 1;
-
- if (table->heap->free_block) {
- n_bufs++;
- }
-
- fprintf(file, ", node heap has %lu buffer(s)\n",
- (ulong) n_bufs);
- }
-}
#endif /* BTR_CUR_HASH_ADAPT */
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 3263260c0b3..b065155be2d 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3864,8 +3864,7 @@ innobase_init(
/* Currently, Galera does not support VATS lock schedule algorithm. */
if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
&& global_system_variables.wsrep_on) {
- ib::info() << "In Galera environment Variance-Aware-Transaction-Sheduling Algorithm"
- " is not supported. Falling back to First-Come-First-Served order. ";
+ ib::info() << "For Galera, using innodb_lock_schedule_algorithm=fcfs";
innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS;
}
#endif /* WITH_WSREP */
diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h
index db53b6c6580..ca4cb0a5f8f 100644
--- a/storage/innobase/include/ha0ha.h
+++ b/storage/innobase/include/ha0ha.h
@@ -198,13 +198,6 @@ ha_validate(
ulint start_index, /*!< in: start index */
ulint end_index); /*!< in: end index */
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
-/*************************************************************//**
-Prints info of a hash table. */
-void
-ha_print_info(
-/*==========*/
- FILE* file, /*!< in: file where to print */
- hash_table_t* table); /*!< in: hash table */
/** The hash table external chain node */
struct ha_node_t {
diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h
index 763b16820d8..13be7291f00 100644
--- a/storage/innobase/include/que0que.h
+++ b/storage/innobase/include/que0que.h
@@ -381,9 +381,6 @@ struct que_thr_t{
thrs; /*!< list of thread nodes of the fork
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)
queue; /*!< list of runnable thread nodes in
the server task queue */
ulint fk_cascade_depth; /*!< maximum cascading call depth
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index 8908376bff1..f7b999ae70a 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -33,7 +33,8 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.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
@@ -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)
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
encountered in crash recovery. If the transaction already was
diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc
index dd6289c91e6..21cc67620f6 100644
--- a/storage/innobase/row/row0quiesce.cc
+++ b/storage/innobase/row/row0quiesce.cc
@@ -520,7 +520,7 @@ row_quiesce_table_start(
ut_ad(fil_space_get(table->space) != NULL);
ib::info() << "Sync to disk of " << table->name << " started.";
- if (trx_purge_state() != PURGE_STATE_DISABLED) {
+ if (srv_undo_sources) {
trx_purge_stop();
}
@@ -603,7 +603,7 @@ row_quiesce_table_complete(
ib::info() << "Deleting the meta-data file '" << cfg_name << "'";
}
- if (trx_purge_state() != PURGE_STATE_DISABLED) {
+ if (srv_undo_sources) {
trx_purge_run();
}
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 2269711ffef..b13b770f0bd 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -1178,7 +1178,16 @@ close_table:
if (!row_undo_search_clust_to_pcur(node)) {
/* As long as this rolling-back transaction exists,
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
node->roll_ptr) and thus there is nothing to roll back.
@@ -1186,8 +1195,11 @@ close_table:
record after successfully acquiring an exclusive lock
on the the clustered index record. That lock will not
be released before the transaction is committed or
- fully rolled back. */
- ut_ad(node->pcur.btr_cur.low_match == node->ref->n_fields);
+ fully rolled back. (Exception: if the server was
+ 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;
}
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index 5a0cd0dc985..252dfb4a6a6 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
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
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);
+ 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);
trx->error_state = err;
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index b6d9fbe635d..19be088912a 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1323,9 +1323,28 @@ srv_printf_innodb_monitor(
#ifdef BTR_CUR_HASH_ADAPT
for (ulint i = 0; i < btr_ahi_parts; ++i) {
- rw_lock_s_lock(btr_search_latches[i]);
- ha_print_info(file, btr_search_sys->hash_tables[i]);
- rw_lock_s_unlock(btr_search_latches[i]);
+ const hash_table_t* table = btr_search_sys->hash_tables[i];
+
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+ /* this is only used for buf_pool->page_hash */
+ ut_ad(!table->heaps);
+ /* this is used for the adaptive hash index */
+ ut_ad(table->heap);
+
+ const mem_heap_t* heap = table->heap;
+ /* The heap may change during the following call,
+ so the data displayed may be garbage. We intentionally
+ avoid acquiring btr_search_latches[] so that the
+ diagnostic output will not stop here even in case another
+ thread hangs while holding btr_search_latches[].
+
+ This should be safe from crashes, because
+ table->heap will be pointing to the same object
+ for the full lifetime of the server. Even during
+ btr_search_disable() the heap will stay valid. */
+ fprintf(file, "Hash table size " ULINTPF
+ ", node heap has " ULINTPF " buffer(s)\n",
+ table->n_cells, heap->base.count - !heap->free_block);
}
fprintf(file,
@@ -2853,6 +2872,9 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
purge_sys->running = false;
+ /* Ensure that the wait in trx_purge_stop() will terminate. */
+ os_event_set(purge_sys->event);
+
rw_lock_x_unlock(&purge_sys->latch);
#ifdef UNIV_DEBUG_THREAD_CREATION
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index d776595568b..886d47e44c0 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2633,8 +2633,6 @@ files_checked:
trx_temp_rseg_create();
}
- srv_is_being_started = false;
-
ut_a(trx_purge_state() == PURGE_STATE_INIT);
/* Create the master thread which does purge and other utility
@@ -2683,6 +2681,8 @@ files_checked:
purge_sys->state = PURGE_STATE_DISABLED;
}
+ srv_is_being_started = false;
+
if (!srv_read_only_mode) {
/* wake main loop of page cleaner up */
os_event_set(buf_flush_event);
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 61c36637a4e..4fd9333c0ba 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -1770,52 +1770,48 @@ void
trx_purge_stop(void)
/*================*/
{
- ut_a(srv_n_purge_threads > 0);
-
rw_lock_x_lock(&purge_sys->latch);
- const int64_t sig_count = os_event_reset(purge_sys->event);
- const purge_state_t state = purge_sys->state;
-
- ut_a(state == PURGE_STATE_RUN || state == PURGE_STATE_STOP);
-
- ++purge_sys->n_stop;
-
- if (state == PURGE_STATE_RUN) {
+ switch (purge_sys->state) {
+ case PURGE_STATE_INIT:
+ case PURGE_STATE_DISABLED:
+ ut_error;
+ case PURGE_STATE_EXIT:
+ /* Shutdown must have been initiated during
+ FLUSH TABLES FOR EXPORT. */
+ ut_ad(!srv_undo_sources);
+unlock:
+ rw_lock_x_unlock(&purge_sys->latch);
+ break;
+ case PURGE_STATE_STOP:
+ ut_ad(srv_n_purge_threads > 0);
+ ++purge_sys->n_stop;
+ purge_sys->state = PURGE_STATE_STOP;
+ if (!purge_sys->running) {
+ goto unlock;
+ }
+ ib::info() << "Waiting for purge to stop";
+ do {
+ rw_lock_x_unlock(&purge_sys->latch);
+ os_thread_sleep(10000);
+ rw_lock_x_lock(&purge_sys->latch);
+ } while (purge_sys->running);
+ goto unlock;
+ case PURGE_STATE_RUN:
+ ut_ad(srv_n_purge_threads > 0);
+ ++purge_sys->n_stop;
ib::info() << "Stopping purge";
/* We need to wakeup the purge thread in case it is suspended,
so that it can acknowledge the state change. */
+ const int64_t sig_count = os_event_reset(purge_sys->event);
+ purge_sys->state = PURGE_STATE_STOP;
srv_purge_wakeup();
- }
-
- purge_sys->state = PURGE_STATE_STOP;
-
- if (state != PURGE_STATE_STOP) {
rw_lock_x_unlock(&purge_sys->latch);
/* Wait for purge coordinator to signal that it
is suspended. */
os_event_wait_low(purge_sys->event, sig_count);
- } else {
- bool once = true;
-
- /* Wait for purge to signal that it has actually stopped. */
- while (purge_sys->running) {
-
- if (once) {
- ib::info() << "Waiting for purge to stop";
- once = false;
- }
-
- rw_lock_x_unlock(&purge_sys->latch);
-
- os_thread_sleep(10000);
-
- rw_lock_x_lock(&purge_sys->latch);
- }
-
- rw_lock_x_unlock(&purge_sys->latch);
}
MONITOR_INC_VALUE(MONITOR_PURGE_STOP_COUNT, 1);
@@ -1830,8 +1826,12 @@ trx_purge_run(void)
rw_lock_x_lock(&purge_sys->latch);
switch (purge_sys->state) {
- case PURGE_STATE_INIT:
case PURGE_STATE_EXIT:
+ /* Shutdown must have been initiated during
+ FLUSH TABLES FOR EXPORT. */
+ ut_ad(!srv_undo_sources);
+ break;
+ case PURGE_STATE_INIT:
case PURGE_STATE_DISABLED:
ut_error;
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index d6857b892da..c9c77acba11 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -24,8 +24,10 @@ Transaction rollback
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 <mysql/service_wsrep.h>
@@ -56,14 +58,7 @@ static const ulint TRX_ROLL_TRUNC_THRESHOLD = 1;
bool trx_rollback_or_clean_is_active;
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
-static const trx_t* trx_roll_crash_recv_trx = NULL;
-
-/** 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;
+const trx_t* trx_roll_crash_recv_trx;
/****************************************************************//**
Finishes a transaction rollback. */
@@ -631,8 +626,6 @@ trx_rollback_active(
que_thr_t* thr;
roll_node_t* roll_node;
dict_table_t* table;
- int64_t rows_to_undo;
- const char* unit = "";
ibool dictionary_locked = FALSE;
heap = mem_heap_create(512);
@@ -651,28 +644,8 @@ trx_rollback_active(
ut_a(thr == que_fork_start_command(fork));
- trx_sys_mutex_enter();
-
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) {
row_mysql_lock_data_dictionary(trx);
dictionary_locked = TRUE;
@@ -683,6 +656,17 @@ trx_rollback_active(
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));
/* Free the memory reserved by the undo graph */
@@ -714,11 +698,13 @@ trx_rollback_active(
}
}
+func_exit:
if (dictionary_locked) {
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);
@@ -736,7 +722,7 @@ ibool
trx_rollback_resurrected(
/*=====================*/
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 */
{
ut_ad(trx_sys_mutex_own());
@@ -747,40 +733,102 @@ trx_rollback_resurrected(
to accidentally clean up a non-recovered transaction here. */
trx_mutex_enter(trx);
- bool is_recovered = trx->is_recovered;
- trx_state_t state = trx->state;
- trx_mutex_exit(trx);
-
- if (!is_recovered) {
+ if (!trx->is_recovered) {
+func_exit:
+ trx_mutex_exit(trx);
return(FALSE);
}
- switch (state) {
+ switch (trx->state) {
case TRX_STATE_COMMITTED_IN_MEMORY:
+ trx_mutex_exit(trx);
trx_sys_mutex_exit();
- ib::info() << "Cleaning up trx with id "
- << trx_get_id_for_print(trx);
+ ib::info() << "Cleaning up trx with id " << ib::hex(trx->id);
trx_cleanup_at_db_startup(trx);
trx_free_resurrected(trx);
return(TRUE);
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_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);
return(TRUE);
}
return(FALSE);
case TRX_STATE_PREPARED:
- return(FALSE);
+ goto func_exit;
case TRX_STATE_NOT_STARTED:
case TRX_STATE_FORCED_ROLLBACK:
break;
}
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);
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE
- && srv_fast_shutdown != 0) {
- all = FALSE;
- break;
- }
-
/* If this function does a cleanup or rollback
then it will release the trx_sys->mutex, therefore
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();
@@ -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(
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_rseg_space = undo->rseg->space;
mutex_exit(&trx->undo_mutex);
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index 5e6b67007ad..11df7011027 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -1826,10 +1826,14 @@ trx_undo_free_prepared(
/* fall through */
case TRX_UNDO_ACTIVE:
/* 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
|| srv_read_only_mode
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
+ || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
+ || srv_fast_shutdown);
break;
default:
ut_error;
@@ -1854,10 +1858,14 @@ trx_undo_free_prepared(
/* fall through */
case TRX_UNDO_ACTIVE:
/* 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
|| srv_read_only_mode
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
+ || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
+ || srv_fast_shutdown);
break;
default:
ut_error;
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index bc30adad43a..e30ddb756a6 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -6342,7 +6342,6 @@ my_bool translog_write_record(LSN *lsn,
short_trid, &parts, trn, hook_arg);
break;
case LOGRECTYPE_NOT_ALLOWED:
- DBUG_ASSERT(0);
default:
DBUG_ASSERT(0);
rc= 1;
diff --git a/storage/rocksdb/mysql-test/storage_engine/disabled.def b/storage/rocksdb/mysql-test/storage_engine/disabled.def
index 0643b2052e2..930e1d82b87 100644
--- a/storage/rocksdb/mysql-test/storage_engine/disabled.def
+++ b/storage/rocksdb/mysql-test/storage_engine/disabled.def
@@ -14,6 +14,7 @@ lock_concurrent : MDEV-13148 - LOCK TABLE on RocksDB table fails with a bog
optimize_table : MDEV-13148 - LOCK TABLE on RocksDB table fails with a bogus error message
repair_table : MDEV-13148 - LOCK TABLE on RocksDB table fails with a bogus error message
select_high_prio : Not supported
+show_engine : SHOW ENGINE produces different number of lines depending on previous tests
show_table_status : MDEV-13152 - Indeterministic row number in SHOW TABLE STATUS on RocksDB table
tbl_opt_data_dir : Not supported
tbl_opt_index_dir : Not supported
diff --git a/storage/rocksdb/mysql-test/storage_engine/type_bit_indexes.rdiff b/storage/rocksdb/mysql-test/storage_engine/type_bit_indexes.rdiff
new file mode 100644
index 00000000000..e53a33b4fba
--- /dev/null
+++ b/storage/rocksdb/mysql-test/storage_engine/type_bit_indexes.rdiff
@@ -0,0 +1,20 @@
+--- suite/storage_engine/type_bit_indexes.result 2017-12-12 20:34:34.000000000 +0200
++++ suite/storage_engine/type_bit_indexes.reject 2017-12-12 20:35:24.539330056 +0200
+@@ -69,7 +69,7 @@
+ (1,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF);
+ EXPLAIN SELECT HEX(b+c) FROM t1 WHERE c > 1 OR HEX(b) < 0xFFFFFF;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # # # b_c # # # #
++# # # # # NULL # # # #
+ SELECT HEX(b+c) FROM t1 WHERE c > 1 OR HEX(b) < 0xFFFFFF;
+ HEX(b+c)
+ 10
+@@ -98,7 +98,7 @@
+ (1,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF);
+ EXPLAIN SELECT DISTINCT a+0 FROM t1 ORDER BY a;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # # # a # # # #
++# # # # # NULL # # # #
+ SELECT DISTINCT a+0 FROM t1 ORDER BY a;
+ a+0
+ 0
diff --git a/storage/rocksdb/mysql-test/storage_engine/type_enum_indexes.rdiff b/storage/rocksdb/mysql-test/storage_engine/type_enum_indexes.rdiff
new file mode 100644
index 00000000000..be83fb6e212
--- /dev/null
+++ b/storage/rocksdb/mysql-test/storage_engine/type_enum_indexes.rdiff
@@ -0,0 +1,11 @@
+--- suite/storage_engine/type_enum_indexes.result 2017-03-12 04:38:50.000000000 +0200
++++ suite/storage_engine/type_enum_indexes.reject 2017-12-12 20:36:47.455331726 +0200
+@@ -30,7 +30,7 @@
+ t1 0 a_b 2 b # # NULL NULL # #
+ EXPLAIN SELECT a FROM t1 WHERE b > 'test2' ORDER BY a;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # # # a_b # # # #
++# # # # # NULL # # # #
+ SELECT a FROM t1 WHERE b > 'test2' ORDER BY a;
+ a
+ Africa
diff --git a/storage/rocksdb/mysql-test/storage_engine/type_set_indexes.rdiff b/storage/rocksdb/mysql-test/storage_engine/type_set_indexes.rdiff
new file mode 100644
index 00000000000..2703e81b745
--- /dev/null
+++ b/storage/rocksdb/mysql-test/storage_engine/type_set_indexes.rdiff
@@ -0,0 +1,20 @@
+--- suite/storage_engine/type_set_indexes.result 2017-03-12 04:38:50.000000000 +0200
++++ suite/storage_engine/type_set_indexes.reject 2017-12-12 20:37:16.187332305 +0200
+@@ -97,7 +97,7 @@
+ Warning 1265 Data truncated for column 'b' at row 7
+ EXPLAIN SELECT a FROM t1 WHERE FIND_IN_SET('Europe',a) > 0;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # # # a # # # #
++# # # # # NULL # # # #
+ SELECT a FROM t1 WHERE FIND_IN_SET('Europe',a) > 0;
+ a
+ Africa,Europe,Asia
+@@ -124,7 +124,7 @@
+ Warning 1265 Data truncated for column 'b' at row 7
+ EXPLAIN SELECT DISTINCT a, b FROM t1 ORDER BY b DESC, a;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # # # b_a # # # #
++# # # # # NULL # # # #
+ SELECT DISTINCT a, b FROM t1 ORDER BY b DESC, a;
+ a b
+ test1,test3
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result
index 73c010c6eb7..ab33725fa3f 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_row_log.result
@@ -226,7 +226,6 @@ master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Rotate # # master-bin.000002;pos=POS
include/show_binlog_events.inc
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 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
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
include/show_binlog_events.inc
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 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
slave-bin.000002 # Gtid # # BEGIN GTID #-#-#
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result
index 83335b0237c..652ef18c039 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_stm_log.result
@@ -222,7 +222,6 @@ master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Rotate # # master-bin.000002;pos=POS
include/show_binlog_events.inc
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 # Query # # use `test`; create table t3 (a int)ENGINE=TokuDB
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
include/show_binlog_events.inc
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 # Query # # use `test`; create table t2 (n int)ENGINE=TokuDB
slave-bin.000002 # Gtid # # BEGIN GTID #-#-#
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 987e86c3927..f4184d48c32 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -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
if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) {
sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n"
@@ -5454,8 +5465,8 @@ innobase_kill_connection(
wsrep_thd_is_BF(current_thd, FALSE),
lock_get_info(trx->lock.wait_lock).c_str());
- if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
- trx->abort_type == TRX_SERVER_ABORT) {
+ if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)
+ && trx->abort_type == TRX_SERVER_ABORT) {
ut_ad(!lock_mutex_own());
lock_mutex_enter();
}
@@ -20463,7 +20474,7 @@ static MYSQL_SYSVAR_ENUM(empty_free_list_algorithm,
&innodb_empty_free_list_algorithm_typelib);
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"
" a lock is released. Possible values are"
" FCFS"
diff --git a/storage/xtradb/include/que0que.h b/storage/xtradb/include/que0que.h
index e5b2a1ba3fc..005f28d2af1 100644
--- a/storage/xtradb/include/que0que.h
+++ b/storage/xtradb/include/que0que.h
@@ -385,9 +385,6 @@ struct que_thr_t{
thrs; /*!< list of thread nodes of the fork
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)
queue; /*!< list of runnable thread nodes in
the server task queue */
ulint fk_cascade_depth; /*!< maximum cascading call depth
diff --git a/storage/xtradb/include/trx0roll.h b/storage/xtradb/include/trx0roll.h
index b2e9d8a077f..565079b17b4 100644
--- a/storage/xtradb/include/trx0roll.h
+++ b/storage/xtradb/include/trx0roll.h
@@ -1,6 +1,7 @@
/*****************************************************************************
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
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 "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
@@ -104,6 +106,11 @@ trx_undo_rec_release(
/*=================*/
trx_t* trx, /*!< in/out: transaction */
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
encountered in crash recovery. If the transaction already was
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index ddaeff69f10..20e3f5adeb7 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -937,14 +937,21 @@ lock_reset_lock_and_trx_wait(
ib_logf(IB_LOG_LEVEL_INFO,
"Trx id " TRX_ID_FMT
- " is waiting a lock in statement %s"
+ " is waiting a lock "
" for this trx id " TRX_ID_FMT
- " and statement %s wait_lock %p",
+ " wait_lock %p",
lock->trx->id,
- stmt ? stmt : "NULL",
trx_id,
- stmt2 ? stmt2 : "NULL",
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);
}
@@ -1162,7 +1169,7 @@ lock_rec_has_to_wait(
type_mode, lock_is_on_supremum);
fprintf(stderr,
"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) );
lock_rec_print(stderr, lock2);
if (for_locking) return FALSE;
@@ -1714,7 +1721,7 @@ lock_rec_other_has_expl_req(
ulint heap_no,/*!< in: heap number of the record */
trx_id_t trx_id) /*!< in: transaction */
{
- const lock_t* lock;
+ lock_t* lock;
ut_ad(lock_mutex_own());
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);
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
&& (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.
@return lock or NULL */
static
-const lock_t*
+lock_t*
lock_rec_other_has_conflicting(
/*===========================*/
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 */
const trx_t* trx) /*!< in: our transaction */
{
- const lock_t* lock;
+ lock_t* lock;
ibool is_supremum;
ut_ad(lock_mutex_own());
@@ -1831,13 +1838,16 @@ lock_rec_other_has_conflicting(
for (lock = lock_rec_get_first(block, heap_no);
lock != NULL;
- lock = lock_rec_get_next_const(heap_no, lock)) {
+ lock = lock_rec_get_next(heap_no, lock)) {
#ifdef WITH_WSREP
if (lock_rec_has_to_wait(TRUE, trx, mode, lock, is_supremum)) {
if (wsrep_on_trx(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);
}
#else
@@ -2045,15 +2055,17 @@ wsrep_print_wait_locks(
{
if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) {
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);
- else
+ } else {
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);
- else
+ } else {
lock_rec_print(stderr, c_lock->trx->lock.wait_lock);
+ }
}
}
#endif /* WITH_WSREP */
@@ -2358,8 +2370,8 @@ lock_rec_create(
if (wsrep_debug) {
fprintf(
stderr,
- "WSREP: c_lock canceled %llu\n",
- (ulonglong) c_lock->trx->id);
+ "WSREP: c_lock canceled " TRX_ID_FMT "\n",
+ c_lock->trx->id);
}
/* have to bail out here to avoid lock_set_lock... */
@@ -2551,6 +2563,16 @@ lock_rec_enqueue_waiting(
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.
if (err != DB_DEADLOCK
&& innodb_lock_schedule_algorithm
@@ -2981,6 +3003,15 @@ lock_rec_has_to_wait_in_queue(
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) &&
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 */
continue;
}
@@ -3139,7 +3170,7 @@ lock_grant_and_move_on_page(
&& !lock_rec_has_to_wait_in_queue(lock)) {
lock_grant(lock, false);
-
+
if (previous != NULL) {
/* Move the lock to the head of the list. */
HASH_GET_NEXT(hash, previous) = HASH_GET_NEXT(hash, lock);
@@ -5017,8 +5048,8 @@ lock_table_create(
}
if (wsrep_debug) {
- fprintf(stderr, "WSREP: c_lock canceled %llu\n",
- (ulonglong) c_lock->trx->id);
+ fprintf(stderr, "WSREP: c_lock canceled " TRX_ID_FMT "\n",
+ c_lock->trx->id);
}
}
if (c_lock) {
@@ -5297,7 +5328,7 @@ Checks if other transactions have an incompatible mode lock request in
the lock queue.
@return lock or NULL */
UNIV_INLINE
-const lock_t*
+lock_t*
lock_table_other_has_incompatible(
/*==============================*/
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 */
enum lock_mode mode) /*!< in: lock mode */
{
- const lock_t* lock;
+ lock_t* lock;
ut_ad(lock_mutex_own());
@@ -5361,7 +5392,7 @@ lock_table(
#endif
trx_t* trx;
dberr_t err;
- const lock_t* wait_for;
+ lock_t* wait_for;
ut_ad(table != NULL);
ut_ad(thr != NULL);
@@ -5412,13 +5443,13 @@ lock_table(
if (wait_for != NULL) {
#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
err = lock_table_enqueue_waiting(mode | flags, table, thr);
#endif
} else {
#ifdef WITH_WSREP
- lock_table_create(c_lock, table, mode | flags, trx);
+ lock_table_create(c_lock, table, mode | flags, trx);
#else
lock_table_create(table, mode | flags, trx);
#endif
@@ -7101,10 +7132,10 @@ lock_rec_insert_check_and_lock(
on the successor, which produced an unnecessary deadlock. */
#ifdef WITH_WSREP
- if ((c_lock = (ib_lock_t*)lock_rec_other_has_conflicting(
- static_cast<enum lock_mode>(
- LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
- block, next_rec_heap_no, trx))) {
+ if ((c_lock = lock_rec_other_has_conflicting(
+ static_cast<enum lock_mode>(
+ LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
+ block, next_rec_heap_no, trx))) {
#else
if (lock_rec_other_has_conflicting(
static_cast<enum lock_mode>(
@@ -7117,7 +7148,7 @@ lock_rec_insert_check_and_lock(
#ifdef WITH_WSREP
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);
#else
err = lock_rec_enqueue_waiting(
diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc
index ca9d05a4829..a0f557e18e5 100644
--- a/storage/xtradb/lock/lock0wait.cc
+++ b/storage/xtradb/lock/lock0wait.cc
@@ -191,22 +191,25 @@ lock_wait_table_reserve_slot(
/*********************************************************************//**
check if lock timeout was for priority thread,
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 */
-static ibool
+static
+bool
wsrep_is_BF_lock_timeout(
-/*====================*/
- trx_t* trx) /* in: trx to check for lock priority */
+ const trx_t* trx,
+ bool locked = true)
{
- if (wsrep_on_trx(trx) &&
- wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
- fprintf(stderr, "WSREP: BF lock wait long\n");
- srv_print_innodb_monitor = TRUE;
- srv_print_innodb_lock_monitor = TRUE;
- os_event_set(srv_monitor_event);
- return TRUE;
- }
- return FALSE;
- }
+ if (wsrep_on_trx(trx)
+ && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
+ fprintf(stderr, "WSREP: BF lock wait long for trx " TRX_ID_FMT "\n", trx->id);
+ srv_print_innodb_monitor = TRUE;
+ srv_print_innodb_lock_monitor = TRUE;
+ os_event_set(srv_monitor_event);
+ return true;
+ }
+ return false;
+}
#endif /* WITH_WSREP */
/***************************************************************//**
@@ -402,15 +405,15 @@ lock_wait_suspend_thread(
if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) {
#ifdef WITH_WSREP
- if (!wsrep_on_trx(trx) ||
- (!wsrep_is_BF_lock_timeout(trx) &&
- trx->error_state != DB_DEADLOCK)) {
+ if (!wsrep_on_trx(trx) ||
+ (!wsrep_is_BF_lock_timeout(trx) &&
+ trx->error_state != DB_DEADLOCK)) {
#endif /* WITH_WSREP */
- trx->error_state = DB_LOCK_WAIT_TIMEOUT;
+ trx->error_state = DB_LOCK_WAIT_TIMEOUT;
#ifdef WITH_WSREP
- }
+ }
#endif /* WITH_WSREP */
MONITOR_INC(MONITOR_TIMEOUT);
}
diff --git a/storage/xtradb/row/row0undo.cc b/storage/xtradb/row/row0undo.cc
index 82b1ab049fa..552b99ab4d4 100644
--- a/storage/xtradb/row/row0undo.cc
+++ b/storage/xtradb/row/row0undo.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
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
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);
+ 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);
trx->error_state = err;
diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc
index 335ef8859c4..9a5fcea71de 100644
--- a/storage/xtradb/trx/trx0roll.cc
+++ b/storage/xtradb/trx/trx0roll.cc
@@ -24,6 +24,9 @@ Transaction rollback
Created 3/26/1996 Heikki Tuuri
*******************************************************/
+#include "my_config.h"
+#include <my_systemd.h>
+
#include "trx0roll.h"
#ifdef UNIV_NONINL
@@ -60,14 +63,7 @@ rollback */
bool trx_rollback_or_clean_is_active;
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
-static const trx_t* trx_roll_crash_recv_trx = NULL;
-
-/** 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;
+const trx_t* trx_roll_crash_recv_trx;
/****************************************************************//**
Finishes a transaction rollback. */
@@ -564,8 +560,6 @@ trx_rollback_active(
que_thr_t* thr;
roll_node_t* roll_node;
dict_table_t* table;
- ib_int64_t rows_to_undo;
- const char* unit = "";
ibool dictionary_locked = FALSE;
heap = mem_heap_create(512);
@@ -584,30 +578,8 @@ trx_rollback_active(
ut_a(thr == que_fork_start_command(fork));
- mutex_enter(&trx_sys->mutex);
-
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) {
row_mysql_lock_data_dictionary(trx);
dictionary_locked = TRUE;
@@ -618,6 +590,16 @@ trx_rollback_active(
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));
/* 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) {
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);
trx_roll_crash_recv_trx = NULL;
@@ -685,7 +668,7 @@ ibool
trx_rollback_resurrected(
/*=====================*/
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 */
{
ut_ad(mutex_own(&trx_sys->mutex));
@@ -696,16 +679,15 @@ trx_rollback_resurrected(
to accidentally clean up a non-recovered transaction here. */
trx_mutex_enter(trx);
- bool is_recovered = trx->is_recovered;
- trx_state_t state = trx->state;
- trx_mutex_exit(trx);
-
- if (!is_recovered) {
+ if (!trx->is_recovered) {
+func_exit:
+ trx_mutex_exit(trx);
return(FALSE);
}
- switch (state) {
+ switch (trx->state) {
case TRX_STATE_COMMITTED_IN_MEMORY:
+ trx_mutex_exit(trx);
mutex_exit(&trx_sys->mutex);
fprintf(stderr,
"InnoDB: Cleaning up trx with id " TRX_ID_FMT "\n",
@@ -714,21 +696,83 @@ trx_rollback_resurrected(
trx_free_for_background(trx);
return(TRUE);
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);
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);
return(TRUE);
}
return(FALSE);
case TRX_STATE_PREPARED:
- return(FALSE);
+ goto func_exit;
case TRX_STATE_NOT_STARTED:
break;
}
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);
- if (srv_shutdown_state != SRV_SHUTDOWN_NONE
- && srv_fast_shutdown != 0) {
- all = FALSE;
- break;
- }
-
/* If this function does a cleanup or rollback
then it will release the trx_sys->mutex, therefore
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);
@@ -1118,7 +1156,6 @@ trx_roll_pop_top_rec_of_trx(
undo_no_t undo_no;
ibool is_insert;
trx_rseg_t* rseg;
- ulint progress_pct;
mtr_t mtr;
rseg = trx->rseg;
@@ -1176,27 +1213,6 @@ try_again:
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;
if (!trx_undo_arr_store_info(trx, undo_no)) {
diff --git a/storage/xtradb/trx/trx0undo.cc b/storage/xtradb/trx/trx0undo.cc
index 3259bcb70b1..24d14e06080 100644
--- a/storage/xtradb/trx/trx0undo.cc
+++ b/storage/xtradb/trx/trx0undo.cc
@@ -2023,10 +2023,14 @@ trx_undo_free_prepared(
/* fall through */
case TRX_UNDO_ACTIVE:
/* 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
|| srv_apply_log_only
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
+ || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
+ || srv_fast_shutdown);
break;
default:
ut_error;
@@ -2048,10 +2052,14 @@ trx_undo_free_prepared(
/* fall through */
case TRX_UNDO_ACTIVE:
/* 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
|| srv_apply_log_only
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
+ || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
+ || srv_fast_shutdown);
break;
default:
ut_error;