1
0
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:
Marko Mäkelä
2018-01-30 21:18:39 +02:00
27 changed files with 651 additions and 415 deletions

View File

@@ -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 */

View 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;

View File

@@ -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;

View 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

View File

@@ -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

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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:
{

View File

@@ -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)

View File

@@ -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))

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)) {

View File

@@ -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: