diff --git a/client/mysql.cc b/client/mysql.cc index 70bb4514dbc..4d450129425 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2068,8 +2068,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case 'I': diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 80f99baab7d..87f7547f248 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -321,8 +321,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; } diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 33f0bf609ed..b97de70b471 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -2162,8 +2162,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case 'v': diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 545139de267..2ad363483c4 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -379,8 +379,15 @@ get_one_option(const struct my_option *opt, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; } diff --git a/client/mysqldump.c b/client/mysqldump.c index ffba37ef4ea..d7abf8465e7 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1073,8 +1073,15 @@ get_one_option(const struct my_option *opt, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; } diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 00daec49499..69dbbf3d5bc 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -264,8 +264,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case '#': diff --git a/client/mysqlshow.c b/client/mysqlshow.c index c7c200fcdfd..2c9126c24fc 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -339,8 +339,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; break; diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 54301576ba9..bef9f9f9e3b 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -777,8 +777,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case '#': diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index df2807bbebf..6122aa4029a 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index cea1a638dd0..4f42e693a16 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/plugin_data_type.h.pp b/include/mysql/plugin_data_type.h.pp index 6c8e3d93f06..d8788f5d4e0 100644 --- a/include/mysql/plugin_data_type.h.pp +++ b/include/mysql/plugin_data_type.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/plugin_encryption.h b/include/mysql/plugin_encryption.h index 3c574aa436c..a036e2215d8 100644 --- a/include/mysql/plugin_encryption.h +++ b/include/mysql/plugin_encryption.h @@ -96,8 +96,11 @@ struct st_mariadb_encryption /** processes (encrypts or decrypts) a chunk of data - writes the output to th dst buffer. note that it might write + writes the output to the dst buffer. note that it might write more bytes that were in the input. or less. or none at all. + + dlen points to the starting lenght of the output buffer. Upon return, it + should be set to the number of bytes written. */ int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen, unsigned char* dst, unsigned int* dlen); @@ -123,4 +126,3 @@ struct st_mariadb_encryption } #endif #endif - diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index b1170bd9fbf..5624c6d6f61 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 38da8c75b0b..46f4e6fc1fe 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/plugin_function.h.pp b/include/mysql/plugin_function.h.pp index 73e86f2c8cb..750f94cbf5d 100644 --- a/include/mysql/plugin_function.h.pp +++ b/include/mysql/plugin_function.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index f6693221b2d..376df1dd330 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -57,10 +57,17 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version))); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version)))) return res1; res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1)); + d2-= d1; res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2)); *dlen= d1 + d2; return res1 ? res1 : res2; diff --git a/include/mysql/service_encryption.h b/include/mysql/service_encryption.h index 4963940758c..812b28613a9 100644 --- a/include/mysql/service_encryption.h +++ b/include/mysql/service_encryption.h @@ -36,6 +36,9 @@ #ifdef __cplusplus extern "C" { #endif +#ifndef MYSQL_ABI_CHECK +#include +#endif /* returned from encryption_key_get_latest_version() */ #define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0) @@ -101,6 +104,11 @@ static inline unsigned int encryption_key_version_exists(unsigned int id, unsign return encryption_key_get(id, version, NULL, &unused) != ENCRYPTION_KEY_VERSION_INVALID; } +/** main entrypoint to perform encryption or decryption + * @invariant `src` is valid for `slen` + * @invariant `dst` is valid for `*dlen`, `*dlen` is initialized + * @invariant `src` and `dst` do not overlap + */ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, unsigned char* dst, unsigned int* dlen, const unsigned char* key, unsigned int klen, @@ -109,11 +117,23 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, { void *ctx= alloca(encryption_ctx_size(key_id, key_version)); int res1, res2; - unsigned int d1, d2; + unsigned int d1, d2= *dlen; + + // Verify dlen is initialized properly. See MDEV-30389 + assert(*dlen >= slen); + assert((dst[*dlen - 1]= 1)); + // Verify buffers do not overlap + if (src < dst) + assert(src + slen <= dst); + else + assert(dst + *dlen <= src); + if ((res1= encryption_ctx_init(ctx, key, klen, iv, ivlen, flags, key_id, key_version))) return res1; res1= encryption_ctx_update(ctx, src, slen, dst, &d1); + d2-= d1; res2= encryption_ctx_finish(ctx, dst + d1, &d2); + *dlen= d1 + d2; return res1 ? res1 : res2; } @@ -124,4 +144,3 @@ static inline int encryption_crypt(const unsigned char* src, unsigned int slen, #define MYSQL_SERVICE_ENCRYPTION_INCLUDED #endif - diff --git a/mysql-test/main/cli_options_force_protocol_win.result b/mysql-test/main/cli_options_force_protocol_win.result index eedfde4f1de..0d17a54dbc7 100644 --- a/mysql-test/main/cli_options_force_protocol_win.result +++ b/mysql-test/main/cli_options_force_protocol_win.result @@ -12,6 +12,12 @@ Connection: localhost via named pipe # exec MYSQL --host=localhost -W -e "status" 2>&1 | findstr /c:"Connection:" Connection: localhost via named pipe # exec MYSQL --host=localhost -W --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" -Connection: localhost via TCP/IP +Connection: localhost via named pipe # exec MYSQL --host=localhost --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" Connection: localhost via TCP/IP +# +# MDEV-30639: Upgrade to 10.8 and later does not work on Windows +# due to connection protocol overwrite +# +# exec MYSQL --host=localhost --protocol=pipe --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" +Connection: localhost via named pipe diff --git a/mysql-test/main/cli_options_force_protocol_win.test b/mysql-test/main/cli_options_force_protocol_win.test index 63024f3b620..31fb47fd72b 100644 --- a/mysql-test/main/cli_options_force_protocol_win.test +++ b/mysql-test/main/cli_options_force_protocol_win.test @@ -25,3 +25,10 @@ --echo # exec MYSQL --host=localhost --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" --exec $MYSQL --host=localhost --socket=$MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" + +--echo # +--echo # MDEV-30639: Upgrade to 10.8 and later does not work on Windows +--echo # due to connection protocol overwrite +--echo # +--echo # exec MYSQL --host=localhost --protocol=pipe --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" +--exec $MYSQL --host=localhost --protocol=pipe --socket=$MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" diff --git a/mysql-test/suite/innodb/r/gap_lock_split.result b/mysql-test/suite/innodb/r/gap_lock_split.result index a5765cb5694..7c10d8eed94 100644 --- a/mysql-test/suite/innodb/r/gap_lock_split.result +++ b/mysql-test/suite/innodb/r/gap_lock_split.result @@ -1,18 +1,22 @@ SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; -CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB; +CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) +ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023; connect con1,localhost,root,,; InnoDB 0 transactions not purged START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; DELETE FROM t1 WHERE id=1788; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug="d,enable_row_purge_del_mark_exit_sync_point"; BEGIN; SELECT * FROM t1 WHERE id=1788 FOR UPDATE; id val connection con1; COMMIT; -InnoDB 0 transactions not purged +SET DEBUG_SYNC = 'now WAIT_FOR row_purge_del_mark_finished'; +SET @@GLOBAL.debug_dbug = @saved_dbug; connection default; INSERT INTO t1 (id,val) VALUES (1787, REPEAT('x',2000)); connection con1; diff --git a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result index 46372cd85f2..e87b35383a7 100644 --- a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result +++ b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result @@ -14,7 +14,6 @@ WHERE TABLE_NAME LIKE '%infoschema_buffer_test%' AND PAGE_TYPE='index'; POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK 0 # # 3 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` GEN_CLUST_INDEX 2 58 0 FILE_PAGE IO_FIX OLD # 0 # # 4 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` idx 2 32 0 FILE_PAGE IO_FIX OLD # -0 # # 5 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` idx 2 32 0 FILE_PAGE IO_FIX OLD # DROP TABLE infoschema_buffer_test; SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE WHERE TABLE_NAME LIKE '%infoschema_buffer_test%'; diff --git a/mysql-test/suite/innodb/r/insert_into_empty.result b/mysql-test/suite/innodb/r/insert_into_empty.result index 7bbbc2c5d43..43b812b586e 100644 --- a/mysql-test/suite/innodb/r/insert_into_empty.result +++ b/mysql-test/suite/innodb/r/insert_into_empty.result @@ -460,3 +460,10 @@ ERROR HY000: Got error 1 "Operation not permitted" during COMMIT COMMIT; DROP TABLE t1; # End of 10.8 tests +# +# MDEV-31537 Bulk insert operation aborts the server +# for redundant table +# +CREATE TABLE t (a CHAR CHARACTER SET utf8) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT t SELECT left(seq,1) FROM seq_1_to_43691; +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/gap_lock_split.test b/mysql-test/suite/innodb/t/gap_lock_split.test index 8211a612d35..e8202615c3f 100644 --- a/mysql-test/suite/innodb/t/gap_lock_split.test +++ b/mysql-test/suite/innodb/t/gap_lock_split.test @@ -1,11 +1,13 @@ --source include/have_innodb.inc --source include/have_sequence.inc --source include/have_debug.inc +--source include/have_debug_sync.inc SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; -CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB; +CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) + ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023; connect(con1,localhost,root,,); @@ -16,13 +18,18 @@ connection default; DELETE FROM t1 WHERE id=1788; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug="d,enable_row_purge_del_mark_exit_sync_point"; + BEGIN; # This will return no result, but should acquire a gap lock. SELECT * FROM t1 WHERE id=1788 FOR UPDATE; connection con1; COMMIT; -source include/wait_all_purged.inc; +SET DEBUG_SYNC = 'now WAIT_FOR row_purge_del_mark_finished'; +SET @@GLOBAL.debug_dbug = @saved_dbug; + connection default; INSERT INTO t1 (id,val) VALUES (1787, REPEAT('x',2000)); diff --git a/mysql-test/suite/innodb/t/insert_into_empty.test b/mysql-test/suite/innodb/t/insert_into_empty.test index 60f04133c82..822c08d2a37 100644 --- a/mysql-test/suite/innodb/t/insert_into_empty.test +++ b/mysql-test/suite/innodb/t/insert_into_empty.test @@ -479,3 +479,11 @@ INSERT INTO t1 VALUES COMMIT; DROP TABLE t1; --echo # End of 10.8 tests + +--echo # +--echo # MDEV-31537 Bulk insert operation aborts the server +--echo # for redundant table +--echo # +CREATE TABLE t (a CHAR CHARACTER SET utf8) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT t SELECT left(seq,1) FROM seq_1_to_43691; +DROP TABLE t; diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index 90de2ebfcc0..6d29876a8eb 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -248,3 +248,17 @@ SELECT NEXTVAL(s); NEXTVAL(s) 1 DROP SEQUENCE s; +# +# MDEV-31607 ER_DUP_KEY in mysql.table_stats upon REANME on sequence +# +CREATE SEQUENCE s1 ENGINE=InnoDB; +CREATE SEQUENCE s2 ENGINE=InnoDB; +SHOW CREATE SEQUENCE s1; +Table Create Table +s1 CREATE SEQUENCE `s1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB +SHOW CREATE SEQUENCE s2; +Table Create Table +s2 CREATE SEQUENCE `s2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB +DROP SEQUENCE s2; +RENAME TABLE s1 TO s2; +DROP SEQUENCE s2; diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index a5e6245d609..3ad9821b0cf 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -161,3 +161,15 @@ CREATE SEQUENCE s; ALTER TABLE s ORDER BY cache_size; SELECT NEXTVAL(s); DROP SEQUENCE s; + +--echo # +--echo # MDEV-31607 ER_DUP_KEY in mysql.table_stats upon REANME on sequence +--echo # + +CREATE SEQUENCE s1 ENGINE=InnoDB; +CREATE SEQUENCE s2 ENGINE=InnoDB; +SHOW CREATE SEQUENCE s1; +SHOW CREATE SEQUENCE s2; +DROP SEQUENCE s2; +RENAME TABLE s1 TO s2; +DROP SEQUENCE s2; diff --git a/sql/encryption.cc b/sql/encryption.cc index 3c7ba2e997b..ca161749c41 100644 --- a/sql/encryption.cc +++ b/sql/encryption.cc @@ -187,6 +187,10 @@ ret: return rc; } +/** Run encryption or decryption on a block. + * `i32_1`, `i32_2`, and `i64` are used to create the initialization vector + * @invariant `src` and `dst` invariants are the same as in `encryption_crypt` + */ int do_crypt(const unsigned char* src, unsigned int slen, unsigned char* dst, unsigned int* dlen, struct st_encryption_scheme *scheme, @@ -224,6 +228,10 @@ int do_crypt(const unsigned char* src, unsigned int slen, iv, sizeof(iv), flag, scheme->key_id, key_version); } +/** Encrypt a block. + * `i32_1`, `i32_2`, and `i64` are used to create the initialization vector + * @invariant `src` and `dst` invariants are the same as in `encryption_crypt` + */ int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, unsigned char* dst, unsigned int* dlen, struct st_encryption_scheme *scheme, @@ -234,7 +242,10 @@ int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, i32_2, i64, ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT); } - +/** Decrypt a block. + * `i32_1`, `i32_2`, and `i64` are used to create the initialization vector + * @invariant `src` and `dst` invariants are the same as in `encryption_crypt` + */ int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, unsigned char* dst, unsigned int* dlen, struct st_encryption_scheme *scheme, diff --git a/sql/log.cc b/sql/log.cc index 7545d5baed5..9718e011ace 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5662,7 +5662,7 @@ bool MYSQL_BIN_LOG::write_event_buffer(uchar* buf, uint len) { DBUG_ASSERT(crypto.scheme == 1); - uint elen; + uint elen= len - 4; uchar iv[BINLOG_IV_LENGTH]; ebuf= (uchar*)my_safe_alloca(len); diff --git a/sql/log_event.cc b/sql/log_event.cc index cabbfc472be..5c116e52659 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -838,7 +838,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, DBUG_RETURN(LOG_READ_MEM); memcpy(newpkt, packet->ptr(), ev_offset); - uint dstlen; + uint dstlen= (uint) sz - ev_offset - 4; uchar *src= (uchar*)packet->ptr() + ev_offset; uchar *dst= (uchar*)newpkt + ev_offset; memcpy(src + EVENT_LEN_OFFSET, src, 4); diff --git a/sql/mf_iocache_encr.cc b/sql/mf_iocache_encr.cc index 63830ec620a..9bbcc623f6a 100644 --- a/sql/mf_iocache_encr.cc +++ b/sql/mf_iocache_encr.cc @@ -85,7 +85,8 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count) do { - uint elength, wlength, length; + uint elength, wlength; + uint length= static_cast(info->buffer_length); uchar iv[MY_AES_BLOCK_SIZE]= {0}; DBUG_ASSERT(pos_in_file % info->buffer_length == 0); @@ -102,6 +103,7 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count) } elength= wlength - (uint)(ebuffer - wbuffer); + length= elength; set_iv(iv, pos_in_file, crypt_data->inbuf_counter); if (encryption_crypt(ebuffer, elength, info->buffer, &length, @@ -181,8 +183,9 @@ static int my_b_encr_write(IO_CACHE *info, const uchar *Buffer, size_t Count) do { + uint wlength; size_t length= MY_MIN(info->buffer_length, Count); - uint elength, wlength; + uint elength= static_cast(length); uchar iv[MY_AES_BLOCK_SIZE]= {0}; crypt_data->inbuf_counter= crypt_data->counter; @@ -272,4 +275,3 @@ int init_io_cache_encryption() _my_b_encr_write= 0; return 0; } - diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index bd380f917e5..834c3d326b8 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -4673,8 +4673,6 @@ class btr_est_cur_t page_id_t m_page_id; /** Current block */ buf_block_t *m_block; - /** mtr savepoint of the current block */ - ulint m_savepoint; /** Page search mode, can differ from m_mode for non-leaf pages, see c-tor comments for details */ page_cur_mode_t m_page_mode; @@ -4733,7 +4731,6 @@ public: bool fetch_child(ulint level, mtr_t &mtr, const buf_block_t *right_parent) { buf_block_t *parent_block= m_block; - ulint parent_savepoint= m_savepoint; m_block= btr_block_get(*index(), m_page_id.page_no(), RW_S_LATCH, &mtr, nullptr); @@ -4741,9 +4738,10 @@ public: return false; if (parent_block && parent_block != right_parent) - mtr.rollback_to_savepoint(parent_savepoint, parent_savepoint + 1); - - m_savepoint= mtr.get_savepoint() - 1; + { + ut_ad(mtr.get_savepoint() >= 2); + mtr.rollback_to_savepoint(1, 2); + } return level == ULINT_UNDEFINED || btr_page_get_level(m_block->page.frame) == level; @@ -4805,10 +4803,10 @@ public: return true; } - /** Gets page id of the current record child. + /** Read page id of the current record child. @param offsets offsets array. @param heap heap for offsets array */ - void get_child(rec_offs **offsets, mem_heap_t **heap) + void read_child_page_id(rec_offs **offsets, mem_heap_t **heap) { const rec_t *node_ptr= page_cur_get_rec(&m_page_cur); @@ -4878,11 +4876,7 @@ public: /** Copies block pointer and savepoint from another btr_est_cur_t in the case if both left and right border cursors point to the same block. @param o reference to the other btr_est_cur_t object. */ - void set_block(const btr_est_cur_t &o) - { - m_block= o.m_block; - m_savepoint= o.m_savepoint; - } + void set_block(const btr_est_cur_t &o) { m_block= o.m_block; } /** @return current record number. */ ulint nth_rec() const { return m_nth_rec; } @@ -4921,7 +4915,6 @@ static ha_rows btr_estimate_n_rows_in_range_on_level( pages before reaching right_page_no, then we estimate the average from the pages scanned so far. */ static constexpr uint n_pages_read_limit= 9; - ulint savepoint= 0; buf_block_t *block= nullptr; const dict_index_t *index= left_cur.index(); @@ -4951,18 +4944,17 @@ static ha_rows btr_estimate_n_rows_in_range_on_level( { page_t *page; buf_block_t *prev_block= block; - ulint prev_savepoint= savepoint; - - savepoint= mtr.get_savepoint(); /* Fetch the page. */ block= btr_block_get(*index, page_id.page_no(), RW_S_LATCH, &mtr, nullptr); if (prev_block) { - mtr.rollback_to_savepoint(prev_savepoint, prev_savepoint + 1); - if (block) - savepoint--; + ulint savepoint = mtr.get_savepoint(); + /* Index s-lock, p1, p2 latches, can also be p1 and p2 parent latch if + they are not diverged */ + ut_ad(savepoint >= 3); + mtr.rollback_to_savepoint(savepoint - 2, savepoint - 1); } if (!block || btr_page_get_level(buf_block_get_frame(block)) != level) @@ -4993,8 +4985,8 @@ static ha_rows btr_estimate_n_rows_in_range_on_level( if (block) { - ut_ad(block == mtr.at_savepoint(savepoint)); - mtr.rollback_to_savepoint(savepoint, savepoint + 1); + ut_ad(block == mtr.at_savepoint(mtr.get_savepoint() - 1)); + mtr.rollback_to_savepoint(mtr.get_savepoint() - 1); } return (n_rows); @@ -5003,8 +4995,8 @@ inexact: if (block) { - ut_ad(block == mtr.at_savepoint(savepoint)); - mtr.rollback_to_savepoint(savepoint, savepoint + 1); + ut_ad(block == mtr.at_savepoint(mtr.get_savepoint() - 1)); + mtr.rollback_to_savepoint(mtr.get_savepoint() - 1); } is_n_rows_exact= false; @@ -5198,8 +5190,12 @@ search_loop: { ut_ad(height > 0); height--; - p1.get_child(&offsets, &heap); - p2.get_child(&offsets, &heap); + ut_ad(mtr.memo_contains(p1.index()->lock, MTR_MEMO_S_LOCK)); + ut_ad(mtr.memo_contains_flagged(p1.block(), MTR_MEMO_PAGE_S_FIX)); + p1.read_child_page_id(&offsets, &heap); + ut_ad(mtr.memo_contains(p2.index()->lock, MTR_MEMO_S_LOCK)); + ut_ad(mtr.memo_contains_flagged(p2.block(), MTR_MEMO_PAGE_S_FIX)); + p2.read_child_page_id(&offsets, &heap); goto search_loop; } diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index eeb39545360..c88db8477ea 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -2105,14 +2105,13 @@ static bool ha_validate(const hash_table_t *table, } /** Validates the search system for given hash table. -@param[in] hash_table_id hash table to validate -@return TRUE if ok */ -static -ibool -btr_search_hash_table_validate(ulint hash_table_id) +@param thd connection, for checking if CHECK TABLE has been killed +@param hash_table_id hash table to validate +@return true if ok */ +static bool btr_search_hash_table_validate(THD *thd, ulint hash_table_id) { ha_node_t* node; - ibool ok = TRUE; + bool ok = true; ulint i; ulint cell_count; mem_heap_t* heap = NULL; @@ -2120,9 +2119,15 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs* offsets = offsets_; btr_search_x_lock_all(); - if (!btr_search_enabled) { + if (!btr_search_enabled || (thd && thd_kill_level(thd))) { +func_exit: btr_search_x_unlock_all(); - return(TRUE); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + return ok; } /* How many cells to check before temporarily releasing @@ -2149,8 +2154,8 @@ btr_search_hash_table_validate(ulint hash_table_id) btr_search_x_lock_all(); - if (!btr_search_enabled) { - ok = true; + if (!btr_search_enabled + || (thd && thd_kill_level(thd))) { goto func_exit; } @@ -2256,8 +2261,8 @@ state_ok: btr_search_x_lock_all(); - if (!btr_search_enabled) { - ok = true; + if (!btr_search_enabled + || (thd && thd_kill_level(thd))) { goto func_exit; } @@ -2278,33 +2283,23 @@ state_ok: ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1); if (!ha_validate(&part.table, i, end_index)) { - ok = FALSE; + ok = false; } } mysql_mutex_unlock(&buf_pool.mutex); -func_exit: - btr_search_x_unlock_all(); - - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - - return(ok); + goto func_exit; } -/** Validate the search system. -@return true if ok. */ -bool -btr_search_validate() +/** Validates the search system. +@param thd connection, for checking if CHECK TABLE has been killed +@return true if ok */ +bool btr_search_validate(THD *thd) { - for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (!btr_search_hash_table_validate(i)) { - return(false); - } - } - - return(true); + for (ulint i= 0; i < btr_ahi_parts; ++i) + if (!btr_search_hash_table_validate(thd, i)) + return(false); + return true; } #ifdef UNIV_DEBUG diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 64c482d22a2..f570a29e55e 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1863,8 +1863,7 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept ib::info() << "Resized log to " << ib::bytes_iec{resizing_completed} << "; start LSN=" << resizing; else - sql_print_error("InnoDB: Resize of log failed at " LSN_PF, - get_flushed_lsn()); + buf_flush_ahead(end_lsn + 1, false); } /** Initiate a log checkpoint, discarding the start of the log. diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 4918cefb947..0d1560a29c0 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -445,11 +445,11 @@ static byte* fil_encrypt_buf_for_non_full_checksum( uint srclen = size - unencrypted_bytes; const byte* src = src_frame + header_len; byte* dst = dst_frame + header_len; - uint32 dstlen = 0; if (page_compressed) { srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA); } + uint dstlen = srclen; int rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen, crypt_data, key_version, @@ -516,7 +516,7 @@ static byte* fil_encrypt_buf_for_full_crc32( + FIL_PAGE_FCRC32_CHECKSUM); const byte* src = src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; byte* dst = dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; - uint dstlen = 0; + uint dstlen = srclen; ut_a(key_version != ENCRYPTION_KEY_VERSION_INVALID); @@ -647,7 +647,6 @@ static dberr_t fil_space_decrypt_full_crc32( /* Calculate the offset where decryption starts */ const byte* src = src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; byte* dst = tmp_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; - uint dstlen = 0; bool corrupted = false; uint size = buf_page_full_crc32_size(src_frame, NULL, &corrupted); if (UNIV_UNLIKELY(corrupted)) { @@ -656,6 +655,7 @@ static dberr_t fil_space_decrypt_full_crc32( uint srclen = size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + FIL_PAGE_FCRC32_CHECKSUM); + uint dstlen = srclen; int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen, crypt_data, key_version, @@ -711,8 +711,8 @@ static dberr_t fil_space_decrypt_for_non_full_checksum( /* Calculate the offset where decryption starts */ const byte* src = src_frame + header_len; byte* dst = tmp_frame + header_len; - uint32 dstlen = 0; uint srclen = uint(physical_size) - header_len - FIL_PAGE_DATA_END; + uint dstlen = srclen; if (page_compressed) { srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 856717eefc3..723e8e809de 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13635,13 +13635,12 @@ err_exit: } if (!table->no_rollback()) - { err= trx->drop_table_foreign(table->name); - if (err == DB_SUCCESS && table_stats && index_stats) - err= trx->drop_table_statistics(table->name); - if (err != DB_SUCCESS) - goto err_exit; - } + + if (err == DB_SUCCESS && table_stats && index_stats) + err= trx->drop_table_statistics(table->name); + if (err != DB_SUCCESS) + goto err_exit; err= trx->drop_table(*table); if (err != DB_SUCCESS) @@ -15256,7 +15255,8 @@ ha_innobase::check( /* We validate the whole adaptive hash index for all tables at every CHECK TABLE only when QUICK flag is not present. */ - if (!(check_opt->flags & T_QUICK) && !btr_search_validate()) { + if (!(check_opt->flags & T_QUICK) + && !btr_search_validate(m_prebuilt->trx->mysql_thd)) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_NOT_KEYFILE, "InnoDB: The adaptive hash index is corrupted."); diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 2786c26271d..6d35ea3c604 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -3870,7 +3870,7 @@ i_s_innodb_buffer_page_get_info( page_info->state = bpage->state(); - if (page_info->state < buf_page_t::FREED) { + if (page_info->state < buf_page_t::UNFIXED) { page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; page_info->compressed_only = false; } else { diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index 48e4fadab9b..b75cad10180 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -127,8 +127,9 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor, void btr_search_update_hash_on_delete(btr_cur_t *cursor); /** Validates the search system. +@param thd connection, for checking if CHECK TABLE has been killed @return true if ok */ -bool btr_search_validate(); +bool btr_search_validate(THD *thd); /** Lock all search latches in exclusive mode. */ static inline void btr_search_x_lock_all(); diff --git a/storage/innobase/include/log0crypt.h b/storage/innobase/include/log0crypt.h index 22c0c9636bf..ad32dc8faa5 100644 --- a/storage/innobase/include/log0crypt.h +++ b/storage/innobase/include/log0crypt.h @@ -84,7 +84,7 @@ void log_decrypt_buf(const byte *iv, byte *buf, const byte *const end); /** Encrypt or decrypt a temporary file block. @param[in] src block to encrypt or decrypt -@param[in] size size of the block +@param[in] size length of both src and dst in bytes @param[out] dst destination block @param[in] offs offset to block @param[in] encrypt true=encrypt; false=decrypt @@ -99,7 +99,7 @@ bool log_tmp_block_encrypt( /** Decrypt a temporary file block. @param[in] src block to decrypt -@param[in] size size of the block +@param[in] size length of both src and dst in bytes @param[out] dst destination block @param[in] offs offset to block @return whether the operation succeeded */ diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index 8a7714101ba..fc7a5180797 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -221,9 +221,9 @@ ATTRIBUTE_COLD bool log_decrypt(byte* buf, lsn_t lsn, ulint size) ut_ad(LOG_CRYPT_HDR_SIZE + dst_size == 512 - LOG_BLOCK_CHECKSUM - LOG_BLOCK_KEY); - uint dst_len; + uint dst_len = static_cast(dst_size); int rc = encryption_crypt( - buf + LOG_CRYPT_HDR_SIZE, static_cast(dst_size), + buf + LOG_CRYPT_HDR_SIZE, dst_len, reinterpret_cast(dst), &dst_len, const_cast(info.crypt_key), MY_AES_BLOCK_SIZE, @@ -332,10 +332,10 @@ ATTRIBUTE_COLD bool log_crypt_101_read_block(byte* buf, lsn_t start_lsn) } found: byte dst[512]; - uint dst_len; byte aes_ctr_iv[MY_AES_BLOCK_SIZE]; const uint src_len = 512 - LOG_BLOCK_HDR_SIZE; + uint dst_len = src_len; ulint log_block_no = log_block_get_hdr_no(buf); @@ -429,7 +429,7 @@ ATTRIBUTE_COLD bool log_crypt_read_checkpoint_buf(const byte* buf) /** Encrypt or decrypt a temporary file block. @param[in] src block to encrypt or decrypt -@param[in] size size of the block +@param[in] size length of both src and dst blocks in bytes @param[out] dst destination block @param[in] offs offset to block @param[in] encrypt true=encrypt; false=decrypt @@ -441,7 +441,7 @@ bool log_tmp_block_encrypt( uint64_t offs, bool encrypt) { - uint dst_len; + uint dst_len = static_cast(size); uint64_t iv[MY_AES_BLOCK_SIZE / sizeof(uint64_t)]; iv[0] = offs; memcpy(iv + 1, tmp_iv, sizeof iv - sizeof *iv); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index d763ef10734..16057750400 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -523,7 +523,14 @@ log_t::resize_start_status log_t::resize_start(os_offset_t size) noexcept log_resize_release(); if (start_lsn) + { + mysql_mutex_lock(&buf_pool.flush_list_mutex); + lsn_t target_lsn= buf_pool.get_oldest_modification(0); + if (start_lsn < target_lsn) + start_lsn= target_lsn + 1; + mysql_mutex_unlock(&buf_pool.flush_list_mutex); buf_flush_ahead(start_lsn, false); + } return status; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index eaf987d115d..40fd8c75be2 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -239,6 +239,7 @@ struct fil_iterator_t { byte* io_buffer; /*!< Buffer to use for IO */ fil_space_crypt_t *crypt_data; /*!< Crypt data (if encrypted) */ byte* crypt_io_buffer; /*!< IO buffer when encrypted */ + byte* crypt_tmp_buffer; /*!< Temporary buffer for crypt use */ }; /** Use the page cursor to iterate over records in a block. */ @@ -2985,17 +2986,25 @@ row_import_read_meta_data( /* decrypt and decompress page if needed */ static dberr_t decrypt_decompress(fil_space_crypt_t *space_crypt, uint32_t space_flags, span page, - uint32_t space_id, byte *page_compress_buf) + uint32_t space_id, byte *page_compress_buf, + byte *tmp_frame) { auto *data= page.data(); if (space_crypt && space_crypt->should_encrypt()) { + uint page_size= static_cast(page.size()); + if (!buf_page_verify_crypt_checksum(data, space_flags)) return DB_CORRUPTION; - if (dberr_t err= fil_space_decrypt(space_id, space_flags, space_crypt, - data, page.size(), data)) + dberr_t err= + fil_space_decrypt(space_id, space_flags, space_crypt, + tmp_frame, page_size, data); + + memcpy(data, tmp_frame, page_size); + + if (err) return err; } @@ -3115,11 +3124,16 @@ static dberr_t handle_instant_metadata(dict_table_t *table, return err; std::unique_ptr page_compress_buf(new byte[get_buf_size()]); + std::unique_ptr crypt_tmp_frame( + static_cast( + aligned_malloc(physical_size, CPU_LEVEL1_DCACHE_LINESIZE)), + &aligned_free); if (dberr_t err= decrypt_decompress(space_crypt, space_flags, {page.get(), static_cast (physical_size)}, - space_id, page_compress_buf.get())) + space_id, page_compress_buf.get(), + crypt_tmp_frame.get())) return err; if (table->supports_instant()) @@ -3173,7 +3187,8 @@ static dberr_t handle_instant_metadata(dict_table_t *table, if (dberr_t err= decrypt_decompress(space_crypt, space_flags, {page.get(), static_cast (physical_size)}, space_id, - page_compress_buf.get())) + page_compress_buf.get(), + crypt_tmp_frame.get())) return err; } @@ -3255,7 +3270,8 @@ static dberr_t handle_instant_metadata(dict_table_t *table, if (dberr_t err= decrypt_decompress(space_crypt, space_flags, {second_page.get(), static_cast(physical_size)}, - space_id, page_compress_buf.get())) + space_id, page_compress_buf.get(), + crypt_tmp_frame.get())) return err; if (fil_page_get_type(second_page.get()) != FIL_PAGE_TYPE_BLOB || @@ -3697,8 +3713,14 @@ page_corrupted: if (!buf_page_verify_crypt_checksum(readptr, m_space_flags)) goto page_corrupted; - if ((err= fil_space_decrypt(get_space_id(), m_space_flags, iter.crypt_data, - readptr, size, readptr))) + dberr_t err= fil_space_decrypt(get_space_id(), m_space_flags, + iter.crypt_data, iter.crypt_tmp_buffer, + size, readptr); + + memcpy_aligned(readptr, iter.crypt_tmp_buffer, + size); + + if (err) goto func_exit; } @@ -4155,17 +4177,21 @@ fil_tablespace_iterate( iter.file_size = file_size; iter.n_io_buffers = n_io_buffers; + size_t buf_size = (1 + iter.n_io_buffers) * srv_page_size; + /* Add an extra page for compressed page scratch area. */ iter.io_buffer = static_cast( - aligned_malloc((1 + iter.n_io_buffers) - << srv_page_size_shift, srv_page_size)); + aligned_malloc(buf_size, srv_page_size)); - iter.crypt_io_buffer = iter.crypt_data - ? static_cast( - aligned_malloc((1 + iter.n_io_buffers) - << srv_page_size_shift, - srv_page_size)) - : NULL; + if (iter.crypt_data) { + iter.crypt_io_buffer = static_cast( + aligned_malloc(buf_size, srv_page_size)); + iter.crypt_tmp_buffer = static_cast( + aligned_malloc(buf_size, CPU_LEVEL1_DCACHE_LINESIZE)); + } else { + iter.crypt_io_buffer = NULL; + iter.crypt_tmp_buffer = NULL; + } if (block->page.zip.ssize) { ut_ad(iter.n_io_buffers == 1); @@ -4180,6 +4206,7 @@ fil_tablespace_iterate( fil_space_destroy_crypt_data(&iter.crypt_data); } + aligned_free(iter.crypt_tmp_buffer); aligned_free(iter.crypt_io_buffer); aligned_free(iter.io_buffer); } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index b35783f1a92..a289a9ee0e0 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -481,6 +481,13 @@ static ulint row_merge_bulk_buf_add(row_merge_buf_t* buf, ulint fixed_len= ifield->fixed_len; + /* CHAR in ROW_FORMAT=REDUNDANT is always + fixed-length, but in the temporary file it is + variable-length for variable-length character sets. */ + if (fixed_len && !index->table->not_redundant() && + col->mbminlen != col->mbmaxlen) + fixed_len= 0; + if (fixed_len); else if (len < 128 || (!DATA_BIG_COL(col))) extra_size++; diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c index a69ebf3928f..268316655dc 100644 --- a/storage/maria/ma_crypt.c +++ b/storage/maria/ma_crypt.c @@ -459,7 +459,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, uint *key_version) { int rc; - uint32 dstlen= 0; /* Must be set because of error message */ + uint32 dstlen= size; *key_version = encryption_key_get_latest_version(crypt_data->scheme.key_id); if (*key_version == ENCRYPTION_KEY_VERSION_INVALID) @@ -486,6 +486,9 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, DBUG_ASSERT(!my_assert_on_error || dstlen == size); if (! (rc == MY_AES_OK && dstlen == size)) { + if (rc != MY_AES_OK) + dstlen= 0; /* reset dstlen if failed, to match expected message */ + my_errno= HA_ERR_DECRYPTION_FAILED; my_printf_error(HA_ERR_DECRYPTION_FAILED, "failed to encrypt '%s' rc: %d dstlen: %u size: %u\n", @@ -503,7 +506,7 @@ static int ma_decrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, uint key_version) { int rc; - uint32 dstlen= 0; /* Must be set because of error message */ + uint32 dstlen= size; rc= encryption_scheme_decrypt(src, size, dst, &dstlen, &crypt_data->scheme, key_version, @@ -513,6 +516,8 @@ static int ma_decrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, DBUG_ASSERT(!my_assert_on_error || dstlen == size); if (! (rc == MY_AES_OK && dstlen == size)) { + if (rc != MY_AES_OK) + dstlen= 0; /* reset dstlen if failed, to match expected message */ my_errno= HA_ERR_DECRYPTION_FAILED; if (!share->silence_encryption_errors) my_printf_error(HA_ERR_DECRYPTION_FAILED, diff --git a/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc b/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc index 40fabce0517..27d73e8d815 100644 --- a/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc +++ b/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc @@ -12,6 +12,10 @@ --source include/default_optimizer_switch.inc +set + @rgmm_hist_type=@@histogram_type, + histogram_type=double_prec_hb; + --disable_warnings drop table if exists t1; --enable_warnings @@ -1436,3 +1440,5 @@ SHOW SESSION STATUS LIKE 'Handler_read%'; DROP TABLE t1; --echo # End of test for Bug#18109609 + +set histogram_type=@rgmm_hist_type; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result index a070ba91a55..5a1350fe0ff 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result @@ -1,5 +1,8 @@ set @debug_tmp= @@debug_dbug; set global debug_dbug="+d,force_group_by"; +set +@rgmm_hist_type=@@histogram_type, +histogram_type=double_prec_hb; drop table if exists t1; create table t1 ( a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(248) default ' ' @@ -3523,4 +3526,5 @@ Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 DROP TABLE t1; # End of test for Bug#18109609 +set histogram_type=@rgmm_hist_type; set global debug_dbug=@debug_tmp; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31463.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31463.result index 78503c66cbb..5cfa56a27e9 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31463.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31463.result @@ -4,7 +4,7 @@ for master_1 for child2 for child3 -CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE SERVER IF NOT EXISTS $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); SET @old_wait_timeout = @@global.wait_timeout; SET GLOBAL wait_timeout=1; CREATE TABLE t (c INT KEY,c1 BLOB,c2 TEXT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv_mdev_31463"'; @@ -15,7 +15,7 @@ SELECT SLEEP (1); SLEEP (1) 0 INSERT INTO t VALUES (1,2,3),(4,5,6),(7,8,9); -ERROR 08S01: Got an error writing communication packets +Got one of the listed errors SELECT * FROM information_schema.key_column_usage; XA END 'a'; XA PREPARE 'a'; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31463.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31463.test index 4722cf06f2a..cc86caaccdb 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31463.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31463.test @@ -9,7 +9,9 @@ --enable_query_log --let $srv=srv_mdev_31463 -evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +--disable_warnings +evalp CREATE SERVER IF NOT EXISTS $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +--enable_warnings SET @old_wait_timeout = @@global.wait_timeout; SET GLOBAL wait_timeout=1; @@ -18,9 +20,17 @@ XA START 'a'; --error ER_WRONG_VALUE_COUNT_ON_ROW INSERT INTO t VALUES (0,0,0,0); SELECT SLEEP (1); ---error ER_NET_ERROR_ON_WRITE +# MDEV-31586: The error code is non-deterministic, presumably due to +# some race condition from the SLEEP statement above. The correct +# error should be 12701 ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM as it is +# the last failure. Nevertheless, this contrived test is needed to +# cover the error reporting when setting lock wait timeout, until we +# find a better one and/or fixing the non-deterministic error +# reporting +--error 12701,ER_NET_ERROR_ON_WRITE,ER_XAER_DUPID INSERT INTO t VALUES (1,2,3),(4,5,6),(7,8,9); --disable_result_log +--error 0,12701,ER_XAER_DUPID SELECT * FROM information_schema.key_column_usage; --enable_result_log