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:
@@ -314,3 +314,45 @@ PARTITION pn VALUES LESS THAN (20));
|
|||||||
INSERT INTO t1 VALUES (1),(21);
|
INSERT INTO t1 VALUES (1),(21);
|
||||||
ERROR HY000: Table has no partition for value 21
|
ERROR HY000: Table has no partition for value 21
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@@ -327,3 +327,38 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB
|
|||||||
INSERT INTO t1 VALUES (1),(21);
|
INSERT INTO t1 VALUES (1),(21);
|
||||||
# Cleanup
|
# Cleanup
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@@ -496,6 +496,13 @@ public:
|
|||||||
return false;
|
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.
|
/** Add the tuple to the transaction bulk buffer for the given index.
|
||||||
@param entry tuple to be inserted
|
@param entry tuple to be inserted
|
||||||
@param index bulk insert for the index
|
@param index bulk insert for the index
|
||||||
@@ -1126,6 +1133,22 @@ public:
|
|||||||
return &it->second;
|
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
|
/** Do the bulk insert for the buffered insert operation
|
||||||
for the transaction.
|
for the transaction.
|
||||||
@return DB_SUCCESS or error code */
|
@return DB_SUCCESS or error code */
|
||||||
@@ -1138,7 +1161,10 @@ public:
|
|||||||
for (auto& t : mod_tables)
|
for (auto& t : mod_tables)
|
||||||
if (t.second.is_bulk_insert())
|
if (t.second.is_bulk_insert())
|
||||||
if (dberr_t err= t.second.write_bulk(t.first, this))
|
if (dberr_t err= t.second.write_bulk(t.first, this))
|
||||||
|
{
|
||||||
|
bulk_rollback();
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user