From 5d142f9958d5cbb08782c1ccfa651f98af59ae3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 9 Nov 2017 23:01:44 +0200 Subject: [PATCH] MDEV-13795/MDEV-14332 Corruption during online table-rebuilding ALTER when VIRTUAL columns exist When MySQL 5.7 introduced indexed virtual columns, it introduced several bugs into the online table-rebuilding ALTER, that is, the row_log_table_apply() family of functions. The online_log format that was introduced for online table-rebuilding ALTER in MySQL 5.6 should be sufficient. Ideally, any indexed virtual column values would be evaluated based on the log records in the temporary file. There is no need to log virtual column values. (For ADD INDEX, that is row_log_apply(), we always must log the values of the keys, no matter if the columns are virtual.) Because omitting the virtual column values removes any chance of row_log_table_apply() working with indexed virtual columns, we will for now refuse LOCK=NONE in table-rebuilding ALTER operations when indexes on virtual columns exist. This restriction would be lifted in MDEV-14341. innobase_indexed_virtual_exist(): New predicate, to determine if indexed virtual columns exist in a table definition. ha_innobase::check_if_supported_inplace_alter(): Refuse online rebuild if indexed virtual columns exist. rec_get_converted_size_temp_v(), rec_convert_dtuple_to_temp_v(): Remove. row_log_table_delete(), row_log_table_update(, row_log_table_insert(): Remove parameters for virtual columns. trx_undo_read_v_rows(): Remove the col_map parameter. row_log_table_apply(): Do not deal with virtual columns. --- .../suite/gcol/r/innodb_virtual_basic.result | 9 +- .../suite/gcol/r/innodb_virtual_debug.result | 173 +--------------- .../gcol/r/innodb_virtual_rebuild.result | 106 ++++++++++ .../suite/gcol/t/innodb_virtual_basic.test | 8 +- .../suite/gcol/t/innodb_virtual_debug.test | 12 +- .../suite/gcol/t/innodb_virtual_rebuild.test | 52 +++++ storage/innobase/btr/btr0cur.cc | 2 +- storage/innobase/handler/handler0alter.cc | 32 ++- storage/innobase/include/rem0rec.h | 23 --- storage/innobase/include/row0log.h | 9 +- storage/innobase/include/trx0rec.h | 6 +- storage/innobase/rem/rem0rec.cc | 105 ---------- storage/innobase/row/row0ins.cc | 7 +- storage/innobase/row/row0log.cc | 184 ++---------------- storage/innobase/row/row0uins.cc | 4 +- storage/innobase/row/row0umod.cc | 8 +- storage/innobase/row/row0upd.cc | 11 +- storage/innobase/trx/trx0rec.cc | 23 +-- 18 files changed, 243 insertions(+), 531 deletions(-) create mode 100644 mysql-test/suite/gcol/r/innodb_virtual_rebuild.result create mode 100644 mysql-test/suite/gcol/t/innodb_virtual_rebuild.test diff --git a/mysql-test/suite/gcol/r/innodb_virtual_basic.result b/mysql-test/suite/gcol/r/innodb_virtual_basic.result index bf0ded2b952..4c7a95b6498 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_basic.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_basic.result @@ -960,9 +960,12 @@ INSERT INTO t1 VALUES (11, 3, DEFAULT, 'mm'); INSERT INTO t1 VALUES (18, 1, DEFAULT, 'mm'); INSERT INTO t1 VALUES (28, 1, DEFAULT, 'mm'); ALTER TABLE t1 ADD INDEX idx12 (c) , FORCE, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t1 ADD INDEX idx12 (c), LOCK=NONE; ALTER TABLE t1 DROP COLUMN h, ADD INDEX idx (c) , FORCE, LOCK=NONE; -Warnings: -Note 1831 Duplicate index `idx`. This is deprecated and will be disallowed in a future release +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t1 DROP COLUMN h, ADD INDEX idx (c), LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED DROP TABLE t1 ; CREATE TABLE t1 (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), d INT GENERATED ALWAYS AS(a+b), h VARCHAR(10)); INSERT INTO t1 VALUES (11, 3, DEFAULT, DEFAULT, 'mm'); @@ -1322,6 +1325,8 @@ t CREATE TABLE `t` ( ALTER TABLE t ADD COLUMN i INT GENERATED ALWAYS AS(a+a+b), ADD COLUMN j INT, ALGORITHM=INPLACE; ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: INPLACE ADD or DROP of virtual columns cannot be combined with other ALTER TABLE actions. Try ALGORITHM=COPY ALTER TABLE t ADD INDEX (x), ADD COLUMN j INT, ALGORITHM=INPLACE, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t ADD INDEX (x), ADD COLUMN j INT, ALGORITHM=INPLACE; SHOW CREATE TABLE t; Table Create Table t CREATE TABLE `t` ( diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug.result b/mysql-test/suite/gcol/r/innodb_virtual_debug.result index af220c7cd17..7774c6c347c 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug.result @@ -53,46 +53,8 @@ a b c h 18 1 19 mm 28 1 29 mm NULL NULL NULL mx -SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; -ALTER TABLE t ADD COLUMN x INT; -connection con1; -SET DEBUG_SYNC = 'now WAIT_FOR start_create'; -start transaction; -update t set a=1 where a = 0; -rollback; -start transaction; -delete from t; -insert into t values(1,null,default,null); -rollback; -start transaction; -update t set b=b+1; -rollback; -SET DEBUG_SYNC = 'now SIGNAL go_ahead'; -connection default; -check table t; -Table Op Msg_type Msg_text -test.t check status OK -SELECT c FROM t; -c -NULL -3 -19 -29 -SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; -ALTER TABLE t ADD COLUMN x2 INT; -connection con1; -SET DEBUG_SYNC = 'now WAIT_FOR start_create'; -start transaction; -DELETE FROM t WHERE a = 0; -ROLLBACK; -DELETE FROM t WHERE a = 0; -SET DEBUG_SYNC = 'now SIGNAL go_ahead'; -connection default; -SELECT c FROM t; -c -NULL -19 -29 +ALTER TABLE t FORCE, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED disconnect con1; DROP TABLE t; SET DEBUG_SYNC = 'RESET'; @@ -123,135 +85,4 @@ NULL 19 29 DROP TABLE t; -# -# Bug#22018532 ASSERTION WHEN ONLINE REAPPLY REBUILD LOG ON -# MULTIPLE INDEXED VIRTUAL COLUMNS -# -create table t ( -a int as (1) virtual, -b int, -c int as (1) virtual, -unique(b), -unique(c), -key(a) -) engine=innodb; -insert ignore into t values(); -SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; -optimize table t; -connect con1,localhost,root,,; -SET DEBUG_SYNC = 'now WAIT_FOR start_create'; -insert ignore into t values(); -Warnings: -Warning 1062 Duplicate entry '1' for key 'c' -SET DEBUG_SYNC = 'now SIGNAL go_ahead'; -connection default; -/* connection default */ optimize table t; -Table Op Msg_type Msg_text -test.t optimize note Table does not support optimize, doing recreate + analyze instead -test.t optimize error Duplicate entry '1' for key 'a' -test.t optimize status Operation failed -Warnings: -Error 1062 Duplicate entry '1' for key 'a' -SELECT c FROM t; -c -1 -SHOW CREATE TABLE t; -Table Create Table -t CREATE TABLE `t` ( - `a` int(11) GENERATED ALWAYS AS (1) VIRTUAL, - `b` int(11) DEFAULT NULL, - `c` int(11) GENERATED ALWAYS AS (1) VIRTUAL, - UNIQUE KEY `b` (`b`), - UNIQUE KEY `c` (`c`), - KEY `a` (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -SELECT * FROM t; -a b c -1 NULL 1 -DROP TABLE t; -CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10)); -INSERT INTO t VALUES (11, 3, DEFAULT, 'mm'); -INSERT INTO t VALUES (18, 1, DEFAULT, 'mm'); -INSERT INTO t VALUES (28, 1, DEFAULT, 'mm'); -INSERT INTO t VALUES (null, null, DEFAULT, 'mm'); -CREATE INDEX idx ON t(c); -SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_rebuild WAIT_FOR go_ahead'; -optimize table t; -connection con1; -SET DEBUG_SYNC = 'now WAIT_FOR start_rebuild'; -INSERT INTO t VALUES (48, 2, DEFAULT, 'xx'); -INSERT INTO t VALUES (68, 3, DEFAULT, 'sx'); -SET DEBUG_SYNC = 'now SIGNAL go_ahead'; -connection default; -/* connection default */ optimize table t; -Table Op Msg_type Msg_text -test.t optimize note Table does not support optimize, doing recreate + analyze instead -test.t optimize status OK -SELECT c FROM t; -c -NULL -14 -19 -29 -50 -71 -disconnect con1; -DROP TABLE t; -# -# Bug#22951879 - ASSERTS RELATED TO ONLINE DDL AND GCOL -# -create table ibstd_14 (a int not null, d int not null, b varchar(198) not null, c char(181), vadcol int as (a+length(d)) stored, vbcol char(2) as (substr(b,2,2)) virtual, vbidxcol char(3) as (substr(b,1,3)) virtual , index(d), index(a), index(vbidxcol), index(a,vbidxcol), index(vbidxcol,d), unique key (b(10), a, d), index(c(99), b(31)), index(b(5), c(10), a) , index(a,d)) engine=InnoDB stats_persistent=1 row_format=dynamic; -SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; -alter table ibstd_14 row_format=compressed key_block_size=4,add key kn3 (d,c,vbcol,b); -connect con1,localhost,root; -SET DEBUG_SYNC = 'now WAIT_FOR start_create'; -insert into ibstd_14 (a,d,b,c, vbidxcol, vbcol) values ('118','6',repeat('oacolaarlruoacuroauurloraarucoooarcooauoolacalllaulrruarrrucruuooclacuoouccarrcoocloccorrrrarourcooalloocooccouruolaorlcaocualolc','1'),repeat('lolrrlalcocroraaulauclaaucolcorcuooaolruaooooluooooouaoorlarucorullalcrrloccououaooaorluorraclrcooouuolocoaolcocaaculruoocucoocoooauuolarcoraraocaoolulolarru','1'),default,default); -insert into ibstd_14 (a,d,b,c, vbidxcol, vbcol) values ('118','6', 'aaaa', 'lll', default, default); -update ibstd_14 set b='11111' where b='aaaa'; -SET DEBUG_SYNC = 'now SIGNAL go_ahead'; -connection default; -select * from ibstd_14; -a d b c vadcol vbcol vbidxcol -118 6 oacolaarlruoacuroauurloraarucoooarcooauoolacalllaulrruarrrucruuooclacuoouccarrcoocloccorrrrarourcooalloocooccouruolaorlcaocualolc lolrrlalcocroraaulauclaaucolcorcuooaolruaooooluooooouaoorlarucorullalcrrloccououaooaorluorraclrcooouuolocoaolcocaaculruoocucoocoooauuolarcoraraocaoolulolarru 119 ac oac -118 6 11111 lll 119 11 111 -select d,c,vbcol,b from ibstd_14; -d c vbcol b -6 lll 11 11111 -6 lolrrlalcocroraaulauclaaucolcorcuooaolruaooooluooooouaoorlarucorullalcrrloccououaooaorluorraclrcooouuolocoaolcocaaculruoocucoocoooauuolarcoraraocaoolulolarru ac oacolaarlruoacuroauurloraarucoooarcooauoolacalllaulrruarrrucruuooclacuoouccarrcoocloccorrrrarourcooalloocooccouruolaorlcaocualolc -select vbcol from ibstd_14; -vbcol -11 -ac -drop table ibstd_14; -# -# Bug#22018745 CORRUPTION IN ONLINE TABLE REBUILD -# (ROW_FORMAT=REDUNDANT, INDEXED VIRTUAL COLUMN) -# -CREATE TABLE t ( -b char(5) PRIMARY KEY, -v char(3) GENERATED ALWAYS AS (substr(b,1,3)) VIRTUAL, KEY(v) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT; -connection con1; -SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL prepared WAIT_FOR apply'; -OPTIMIZE TABLE t; -connection default; -SET DEBUG_SYNC='now WAIT_FOR prepared'; -INSERT INTO t SET b='fubar'; -BEGIN; -DELETE FROM t; -ROLLBACK; -SET DEBUG_SYNC='now SIGNAL apply'; -connection con1; -Table Op Msg_type Msg_text -test.t optimize note Table does not support optimize, doing recreate + analyze instead -test.t optimize status OK -connection default; -CHECK TABLE t; -Table Op Msg_type Msg_text -test.t check status OK -SELECT * FROM t; -b v -fubar fub -DROP TABLE t; -disconnect con1; SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result b/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result new file mode 100644 index 00000000000..7ebf25cf072 --- /dev/null +++ b/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result @@ -0,0 +1,106 @@ +CREATE TABLE t1 (j SERIAL, i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB; +CREATE TABLE t2 (j SERIAL, i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB +ROW_FORMAT=REDUNDANT; +CREATE TABLE t3 (i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB; +CREATE TABLE t4 (i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB +ROW_FORMAT=REDUNDANT; +INSERT INTO t4 SET i=1; +ALTER TABLE t4 ADD INDEX(v), LOCK=NONE; +ALTER TABLE t4 ADD COLUMN k INT, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t4 ADD COLUMN k INT; +ALTER TABLE t4 DROP k, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t4 DROP INDEX v, LOCK=NONE; +ALTER TABLE t4 DROP k, LOCK=NONE; +INSERT INTO t3 SET i=1; +ALTER TABLE t3 ADD INDEX(v), LOCK=NONE; +ALTER TABLE t3 ADD COLUMN k INT, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t3 ADD COLUMN k INT; +ALTER TABLE t3 DROP k, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t3 DROP INDEX v, LOCK=NONE; +ALTER TABLE t3 DROP k, LOCK=NONE; +INSERT INTO t2 SET i=1; +ALTER TABLE t2 ADD INDEX(v), LOCK=NONE; +ALTER TABLE t2 ADD COLUMN k INT, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t2 ADD COLUMN k INT; +ALTER TABLE t2 DROP k, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t2 DROP INDEX v, LOCK=NONE; +ALTER TABLE t2 DROP k, LOCK=NONE; +INSERT INTO t1 SET i=1; +ALTER TABLE t1 ADD INDEX(v), LOCK=NONE; +ALTER TABLE t1 ADD COLUMN k INT, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t1 ADD COLUMN k INT; +ALTER TABLE t1 DROP k, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED +ALTER TABLE t1 DROP INDEX v, LOCK=NONE; +ALTER TABLE t1 DROP k, LOCK=NONE; +connect ddl,localhost,root,,test; +connection default; +connection ddl; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL copied WAIT_FOR dml'; +ALTER TABLE t4 FORCE; +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +UPDATE t4 SET i = 0; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL dml'; +connection ddl; +connection default; +SELECT * FROM t4; +i v +1 1 +DROP TABLE t4; +connection ddl; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL copied WAIT_FOR dml'; +ALTER TABLE t3 FORCE; +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +UPDATE t3 SET i = 0; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL dml'; +connection ddl; +connection default; +SELECT * FROM t3; +i v +1 1 +DROP TABLE t3; +connection ddl; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL copied WAIT_FOR dml'; +ALTER TABLE t2 FORCE; +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +UPDATE t2 SET i = 0; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL dml'; +connection ddl; +connection default; +SELECT * FROM t2; +j i v +1 1 1 +DROP TABLE t2; +connection ddl; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL copied WAIT_FOR dml'; +ALTER TABLE t1 FORCE; +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +UPDATE t1 SET i = 0; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL dml'; +connection ddl; +connection default; +SELECT * FROM t1; +j i v +1 1 1 +DROP TABLE t1; +disconnect ddl; +SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_basic.test b/mysql-test/suite/gcol/t/innodb_virtual_basic.test index 4fd8360eb26..674698e77c4 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_basic.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_basic.test @@ -877,8 +877,13 @@ INSERT INTO t1 VALUES (18, 1, DEFAULT, 'mm'); INSERT INTO t1 VALUES (28, 1, DEFAULT, 'mm'); +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE t1 ADD INDEX idx12 (c) , FORCE, LOCK=NONE; +ALTER TABLE t1 ADD INDEX idx12 (c), LOCK=NONE; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE t1 DROP COLUMN h, ADD INDEX idx (c) , FORCE, LOCK=NONE; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 DROP COLUMN h, ADD INDEX idx (c), LOCK=NONE; DROP TABLE t1 ; @@ -1304,8 +1309,9 @@ SHOW CREATE TABLE t; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE t ADD COLUMN i INT GENERATED ALWAYS AS(a+a+b), ADD COLUMN j INT, ALGORITHM=INPLACE; -# Add an index along with adding a regular column is allowed. +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE t ADD INDEX (x), ADD COLUMN j INT, ALGORITHM=INPLACE, LOCK=NONE; +ALTER TABLE t ADD INDEX (x), ADD COLUMN j INT, ALGORITHM=INPLACE; SHOW CREATE TABLE t; # Online add an index on newly added virtual column is not allowed. diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug.test b/mysql-test/suite/gcol/t/innodb_virtual_debug.test index 7ccf0fb8fc7..3870f84e066 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug.test @@ -53,8 +53,11 @@ SELECT c FROM t; SHOW CREATE TABLE t; SELECT * FROM t; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t FORCE, LOCK=NONE; +if (0) {# MDEV-14341 TODO: re-enable this SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; ---send ALTER TABLE t ADD COLUMN x INT +--send ALTER TABLE t FORCE connection con1; @@ -78,7 +81,7 @@ check table t; SELECT c FROM t; SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; ---send ALTER TABLE t ADD COLUMN x2 INT +--send ALTER TABLE t FORCE connection con1; @@ -93,6 +96,7 @@ connection default; reap; SELECT c FROM t; +} disconnect con1; DROP TABLE t; @@ -129,7 +133,7 @@ SELECT c FROM t; DROP TABLE t; - +if (0) {# MDEV-14341 TODO: re-enable LOCK=NONE and these tests --echo # --echo # Bug#22018532 ASSERTION WHEN ONLINE REAPPLY REBUILD LOG ON --echo # MULTIPLE INDEXED VIRTUAL COLUMNS @@ -264,7 +268,7 @@ SELECT * FROM t; DROP TABLE t; disconnect con1; - +} SET DEBUG_SYNC = 'RESET'; --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test b/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test new file mode 100644 index 00000000000..8eaefbe5ec0 --- /dev/null +++ b/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test @@ -0,0 +1,52 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1 (j SERIAL, i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB; +CREATE TABLE t2 (j SERIAL, i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB +ROW_FORMAT=REDUNDANT; +CREATE TABLE t3 (i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB; +CREATE TABLE t4 (i INT, v INT AS (i) VIRTUAL) ENGINE=InnoDB +ROW_FORMAT=REDUNDANT; + +let $n=4; +while ($n) +{ +eval INSERT INTO t$n SET i=1; +eval ALTER TABLE t$n ADD INDEX(v), LOCK=NONE; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +eval ALTER TABLE t$n ADD COLUMN k INT, LOCK=NONE; +eval ALTER TABLE t$n ADD COLUMN k INT; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +eval ALTER TABLE t$n DROP k, LOCK=NONE; +eval ALTER TABLE t$n DROP INDEX v, LOCK=NONE; +eval ALTER TABLE t$n DROP k, LOCK=NONE; +dec $n; +} + +connect (ddl,localhost,root,,test); +connection default; + +let $n=4; +while ($n) +{ +connection ddl; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL copied WAIT_FOR dml'; +send_eval ALTER TABLE t$n FORCE; + +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +BEGIN; +eval UPDATE t$n SET i = 0; +ROLLBACK; +SET DEBUG_SYNC = 'now SIGNAL dml'; + +connection ddl; +reap; +connection default; +eval SELECT * FROM t$n; +eval DROP TABLE t$n; +dec $n; +} +disconnect ddl; +SET DEBUG_SYNC = 'RESET'; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 4bb87cfaafb..614e7f690b7 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -4707,7 +4707,7 @@ btr_cur_del_mark_set_clust_rec( << rec_printer(rec, offsets).str()); if (dict_index_is_online_ddl(index)) { - row_log_table_delete(rec, entry, index, offsets, NULL); + row_log_table_delete(rec, index, offsets, NULL); } row_upd_rec_sys_fields(rec, page_zip, index, offsets, trx, roll_ptr); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index e668200180d..f2ad11845d8 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -372,6 +372,26 @@ innobase_fulltext_exist( return(false); } +/** Determine whether indexed virtual columns exist in a table. +@param[in] table table definition +@return whether indexes exist on virtual columns */ +static bool innobase_indexed_virtual_exist(const TABLE* table) +{ + const KEY* const end = &table->key_info[table->s->keys]; + + for (const KEY* key = table->key_info; key < end; key++) { + const KEY_PART_INFO* const key_part_end = key->key_part + + key->user_defined_key_parts; + for (const KEY_PART_INFO* key_part = key->key_part; + key_part < key_part_end; key_part++) { + if (!key_part->field->stored_in_db()) + return true; + } + } + + return false; +} + /** Determine if spatial indexes exist in a given table. @param table MySQL table @return whether spatial indexes exist on the table */ @@ -903,9 +923,11 @@ ha_innobase::check_if_supported_inplace_alter( & Alter_inplace_info::ADD_PK_INDEX) || innobase_need_rebuild(ha_alter_info, table)) && (innobase_fulltext_exist(altered_table) - || innobase_spatial_exist(altered_table))) { + || innobase_spatial_exist(altered_table) + || innobase_indexed_virtual_exist(altered_table))) { /* Refuse to rebuild the table online, if - FULLTEXT OR SPATIAL indexes are to survive the rebuild. */ + FULLTEXT OR SPATIAL indexes or indexed virtual columns + are to survive the rebuild. */ online = false; /* If the table already contains fulltext indexes, refuse to rebuild the table natively altogether. */ @@ -919,6 +941,10 @@ ha_innobase::check_if_supported_inplace_alter( ha_alter_info->unsupported_reason = innobase_get_err_msg( ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); + } else if (!innobase_fulltext_exist(altered_table)) { + /* MDEV-14341 FIXME: Remove this limitation. */ + ha_alter_info->unsupported_reason = + "online rebuild with indexed virtual columns"; } else { ha_alter_info->unsupported_reason = innobase_get_err_msg( @@ -1054,8 +1080,6 @@ next_column: af++; } - cf_it.rewind(); - DBUG_RETURN(online ? HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE : HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE); diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 6e927da9bd9..3b1f1c7f742 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -794,29 +794,6 @@ rec_get_converted_size_temp( ulint* extra) MY_ATTRIBUTE((warn_unused_result, nonnull(1,2))); -/** Determine the converted size of virtual column data in a temporary file. -@see rec_convert_dtuple_to_temp_v() -@param[in] index clustered index -@param[in] v clustered index record augmented with the values - of virtual columns -@return size in bytes */ -ulint -rec_get_converted_size_temp_v(const dict_index_t* index, const dtuple_t* v) - MY_ATTRIBUTE((warn_unused_result, nonnull)); - -/** Write indexed virtual column data into a temporary file. -@see rec_get_converted_size_temp_v() -@param[out] rec serialized record -@param[in] index clustered index -@param[in] v_entry clustered index record augmented with the values - of virtual columns */ -void -rec_convert_dtuple_to_temp_v( - byte* rec, - const dict_index_t* index, - const dtuple_t* v_entry) - MY_ATTRIBUTE((nonnull)); - /******************************************************//** Determine the offset to each field in temporary file. @see rec_convert_dtuple_to_temp() */ diff --git a/storage/innobase/include/row0log.h b/storage/innobase/include/row0log.h index 5657e09cc22..c52beb495da 100644 --- a/storage/innobase/include/row0log.h +++ b/storage/innobase/include/row0log.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -131,7 +132,6 @@ row_log_table_delete( /*=================*/ const rec_t* rec, /*!< in: clustered index leaf page record, page X-latched */ - const dtuple_t* ventry, /*!< in: dtuple holding virtual column info */ dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */ @@ -150,12 +150,8 @@ row_log_table_update( dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */ - const dtuple_t* old_pk, /*!< in: row_log_table_get_pk() + const dtuple_t* old_pk);/*!< in: row_log_table_get_pk() before the update */ - const dtuple_t* new_v_row,/*!< in: dtuple contains the new virtual - columns */ - const dtuple_t* old_v_row);/*!< in: dtuple contains the old virtual - columns */ /******************************************************//** Constructs the old PRIMARY KEY and DB_TRX_ID,DB_ROLL_PTR @@ -184,7 +180,6 @@ row_log_table_insert( /*=================*/ const rec_t* rec, /*!< in: clustered index leaf page record, page X-latched */ - const dtuple_t* ventry, /*!< in: dtuple holding virtual column info */ dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets);/*!< in: rec_get_offsets(rec,index) */ diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index 61398d3540d..f2c30a20f7f 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -292,15 +292,13 @@ trx_undo_rec_get_col_val( @param[in] table the table @param[in] ptr undo log pointer @param[in,out] row the dtuple to fill -@param[in] in_purge called by purge thread -@param[in] col_map online rebuild column map */ +@param[in] in_purge whether this is called by purge */ void trx_undo_read_v_cols( const dict_table_t* table, const byte* ptr, const dtuple_t* row, - bool in_purge, - const ulint* col_map); + bool in_purge); /** Read virtual column index from undo log if the undo log contains such info, and verify the column is still indexed, and output its position diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index f755eac84f3..b29a43772b0 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -936,49 +936,6 @@ rec_get_converted_size_comp_prefix_low( return(extra_size + data_size); } -/** Determine the converted size of virtual column data in a temporary file. -@see rec_convert_dtuple_to_temp_v() -@param[in] index clustered index -@param[in] v clustered index record augmented with the values - of virtual columns -@return size in bytes */ -ulint -rec_get_converted_size_temp_v(const dict_index_t* index, const dtuple_t* v) -{ - ut_ad(dict_index_is_clust(index)); - - /* length marker */ - ulint data_size = 2; - const ulint n_v_fields = dtuple_get_n_v_fields(v); - - for (ulint i = 0; i < n_v_fields; i++) { - const dict_v_col_t* col - = dict_table_get_nth_v_col(index->table, i); - - /* Only those indexed needs to be logged */ - if (!col->m_col.ord_part) { - continue; - } - - data_size += mach_get_compressed_size(i + REC_MAX_N_FIELDS); - const dfield_t* vfield = dtuple_get_nth_v_field(v, col->v_pos); - ulint flen = vfield->len; - - if (flen != UNIV_SQL_NULL) { - flen = ut_min( - flen, - static_cast( - DICT_MAX_FIELD_LEN_BY_FORMAT( - index->table))); - data_size += flen; - } - - data_size += mach_get_compressed_size(flen); - } - - return(data_size); -} - /**********************************************************//** Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT. @return total size */ @@ -1376,68 +1333,6 @@ rec_convert_dtuple_to_rec_comp( } } -/** Write indexed virtual column data into a temporary file. -@see rec_get_converted_size_temp_v() -@param[out] rec serialized record -@param[in] index clustered index -@param[in] v_entry clustered index record augmented with the values - of virtual columns */ -void -rec_convert_dtuple_to_temp_v( - byte* rec, - const dict_index_t* index, - const dtuple_t* v_entry) -{ - ut_ad(dict_index_is_clust(index)); - const ulint num_v = dtuple_get_n_v_fields(v_entry); - - /* reserve 2 bytes for writing length */ - byte* ptr = rec; - ptr += 2; - - /* Now log information on indexed virtual columns */ - for (ulint col_no = 0; col_no < num_v; col_no++) { - dfield_t* vfield; - ulint flen; - - const dict_v_col_t* col - = dict_table_get_nth_v_col(index->table, col_no); - - if (col->m_col.ord_part) { - ulint pos = col_no; - - pos += REC_MAX_N_FIELDS; - - ptr += mach_write_compressed(ptr, pos); - - vfield = dtuple_get_nth_v_field( - v_entry, col->v_pos); - - flen = vfield->len; - - if (flen != UNIV_SQL_NULL) { - /* The virtual column can only be in sec - index, and index key length is bound by - DICT_MAX_FIELD_LEN_BY_FORMAT */ - flen = ut_min( - flen, - static_cast( - DICT_MAX_FIELD_LEN_BY_FORMAT( - index->table))); - } - - ptr += mach_write_compressed(ptr, flen); - - if (flen != UNIV_SQL_NULL) { - ut_memcpy(ptr, dfield_get_data(vfield), flen); - ptr += flen; - } - } - } - - mach_write_to_2(rec, ptr - rec); -} - /*********************************************************//** Builds a new-style physical record out of a data tuple and stores it beginning from the start of the given buffer. diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index c5e0aabff2f..a4c395610f5 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2507,8 +2507,7 @@ row_ins_index_entry_big_rec( if (error == DB_SUCCESS && dict_index_is_online_ddl(index)) { - row_log_table_insert(btr_pcur_get_rec(&pcur), entry, - index, offsets); + row_log_table_insert(btr_pcur_get_rec(&pcur), index, offsets); } mtr.commit(); @@ -2689,7 +2688,7 @@ err_exit: entry_heap, entry, thr, &mtr); if (err == DB_SUCCESS && dict_index_is_online_ddl(index)) { - row_log_table_insert(btr_cur_get_rec(cursor), entry, + row_log_table_insert(btr_cur_get_rec(cursor), index, offsets); } @@ -2749,7 +2748,7 @@ err_exit: if (err == DB_SUCCESS && dict_index_is_online_ddl(index)) { row_log_table_insert( - insert_rec, entry, index, offsets); + insert_rec, index, offsets); } mtr_commit(&mtr); diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 3fc7deab4ae..e9363d12c77 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -595,7 +595,6 @@ row_log_table_delete( /*=================*/ const rec_t* rec, /*!< in: clustered index leaf page record, page X-latched */ - const dtuple_t* ventry, /*!< in: dtuple holding virtual column info */ dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */ @@ -713,11 +712,6 @@ row_log_table_delete( } } - /* Check if we need to log virtual column data */ - if (ventry->n_v_fields > 0) { - mrec_size += rec_get_converted_size_temp_v(new_index, ventry); - } - if (byte* b = row_log_table_open(index->online_log, mrec_size, &avail_size)) { *b++ = ROW_T_DELETE; @@ -760,12 +754,6 @@ row_log_table_delete( b += ext_size; } - /* log virtual columns */ - if (ventry->n_v_fields > 0) { - rec_convert_dtuple_to_temp_v(b, new_index, ventry); - b += mach_read_from_2(b); - } - row_log_table_close(index, b, mrec_size, avail_size); } @@ -782,10 +770,6 @@ row_log_table_low_redundant( const rec_t* rec, /*!< in: clustered index leaf page record in ROW_FORMAT=REDUNDANT, page X-latched */ - const dtuple_t* ventry, /*!< in: dtuple holding virtual - column info or NULL */ - const dtuple_t* o_ventry,/*!< in: old dtuple holding virtual - column info or NULL */ dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ bool insert, /*!< in: true if insert, @@ -805,7 +789,6 @@ row_log_table_low_redundant( ulint avail_size; mem_heap_t* heap = NULL; dtuple_t* tuple; - ulint num_v = ventry ? dtuple_get_n_v_fields(ventry) : 0; ut_ad(!page_is_comp(page_align(rec))); ut_ad(dict_index_get_n_fields(index) == rec_get_n_fields_old(rec)); @@ -814,13 +797,9 @@ row_log_table_low_redundant( ut_ad(dict_index_is_clust(new_index)); heap = mem_heap_create(DTUPLE_EST_ALLOC(index->n_fields)); - tuple = dtuple_create_with_vcol(heap, index->n_fields, num_v); + tuple = dtuple_create(heap, index->n_fields); dict_index_copy_types(tuple, index, index->n_fields); - if (num_v) { - dict_table_copy_v_types(tuple, index->table); - } - dtuple_set_n_fields_cmp(tuple, dict_index_get_n_unique(index)); if (rec_get_1byte_offs_flag(rec)) { @@ -853,19 +832,8 @@ row_log_table_low_redundant( size = rec_get_converted_size_temp( index, tuple->fields, tuple->n_fields, &extra_size); - ulint v_size = num_v - ? rec_get_converted_size_temp_v(index, ventry) : 0; - mrec_size = ROW_LOG_HEADER_SIZE + size + v_size + (extra_size >= 0x80); - - if (num_v) { - if (o_ventry) { - mrec_size += rec_get_converted_size_temp_v( - index, o_ventry); - } - } else if (index->table->n_v_cols) { - mrec_size += 2; - } + mrec_size = ROW_LOG_HEADER_SIZE + size + (extra_size >= 0x80); if (insert || index->online_log->same_pk) { ut_ad(!old_pk); @@ -909,22 +877,6 @@ row_log_table_low_redundant( rec_convert_dtuple_to_temp( b + extra_size, index, tuple->fields, tuple->n_fields); b += size; - ut_ad(!num_v == !v_size); - if (num_v) { - rec_convert_dtuple_to_temp_v(b, new_index, ventry); - b += v_size; - if (o_ventry) { - rec_convert_dtuple_to_temp_v( - b, new_index, o_ventry); - b += mach_read_from_2(b); - } - } else if (index->table->n_v_cols) { - /* The table contains virtual columns, but nothing - has changed for them, so just mark a 2 bytes length - field */ - mach_write_to_2(b, 2); - b += 2; - } row_log_table_close(index, b, mrec_size, avail_size); } @@ -940,9 +892,6 @@ row_log_table_low( /*==============*/ const rec_t* rec, /*!< in: clustered index leaf page record, page X-latched */ - const dtuple_t* ventry, /*!< in: dtuple holding virtual column info */ - const dtuple_t* o_ventry,/*!< in: dtuple holding old virtual column - info */ dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */ @@ -977,8 +926,6 @@ row_log_table_low( with no information on virtual columns */ ut_ad(!old_pk || !insert); ut_ad(!old_pk || old_pk->n_v_fields == 0); - ut_ad(!o_ventry || !insert); - ut_ad(!o_ventry || ventry); if (dict_index_is_corrupted(index) || !dict_index_is_online_ddl(index) @@ -988,8 +935,7 @@ row_log_table_low( if (!rec_offs_comp(offsets)) { row_log_table_low_redundant( - rec, ventry, o_ventry, index, insert, - old_pk, new_index); + rec, index, insert, old_pk, new_index); return; } @@ -1003,20 +949,6 @@ row_log_table_low( mrec_size = ROW_LOG_HEADER_SIZE + (extra_size >= 0x80) + rec_offs_size(offsets) - omit_size; - if (ventry && ventry->n_v_fields > 0) { - mrec_size += rec_get_converted_size_temp_v(new_index, ventry); - - if (o_ventry) { - mrec_size += rec_get_converted_size_temp_v( - new_index, o_ventry); - } - } else if (index->table->n_v_cols) { - /* Always leave 2 bytes length marker for virtual column - data logging even if there is none of them is indexed if table - has virtual columns */ - mrec_size += 2; - } - if (insert || index->online_log->same_pk) { ut_ad(!old_pk); old_pk_extra_size = old_pk_size = 0; @@ -1061,23 +993,6 @@ row_log_table_low( memcpy(b, rec, rec_offs_data_size(offsets)); b += rec_offs_data_size(offsets); - if (ventry && ventry->n_v_fields > 0) { - rec_convert_dtuple_to_temp_v(b, new_index, ventry); - b += mach_read_from_2(b); - - if (o_ventry) { - rec_convert_dtuple_to_temp_v( - b, new_index, o_ventry); - b += mach_read_from_2(b); - } - } else if (index->table->n_v_cols) { - /* The table contains virtual columns, but nothing - has changed for them, so just mark a 2 bytes length - field */ - mach_write_to_2(b, 2); - b += 2; - } - row_log_table_close(index, b, mrec_size, avail_size); } } @@ -1093,15 +1008,10 @@ row_log_table_update( dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */ - const dtuple_t* old_pk, /*!< in: row_log_table_get_pk() + const dtuple_t* old_pk) /*!< in: row_log_table_get_pk() before the update */ - const dtuple_t* new_v_row,/*!< in: dtuple contains the new virtual - columns */ - const dtuple_t* old_v_row)/*!< in: dtuple contains the old virtual - columns */ { - row_log_table_low(rec, new_v_row, old_v_row, index, offsets, - false, old_pk); + row_log_table_low(rec, index, offsets, false, old_pk); } /** Gets the old table column of a PRIMARY KEY column. @@ -1391,12 +1301,11 @@ row_log_table_insert( /*=================*/ const rec_t* rec, /*!< in: clustered index leaf page record, page X-latched */ - const dtuple_t* ventry, /*!< in: dtuple holding virtual column info */ dict_index_t* index, /*!< in/out: clustered index, S-latched or X-latched */ const ulint* offsets)/*!< in: rec_get_offsets(rec,index) */ { - row_log_table_low(rec, ventry, NULL, index, offsets, true, NULL); + row_log_table_low(rec, index, offsets, true, NULL); } /******************************************************//** @@ -1494,7 +1403,6 @@ row_log_table_apply_convert_mrec( reason of failure */ { dtuple_t* row; - ulint num_v = dict_table_get_n_v_cols(log->table); *error = DB_SUCCESS; @@ -1508,8 +1416,7 @@ row_log_table_apply_convert_mrec( dfield_get_type(dtuple_get_nth_field(row, i))); } } else { - row = dtuple_create_with_vcol( - heap, dict_table_get_n_cols(log->table), num_v); + row = dtuple_create(heap, dict_table_get_n_cols(log->table)); dict_table_copy_types(row, log->table); } @@ -1631,14 +1538,6 @@ blob_done: dfield_get_type(dfield))); } - /* read the virtual column data if any */ - if (num_v) { - byte* b = const_cast(mrec) - + rec_offs_data_size(offsets); - trx_undo_read_v_cols(log->table, b, row, false, - &(log->col_map[log->n_old_col])); - } - return(row); } @@ -1782,8 +1681,6 @@ row_log_table_apply_delete_low( /*===========================*/ btr_pcur_t* pcur, /*!< in/out: B-tree cursor, will be trashed */ - const dtuple_t* ventry, /*!< in: dtuple holding - virtual column info */ const ulint* offsets, /*!< in: offsets on pcur */ const row_ext_t* save_ext, /*!< in: saved external field info, or NULL */ @@ -1809,9 +1706,6 @@ row_log_table_apply_delete_low( ROW_COPY_DATA, index, btr_pcur_get_rec(pcur), offsets, NULL, NULL, NULL, save_ext ? NULL : &ext, heap); - if (ventry) { - dtuple_copy_v_fields(row, ventry); - } if (!save_ext) { save_ext = ext; @@ -1903,20 +1797,15 @@ row_log_table_apply_delete( mtr_t mtr; btr_pcur_t pcur; ulint* offsets; - ulint num_v = new_table->n_v_cols; ut_ad(rec_offs_n_fields(moffsets) == dict_index_get_n_unique(index) + 2); ut_ad(!rec_offs_any_extern(moffsets)); /* Convert the row to a search tuple. */ - old_pk = dtuple_create_with_vcol(heap, index->n_uniq, num_v); + old_pk = dtuple_create(heap, index->n_uniq); dict_index_copy_types(old_pk, index, index->n_uniq); - if (num_v) { - dict_table_copy_v_types(old_pk, index->table); - } - for (ulint i = 0; i < index->n_uniq; i++) { ulint len; const void* field; @@ -2002,14 +1891,7 @@ all_done: } } - if (num_v) { - byte* b = (byte*)mrec + rec_offs_data_size(moffsets) - + ext_size; - trx_undo_read_v_cols(log->table, b, old_pk, false, - &(log->col_map[log->n_old_col])); - } - - return(row_log_table_apply_delete_low(&pcur, old_pk, + return(row_log_table_apply_delete_low(&pcur, offsets, save_ext, heap, &mtr)); } @@ -2223,13 +2105,12 @@ func_exit_committed: /* Some BLOBs are missing, so we are interpreting this ROW_T_UPDATE as ROW_T_DELETE (see *1). */ error = row_log_table_apply_delete_low( - &pcur, old_pk, cur_offsets, NULL, heap, &mtr); + &pcur, cur_offsets, NULL, heap, &mtr); goto func_exit_committed; } - /** It allows to create tuple with virtual column information. */ dtuple_t* entry = row_build_index_entry_low( - row, NULL, index, heap, ROW_BUILD_FOR_INSERT); + row, NULL, index, heap, ROW_BUILD_NORMAL); upd_t* update = row_upd_build_difference_binary( index, entry, btr_pcur_get_rec(&pcur), cur_offsets, false, NULL, heap, dup->table); @@ -2262,7 +2143,7 @@ func_exit_committed: } error = row_log_table_apply_delete_low( - &pcur, old_pk, cur_offsets, NULL, heap, &mtr); + &pcur, cur_offsets, NULL, heap, &mtr); ut_ad(mtr.has_committed()); if (error == DB_SUCCESS) { @@ -2545,7 +2426,6 @@ row_log_table_apply_op( definition of the columns belonging to PRIMARY KEY is not changed, the log will only contain DB_TRX_ID,new_row. */ - ulint num_v = new_index->table->n_v_cols; if (dup->index->online_log->same_pk) { ut_ad(new_index->n_uniq == dup->index->n_uniq); @@ -2574,14 +2454,9 @@ row_log_table_apply_op( return(NULL); } - old_pk = dtuple_create_with_vcol( - heap, new_index->n_uniq, num_v); + old_pk = dtuple_create(heap, new_index->n_uniq); dict_index_copy_types( old_pk, new_index, old_pk->n_fields); - if (num_v) { - dict_table_copy_v_types( - old_pk, new_index->table); - } /* Copy the PRIMARY KEY fields from mrec to old_pk. */ for (ulint i = 0; i < new_index->n_uniq; i++) { @@ -2619,16 +2494,10 @@ row_log_table_apply_op( /* Copy the PRIMARY KEY fields and DB_TRX_ID, DB_ROLL_PTR from mrec to old_pk. */ - old_pk = dtuple_create_with_vcol( - heap, new_index->n_uniq + 2, num_v); + old_pk = dtuple_create(heap, new_index->n_uniq + 2); dict_index_copy_types(old_pk, new_index, old_pk->n_fields); - if (num_v) { - dict_table_copy_v_types( - old_pk, new_index->table); - } - for (ulint i = 0; i < dict_index_get_n_unique(new_index) + 2; i++) { @@ -2675,31 +2544,6 @@ row_log_table_apply_op( } } - /* Read virtual column info from log */ - if (num_v) { - ulint o_v_size = 0; - ulint n_v_size = 0; - n_v_size = mach_read_from_2(next_mrec); - next_mrec += n_v_size; - if (next_mrec > mrec_end) { - return(NULL); - } - - /* if there is more than 2 bytes length info */ - if (n_v_size > 2) { - trx_undo_read_v_cols( - log->table, const_cast( - next_mrec), old_pk, false, - &(log->col_map[log->n_old_col])); - o_v_size = mach_read_from_2(next_mrec); - } - - next_mrec += o_v_size; - if (next_mrec > mrec_end) { - return(NULL); - } - } - ut_ad(next_mrec <= mrec_end); log->head.total += next_mrec - mrec_start; dtuple_set_n_fields_cmp(old_pk, new_index->n_uniq); diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index b50b4e94cfb..09c22cdcfd2 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -116,7 +116,7 @@ row_undo_ins_remove_clust_rec( mem_heap_t* heap = NULL; const ulint* offsets = rec_get_offsets( rec, index, NULL, true, ULINT_UNDEFINED, &heap); - row_log_table_delete(rec, node->row, index, offsets, NULL); + row_log_table_delete(rec, index, offsets, NULL); mem_heap_free(heap); } @@ -380,7 +380,7 @@ close_table: } if (node->table->n_v_cols) { trx_undo_read_v_cols(node->table, ptr, - node->row, false, NULL); + node->row, false); } } else { diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index ca2e493e2d6..2269711ffef 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -334,18 +334,16 @@ row_undo_mod_clust( switch (node->rec_type) { case TRX_UNDO_DEL_MARK_REC: row_log_table_insert( - btr_pcur_get_rec(pcur), node->row, - index, offsets); + btr_pcur_get_rec(pcur), index, offsets); break; case TRX_UNDO_UPD_EXIST_REC: row_log_table_update( btr_pcur_get_rec(pcur), index, offsets, - rebuilt_old_pk, node->undo_row, node->row); + rebuilt_old_pk); break; case TRX_UNDO_UPD_DEL_REC: row_log_table_delete( - btr_pcur_get_rec(pcur), node->row, - index, offsets, sys); + btr_pcur_get_rec(pcur), index, offsets, sys); break; default: ut_ad(0); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 3cc5a242fe4..2c77d703687 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2902,18 +2902,9 @@ row_upd_clust_rec( if (err == DB_SUCCESS) { success: if (dict_index_is_online_ddl(index)) { - dtuple_t* new_v_row = NULL; - dtuple_t* old_v_row = NULL; - - if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { - new_v_row = node->upd_row; - old_v_row = node->update->old_vrow; - } - row_log_table_update( btr_cur_get_rec(btr_cur), - index, offsets, rebuilt_old_pk, new_v_row, - old_v_row); + index, offsets, rebuilt_old_pk); } } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 7cdb1e05be3..6ed554c1810 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2359,7 +2359,7 @@ trx_undo_prev_version_build( ut_ad(index->table->n_v_cols); trx_undo_read_v_cols(index->table, ptr, *vrow, - v_status & TRX_UNDO_PREV_IN_PURGE, NULL); + v_status & TRX_UNDO_PREV_IN_PURGE); } return(true); @@ -2368,16 +2368,14 @@ trx_undo_prev_version_build( /** Read virtual column value from undo log @param[in] table the table @param[in] ptr undo log pointer -@param[in,out] row the row struct to fill -@param[in] in_purge called by purge thread -@param[in] col_map online rebuild column map */ +@param[in,out] row the dtuple to fill +@param[in] in_purge whether this is called by purge */ void trx_undo_read_v_cols( const dict_table_t* table, const byte* ptr, const dtuple_t* row, - bool in_purge, - const ulint* col_map) + bool in_purge) { const byte* end_ptr; bool first_v_col = true; @@ -2417,21 +2415,10 @@ trx_undo_read_v_cols( } if (is_virtual) { - ulint col_no; dict_v_col_t* vcol = dict_table_get_nth_v_col( table, field_no); - if (!col_map) { - col_no = vcol->v_pos; - } else { - col_no = col_map[vcol->v_pos]; - } - - if (col_no == ULINT_UNDEFINED) { - continue; - } - - dfield = dtuple_get_nth_v_field(row, col_no); + dfield = dtuple_get_nth_v_field(row, vcol->v_pos); if (!in_purge || dfield_get_type(dfield)->mtype == DATA_MISSING) {