1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-29761 Bulk insert fails to rollback during insert..select

- InnoDB should do partial rollback when error happens during
buffered bulk insert write operation.
This commit is contained in:
Thirunarayanan Balathandayuthapani
2022-10-25 12:14:09 +05:30
parent 2e3d08ef51
commit dd9da61dcf
3 changed files with 103 additions and 0 deletions

View File

@@ -314,3 +314,45 @@ PARTITION pn VALUES LESS THAN (20));
INSERT INTO t1 VALUES (1),(21);
ERROR HY000: Table has no partition for value 21
DROP TABLE t1;
#
# MDEV-29761 Bulk insert fails to rollback
# during insert..select
#
CREATE TABLE t1 (f1 INT)ENGINE=InnoDB;
CREATE TABLE t2 (f1 INT, UNIQUE INDEX(f1)) ENGINE=InnoDB;
CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES(1);
BEGIN;
INSERT t1 SELECT 1 FROM seq_1_to_2;
COMMIT;
SELECT * FROM t1;
f1
SELECT * FROM t2;
f1
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
CHECK TABLE t2;
Table Op Msg_type Msg_text
test.t2 check status OK
DROP TABLE t1, t2;
#
# MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
# insert operation
#
call mtr.add_suppression("InnoDB: Cannot add field `c11` in table");
SET @format= @@innodb_default_row_format;
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
c04 text, c05 text, c06 text, c07 text, c08 text,
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
ALTER TABLE t1 FORCE;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
INSERT IGNORE INTO t1 VALUES
(1, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107)),
(2, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107));
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= @format;

View File

@@ -327,3 +327,38 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB
INSERT INTO t1 VALUES (1),(21);
# Cleanup
DROP TABLE t1;
--echo #
--echo # MDEV-29761 Bulk insert fails to rollback
--echo # during insert..select
--echo #
CREATE TABLE t1 (f1 INT)ENGINE=InnoDB;
CREATE TABLE t2 (f1 INT, UNIQUE INDEX(f1)) ENGINE=InnoDB;
CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES(1);
BEGIN;
INSERT t1 SELECT 1 FROM seq_1_to_2;
COMMIT;
SELECT * FROM t1;
SELECT * FROM t2;
CHECK TABLE t1;
CHECK TABLE t2;
DROP TABLE t1, t2;
--echo #
--echo # MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
--echo # insert operation
--echo #
call mtr.add_suppression("InnoDB: Cannot add field `c11` in table");
SET @format= @@innodb_default_row_format;
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
c04 text, c05 text, c06 text, c07 text, c08 text,
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
ALTER TABLE t1 FORCE;
INSERT IGNORE INTO t1 VALUES
(1, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107)),
(2, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107));
CHECK TABLE t1;
DROP TABLE t1;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= @format;

View File

@@ -496,6 +496,13 @@ public:
return false;
}
/** @return the first undo record that modified the table */
undo_no_t get_first() const
{
ut_ad(valid());
return LIMIT & first;
}
/** Add the tuple to the transaction bulk buffer for the given index.
@param entry tuple to be inserted
@param index bulk insert for the index
@@ -1126,6 +1133,22 @@ public:
return &it->second;
}
/** Rollback all bulk insert operations */
void bulk_rollback()
{
undo_no_t low_limit= UINT64_MAX;
for (auto& t : mod_tables)
{
if (!t.second.is_bulk_insert())
continue;
if (t.second.get_first() < low_limit)
low_limit= t.second.get_first();
}
trx_savept_t bulk_save{low_limit};
rollback(&bulk_save);
}
/** Do the bulk insert for the buffered insert operation
for the transaction.
@return DB_SUCCESS or error code */
@@ -1138,7 +1161,10 @@ public:
for (auto& t : mod_tables)
if (t.second.is_bulk_insert())
if (dberr_t err= t.second.write_bulk(t.first, this))
{
bulk_rollback();
return err;
}
return DB_SUCCESS;
}