diff --git a/mysql-test/suite/maria/alter.result b/mysql-test/suite/maria/alter.result index 4e6f21b70a7..c79c86e8ba0 100644 --- a/mysql-test/suite/maria/alter.result +++ b/mysql-test/suite/maria/alter.result @@ -104,3 +104,63 @@ DROP TABLE t1; # # End of 10.2 test # +# +# MDEV-17665 Assertion `!share || share->page_type == PAGECACHE_LSN_PAGE', +# `type != PAGECACHE_READ_UNKNOWN_PAGE' and similar ones upon concurrent +# Aria operations +# +CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, KEY(a)) ENGINE=Aria; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; +connect con1,localhost,root,,test; +connect con2,localhost,root,,test; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; +connection con1; +FLUSH TABLES; +connection default; +INSERT INTO t1 SELECT 1; +ERROR 21S01: Column count doesn't match value count at row 1 +connection con2; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +disconnect con2; +connection con1; +disconnect con1; +connection default; +DROP TABLE t1; +# +# MDEV-22674 Server crash in compare_bin, ASAN heap-buffer-overflow in +# _ma_dpointer, Assertion `!info->s->have_versioning || +# info->s->lock_key_trees' failed in restore_table_state_after_repair +# +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +connect con1,localhost,root,,test; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 (id) SELECT b FROM t2; +connection default; +INSERT INTO t1 SELECT a FROM t2; +ERROR 21S01: Column count doesn't match value count at row 1 +connection con1; +ERROR 42S22: Unknown column 'b' in 'field list' +disconnect con1; +connection default; +drop table t1, t2; +# This is also in MDEV-22674 +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 (id) SELECT b FROM t2; +ERROR 42S22: Unknown column 'b' in 'field list' +INSERT INTO t1 SELECT a FROM t2; +ERROR 21S01: Column count doesn't match value count at row 1 +SELECT COUNT(*) FROM t1; +COUNT(*) +500 +DROP TABLE t1,t2; +# +# End of 10.4 test +# diff --git a/mysql-test/suite/maria/alter.test b/mysql-test/suite/maria/alter.test index 31eeac1df87..17a270f2a90 100644 --- a/mysql-test/suite/maria/alter.test +++ b/mysql-test/suite/maria/alter.test @@ -1,6 +1,8 @@ # Testing of potential problems in Aria and alter table -- source include/have_maria.inc +-- source include/have_innodb.inc +-- source include/have_sequence.inc drop table if exists t1; @@ -90,3 +92,85 @@ DROP TABLE t1; --echo # --echo # End of 10.2 test --echo # + +--echo # +--echo # MDEV-17665 Assertion `!share || share->page_type == PAGECACHE_LSN_PAGE', +--echo # `type != PAGECACHE_READ_UNKNOWN_PAGE' and similar ones upon concurrent +--echo # Aria operations +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, KEY(a)) ENGINE=Aria; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; + +--connect (con1,localhost,root,,test) +--connect (con2,localhost,root,,test) +--send + INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; + +--connection con1 +--send + FLUSH TABLES; + +--connection default +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT 1; + +# Cleanup +--connection con2 +--error ER_DUP_ENTRY +--reap +--disconnect con2 +--connection con1 +--reap +--disconnect con1 +--connection default +DROP TABLE t1; + +--echo # +--echo # MDEV-22674 Server crash in compare_bin, ASAN heap-buffer-overflow in +--echo # _ma_dpointer, Assertion `!info->s->have_versioning || +--echo # info->s->lock_key_trees' failed in restore_table_state_after_repair +--echo # + +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; + +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); + +--connect (con1,localhost,root,,test) +ALTER TABLE t1 DISABLE KEYS; +--send + INSERT INTO t1 (id) SELECT b FROM t2; + +--connection default +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT a FROM t2; + +# Cleanup +--connection con1 +--error ER_BAD_FIELD_ERROR +--reap +--disconnect con1 + +--connection default +drop table t1, t2; + +--echo # This is also in MDEV-22674 + +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +ALTER TABLE t1 DISABLE KEYS; +--error ER_BAD_FIELD_ERROR +INSERT INTO t1 (id) SELECT b FROM t2; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT a FROM t2; +SELECT COUNT(*) FROM t1; +DROP TABLE t1,t2; + +--echo # +--echo # End of 10.4 test +--echo # diff --git a/mysql-test/suite/maria/maria-no-logging.result b/mysql-test/suite/maria/maria-no-logging.result index fb175d0e326..e79686c4731 100644 --- a/mysql-test/suite/maria/maria-no-logging.result +++ b/mysql-test/suite/maria/maria-no-logging.result @@ -31,6 +31,9 @@ insert into t1 select * from t2; show engine aria logs; Type Name Status Aria Size 24576 aria_log.00000001 unknown +select count(*) from t1; +count(*) +65 connection default; connection admin; * shut down mysqld, removed logs, restarted it @@ -40,6 +43,9 @@ insert into t1 select * from t2; show engine aria logs; Type Name Status Aria Size 16384 aria_log.00000001 unknown +select count(*) from t1; +count(*) +64 drop table t1; connection default; connection admin; diff --git a/mysql-test/suite/maria/maria-no-logging.test b/mysql-test/suite/maria/maria-no-logging.test index fb2f34f7708..5d8029156ed 100644 --- a/mysql-test/suite/maria/maria-no-logging.test +++ b/mysql-test/suite/maria/maria-no-logging.test @@ -48,6 +48,7 @@ insert into t1 values('a'); insert into t1 select * from t2; --replace_regex /; .+aria_log/aria_log/ show engine aria logs; +select count(*) from t1; # optimization because table is empty -- source include/maria_empty_logs.inc @@ -55,6 +56,7 @@ truncate table t1; insert into t1 select * from t2; --replace_regex /; .+aria_log/aria_log/ show engine aria logs; +select count(*) from t1; drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3831bd03802..c90387cf1c3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10614,6 +10614,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool make_versioned= !from->versioned() && to->versioned(); bool make_unversioned= from->versioned() && !to->versioned(); bool keep_versioned= from->versioned() && to->versioned(); + bool bulk_insert_started= 0; Field *to_row_start= NULL, *to_row_end= NULL, *from_row_end= NULL; MYSQL_TIME query_start; DBUG_ENTER("copy_data_between_tables"); @@ -10652,6 +10653,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE); to->file->ha_start_bulk_insert(from->file->stats.records, ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT); + bulk_insert_started= 1; List_iterator it(create); Create_field *def; copy_end=copy; @@ -10914,6 +10916,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, to->file->print_error(my_errno,MYF(0)); error= 1; } + bulk_insert_started= 0; if (!ignore) to->file->extra(HA_EXTRA_END_ALTER_COPY); @@ -10927,7 +10930,10 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, error= 1; err: - /* Free resources */ + if (bulk_insert_started) + (void) to->file->ha_end_bulk_insert(); + +/* Free resources */ if (init_read_record_done) end_read_record(&info); delete [] copy; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 013c740582b..aa99bc157c9 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1025,7 +1025,7 @@ int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_CAN_VIRTUAL_COLUMNS | HA_CAN_EXPORT | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_TABLES_WITHOUT_ROLLBACK), -can_enable_indexes(1), bulk_insert_single_undo(BULK_INSERT_NONE) +can_enable_indexes(0), bulk_insert_single_undo(BULK_INSERT_NONE) {} @@ -2089,6 +2089,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) DBUG_ENTER("ha_maria::start_bulk_insert"); THD *thd= table->in_use; MARIA_SHARE *share= file->s; + bool index_disabled= 0; DBUG_PRINT("info", ("start_bulk_insert: rows %lu", (ulong) rows)); /* don't enable row cache if too few rows */ @@ -2152,6 +2153,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) { /* Internal table; If we get a duplicate something is very wrong */ file->update|= HA_STATE_CHANGED; + index_disabled= share->base.keys > 0; maria_clear_all_keys_active(file->s->state.key_map); } else @@ -2179,6 +2181,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) table->key_info[i].algorithm != HA_KEY_ALG_LONG_HASH) { maria_clear_key_active(share->state.key_map, i); + index_disabled= 1; file->update|= HA_STATE_CHANGED; file->create_unique_index_by_sort= all_keys; } @@ -2208,6 +2211,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) rows); } } + can_enable_indexes= index_disabled; DBUG_VOID_RETURN; } @@ -2246,7 +2250,6 @@ int ha_maria::end_bulk_insert() if (bulk_insert_single_undo != BULK_INSERT_NONE) { - DBUG_ASSERT(can_enable_indexes); /* Table was transactional just before start_bulk_insert(). No need to flush pages if we did a repair (which already flushed). @@ -2257,6 +2260,7 @@ int ha_maria::end_bulk_insert() first_error= first_error ? first_error : error; bulk_insert_single_undo= BULK_INSERT_NONE; // Safety } + can_enable_indexes= 0; DBUG_RETURN(first_error); } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 1b994210ddf..f0df75aa578 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -726,7 +726,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg) HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_REPAIR | HA_CAN_TABLES_WITHOUT_ROLLBACK), - can_enable_indexes(1) + can_enable_indexes(0) {} handler *ha_myisam::clone(const char *name __attribute__((unused)), @@ -1729,6 +1729,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) THD *thd= table->in_use; ulong size= MY_MIN(thd->variables.read_buff_size, (ulong) (table->s->avg_row_length*rows)); + bool index_disabled= 0; DBUG_PRINT("info",("start_bulk_insert: rows %lu size %lu", (ulong) rows, size)); @@ -1752,6 +1753,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) if (file->open_flag & HA_OPEN_INTERNAL_TABLE) { file->update|= HA_STATE_CHANGED; + index_disabled= file->s->base.keys > 0; mi_clear_all_keys_active(file->s->state.key_map); } else @@ -1782,6 +1784,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) table->key_info[i].algorithm != HA_KEY_ALG_LONG_HASH) { mi_clear_key_active(share->state.key_map, i); + index_disabled= 1; file->update|= HA_STATE_CHANGED; file->create_unique_index_by_sort= all_keys; } @@ -1789,12 +1792,15 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) } } else + { if (!file->bulk_insert && (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT)) { mi_init_bulk_insert(file, (size_t) thd->variables.bulk_insert_buff_size, rows); } + } + can_enable_indexes= index_disabled; DBUG_VOID_RETURN; } @@ -1846,6 +1852,7 @@ int ha_myisam::end_bulk_insert() file->s->state.changed&= ~(STATE_CRASHED|STATE_CRASHED_ON_REPAIR); } } + can_enable_indexes= 0; } DBUG_PRINT("exit", ("first_error: %d", first_error)); DBUG_RETURN(first_error);