Skip to content

Commit db3be9b

Browse files
MDEV-35237 Bulk insert fails to apply buffered operation during CREATE..SELECT statement
Problem: ======= - InnoDB fails to write the buffered insert operation during create..select operation. This happens when bulk_insert in transaction is reset to false while unlocking a source table. Fix: === - InnoDB should apply the previous buffered changes to all tables if we encounter any statement other than pure INSERT or INSERT..SELECT statement in ha_innobase::external_lock() and start_stmt(). - Remove the function bulk_insert_apply_for_table() start_stmt(), external_lock(): Assert that trx->duplicates should be enabled during bulk insert operation
1 parent 63a7e4c commit db3be9b

File tree

5 files changed

+37
-26
lines changed

5 files changed

+37
-26
lines changed

mysql-test/suite/innodb/r/alter_copy_bulk.result

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,20 @@ ALTER TABLE t2 ALGORITHM=COPY, FORCE;
5050
affected rows: 1
5151
info: Records: 1 Duplicates: 0 Warnings: 0
5252
DROP TABLE t2, t1;
53+
#
54+
# MDEV-35237 Bulk insert fails to apply buffered
55+
# operation during copy alter
56+
#
57+
CREATE TABLE t1 (f1 int NOT NULL, f2 tinyint(1) NOT NULL,
58+
f3 varchar(80) NOT NULL, PRIMARY KEY(f1),
59+
KEY(f2), KEY(f3))ENGINE=InnoDB;
60+
INSERT INTO t1 VALUES(1,1,''),(2,0,''), (4,1,'e');
61+
CREATE TABLE t2 (f1 int NOT NULL, f2 int NOT NULL,KEY(f1))ENGINE=InnoDB;
62+
INSERT INTO t2 VALUES (1,0),(1,0);
63+
CREATE TABLE t engine=innodb
64+
SELECT t2.f2 FROM t2 JOIN t1 ON t1.f1 = t2.f1 AND t1.f3 = '' AND t1.f2=1 ;
65+
SELECT COUNT(*) FROM t;
66+
COUNT(*)
67+
2
68+
DROP TABLE t1, t2, t;
5369
SET GLOBAL innodb_stats_persistent=@default_stats_persistent;

mysql-test/suite/innodb/t/alter_copy_bulk.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,19 @@ ALTER TABLE t1 ALGORITHM=COPY, FORCE;
6868
ALTER TABLE t2 ALGORITHM=COPY, FORCE;
6969
--disable_info
7070
DROP TABLE t2, t1;
71+
72+
--echo #
73+
--echo # MDEV-35237 Bulk insert fails to apply buffered
74+
--echo # operation during copy alter
75+
--echo #
76+
CREATE TABLE t1 (f1 int NOT NULL, f2 tinyint(1) NOT NULL,
77+
f3 varchar(80) NOT NULL, PRIMARY KEY(f1),
78+
KEY(f2), KEY(f3))ENGINE=InnoDB;
79+
INSERT INTO t1 VALUES(1,1,''),(2,0,''), (4,1,'e');
80+
CREATE TABLE t2 (f1 int NOT NULL, f2 int NOT NULL,KEY(f1))ENGINE=InnoDB;
81+
INSERT INTO t2 VALUES (1,0),(1,0);
82+
CREATE TABLE t engine=innodb
83+
SELECT t2.f2 FROM t2 JOIN t1 ON t1.f1 = t2.f1 AND t1.f3 = '' AND t1.f2=1 ;
84+
SELECT COUNT(*) FROM t;
85+
DROP TABLE t1, t2, t;
7186
SET GLOBAL innodb_stats_persistent=@default_stats_persistent;

storage/innobase/handler/ha_innodb.cc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15902,20 +15902,17 @@ ha_innobase::start_stmt(
1590215902
if (trx->is_bulk_insert()) {
1590315903
/* Allow a subsequent INSERT into an empty table
1590415904
if !unique_checks && !foreign_key_checks. */
15905+
ut_ad(!trx->duplicates);
1590515906
break;
1590615907
}
1590715908
/* fall through */
1590815909
default:
15909-
trx->bulk_insert_apply_for_table(m_prebuilt->table);
15910+
trx->bulk_insert_apply();
15911+
trx->end_bulk_insert();
1591015912
if (!trx->bulk_insert) {
1591115913
break;
1591215914
}
1591315915

15914-
/* Trigger could've initiated another stmt.
15915-
So apply all bulk operation and mark as
15916-
end bulk insert for all tables */
15917-
trx->bulk_insert_apply();
15918-
trx->end_bulk_insert();
1591915916
trx->bulk_insert = false;
1592015917
trx->last_sql_stat_start.least_undo_no = trx->undo_no;
1592115918
}
@@ -16096,11 +16093,13 @@ ha_innobase::external_lock(
1609616093
if (trx->is_bulk_insert()) {
1609716094
/* Allow a subsequent INSERT into an empty table
1609816095
if !unique_checks && !foreign_key_checks. */
16096+
ut_ad(!trx->duplicates);
1609916097
break;
1610016098
}
1610116099
/* fall through */
1610216100
default:
16103-
trx->bulk_insert_apply_for_table(m_prebuilt->table);
16101+
trx->bulk_insert_apply();
16102+
trx->end_bulk_insert();
1610416103
if (!trx->bulk_insert) {
1610516104
break;
1610616105
}

storage/innobase/include/trx0trx.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,10 +1172,6 @@ struct trx_t : ilist_node<>
11721172
return UNIV_UNLIKELY(bulk_insert) ? bulk_insert_apply_low(): DB_SUCCESS;
11731173
}
11741174

1175-
/** Do the bulk insert for the buffered insert operation of a table.
1176-
@param table bulk insert operation
1177-
@return DB_SUCCESS or error code. */
1178-
dberr_t bulk_insert_apply_for_table(dict_table_t *table);
11791175
private:
11801176
/** Apply the buffered bulk inserts. */
11811177
dberr_t bulk_insert_apply_low();

storage/innobase/row/row0merge.cc

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5345,21 +5345,6 @@ void trx_t::bulk_rollback_low()
53455345
rollback(&bulk_save);
53465346
}
53475347

5348-
dberr_t trx_t::bulk_insert_apply_for_table(dict_table_t *table)
5349-
{
5350-
auto it= mod_tables.find(table);
5351-
if (it != mod_tables.end())
5352-
{
5353-
if (dberr_t err= it->second.write_bulk(table, this))
5354-
{
5355-
bulk_rollback_low();
5356-
return err;
5357-
}
5358-
it->second.end_bulk_insert();
5359-
}
5360-
return DB_SUCCESS;
5361-
}
5362-
53635348
dberr_t trx_t::bulk_insert_apply_low()
53645349
{
53655350
ut_ad(bulk_insert);

0 commit comments

Comments
 (0)