mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge bb-10.2-ext into 10.3
MDEV-11415 Remove excessive undo logging during ALTER TABLE…ALGORITHM=COPY Move a test from innodb.rename_table_debug to innodb.alter_copy. ha_innobase::extra(HA_EXTRA_BEGIN_ALTER_COPY): Register id-versioned tables so that mysql.transaction_registry will be updated, even for empty tables that are subjected to ALTER TABLE…ALGORITHM=COPY.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 1995, 2017, MariaDB Corporation.
|
||||
Copyright (c) 1995, 2018, 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
|
||||
@@ -208,7 +208,13 @@ enum ha_extra_function {
|
||||
Used in ha_partition::handle_ordered_index_scan() to inform engine
|
||||
that we are starting an ordered index scan. Needed by Spider
|
||||
*/
|
||||
HA_EXTRA_STARTING_ORDERED_INDEX_SCAN
|
||||
HA_EXTRA_STARTING_ORDERED_INDEX_SCAN,
|
||||
/** Start writing rows during ALTER TABLE...ALGORITHM=COPY. */
|
||||
HA_EXTRA_BEGIN_ALTER_COPY,
|
||||
/** Finish writing rows during ALTER TABLE...ALGORITHM=COPY. */
|
||||
HA_EXTRA_END_ALTER_COPY,
|
||||
/** Fake the start of a statement after wsrep_load_data_splitting hack */
|
||||
HA_EXTRA_FAKE_START_STMT
|
||||
};
|
||||
|
||||
/* Compatible option, to be deleted in 6.0 */
|
||||
|
||||
213
mysql-test/suite/innodb/r/alter_copy.result
Normal file
213
mysql-test/suite/innodb/r/alter_copy.result
Normal file
@@ -0,0 +1,213 @@
|
||||
#
|
||||
# MDEV-11415 AVOID INTERMEDIATE COMMIT WHILE DOING
|
||||
# ALTER TABLE...ALGORITHM=COPY
|
||||
#
|
||||
CREATE TABLE t(a SERIAL, b INT, c INT, d INT) ENGINE=InnoDB;
|
||||
CREATE TABLE t1(a INT, b TEXT, c TEXT,
|
||||
FULLTEXT(b), FULLTEXT(c(3)), FULLTEXT(b,c)) ENGINE=InnoDB;
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
SELECT COUNT(*) FROM t;
|
||||
COUNT(*)
|
||||
999
|
||||
UPDATE t SET b=a%7, c=a%11, d=a%13;
|
||||
INSERT INTO t1 VALUES(1, 'This is a first b column', 'This is a first c column');
|
||||
INSERT INTO t1 VALUES(2, 'This is a second b column', 'This is a second c column');
|
||||
INSERT INTO t1(a) VALUES(3);
|
||||
INSERT INTO t1 VALUES(4, 'This is a third b column', 'This is a third c column');
|
||||
DELETE FROM t1 WHERE a = 2;
|
||||
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
4 This is a third b column This is a third c column
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` text DEFAULT NULL,
|
||||
`c` text DEFAULT NULL,
|
||||
FULLTEXT KEY `b` (`b`),
|
||||
FULLTEXT KEY `c` (`c`),
|
||||
FULLTEXT KEY `b_2` (`b`,`c`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
|
||||
SET DEBUG_DBUG='+d,crash_commit_before';
|
||||
ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
|
||||
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
|
||||
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
|
||||
ADD INDEX(c,a,b,d),ADD INDEX(c,a,d,b),ADD INDEX(c,b,a,d),ADD INDEX(c,b,d,a),
|
||||
ADD INDEX(c,d,a,b),ADD INDEX(c,d,b,a),ADD INDEX(d,a,b,c),ADD INDEX(d,a,c,b),
|
||||
ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
|
||||
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
|
||||
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
|
||||
ALGORITHM=COPY;
|
||||
ERROR HY000: Lost connection to MySQL server during query
|
||||
#sql-temporary.frm
|
||||
#sql-temporary.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTSBEING_DELETED.ibd
|
||||
FTSBEING_DELETED_CACHE.ibd
|
||||
FTSCONFIG.ibd
|
||||
FTSDELETED.ibd
|
||||
FTSDELETED_CACHE.ibd
|
||||
t.frm
|
||||
t.ibd
|
||||
t1.frm
|
||||
t1.ibd
|
||||
SHOW CREATE TABLE t;
|
||||
Table Create Table
|
||||
t CREATE TABLE `t` (
|
||||
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
`d` int(11) DEFAULT NULL,
|
||||
UNIQUE KEY `a` (`a`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=latin1
|
||||
SELECT COUNT(*) FROM t;
|
||||
COUNT(*)
|
||||
999
|
||||
CHECK TABLE t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
4 This is a third b column This is a third c column
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` text DEFAULT NULL,
|
||||
`c` text DEFAULT NULL,
|
||||
FULLTEXT KEY `b` (`b`),
|
||||
FULLTEXT KEY `c` (`c`),
|
||||
FULLTEXT KEY `b_2` (`b`,`c`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
#sql-temporary.frm
|
||||
#sql-temporary.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTSBEING_DELETED.ibd
|
||||
FTSBEING_DELETED_CACHE.ibd
|
||||
FTSCONFIG.ibd
|
||||
FTSDELETED.ibd
|
||||
FTSDELETED_CACHE.ibd
|
||||
t.frm
|
||||
t.ibd
|
||||
t1.frm
|
||||
t1.ibd
|
||||
SHOW CREATE TABLE t;
|
||||
Table Create Table
|
||||
t CREATE TABLE `t` (
|
||||
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
`d` int(11) DEFAULT NULL,
|
||||
UNIQUE KEY `a` (`a`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=latin1
|
||||
SELECT COUNT(*) FROM t;
|
||||
COUNT(*)
|
||||
999
|
||||
CHECK TABLE t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||
a b c
|
||||
1 This is a first b column This is a first c column
|
||||
4 This is a third b column This is a third c column
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` text DEFAULT NULL,
|
||||
`c` text DEFAULT NULL,
|
||||
FULLTEXT KEY `b` (`b`),
|
||||
FULLTEXT KEY `c` (`c`),
|
||||
FULLTEXT KEY `b_2` (`b`,`c`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
#sql-temporary.frm
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTS_INDEX_1.ibd
|
||||
FTS_INDEX_2.ibd
|
||||
FTS_INDEX_3.ibd
|
||||
FTS_INDEX_4.ibd
|
||||
FTS_INDEX_5.ibd
|
||||
FTS_INDEX_6.ibd
|
||||
FTSBEING_DELETED.ibd
|
||||
FTSBEING_DELETED_CACHE.ibd
|
||||
FTSCONFIG.ibd
|
||||
FTSDELETED.ibd
|
||||
FTSDELETED_CACHE.ibd
|
||||
t.frm
|
||||
t.ibd
|
||||
t1.frm
|
||||
t1.ibd
|
||||
DROP TABLE t1,t;
|
||||
@@ -9,27 +9,4 @@ disconnect con1;
|
||||
SELECT * FROM t1;
|
||||
a b c d
|
||||
1 NULL NULL NULL
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
UPDATE t1 SET b=a%7, c=a%11, d=a%13;
|
||||
SET DEBUG_DBUG='+d,crash_commit_before';
|
||||
ALTER TABLE t1
|
||||
ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
|
||||
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
|
||||
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
|
||||
ADD INDEX(c,a,b,d),ADD INDEX(c,a,d,b),ADD INDEX(c,b,a,d),ADD INDEX(c,b,d,a),
|
||||
ADD INDEX(c,d,a,b),ADD INDEX(c,d,b,a),ADD INDEX(d,a,b,c),ADD INDEX(d,a,c,b),
|
||||
ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
|
||||
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
|
||||
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
|
||||
ALGORITHM=COPY;
|
||||
ERROR HY000: Lost connection to MySQL server during query
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
1000
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL innodb_background_drop_list_empty=
|
||||
@@GLOBAL.innodb_background_drop_list_empty;
|
||||
|
||||
91
mysql-test/suite/innodb/t/alter_copy.test
Normal file
91
mysql-test/suite/innodb/t/alter_copy.test
Normal file
@@ -0,0 +1,91 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-11415 AVOID INTERMEDIATE COMMIT WHILE DOING
|
||||
--echo # ALTER TABLE...ALGORITHM=COPY
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t(a SERIAL, b INT, c INT, d INT) ENGINE=InnoDB;
|
||||
CREATE TABLE t1(a INT, b TEXT, c TEXT,
|
||||
FULLTEXT(b), FULLTEXT(c(3)), FULLTEXT(b,c)) ENGINE=InnoDB;
|
||||
|
||||
let $c = 999;
|
||||
BEGIN;
|
||||
--disable_query_log
|
||||
while ($c) {
|
||||
INSERT INTO t() VALUES();
|
||||
dec $c;
|
||||
}
|
||||
--enable_query_log
|
||||
COMMIT;
|
||||
|
||||
SELECT COUNT(*) FROM t;
|
||||
# try to make the to-be-created secondary index keys randomly distributed
|
||||
UPDATE t SET b=a%7, c=a%11, d=a%13;
|
||||
|
||||
INSERT INTO t1 VALUES(1, 'This is a first b column', 'This is a first c column');
|
||||
INSERT INTO t1 VALUES(2, 'This is a second b column', 'This is a second c column');
|
||||
INSERT INTO t1(a) VALUES(3);
|
||||
INSERT INTO t1 VALUES(4, 'This is a third b column', 'This is a third c column');
|
||||
DELETE FROM t1 WHERE a = 2;
|
||||
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||
SHOW CREATE TABLE t1;
|
||||
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
|
||||
|
||||
# crash right after the last write_row(), before the first commit of ALTER TABLE
|
||||
--source include/expect_crash.inc
|
||||
|
||||
SET DEBUG_DBUG='+d,crash_commit_before';
|
||||
--error 2013
|
||||
# create 32 secondary indexes
|
||||
ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
|
||||
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
|
||||
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
|
||||
ADD INDEX(c,a,b,d),ADD INDEX(c,a,d,b),ADD INDEX(c,b,a,d),ADD INDEX(c,b,d,a),
|
||||
ADD INDEX(c,d,a,b),ADD INDEX(c,d,b,a),ADD INDEX(d,a,b,c),ADD INDEX(d,a,c,b),
|
||||
ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
|
||||
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
|
||||
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
|
||||
ALGORITHM=COPY;
|
||||
|
||||
--let $restart_parameters= --innodb-force-recovery=3
|
||||
--source include/start_mysqld.inc
|
||||
let $datadir=`select @@datadir`;
|
||||
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
|
||||
--list_files $datadir/test
|
||||
SHOW CREATE TABLE t;
|
||||
SELECT COUNT(*) FROM t;
|
||||
CHECK TABLE t;
|
||||
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||
SHOW CREATE TABLE t1;
|
||||
CHECK TABLE t1;
|
||||
|
||||
--let $restart_parameters= --innodb-read-only
|
||||
--source include/restart_mysqld.inc
|
||||
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
|
||||
|
||||
--list_files $datadir/test
|
||||
SHOW CREATE TABLE t;
|
||||
SELECT COUNT(*) FROM t;
|
||||
CHECK TABLE t;
|
||||
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||
SHOW CREATE TABLE t1;
|
||||
CHECK TABLE t1;
|
||||
|
||||
--let $restart_parameters=
|
||||
--source include/restart_mysqld.inc
|
||||
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
|
||||
--list_files $datadir/test
|
||||
DROP TABLE t1,t;
|
||||
|
||||
# Work around missing crash recovery at the SQL layer.
|
||||
--remove_files_wildcard $datadir/test #sql-*.frm
|
||||
@@ -18,37 +18,4 @@ SET DEBUG_SYNC='now WAIT_FOR renamed';
|
||||
--source include/restart_mysqld.inc
|
||||
--disconnect con1
|
||||
SELECT * FROM t1;
|
||||
|
||||
let $c = 999;
|
||||
BEGIN;
|
||||
--disable_query_log
|
||||
while ($c) {
|
||||
INSERT INTO t1() VALUES();
|
||||
dec $c;
|
||||
}
|
||||
--enable_query_log
|
||||
COMMIT;
|
||||
UPDATE t1 SET b=a%7, c=a%11, d=a%13;
|
||||
|
||||
--source include/expect_crash.inc
|
||||
SET DEBUG_DBUG='+d,crash_commit_before';
|
||||
--error 2013
|
||||
ALTER TABLE t1
|
||||
ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
|
||||
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
|
||||
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
|
||||
ADD INDEX(c,a,b,d),ADD INDEX(c,a,d,b),ADD INDEX(c,b,a,d),ADD INDEX(c,b,d,a),
|
||||
ADD INDEX(c,d,a,b),ADD INDEX(c,d,b,a),ADD INDEX(d,a,b,c),ADD INDEX(d,a,c,b),
|
||||
ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
|
||||
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
|
||||
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
|
||||
ALGORITHM=COPY;
|
||||
--source include/start_mysqld.inc
|
||||
CHECK TABLE t1;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
DROP TABLE t1;
|
||||
# MDEV-11415 TODO: remove the following
|
||||
SET GLOBAL innodb_background_drop_list_empty=
|
||||
@@GLOBAL.innodb_background_drop_list_empty;
|
||||
# Work around missing crash recovery at the SQL layer.
|
||||
--remove_files_wildcard $datadir/test #sql-*.frm
|
||||
|
||||
@@ -53,8 +53,8 @@ add column e bigint unsigned as row end,
|
||||
add period for system_time(s, e),
|
||||
add system versioning,
|
||||
algorithm=copy;
|
||||
select check_result(count(*) = @tmp) from mysql.transaction_registry;
|
||||
check_result(count(*) = @tmp)
|
||||
select check_result(count(*) = @tmp + 1) from mysql.transaction_registry;
|
||||
check_result(count(*) = @tmp + 1)
|
||||
[CORRECT]
|
||||
# TRX_ID to TIMESTAMP versioning switch
|
||||
create or replace table t1 (
|
||||
|
||||
@@ -57,8 +57,8 @@ alter table t1
|
||||
add period for system_time(s, e),
|
||||
add system versioning,
|
||||
algorithm=copy;
|
||||
select check_result(count(*) = @tmp) from mysql.transaction_registry;
|
||||
|
||||
# With MDEV-14511 the transaction will be registered even for empty tables.
|
||||
select check_result(count(*) = @tmp + 1) from mysql.transaction_registry;
|
||||
|
||||
--echo # TRX_ID to TIMESTAMP versioning switch
|
||||
create or replace table t1 (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2005, 2017, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2017, MariaDB
|
||||
Copyright (c) 2009, 2018, MariaDB
|
||||
|
||||
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
|
||||
@@ -8897,6 +8897,9 @@ int ha_partition::extra(enum ha_extra_function operation)
|
||||
*/
|
||||
DBUG_RETURN(ER_UNSUPORTED_LOG_ENGINE);
|
||||
case HA_EXTRA_STARTING_ORDERED_INDEX_SCAN:
|
||||
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||
case HA_EXTRA_END_ALTER_COPY:
|
||||
case HA_EXTRA_FAKE_START_STMT:
|
||||
DBUG_RETURN(loop_extra(operation));
|
||||
default:
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2017, MariaDB Corporation
|
||||
Copyright (c) 2010, 2018, 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
|
||||
@@ -97,6 +97,45 @@ public:
|
||||
#define GET (stack_pos != stack ? *--stack_pos : my_b_get(&cache))
|
||||
#define PUSH(A) *(stack_pos++)=(A)
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
/** If requested by wsrep_load_data_splitting, commit and restart
|
||||
the transaction after every 10,000 inserted rows. */
|
||||
|
||||
static bool wsrep_load_data_split(THD *thd, const TABLE *table,
|
||||
const COPY_INFO &info)
|
||||
{
|
||||
extern struct handlerton* innodb_hton_ptr;
|
||||
|
||||
DBUG_ENTER("wsrep_load_data_split");
|
||||
|
||||
if (wsrep_load_data_splitting && wsrep_on(thd)
|
||||
&& info.records && !(info.records % 10000)
|
||||
&& thd->transaction.stmt.ha_list
|
||||
&& thd->transaction.stmt.ha_list->ht() == binlog_hton
|
||||
&& thd->transaction.stmt.ha_list->next()
|
||||
&& thd->transaction.stmt.ha_list->next()->ht() == innodb_hton_ptr
|
||||
&& !thd->transaction.stmt.ha_list->next()->next())
|
||||
{
|
||||
WSREP_DEBUG("intermediate transaction commit in LOAD DATA");
|
||||
if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true);
|
||||
if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true);
|
||||
wsrep_post_commit(thd, true);
|
||||
innodb_hton_ptr->commit(innodb_hton_ptr, thd, true);
|
||||
table->file->extra(HA_EXTRA_FAKE_START_STMT);
|
||||
}
|
||||
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
# define WSREP_LOAD_DATA_SPLIT(thd,table,info) \
|
||||
if (wsrep_load_data_split(thd,table,info)) \
|
||||
{ \
|
||||
table->auto_increment_field_not_null= FALSE; \
|
||||
DBUG_RETURN(1); \
|
||||
}
|
||||
#else /* WITH_WSREP */
|
||||
#define WSREP_LOAD_DATA_SPLIT(thd,table,info) /* empty */
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
class READ_INFO {
|
||||
File file;
|
||||
String data; /* Read buffer */
|
||||
@@ -989,6 +1028,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
WSREP_LOAD_DATA_SPLIT(thd, table, info);
|
||||
err= write_record(thd, table, &info);
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
if (err)
|
||||
@@ -1194,6 +1234,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
WSREP_LOAD_DATA_SPLIT(thd, table, info);
|
||||
err= write_record(thd, table, &info);
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
if (err)
|
||||
@@ -1348,6 +1389,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
WSREP_LOAD_DATA_SPLIT(thd, table, info);
|
||||
err= write_record(thd, table, &info);
|
||||
table->auto_increment_field_not_null= false;
|
||||
if (err)
|
||||
|
||||
@@ -10357,6 +10357,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
|
||||
thd->progress.max_counter= from->file->records();
|
||||
time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
|
||||
if (!ignore) /* for now, InnoDB needs the undo log for ALTER IGNORE */
|
||||
to->file->extra(HA_EXTRA_BEGIN_ALTER_COPY);
|
||||
|
||||
while (!(error= info.read_record()))
|
||||
{
|
||||
@@ -10516,6 +10518,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
to->file->print_error(my_errno,MYF(0));
|
||||
error= 1;
|
||||
}
|
||||
if (!ignore)
|
||||
to->file->extra(HA_EXTRA_END_ALTER_COPY);
|
||||
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
if (mysql_trans_commit_alter_copy_data(thd))
|
||||
|
||||
@@ -2309,7 +2309,6 @@ fts_savepoint_create(
|
||||
/******************************************************************//**
|
||||
Create an FTS trx.
|
||||
@return FTS trx */
|
||||
static
|
||||
fts_trx_t*
|
||||
fts_trx_create(
|
||||
/*===========*/
|
||||
@@ -3340,6 +3339,144 @@ fts_fetch_doc_from_rec(
|
||||
}
|
||||
}
|
||||
|
||||
/** Fetch the data from tuple and tokenize the document.
|
||||
@param[in] get_doc FTS index's get_doc struct
|
||||
@param[in] tuple tuple should be arranged in table schema order
|
||||
@param[out] doc fts doc to hold parsed documents. */
|
||||
static
|
||||
void
|
||||
fts_fetch_doc_from_tuple(
|
||||
fts_get_doc_t* get_doc,
|
||||
const dtuple_t* tuple,
|
||||
fts_doc_t* doc)
|
||||
{
|
||||
dict_index_t* index;
|
||||
st_mysql_ftparser* parser;
|
||||
ulint doc_len = 0;
|
||||
ulint processed_doc = 0;
|
||||
ulint num_field;
|
||||
|
||||
if (get_doc == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = get_doc->index_cache->index;
|
||||
parser = get_doc->index_cache->index->parser;
|
||||
num_field = dict_index_get_n_fields(index);
|
||||
|
||||
for (ulint i = 0; i < num_field; i++) {
|
||||
const dict_field_t* ifield;
|
||||
const dict_col_t* col;
|
||||
ulint pos;
|
||||
dfield_t* field;
|
||||
|
||||
ifield = dict_index_get_nth_field(index, i);
|
||||
col = dict_field_get_col(ifield);
|
||||
pos = dict_col_get_no(col);
|
||||
field = dtuple_get_nth_field(tuple, pos);
|
||||
|
||||
if (!get_doc->index_cache->charset) {
|
||||
get_doc->index_cache->charset = fts_get_charset(
|
||||
ifield->col->prtype);
|
||||
}
|
||||
|
||||
ut_ad(!dfield_is_ext(field));
|
||||
|
||||
doc->text.f_str = (byte*) dfield_get_data(field);
|
||||
doc->text.f_len = dfield_get_len(field);
|
||||
doc->found = TRUE;
|
||||
doc->charset = get_doc->index_cache->charset;
|
||||
|
||||
/* field data is NULL. */
|
||||
if (doc->text.f_len == UNIV_SQL_NULL || doc->text.f_len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (processed_doc == 0) {
|
||||
fts_tokenize_document(doc, NULL, parser);
|
||||
} else {
|
||||
fts_tokenize_document_next(doc, doc_len, NULL, parser);
|
||||
}
|
||||
|
||||
processed_doc++;
|
||||
doc_len += doc->text.f_len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Fetch the document from tuple, tokenize the text data and
|
||||
insert the text data into fts auxiliary table and
|
||||
its cache. Moreover this tuple fields doesn't contain any information
|
||||
about externally stored field. This tuple contains data directly
|
||||
converted from mysql.
|
||||
@param[in] ftt FTS transaction table
|
||||
@param[in] doc_id doc id
|
||||
@param[in] tuple tuple from where data can be retrieved
|
||||
and tuple should be arranged in table
|
||||
schema order. */
|
||||
void
|
||||
fts_add_doc_from_tuple(
|
||||
fts_trx_table_t*ftt,
|
||||
doc_id_t doc_id,
|
||||
const dtuple_t* tuple)
|
||||
{
|
||||
mtr_t mtr;
|
||||
fts_cache_t* cache = ftt->table->fts->cache;
|
||||
|
||||
ut_ad(cache->get_docs);
|
||||
|
||||
if (!(ftt->table->fts->fts_status & ADDED_TABLE_SYNCED)) {
|
||||
fts_init_index(ftt->table, FALSE);
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
ulint num_idx = ib_vector_size(cache->get_docs);
|
||||
|
||||
for (ulint i = 0; i < num_idx; ++i) {
|
||||
fts_doc_t doc;
|
||||
dict_table_t* table;
|
||||
fts_get_doc_t* get_doc;
|
||||
|
||||
get_doc = static_cast<fts_get_doc_t*>(
|
||||
ib_vector_get(cache->get_docs, i));
|
||||
table = get_doc->index_cache->index->table;
|
||||
|
||||
fts_doc_init(&doc);
|
||||
fts_fetch_doc_from_tuple(
|
||||
get_doc, tuple, &doc);
|
||||
|
||||
if (doc.found) {
|
||||
mtr_commit(&mtr);
|
||||
rw_lock_x_lock(&table->fts->cache->lock);
|
||||
|
||||
if (table->fts->cache->stopword_info.status
|
||||
& STOPWORD_NOT_INIT) {
|
||||
fts_load_stopword(table, NULL, NULL,
|
||||
NULL, TRUE, TRUE);
|
||||
}
|
||||
|
||||
fts_cache_add_doc(
|
||||
table->fts->cache,
|
||||
get_doc->index_cache,
|
||||
doc_id, doc.tokens);
|
||||
|
||||
rw_lock_x_unlock(&table->fts->cache->lock);
|
||||
|
||||
if (cache->total_size > fts_max_cache_size / 5
|
||||
|| fts_need_sync) {
|
||||
fts_sync(cache->sync, true, false, false);
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
}
|
||||
|
||||
fts_doc_free(&doc);
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
This function fetches the document inserted during the committing
|
||||
transaction, and tokenize the inserted text data and insert into
|
||||
|
||||
@@ -185,7 +185,7 @@ static mysql_mutex_t pending_checkpoint_mutex;
|
||||
|
||||
#define EQ_CURRENT_THD(thd) ((thd) == current_thd)
|
||||
|
||||
static struct handlerton* innodb_hton_ptr;
|
||||
struct handlerton* innodb_hton_ptr;
|
||||
|
||||
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
|
||||
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
|
||||
@@ -2996,7 +2996,6 @@ ha_innobase::ha_innobase(
|
||||
| (srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0)
|
||||
),
|
||||
m_start_of_scan(),
|
||||
m_num_write_row(),
|
||||
m_mysql_has_locked()
|
||||
{}
|
||||
|
||||
@@ -8177,7 +8176,6 @@ ha_innobase::write_row(
|
||||
#ifdef WITH_WSREP
|
||||
ibool auto_inc_inserted= FALSE; /* if NULL was inserted */
|
||||
#endif
|
||||
ulint sql_command;
|
||||
int error_result = 0;
|
||||
bool auto_inc_used = false;
|
||||
|
||||
@@ -8195,7 +8193,7 @@ ha_innobase::write_row(
|
||||
DB_FORCED_ABORT, 0, m_user_thd));
|
||||
}
|
||||
|
||||
/* Step-1: Validation checks before we commence write_row operation. */
|
||||
/* Validation checks before we commence write_row operation. */
|
||||
if (high_level_read_only) {
|
||||
ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
|
||||
DBUG_RETURN(HA_ERR_TABLE_READONLY);
|
||||
@@ -8216,131 +8214,7 @@ ha_innobase::write_row(
|
||||
++trx->will_lock;
|
||||
}
|
||||
|
||||
/* Step-2: Intermediate commit if original operation involves ALTER
|
||||
table with algorithm = copy. Intermediate commit ease pressure on
|
||||
recovery if server crashes while ALTER is active. */
|
||||
sql_command = thd_sql_command(m_user_thd);
|
||||
|
||||
if ((sql_command == SQLCOM_ALTER_TABLE
|
||||
|| sql_command == SQLCOM_OPTIMIZE
|
||||
|| sql_command == SQLCOM_CREATE_INDEX
|
||||
#ifdef WITH_WSREP
|
||||
|| (sql_command == SQLCOM_LOAD
|
||||
&& wsrep_load_data_splitting && wsrep_on(m_user_thd)
|
||||
&& !thd_test_options(
|
||||
m_user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
||||
#endif /* WITH_WSREP */
|
||||
|| sql_command == SQLCOM_DROP_INDEX)
|
||||
&& m_num_write_row >= 10000) {
|
||||
#ifdef WITH_WSREP
|
||||
if (sql_command == SQLCOM_LOAD && wsrep_on(m_user_thd)) {
|
||||
WSREP_DEBUG("forced trx split for LOAD: %s",
|
||||
wsrep_thd_query(m_user_thd));
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
/* ALTER TABLE is COMMITted at every 10000 copied rows.
|
||||
The IX table lock for the original table has to be re-issued.
|
||||
As this method will be called on a temporary table where the
|
||||
contents of the original table is being copied to, it is
|
||||
a bit tricky to determine the source table. The cursor
|
||||
position in the source table need not be adjusted after the
|
||||
intermediate COMMIT, since writes by other transactions are
|
||||
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
|
||||
|
||||
dict_table_t* src_table;
|
||||
enum lock_mode mode;
|
||||
|
||||
m_num_write_row = 0;
|
||||
|
||||
/* Commit the transaction. This will release the table
|
||||
locks, so they have to be acquired again. */
|
||||
|
||||
/* Altering an InnoDB table */
|
||||
/* Get the source table. */
|
||||
src_table = lock_get_src_table(
|
||||
m_prebuilt->trx, m_prebuilt->table, &mode);
|
||||
if (!src_table) {
|
||||
no_commit:
|
||||
/* Unknown situation: do not commit */
|
||||
;
|
||||
} else if (src_table == m_prebuilt->table) {
|
||||
#ifdef WITH_WSREP
|
||||
if (wsrep_on(m_user_thd) &&
|
||||
wsrep_load_data_splitting &&
|
||||
sql_command == SQLCOM_LOAD &&
|
||||
!thd_test_options(m_user_thd,
|
||||
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
||||
{
|
||||
switch (wsrep_run_wsrep_commit(m_user_thd, 1)) {
|
||||
case WSREP_TRX_OK:
|
||||
break;
|
||||
case WSREP_TRX_SIZE_EXCEEDED:
|
||||
case WSREP_TRX_CERT_FAIL:
|
||||
case WSREP_TRX_ERROR:
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (binlog_hton->commit(binlog_hton, m_user_thd, 1)) {
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
wsrep_post_commit(m_user_thd, TRUE);
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
/* Source table is not in InnoDB format:
|
||||
no need to re-acquire locks on it. */
|
||||
|
||||
/* Altering to InnoDB format */
|
||||
innobase_commit(ht, m_user_thd, 1);
|
||||
/* Note that this transaction is still active. */
|
||||
trx_register_for_2pc(m_prebuilt->trx);
|
||||
/* We will need an IX lock on the destination table. */
|
||||
m_prebuilt->sql_stat_start = TRUE;
|
||||
} else {
|
||||
#ifdef WITH_WSREP
|
||||
if (wsrep_on(m_user_thd) &&
|
||||
wsrep_load_data_splitting &&
|
||||
sql_command == SQLCOM_LOAD &&
|
||||
!thd_test_options(m_user_thd,
|
||||
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
|
||||
switch (wsrep_run_wsrep_commit(m_user_thd, 1)) {
|
||||
case WSREP_TRX_OK:
|
||||
break;
|
||||
case WSREP_TRX_SIZE_EXCEEDED:
|
||||
case WSREP_TRX_CERT_FAIL:
|
||||
case WSREP_TRX_ERROR:
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (binlog_hton->commit(binlog_hton, m_user_thd, 1)) {
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
wsrep_post_commit(m_user_thd, TRUE);
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
/* Ensure that there are no other table locks than
|
||||
LOCK_IX and LOCK_AUTO_INC on the destination table. */
|
||||
|
||||
if (!lock_is_table_exclusive(m_prebuilt->table,
|
||||
m_prebuilt->trx)) {
|
||||
goto no_commit;
|
||||
}
|
||||
|
||||
/* Commit the transaction. This will release the table
|
||||
locks, so they have to be acquired again. */
|
||||
innobase_commit(ht, m_user_thd, 1);
|
||||
/* Note that this transaction is still active. */
|
||||
trx_register_for_2pc(m_prebuilt->trx);
|
||||
/* Re-acquire the table lock on the source table. */
|
||||
row_lock_table_for_mysql(m_prebuilt, src_table, mode);
|
||||
/* We will need an IX lock on the destination table. */
|
||||
m_prebuilt->sql_stat_start = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
m_num_write_row++;
|
||||
|
||||
/* Step-3: Handling of Auto-Increment Columns. */
|
||||
/* Handling of Auto-Increment Columns. */
|
||||
if (table->next_number_field && record == table->record[0]) {
|
||||
|
||||
/* Reset the error code before calling
|
||||
@@ -8373,7 +8247,7 @@ no_commit:
|
||||
auto_inc_used = true;
|
||||
}
|
||||
|
||||
/* Step-4: Prepare INSERT graph that will be executed for actual INSERT
|
||||
/* Prepare INSERT graph that will be executed for actual INSERT
|
||||
(This is a one time operation) */
|
||||
if (m_prebuilt->mysql_template == NULL
|
||||
|| m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
|
||||
@@ -8389,12 +8263,12 @@ no_commit:
|
||||
vers_set_fields = table->versioned_write(VERS_TRX_ID) ?
|
||||
ROW_INS_VERSIONED : ROW_INS_NORMAL;
|
||||
|
||||
/* Step-5: Execute insert graph that will result in actual insert. */
|
||||
/* Execute insert graph that will result in actual insert. */
|
||||
error = row_insert_for_mysql((byte*) record, m_prebuilt, vers_set_fields);
|
||||
|
||||
DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
|
||||
|
||||
/* Step-6: Handling of errors related to auto-increment. */
|
||||
/* Handling of errors related to auto-increment. */
|
||||
if (auto_inc_used) {
|
||||
ulonglong auto_inc;
|
||||
ulonglong col_max_value;
|
||||
@@ -8422,13 +8296,11 @@ no_commit:
|
||||
must update the autoinc counter if we are performing
|
||||
those statements. */
|
||||
|
||||
switch (sql_command) {
|
||||
switch (thd_sql_command(m_user_thd)) {
|
||||
case SQLCOM_LOAD:
|
||||
if (trx->duplicates) {
|
||||
|
||||
goto set_max_autoinc;
|
||||
if (!trx->duplicates) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQLCOM_REPLACE:
|
||||
case SQLCOM_INSERT_SELECT:
|
||||
@@ -8517,7 +8389,7 @@ set_max_autoinc:
|
||||
innobase_srv_conc_exit_innodb(m_prebuilt);
|
||||
|
||||
report_error:
|
||||
/* Step-7: Cleanup and exit. */
|
||||
/* Cleanup and exit. */
|
||||
if (error == DB_TABLESPACE_DELETED) {
|
||||
ib_senderrf(
|
||||
trx->mysql_thd, IB_LOG_LEVEL_ERROR,
|
||||
@@ -15752,6 +15624,26 @@ ha_innobase::extra(
|
||||
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
||||
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
||||
break;
|
||||
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||
m_prebuilt->table->skip_alter_undo = 1;
|
||||
if (m_prebuilt->table->is_temporary()
|
||||
|| !m_prebuilt->table->versioned_by_id()) {
|
||||
break;
|
||||
}
|
||||
trx_start_if_not_started(m_prebuilt->trx, true);
|
||||
m_prebuilt->trx->mod_tables.insert(
|
||||
trx_mod_tables_t::value_type(
|
||||
const_cast<dict_table_t*>(m_prebuilt->table),
|
||||
0))
|
||||
.first->second.set_versioned(0);
|
||||
break;
|
||||
case HA_EXTRA_END_ALTER_COPY:
|
||||
m_prebuilt->table->skip_alter_undo = 0;
|
||||
break;
|
||||
case HA_EXTRA_FAKE_START_STMT:
|
||||
trx_register_for_2pc(m_prebuilt->trx);
|
||||
m_prebuilt->sql_stat_start = true;
|
||||
break;
|
||||
default:/* Do nothing */
|
||||
;
|
||||
}
|
||||
@@ -15854,7 +15746,7 @@ ha_innobase::start_stmt(
|
||||
init_table_handle_for_HANDLER();
|
||||
m_prebuilt->select_lock_type = LOCK_X;
|
||||
m_prebuilt->stored_select_lock_type = LOCK_X;
|
||||
error = row_lock_table_for_mysql(m_prebuilt, NULL, 1);
|
||||
error = row_lock_table(m_prebuilt);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
int st = convert_error_code_to_mysql(
|
||||
@@ -16118,8 +16010,7 @@ ha_innobase::external_lock(
|
||||
&& thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
|
||||
&& thd_in_lock_tables(thd)) {
|
||||
|
||||
dberr_t error = row_lock_table_for_mysql(
|
||||
m_prebuilt, NULL, 0);
|
||||
dberr_t error = row_lock_table(m_prebuilt);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
||||
|
||||
@@ -515,9 +515,6 @@ protected:
|
||||
ROW_SEL_EXACT_PREFIX, or undefined */
|
||||
uint m_last_match_mode;
|
||||
|
||||
/** number of write_row() calls */
|
||||
uint m_num_write_row;
|
||||
|
||||
/** If mysql has locked with external_lock() */
|
||||
bool m_mysql_has_locked;
|
||||
};
|
||||
|
||||
@@ -1609,6 +1609,13 @@ struct dict_table_t {
|
||||
Use DICT_TF2_FLAG_IS_SET() to parse this flag. */
|
||||
unsigned flags2:DICT_TF2_BITS;
|
||||
|
||||
/** TRUE if the table is an intermediate table during copy alter
|
||||
operation or a partition/subpartition which is required for copying
|
||||
data and skip the undo log for insertion of row in the table.
|
||||
This variable will be set and unset during extra(), or during the
|
||||
process of altering partitions */
|
||||
unsigned skip_alter_undo:1;
|
||||
|
||||
/*!< whether this is in a single-table tablespace and the .ibd
|
||||
file is missing or page decryption failed and page is corrupted */
|
||||
unsigned file_unreadable:1;
|
||||
|
||||
@@ -1015,5 +1015,27 @@ fts_check_corrupt(
|
||||
dict_table_t* base_table,
|
||||
trx_t* trx);
|
||||
|
||||
/** Fetch the document from tuple, tokenize the text data and
|
||||
insert the text data into fts auxiliary table and
|
||||
its cache. Moreover this tuple fields doesn't contain any information
|
||||
about externally stored field. This tuple contains data directly
|
||||
converted from mysql.
|
||||
@param[in] ftt FTS transaction table
|
||||
@param[in] doc_id doc id
|
||||
@param[in] tuple tuple from where data can be retrieved
|
||||
and tuple should be arranged in table
|
||||
schema order. */
|
||||
void
|
||||
fts_add_doc_from_tuple(
|
||||
fts_trx_table_t*ftt,
|
||||
doc_id_t doc_id,
|
||||
const dtuple_t* tuple);
|
||||
|
||||
/** Create an FTS trx.
|
||||
@param[in,out] trx InnoDB Transaction
|
||||
@return FTS transaction. */
|
||||
fts_trx_t*
|
||||
fts_trx_create(
|
||||
trx_t* trx);
|
||||
|
||||
#endif /*!< fts0fts.h */
|
||||
|
||||
@@ -554,30 +554,6 @@ lock_rec_find_set_bit(
|
||||
bit set */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the source table of an ALTER TABLE transaction. The table must be
|
||||
covered by an IX or IS table lock.
|
||||
@return the source table of transaction, if it is covered by an IX or
|
||||
IS table lock; dest if there is no source table, and NULL if the
|
||||
transaction is locking more than two tables or an inconsistency is
|
||||
found */
|
||||
dict_table_t*
|
||||
lock_get_src_table(
|
||||
/*===============*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_table_t* dest, /*!< in: destination of ALTER TABLE */
|
||||
lock_mode* mode); /*!< out: lock mode of the source table */
|
||||
/*********************************************************************//**
|
||||
Determine if the given table is exclusively "owned" by the given
|
||||
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
|
||||
on the table.
|
||||
@return TRUE if table is only locked by trx, with LOCK_IX, and
|
||||
possibly LOCK_AUTO_INC */
|
||||
ibool
|
||||
lock_is_table_exclusive(
|
||||
/*====================*/
|
||||
const dict_table_t* table, /*!< in: table */
|
||||
const trx_t* trx); /*!< in: transaction */
|
||||
/*********************************************************************//**
|
||||
Checks if a lock request lock1 has to wait for request lock2.
|
||||
@return TRUE if lock1 has to wait for lock2 to be removed */
|
||||
ibool
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2017, MariaDB Corporation.
|
||||
Copyright (c) 2017, 2018, 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
|
||||
@@ -219,21 +219,11 @@ row_lock_table_autoinc_for_mysql(
|
||||
table handle */
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets a table lock on the table mentioned in prebuilt.
|
||||
/** Lock a table.
|
||||
@param[in,out] prebuilt table handle
|
||||
@return error code or DB_SUCCESS */
|
||||
dberr_t
|
||||
row_lock_table_for_mysql(
|
||||
/*=====================*/
|
||||
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in the MySQL
|
||||
table handle */
|
||||
dict_table_t* table, /*!< in: table to lock, or NULL
|
||||
if prebuilt->table should be
|
||||
locked as
|
||||
prebuilt->select_lock_type */
|
||||
ulint mode) /*!< in: lock mode of table
|
||||
(ignored if table==NULL) */
|
||||
MY_ATTRIBUTE((nonnull(1)));
|
||||
row_lock_table(row_prebuilt_t* prebuilt);
|
||||
|
||||
/** System Versioning: row_insert_for_mysql() modes */
|
||||
enum ins_mode_t {
|
||||
|
||||
@@ -617,145 +617,6 @@ lock_get_size(void)
|
||||
return((ulint) sizeof(lock_t));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the source table of an ALTER TABLE transaction. The table must be
|
||||
covered by an IX or IS table lock.
|
||||
@return the source table of transaction, if it is covered by an IX or
|
||||
IS table lock; dest if there is no source table, and NULL if the
|
||||
transaction is locking more than two tables or an inconsistency is
|
||||
found */
|
||||
dict_table_t*
|
||||
lock_get_src_table(
|
||||
/*===============*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_table_t* dest, /*!< in: destination of ALTER TABLE */
|
||||
lock_mode* mode) /*!< out: lock mode of the source table */
|
||||
{
|
||||
dict_table_t* src;
|
||||
lock_t* lock;
|
||||
|
||||
ut_ad(!lock_mutex_own());
|
||||
|
||||
src = NULL;
|
||||
*mode = LOCK_NONE;
|
||||
|
||||
/* The trx mutex protects the trx_locks for our purposes.
|
||||
Other transactions could want to convert one of our implicit
|
||||
record locks to an explicit one. For that, they would need our
|
||||
trx mutex. Waiting locks can be removed while only holding
|
||||
lock_sys->mutex, but this is a running transaction and cannot
|
||||
thus be holding any waiting locks. */
|
||||
trx_mutex_enter(trx);
|
||||
|
||||
for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
|
||||
lock != NULL;
|
||||
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
|
||||
lock_table_t* tab_lock;
|
||||
lock_mode lock_mode;
|
||||
if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
|
||||
/* We are only interested in table locks. */
|
||||
continue;
|
||||
}
|
||||
tab_lock = &lock->un_member.tab_lock;
|
||||
if (dest == tab_lock->table) {
|
||||
/* We are not interested in the destination table. */
|
||||
continue;
|
||||
} else if (!src) {
|
||||
/* This presumably is the source table. */
|
||||
src = tab_lock->table;
|
||||
if (UT_LIST_GET_LEN(src->locks) != 1
|
||||
|| UT_LIST_GET_FIRST(src->locks) != lock) {
|
||||
/* We only support the case when
|
||||
there is only one lock on this table. */
|
||||
src = NULL;
|
||||
goto func_exit;
|
||||
}
|
||||
} else if (src != tab_lock->table) {
|
||||
/* The transaction is locking more than
|
||||
two tables (src and dest): abort */
|
||||
src = NULL;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* Check that the source table is locked by
|
||||
LOCK_IX or LOCK_IS. */
|
||||
lock_mode = lock_get_mode(lock);
|
||||
if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
|
||||
if (*mode != LOCK_NONE && *mode != lock_mode) {
|
||||
/* There are multiple locks on src. */
|
||||
src = NULL;
|
||||
goto func_exit;
|
||||
}
|
||||
*mode = lock_mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
/* No source table lock found: flag the situation to caller */
|
||||
src = dest;
|
||||
}
|
||||
|
||||
func_exit:
|
||||
trx_mutex_exit(trx);
|
||||
return(src);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Determine if the given table is exclusively "owned" by the given
|
||||
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
|
||||
on the table.
|
||||
@return TRUE if table is only locked by trx, with LOCK_IX, and
|
||||
possibly LOCK_AUTO_INC */
|
||||
ibool
|
||||
lock_is_table_exclusive(
|
||||
/*====================*/
|
||||
const dict_table_t* table, /*!< in: table */
|
||||
const trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
const lock_t* lock;
|
||||
ibool ok = FALSE;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(trx);
|
||||
|
||||
lock_mutex_enter();
|
||||
|
||||
for (lock = UT_LIST_GET_FIRST(table->locks);
|
||||
lock != NULL;
|
||||
lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
|
||||
if (lock->trx != trx) {
|
||||
/* A lock on the table is held
|
||||
by some other transaction. */
|
||||
goto not_ok;
|
||||
}
|
||||
|
||||
if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
|
||||
/* We are interested in table locks only. */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (lock_get_mode(lock)) {
|
||||
case LOCK_IX:
|
||||
ok = TRUE;
|
||||
break;
|
||||
case LOCK_AUTO_INC:
|
||||
/* It is allowed for trx to hold an
|
||||
auto_increment lock. */
|
||||
break;
|
||||
default:
|
||||
not_ok:
|
||||
/* Other table locks than LOCK_IX are not allowed. */
|
||||
ok = FALSE;
|
||||
goto func_exit;
|
||||
}
|
||||
}
|
||||
|
||||
func_exit:
|
||||
lock_mutex_exit();
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets the wait flag of a lock and the back pointer in trx to lock. */
|
||||
UNIV_INLINE
|
||||
|
||||
@@ -3230,7 +3230,7 @@ row_ins_clust_index_entry(
|
||||
|
||||
n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0;
|
||||
|
||||
const ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
|
||||
ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
|
||||
: dict_table_is_temporary(index->table)
|
||||
? BTR_NO_LOCKING_FLAG : 0;
|
||||
const ulint orig_n_fields = entry->n_fields;
|
||||
@@ -3238,6 +3238,17 @@ row_ins_clust_index_entry(
|
||||
/* Try first optimistic descent to the B-tree */
|
||||
log_free_check();
|
||||
|
||||
/* For intermediate table during copy alter table,
|
||||
skip the undo log and record lock checking for
|
||||
insertion operation.
|
||||
*/
|
||||
if (index->table->skip_alter_undo) {
|
||||
flags |= BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG;
|
||||
}
|
||||
|
||||
/* Try first optimistic descent to the B-tree */
|
||||
log_free_check();
|
||||
|
||||
err = row_ins_clust_index_entry_low(
|
||||
flags, BTR_MODIFY_LEAF, index, n_uniq, entry,
|
||||
n_ext, thr, dup_chk_only);
|
||||
@@ -3283,6 +3294,7 @@ row_ins_sec_index_entry(
|
||||
dberr_t err;
|
||||
mem_heap_t* offsets_heap;
|
||||
mem_heap_t* heap;
|
||||
trx_id_t trx_id = 0;
|
||||
|
||||
DBUG_EXECUTE_IF("row_ins_sec_index_entry_timeout", {
|
||||
DBUG_SET("-d,row_ins_sec_index_entry_timeout");
|
||||
@@ -3305,13 +3317,22 @@ row_ins_sec_index_entry(
|
||||
/* Try first optimistic descent to the B-tree */
|
||||
|
||||
log_free_check();
|
||||
const ulint flags = dict_table_is_temporary(index->table)
|
||||
ulint flags = dict_table_is_temporary(index->table)
|
||||
? BTR_NO_LOCKING_FLAG
|
||||
: 0;
|
||||
|
||||
/* For intermediate table during copy alter table,
|
||||
skip the undo log and record lock checking for
|
||||
insertion operation.
|
||||
*/
|
||||
if (index->table->skip_alter_undo) {
|
||||
trx_id = thr_get_trx(thr)->id;
|
||||
flags |= BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG;
|
||||
}
|
||||
|
||||
err = row_ins_sec_index_entry_low(
|
||||
flags, BTR_MODIFY_LEAF, index, offsets_heap, heap, entry,
|
||||
0, thr, dup_chk_only);
|
||||
trx_id, thr, dup_chk_only);
|
||||
if (err == DB_FAIL) {
|
||||
mem_heap_empty(heap);
|
||||
|
||||
|
||||
@@ -1266,20 +1266,11 @@ run_again:
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets a table lock on the table mentioned in prebuilt.
|
||||
/** Lock a table.
|
||||
@param[in,out] prebuilt table handle
|
||||
@return error code or DB_SUCCESS */
|
||||
dberr_t
|
||||
row_lock_table_for_mysql(
|
||||
/*=====================*/
|
||||
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in the MySQL
|
||||
table handle */
|
||||
dict_table_t* table, /*!< in: table to lock, or NULL
|
||||
if prebuilt->table should be
|
||||
locked as
|
||||
prebuilt->select_lock_type */
|
||||
ulint mode) /*!< in: lock mode of table
|
||||
(ignored if table==NULL) */
|
||||
row_lock_table(row_prebuilt_t* prebuilt)
|
||||
{
|
||||
trx_t* trx = prebuilt->trx;
|
||||
que_thr_t* thr;
|
||||
@@ -1309,17 +1300,10 @@ run_again:
|
||||
|
||||
trx_start_if_not_started_xa(trx, false);
|
||||
|
||||
if (table) {
|
||||
err = lock_table(
|
||||
0, table,
|
||||
static_cast<enum lock_mode>(mode), thr);
|
||||
} else {
|
||||
err = lock_table(
|
||||
0, prebuilt->table,
|
||||
static_cast<enum lock_mode>(
|
||||
prebuilt->select_lock_type),
|
||||
thr);
|
||||
}
|
||||
err = lock_table(0, prebuilt->table,
|
||||
static_cast<enum lock_mode>(
|
||||
prebuilt->select_lock_type),
|
||||
thr);
|
||||
|
||||
trx->error_state = err;
|
||||
|
||||
@@ -1599,9 +1583,21 @@ error_exit:
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass NULL for the columns affected, since an INSERT affects
|
||||
all FTS indexes. */
|
||||
fts_trx_add_op(trx, table, doc_id, FTS_INSERT, NULL);
|
||||
if (table->skip_alter_undo) {
|
||||
if (trx->fts_trx == NULL) {
|
||||
trx->fts_trx = fts_trx_create(trx);
|
||||
}
|
||||
|
||||
fts_trx_table_t ftt;
|
||||
ftt.table = table;
|
||||
ftt.fts_trx = trx->fts_trx;
|
||||
|
||||
fts_add_doc_from_tuple(&ftt, doc_id, node->row);
|
||||
} else {
|
||||
/* Pass NULL for the columns affected, since an INSERT affects
|
||||
all FTS indexes. */
|
||||
fts_trx_add_op(trx, table, doc_id, FTS_INSERT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
que_thr_stop_for_mysql_no_error(thr, trx);
|
||||
|
||||
@@ -752,6 +752,7 @@ row_purge_upd_exist_or_extern_func(
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
||||
ut_ad(!node->table->skip_alter_undo);
|
||||
|
||||
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
|
||||
|| (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
|
||||
@@ -1035,6 +1036,7 @@ row_purge_record_func(
|
||||
bool purged = true;
|
||||
|
||||
ut_ad(!node->found_clust);
|
||||
ut_ad(!node->table->skip_alter_undo);
|
||||
|
||||
clust_index = dict_table_get_first_index(node->table);
|
||||
|
||||
|
||||
@@ -456,6 +456,7 @@ close_table:
|
||||
dict_table_close(node->table, dict_locked, FALSE);
|
||||
node->table = NULL;
|
||||
} else {
|
||||
ut_ad(!node->table->skip_alter_undo);
|
||||
clust_index = dict_table_get_first_index(node->table);
|
||||
|
||||
if (clust_index != NULL) {
|
||||
|
||||
@@ -1144,6 +1144,8 @@ row_undo_mod_parse_undo_rec(
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(!node->table->skip_alter_undo);
|
||||
|
||||
if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) {
|
||||
close_table:
|
||||
/* Normally, tables should not disappear or become
|
||||
|
||||
@@ -172,6 +172,8 @@ row_undo_search_clust_to_pcur(
|
||||
ulint* offsets = offsets_;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
ut_ad(!node->table->skip_alter_undo);
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
clust_index = dict_table_get_first_index(node->table);
|
||||
|
||||
@@ -581,6 +581,7 @@ row_upd_changes_field_size_or_external(
|
||||
ulint i;
|
||||
|
||||
ut_ad(rec_offs_validate(NULL, index, offsets));
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
n_fields = upd_get_n_fields(update);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
@@ -705,6 +706,7 @@ row_upd_rec_in_place(
|
||||
ulint i;
|
||||
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
if (rec_offs_comp(offsets)) {
|
||||
#ifdef UNIV_DEBUG
|
||||
@@ -1013,6 +1015,7 @@ row_upd_build_sec_rec_difference_binary(
|
||||
ut_ad(rec_offs_n_fields(offsets) == dtuple_get_n_fields(entry));
|
||||
ut_ad(!rec_offs_any_extern(offsets));
|
||||
ut_ad(!rec_offs_any_default(offsets));
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
update = upd_create(dtuple_get_n_fields(entry), heap);
|
||||
|
||||
@@ -1094,6 +1097,7 @@ row_upd_build_difference_binary(
|
||||
|
||||
/* This function is used only for a clustered index */
|
||||
ut_a(dict_index_is_clust(index));
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
update = upd_create(n_fld + n_v_fld, heap);
|
||||
|
||||
@@ -1356,6 +1360,8 @@ row_upd_index_replace_new_col_vals_index_pos(
|
||||
const upd_t* update,
|
||||
mem_heap_t* heap)
|
||||
{
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
const page_size_t& page_size = dict_table_page_size(index->table);
|
||||
|
||||
dtuple_set_info_bits(entry, update->info_bits);
|
||||
@@ -1410,6 +1416,8 @@ row_upd_index_replace_new_col_vals(
|
||||
= dict_table_get_first_index(index->table);
|
||||
const page_size_t& page_size = dict_table_page_size(index->table);
|
||||
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
dtuple_set_info_bits(entry, update->info_bits);
|
||||
|
||||
for (i = 0; i < dict_index_get_n_fields(index); i++) {
|
||||
@@ -1484,6 +1492,8 @@ row_upd_replace_vcol(
|
||||
ulint i;
|
||||
ulint n_cols;
|
||||
|
||||
ut_ad(!table->skip_alter_undo);
|
||||
|
||||
n_cols = dtuple_get_n_v_fields(row);
|
||||
for (col_no = 0; col_no < n_cols; col_no++) {
|
||||
dfield_t* dfield;
|
||||
@@ -1705,6 +1715,7 @@ row_upd_changes_ord_field_binary_func(
|
||||
ut_ad(thr);
|
||||
ut_ad(thr->graph);
|
||||
ut_ad(thr->graph->trx);
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
@@ -1964,6 +1975,8 @@ row_upd_changes_doc_id(
|
||||
dict_index_t* clust_index;
|
||||
fts_t* fts = table->fts;
|
||||
|
||||
ut_ad(!table->skip_alter_undo);
|
||||
|
||||
clust_index = dict_table_get_first_index(table);
|
||||
|
||||
/* Convert from index-specific column number to table-global
|
||||
@@ -1986,6 +1999,8 @@ row_upd_changes_fts_column(
|
||||
dict_index_t* clust_index;
|
||||
fts_t* fts = table->fts;
|
||||
|
||||
ut_ad(!table->skip_alter_undo);
|
||||
|
||||
if (upd_fld_is_virtual_col(upd_field)) {
|
||||
col_no = upd_field->field_no;
|
||||
return(dict_table_is_fts_column(fts->indexes, col_no, true));
|
||||
@@ -2836,6 +2851,7 @@ row_upd_clust_rec(
|
||||
ut_ad(node);
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
ut_ad(!thr_get_trx(thr)->in_rollback);
|
||||
ut_ad(!node->table->skip_alter_undo);
|
||||
|
||||
pcur = node->pcur;
|
||||
btr_cur = btr_pcur_get_btr_cur(pcur);
|
||||
|
||||
@@ -2290,6 +2290,8 @@ trx_undo_prev_version_build(
|
||||
const bool is_temp = dict_table_is_temporary(index->table);
|
||||
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
|
||||
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
|
||||
if (trx_undo_get_undo_rec(
|
||||
roll_ptr, is_temp, heap, rec_trx_id, index->table->name,
|
||||
&undo_rec)) {
|
||||
|
||||
@@ -542,6 +542,16 @@ static const char *mrn_inspect_extra_function(enum ha_extra_function operation)
|
||||
inspected = "HA_EXTRA_DETACH_CHILDREN";
|
||||
break;
|
||||
case HA_EXTRA_STARTING_ORDERED_INDEX_SCAN:
|
||||
inspected = "HA_EXTRA_STARTING_ORDERED_INDEX_SCAN";
|
||||
break;
|
||||
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||
inspected = "HA_EXTRA_BEGIN_ALTER_COPY";
|
||||
break;
|
||||
case HA_EXTRA_END_ALTER_COPY:
|
||||
inspected = "HA_EXTRA_END_ALTER_COPY";
|
||||
break;
|
||||
case HA_EXTRA_FAKE_START_STMT:
|
||||
inspected = "HA_EXTRA_FAKE_START_STMT";
|
||||
break;
|
||||
#ifdef MRN_HAVE_HA_EXTRA_EXPORT
|
||||
case HA_EXTRA_EXPORT:
|
||||
|
||||
Reference in New Issue
Block a user