Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2021-06-21 12:38:25 +03:00
commit d3e4fae797
65 changed files with 708 additions and 568 deletions

View File

@ -1,7 +1,6 @@
Code status: Code status:
------------ ------------
* [![Travis CI status](https://secure.travis-ci.org/MariaDB/server.png?branch=10.4)](https://travis-ci.org/MariaDB/server) travis-ci.org (10.4 branch)
* [![Appveyor CI status](https://ci.appveyor.com/api/projects/status/4u6pexmtpuf8jq66?svg=true)](https://ci.appveyor.com/project/rasmushoj/server) ci.appveyor.com * [![Appveyor CI status](https://ci.appveyor.com/api/projects/status/4u6pexmtpuf8jq66?svg=true)](https://ci.appveyor.com/project/rasmushoj/server) ci.appveyor.com
## MariaDB: drop-in replacement for MySQL ## MariaDB: drop-in replacement for MySQL
@ -83,5 +82,3 @@ https://bugs.mysql.com
The code for MariaDB, including all revision history, can be found at: The code for MariaDB, including all revision history, can be found at:
https://github.com/MariaDB/server https://github.com/MariaDB/server
***************************************************************************

View File

@ -90,6 +90,8 @@ static my_bool non_blocking_api_enabled= 0;
#define QUERY_PRINT_ORIGINAL_FLAG 4 #define QUERY_PRINT_ORIGINAL_FLAG 4
#define CLOSED_CONNECTION "-closed_connection-"
#ifndef HAVE_SETENV #ifndef HAVE_SETENV
static int setenv(const char *name, const char *value, int overwrite); static int setenv(const char *name, const char *value, int overwrite);
#endif #endif
@ -5582,11 +5584,12 @@ void do_close_connection(struct st_command *command)
my_free(con->name); my_free(con->name);
/* /*
When the connection is closed set name to "-closed_connection-" When the connection is closed set name to CLOSED_CONNECTION
to make it possible to reuse the connection name. to make it possible to reuse the connection name.
*/ */
if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME)))) if (!(con->name = my_strdup(CLOSED_CONNECTION, MYF(MY_WME))))
die("Out of memory"); die("Out of memory");
con->name_len= sizeof(CLOSED_CONNECTION)-1;
if (con == cur_con) if (con == cur_con)
{ {
@ -5959,7 +5962,7 @@ void do_connect(struct st_command *command)
con_slot= next_con; con_slot= next_con;
else else
{ {
if (!(con_slot= find_connection_by_name("-closed_connection-"))) if (!(con_slot= find_connection_by_name(CLOSED_CONNECTION)))
die("Connection limit exhausted, you can have max %d connections", die("Connection limit exhausted, you can have max %d connections",
opt_max_connections); opt_max_connections);
my_free(con_slot->name); my_free(con_slot->name);
@ -8552,7 +8555,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
log_file.flush(); log_file.flush();
dynstr_set(&ds_res, 0); dynstr_set(&ds_res, 0);
if (view_protocol_enabled && if (view_protocol_enabled && mysql &&
complete_query && complete_query &&
match_re(&view_re, query)) match_re(&view_re, query))
{ {
@ -8598,7 +8601,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
dynstr_free(&query_str); dynstr_free(&query_str);
} }
if (sp_protocol_enabled && if (sp_protocol_enabled && mysql &&
complete_query && complete_query &&
match_re(&sp_re, query)) match_re(&sp_re, query))
{ {
@ -8961,7 +8964,7 @@ static void dump_backtrace(void)
struct st_connection *conn= cur_con; struct st_connection *conn= cur_con;
fprintf(stderr, "read_command_buf (%p): ", read_command_buf); fprintf(stderr, "read_command_buf (%p): ", read_command_buf);
my_safe_print_str(read_command_buf, sizeof(read_command_buf)); fprintf(stderr, "%.*s\n", (int)read_command_buflen, read_command_buf);
fputc('\n', stderr); fputc('\n', stderr);
if (conn) if (conn)

View File

@ -74,7 +74,9 @@ FOREACH(file ${ABI_HEADERS})
FILE(REMOVE ${tmpfile}) FILE(REMOVE ${tmpfile})
EXECUTE_PROCESS( EXECUTE_PROCESS(
COMMAND diff -w ${file}.pp ${abi_check_out} RESULT_VARIABLE result) COMMAND diff -w ${file}.pp ${abi_check_out} RESULT_VARIABLE result)
IF(NOT ${result} EQUAL 0) IF(result MATCHES "No such file or directory")
MESSAGE("Command 'diff' not found. ABI check for ${file} skipped.")
ELSEIF(NOT result EQUAL 0)
IF(ABI_UPDATE) IF(ABI_UPDATE)
EXECUTE_PROCESS(COMMAND mv -v ${abi_check_out} ${file}.pp) EXECUTE_PROCESS(COMMAND mv -v ${abi_check_out} ${file}.pp)
ELSE(ABI_UPDATE) ELSE(ABI_UPDATE)
@ -84,4 +86,3 @@ FOREACH(file ${ABI_HEADERS})
ENDIF() ENDIF()
FILE(REMOVE ${abi_check_out}) FILE(REMOVE ${abi_check_out})
ENDFOREACH() ENDFOREACH()

22
cmake/os/OpenBSD.cmake Normal file
View File

@ -0,0 +1,22 @@
# Copyright (C) 2012 Monty Program Ab, 2021 Brad Smith
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
# This file includes OpenBSD specific options and quirks, related to system checks
# Find libexecinfo (library that contains backtrace_symbols etc)
FIND_LIBRARY(EXECINFO NAMES execinfo)
IF(EXECINFO)
SET(LIBEXECINFO ${EXECINFO})
ENDIF()

View File

@ -1,6 +1,6 @@
/* /*
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2014, 2019, MariaDB Corporation. Copyright (c) 2014, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -112,13 +112,10 @@ static ulong write_check;
struct innodb_page_type { struct innodb_page_type {
int n_undo_state_active; int n_undo_state_active;
int n_undo_state_cached; int n_undo_state_cached;
int n_undo_state_to_free;
int n_undo_state_to_purge; int n_undo_state_to_purge;
int n_undo_state_prepared; int n_undo_state_prepared;
int n_undo_state_other; int n_undo_state_other;
int n_undo_insert; int n_undo;
int n_undo_update;
int n_undo_other;
int n_fil_page_index; int n_fil_page_index;
int n_fil_page_undo_log; int n_fil_page_undo_log;
int n_fil_page_inode; int n_fil_page_inode;
@ -938,21 +935,7 @@ parse_page(
fprintf(file, "#::%llu\t\t|\t\tUndo log page\t\t\t|", fprintf(file, "#::%llu\t\t|\t\tUndo log page\t\t\t|",
cur_page_num); cur_page_num);
} }
if (undo_page_type == TRX_UNDO_INSERT) { page_type.n_undo++;
page_type.n_undo_insert++;
if (page_type_dump) {
fprintf(file, "\t%s",
"Insert Undo log page");
}
} else if (undo_page_type == TRX_UNDO_UPDATE) {
page_type.n_undo_update++;
if (page_type_dump) {
fprintf(file, "\t%s",
"Update undo log page");
}
}
undo_page_type = mach_read_from_2(page + TRX_UNDO_SEG_HDR + undo_page_type = mach_read_from_2(page + TRX_UNDO_SEG_HDR +
TRX_UNDO_STATE); TRX_UNDO_STATE);
switch (undo_page_type) { switch (undo_page_type) {
@ -972,14 +955,6 @@ parse_page(
} }
break; break;
case TRX_UNDO_TO_FREE:
page_type.n_undo_state_to_free++;
if (page_type_dump) {
fprintf(file, ", %s", "Insert undo "
"segment that can be freed");
}
break;
case TRX_UNDO_TO_PURGE: case TRX_UNDO_TO_PURGE:
page_type.n_undo_state_to_purge++; page_type.n_undo_state_to_purge++;
if (page_type_dump) { if (page_type_dump) {
@ -1203,15 +1178,11 @@ print_summary(
fprintf(fil_out, "\n===============================================\n"); fprintf(fil_out, "\n===============================================\n");
fprintf(fil_out, "Additional information:\n"); fprintf(fil_out, "Additional information:\n");
fprintf(fil_out, "Undo page type: %d insert, %d update, %d other\n", fprintf(fil_out, "Undo page type: %d\n", page_type.n_undo);
page_type.n_undo_insert, fprintf(fil_out, "Undo page state: %d active, %d cached, %d"
page_type.n_undo_update,
page_type.n_undo_other);
fprintf(fil_out, "Undo page state: %d active, %d cached, %d to_free, %d"
" to_purge, %d prepared, %d other\n", " to_purge, %d prepared, %d other\n",
page_type.n_undo_state_active, page_type.n_undo_state_active,
page_type.n_undo_state_cached, page_type.n_undo_state_cached,
page_type.n_undo_state_to_free,
page_type.n_undo_state_to_purge, page_type.n_undo_state_to_purge,
page_type.n_undo_state_prepared, page_type.n_undo_state_prepared,
page_type.n_undo_state_other); page_type.n_undo_state_other);

@ -1 +1 @@
Subproject commit 180c543704d627a50a52aaf60e24ca14e0ec4686 Subproject commit 802ce584a26fdc0ba67fcf35e277bf3c7440956a

View File

@ -3892,6 +3892,25 @@ id rn
1 1 1 1
drop table t1; drop table t1;
# #
# MDEV-25630: Crash with window function in left expr of IN subquery
#
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT lag(i) over (ORDER BY i) IN ( SELECT 1 FROM t1 a) FROM t1;
lag(i) over (ORDER BY i) IN ( SELECT 1 FROM t1 a)
NULL
1
0
DROP TABLE t1;
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT sum(i) over () IN ( SELECT 1 FROM t1 a) FROM t1;
sum(i) over () IN ( SELECT 1 FROM t1 a)
0
0
0
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
# #

View File

@ -2542,6 +2542,20 @@ order by rn desc;
drop table t1; drop table t1;
--echo #
--echo # MDEV-25630: Crash with window function in left expr of IN subquery
--echo #
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT lag(i) over (ORDER BY i) IN ( SELECT 1 FROM t1 a) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT sum(i) over () IN ( SELECT 1 FROM t1 a) FROM t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #

View File

@ -1,7 +1,3 @@
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
NAME
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
NAME
SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_file_per_table = ON;
set global innodb_compression_algorithm = 1; set global innodb_compression_algorithm = 1;
create database enctests; create database enctests;

View File

@ -0,0 +1,20 @@
create table t1(f1 int not null)engine=innodb;
create table t2(f1 int not null)engine=innodb;
insert into t1 select * from seq_1_to_100;
insert into t2 select * from seq_1_to_100;
# restart: --innodb_encrypt_tables=0 --innodb_encryption_threads=1 --innodb_encryption_rotate_key_age=9
# Enable encryption
set global innodb_encrypt_tables=ON;
# Create a new table and it is added to rotation list
create table t3(f1 int not null)engine=innodb;
insert into t3 select * from seq_1_to_100;
# Increase the version and it should set rotation
# variable for the encryption plugin
set global debug_key_management_version=10;
select @@debug_key_management_version;
@@debug_key_management_version
10
# Decrease the key version and Disable the encryption
set global debug_key_management_version=1;
set global innodb_encrypt_tables=off;
DROP TABLE t1, t2, t3;

View File

@ -3898,6 +3898,25 @@ id rn
1 1 1 1
drop table t1; drop table t1;
# #
# MDEV-25630: Crash with window function in left expr of IN subquery
#
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT lag(i) over (ORDER BY i) IN ( SELECT 1 FROM t1 a) FROM t1;
lag(i) over (ORDER BY i) IN ( SELECT 1 FROM t1 a)
NULL
1
0
DROP TABLE t1;
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT sum(i) over () IN ( SELECT 1 FROM t1 a) FROM t1;
sum(i) over () IN ( SELECT 1 FROM t1 a)
0
0
0
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
# #

View File

@ -3,9 +3,6 @@
# not embedded because of restarts # not embedded because of restarts
-- source include/not_embedded.inc -- source include/not_embedded.inc
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
let $encryption = `SELECT @@innodb_encrypt_tables`; let $encryption = `SELECT @@innodb_encrypt_tables`;
SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_file_per_table = ON;
# zlib # zlib

View File

@ -0,0 +1,2 @@
--innodb-tablespaces-encryption
--plugin-load-add=$DEBUG_KEY_MANAGEMENT_SO

View File

@ -0,0 +1,41 @@
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_sequence.inc
create table t1(f1 int not null)engine=innodb;
create table t2(f1 int not null)engine=innodb;
insert into t1 select * from seq_1_to_100;
insert into t2 select * from seq_1_to_100;
let $restart_parameters=--innodb_encrypt_tables=0 --innodb_encryption_threads=1 --innodb_encryption_rotate_key_age=9;
--source include/restart_mysqld.inc
--echo # Enable encryption
set global innodb_encrypt_tables=ON;
--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'`
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
--source include/wait_condition.inc
--echo # Create a new table and it is added to rotation list
create table t3(f1 int not null)engine=innodb;
insert into t3 select * from seq_1_to_100;
--echo # Increase the version and it should set rotation
--echo # variable for the encryption plugin
set global debug_key_management_version=10;
select @@debug_key_management_version;
--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'`
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
--source include/wait_condition.inc
--echo # Decrease the key version and Disable the encryption
set global debug_key_management_version=1;
set global innodb_encrypt_tables=off;
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
--source include/wait_condition.inc
DROP TABLE t1, t2, t3;

View File

@ -262,3 +262,37 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index
# upon ALTER on table with indexed virtual columns
#
CREATE TABLE t1 (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
a INT,
va INT ZEROFILL AS (a) VIRTUAL,
b TIMESTAMP,
c CHAR(204),
vc CHAR(8),
KEY(vc,c(64),b,va)
) ENGINE=InnoDB CHARACTER SET utf32;
INSERT INTO t1 (id) SELECT NULL FROM seq_1_to_75;
INSERT IGNORE INTO t1 (id, a) VALUES (NULL, -1);
Warnings:
Warning 1264 Out of range value for column 'va' at row 1
ALTER TABLE t1 FORCE;
ERROR 22003: Out of range value for column 'va' at row 1
DROP TABLE t1;
#
# MDEV-24713 Assertion `dict_table_is_comp(index->table)' failed
# in row_merge_buf_add()
#
CREATE TABLE t1 (id INT PRIMARY KEY, a CHAR(3),
b CHAR(8) AS (a) VIRTUAL, KEY(b))
ROW_FORMAT=REDUNDANT ENGINE=InnoDB
CHARACTER SET utf8;
INSERT INTO t1 (id,a) VALUES (1,'foo');
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
DROP TABLE t1;

View File

@ -0,0 +1 @@
--innodb_sort_buffer_size=64k

View File

@ -1,4 +1,5 @@
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_sequence.inc
# Ensure that the history list length will actually be decremented by purge. # Ensure that the history list length will actually be decremented by purge.
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
@ -281,3 +282,35 @@ ROLLBACK;
SELECT * FROM t1; SELECT * FROM t1;
CHECK TABLE t1; CHECK TABLE t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index
--echo # upon ALTER on table with indexed virtual columns
--echo #
CREATE TABLE t1 (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
a INT,
va INT ZEROFILL AS (a) VIRTUAL,
b TIMESTAMP,
c CHAR(204),
vc CHAR(8),
KEY(vc,c(64),b,va)
) ENGINE=InnoDB CHARACTER SET utf32;
INSERT INTO t1 (id) SELECT NULL FROM seq_1_to_75;
INSERT IGNORE INTO t1 (id, a) VALUES (NULL, -1);
--error ER_WARN_DATA_OUT_OF_RANGE
ALTER TABLE t1 FORCE;
DROP TABLE t1;
--echo #
--echo # MDEV-24713 Assertion `dict_table_is_comp(index->table)' failed
--echo # in row_merge_buf_add()
--echo #
CREATE TABLE t1 (id INT PRIMARY KEY, a CHAR(3),
b CHAR(8) AS (a) VIRTUAL, KEY(b))
ROW_FORMAT=REDUNDANT ENGINE=InnoDB
CHARACTER SET utf8;
INSERT INTO t1 (id,a) VALUES (1,'foo');
OPTIMIZE TABLE t1;
DROP TABLE t1;

View File

@ -1052,10 +1052,13 @@ a
10 10
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB;
SET @save_allowed = @@GLOBAL.innodb_instant_alter_column_allowed;
SET GLOBAL innodb_instant_alter_column_allowed=never;
iNSERT INTO t1 VALUES (10); iNSERT INTO t1 VALUES (10);
ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0); ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
affected rows: 0 affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0 info: Records: 0 Duplicates: 0 Warnings: 0
SET GLOBAL innodb_instant_alter_column_allowed=@save_allowed;
SELECT * FROM t1; SELECT * FROM t1;
a b a b
10 2001-01-01 10 2001-01-01

View File

@ -652,10 +652,13 @@ DROP TABLE t1;
# DATETIME-to-DATE truncation is OK # DATETIME-to-DATE truncation is OK
CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB;
SET @save_allowed = @@GLOBAL.innodb_instant_alter_column_allowed;
SET GLOBAL innodb_instant_alter_column_allowed=never;
iNSERT INTO t1 VALUES (10); iNSERT INTO t1 VALUES (10);
--enable_info --enable_info
ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0); ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
--disable_info --disable_info
SET GLOBAL innodb_instant_alter_column_allowed=@save_allowed;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;

View File

@ -31,19 +31,17 @@ DROP TABLE t2, t1;
# #
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB; CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
connect con1,localhost,root,,test; connect con1,localhost,root,,test;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL s1 WAIT_FOR g1'; SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2'; SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
ALTER TABLE t1 ADD FULLTEXT(c); ALTER TABLE t1 ADD FULLTEXT(c);
connection default; connection default;
SET DEBUG_SYNC='now WAIT_FOR s1'; SET DEBUG_SYNC='now WAIT_FOR s2';
KILL QUERY @id;
SET DEBUG_SYNC='now SIGNAL g1 WAIT_FOR s2';
START TRANSACTION; START TRANSACTION;
SELECT * FROM t1; SELECT * FROM t1;
a b c a b c
SET DEBUG_SYNC='now SIGNAL s2'; SET DEBUG_SYNC='now SIGNAL g2';
connection con1; connection con1;
ERROR 70100: Query execution was interrupted ERROR HY000: Out of memory.
disconnect con1; disconnect con1;
connection default; connection default;
SET DEBUG_SYNC=RESET; SET DEBUG_SYNC=RESET;

View File

@ -60,20 +60,16 @@ DROP TABLE t2, t1;
--echo # --echo #
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB; CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
connect(con1,localhost,root,,test); connect(con1,localhost,root,,test);
let $ID= `SELECT @id := CONNECTION_ID()`; SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL s1 WAIT_FOR g1';
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2'; SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
send ALTER TABLE t1 ADD FULLTEXT(c); send ALTER TABLE t1 ADD FULLTEXT(c);
connection default; connection default;
SET DEBUG_SYNC='now WAIT_FOR s1'; SET DEBUG_SYNC='now WAIT_FOR s2';
let $ignore= `SELECT @id := $ID`;
KILL QUERY @id;
SET DEBUG_SYNC='now SIGNAL g1 WAIT_FOR s2';
START TRANSACTION; START TRANSACTION;
SELECT * FROM t1; SELECT * FROM t1;
SET DEBUG_SYNC='now SIGNAL s2'; SET DEBUG_SYNC='now SIGNAL g2';
connection con1; connection con1;
--error ER_QUERY_INTERRUPTED --error ER_OUT_OF_RESOURCES
reap; reap;
disconnect con1; disconnect con1;
connection default; connection default;

View File

@ -112,8 +112,8 @@ File::tab#.ibd
=============================================== ===============================================
Additional information: Additional information:
Undo page type: # insert, # update, # other Undo page type: #
Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other Undo page state: # active, # cached, # to_purge, # prepared, # other
index_id #pages #leaf_pages #recs_per_page #bytes_per_page index_id #pages #leaf_pages #recs_per_page #bytes_per_page
# # # # # # # # # #
# # # # # # # # # #
@ -147,8 +147,8 @@ File::tab#.ibd
=============================================== ===============================================
Additional information: Additional information:
Undo page type: # insert, # update, # other Undo page type: #
Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other Undo page state: # active, # cached, # to_purge, # prepared, # other
index_id #pages #leaf_pages #recs_per_page #bytes_per_page index_id #pages #leaf_pages #recs_per_page #bytes_per_page
# # # # # # # # # #
# # # # # # # # # #

View File

@ -1,5 +1,5 @@
INSTALL SONAME 'auth_named_pipe'; INSTALL SONAME 'auth_named_pipe';
CREATE USER 'USERNAME' IDENTIFIED WITH named_pipe; CREATE USER 'USERNAME' IDENTIFIED WITH named_pipe;
GRANT ALL PRIVILEGES ON *.* to USERNAME; GRANT ALL PRIVILEGES ON *.* to 'USERNAME';
DROP USER 'USERNAME'; DROP USER 'USERNAME';
UNINSTALL SONAME 'auth_named_pipe'; UNINSTALL SONAME 'auth_named_pipe';

View File

@ -18,7 +18,7 @@ INSTALL SONAME 'auth_named_pipe';
--replace_result $USERNAME USERNAME --replace_result $USERNAME USERNAME
eval CREATE USER '$USERNAME' IDENTIFIED WITH named_pipe; eval CREATE USER '$USERNAME' IDENTIFIED WITH named_pipe;
--replace_result $USERNAME USERNAME --replace_result $USERNAME USERNAME
eval GRANT ALL PRIVILEGES ON *.* to $USERNAME; eval GRANT ALL PRIVILEGES ON *.* to '$USERNAME';
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
--disable_result_log --disable_result_log

View File

@ -1,7 +1,7 @@
# #
# with named user # with named user
# #
create user USER identified via unix_socket; create user 'USER' identified via unix_socket;
# #
# name match = ok # name match = ok
# #
@ -11,7 +11,7 @@ USER@localhost USER@% test
# #
# name does not match = failure # name does not match = failure
# #
drop user USER; drop user 'USER';
# #
# and now with anonymous user # and now with anonymous user
# #

View File

@ -4,9 +4,9 @@
--echo # with named user --echo # with named user
--echo # --echo #
--let $replace=create user $USER --let $replace=create user '$USER'
--replace_result $replace "create user USER" --replace_result $replace "create user 'USER'"
eval create user $USER identified via unix_socket; eval create user '$USER' identified via unix_socket;
--write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt --write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt
--let $replace1=$USER@localhost --let $replace1=$USER@localhost
@ -26,9 +26,9 @@ EOF
--error 1 --error 1
--exec $MYSQL_TEST -u foobar < $MYSQLTEST_VARDIR/tmp/peercred_test.txt --exec $MYSQL_TEST -u foobar < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
--let $replace=drop user $USER --let $replace=drop user '$USER'
--replace_result $replace "drop user USER" --replace_result $replace "drop user 'USER'"
eval drop user $USER; eval drop user '$USER';
--echo # --echo #
--echo # and now with anonymous user --echo # and now with anonymous user

View File

@ -1394,7 +1394,7 @@ static void copy_to_read_buffer(IO_CACHE *write_cache,
static int _my_b_seq_read(IO_CACHE *info, uchar *Buffer, size_t Count) static int _my_b_seq_read(IO_CACHE *info, uchar *Buffer, size_t Count)
{ {
size_t length, diff_length, left_length= 0, save_count, max_length; size_t length, diff_length, save_count, max_length;
my_off_t pos_in_file; my_off_t pos_in_file;
save_count=Count; save_count=Count;
@ -1445,7 +1445,6 @@ static int _my_b_seq_read(IO_CACHE *info, uchar *Buffer, size_t Count)
*/ */
goto read_append_buffer; goto read_append_buffer;
} }
left_length+=length;
diff_length=0; diff_length=0;
} }

View File

@ -1190,7 +1190,6 @@ trim_string()
check_pid() check_pid()
{ {
local pid_file="$1" local pid_file="$1"
local remove=${2:-0}
if [ -r "$pid_file" ]; then if [ -r "$pid_file" ]; then
local pid=$(cat "$pid_file" 2>/dev/null) local pid=$(cat "$pid_file" 2>/dev/null)
if [ -n "$pid" ]; then if [ -n "$pid" ]; then
@ -1201,6 +1200,7 @@ check_pid()
fi fi
fi fi
fi fi
local remove=${2:-0}
if [ $remove -eq 1 ]; then if [ $remove -eq 1 ]; then
rm -f "$pid_file" rm -f "$pid_file"
fi fi
@ -1223,7 +1223,7 @@ check_pid()
# #
cleanup_pid() cleanup_pid()
{ {
local pid="$1" local pid=$1
local pid_file="${2:-}" local pid_file="${2:-}"
local config="${3:-}" local config="${3:-}"
@ -1241,8 +1241,9 @@ cleanup_pid()
round=8 round=8
force=1 force=1
kill -9 $pid >/dev/null 2>&1 kill -9 $pid >/dev/null 2>&1
sleep 0.5
else else
return 1; return 1
fi fi
fi fi
done done

View File

@ -741,15 +741,15 @@ recv_joiner()
fi fi
# check donor supplied secret # check donor supplied secret
SECRET=$(grep -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2) SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2)
if [ "$SECRET" != "$MY_SECRET" ]; then if [ "$SECRET" != "$MY_SECRET" ]; then
wsrep_log_error "Donor does not know my secret!" wsrep_log_error "Donor does not know my secret!"
wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'" wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'"
exit 32 exit 32
fi fi
# remove secret from magic file # remove secret from the magic file
grep -v -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new" grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new"
mv "$MAGIC_FILE.new" "$MAGIC_FILE" mv "$MAGIC_FILE.new" "$MAGIC_FILE"
fi fi
} }

View File

@ -68,6 +68,8 @@ cleanup_joiner()
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
wsrep_cleanup_progress_file wsrep_cleanup_progress_file
fi fi
[ -f "$SST_PID" ] && rm -f "$SST_PID"
} }
check_pid_and_port() check_pid_and_port()
@ -281,6 +283,7 @@ then
*) *)
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'" wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
exit 22 # EINVAL exit 22 # EINVAL
;;
esac esac
if [ -z "$CAFILE_OPT" ]; then if [ -z "$CAFILE_OPT" ]; then
wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file" wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file"
@ -426,7 +429,7 @@ EOF
exit 255 # unknown error exit 255 # unknown error
fi fi
# second, we transfer InnoDB log files # second, we transfer InnoDB and Aria log files
rsync ${STUNNEL:+--rsh="$STUNNEL"} \ rsync ${STUNNEL:+--rsh="$STUNNEL"} \
--owner --group --perms --links --specials \ --owner --group --perms --links --specials \
--ignore-times --inplace --dirs --delete --quiet \ --ignore-times --inplace --dirs --delete --quiet \
@ -499,7 +502,22 @@ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
then then
check_sockets_utils check_sockets_utils
# give some time for lingering stunnel from previous SST to complete SST_PID="$WSREP_SST_OPT_DATA/wsrep_rsync_sst.pid"
# give some time for previous SST to complete:
check_round=0
while check_pid "$SST_PID" 0
do
wsrep_log_info "previous SST is not completed, waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 10 ]; then
wsrep_log_error "previous SST script still running."
exit 114 # EALREADY
fi
sleep 1
done
# give some time for stunnel from the previous SST to complete:
check_round=0 check_round=0
while check_pid "$STUNNEL_PID" 1 while check_pid "$STUNNEL_PID" 1
do do
@ -516,7 +534,7 @@ then
RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid"
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
# give some time for lingering rsync from previous SST to complete # give some time for rsync from the previous SST to complete:
check_round=0 check_round=0
while check_pid "$RSYNC_PID" 1 while check_pid "$RSYNC_PID" 1
do do
@ -583,12 +601,14 @@ EOF
RSYNC_ADDR="*" RSYNC_ADDR="*"
fi fi
echo $$ > "$SST_PID"
if [ -z "$STUNNEL" ] if [ -z "$STUNNEL" ]
then then
rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS & rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS &
RSYNC_REAL_PID=$! RSYNC_REAL_PID=$!
TRANSFER_REAL_PID="$RSYNC_REAL_PID" TRANSFER_REAL_PID=$RSYNC_REAL_PID
TRANSFER_PID=$RSYNC_PID TRANSFER_PID="$RSYNC_PID"
else else
# Let's check if the path to the config file contains a space? # Let's check if the path to the config file contains a space?
if [ "${RSYNC_CONF#* }" = "$RSYNC_CONF" ]; then if [ "${RSYNC_CONF#* }" = "$RSYNC_CONF" ]; then
@ -631,8 +651,8 @@ EOF
fi fi
stunnel "$STUNNEL_CONF" & stunnel "$STUNNEL_CONF" &
STUNNEL_REAL_PID=$! STUNNEL_REAL_PID=$!
TRANSFER_REAL_PID="$STUNNEL_REAL_PID" TRANSFER_REAL_PID=$STUNNEL_REAL_PID
TRANSFER_PID=$STUNNEL_PID TRANSFER_PID="$STUNNEL_PID"
fi fi
if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ] if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]
@ -691,21 +711,35 @@ EOF
# Clean up old binlog files first # Clean up old binlog files first
rm -f "$BINLOG_FILENAME".[0-9]* rm -f "$BINLOG_FILENAME".[0-9]*
[ -f "$binlog_index" ] && rm "$binlog_index" [ -f "$binlog_index" ] && rm -f "$binlog_index"
# Create a temporary file:
tmpdir=$(parse_cnf '--mysqld|sst' 'tmpdir')
if [ -z "$tmpdir" ]; then
tmpfile="$(mktemp)"
else
tmpfile=$(mktemp "--tmpdir=$tmpdir")
fi
wsrep_log_info "Extracting binlog files:" wsrep_log_info "Extracting binlog files:"
tar -xvf "$BINLOG_TAR_FILE" >> _binlog_tmp_files_$! if ! tar -xvf "$BINLOG_TAR_FILE" > "$tmpfile"; then
wsrep_log_error "Error unpacking tar file with binlog files"
rm -f "$tmpfile"
exit 32
fi
# Rebuild binlog index:
while read bin_file; do while read bin_file; do
echo "$BINLOG_DIRNAME/$bin_file" >> "$binlog_index" echo "$BINLOG_DIRNAME/$bin_file" >> "$binlog_index"
done < _binlog_tmp_files_$! done < "$tmpfile"
rm -f _binlog_tmp_files_$! rm -f "$tmpfile"
cd "$OLD_PWD" cd "$OLD_PWD"
fi fi
fi fi
if [ -r "$MAGIC_FILE" ] if [ -r "$MAGIC_FILE" ]; then
then if [ -n "$MY_SECRET" ]; then
# check donor supplied secret # check donor supplied secret
SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2) SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2)
if [ "$SECRET" != "$MY_SECRET" ]; then if [ "$SECRET" != "$MY_SECRET" ]; then
@ -713,13 +747,13 @@ EOF
wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'" wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'"
exit 32 exit 32
fi fi
# remove secret from the magic file, and output
# remove secret from magic file # the UUID:seqno & wsrep_gtid_domain_id:
grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new" grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE"
else
mv "$MAGIC_FILE.new" "$MAGIC_FILE" # Output the UUID:seqno and wsrep_gtid_domain_id:
# UUID:seqno & wsrep_gtid_domain_id is received here. cat "$MAGIC_FILE"
cat "$MAGIC_FILE" # Output : UUID:seqno wsrep_gtid_domain_id fi
else else
# this message should cause joiner to abort # this message should cause joiner to abort
echo "rsync process ended without creating '$MAGIC_FILE'" echo "rsync process ended without creating '$MAGIC_FILE'"

View File

@ -434,7 +434,7 @@ Event_scheduler::start(int *err_no)
scheduler_thd= NULL; scheduler_thd= NULL;
deinit_event_thread(new_thd); deinit_event_thread(new_thd);
delete scheduler_param_value; my_free(scheduler_param_value);
ret= true; ret= true;
} }

View File

@ -8470,6 +8470,7 @@ Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg):
with_field= orig_item->with_field; with_field= orig_item->with_field;
name= item_arg->name; name= item_arg->name;
m_with_subquery= orig_item->with_subquery(); m_with_subquery= orig_item->with_subquery();
with_window_func= orig_item->with_window_func;
if ((expr_value= orig_item->get_cache(thd))) if ((expr_value= orig_item->get_cache(thd)))
expr_value->setup(thd, orig_item); expr_value->setup(thd, orig_item);

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. /* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2009, 2019, MariaDB Copyright (c) 2009, 2021, MariaDB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -1383,6 +1383,9 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
maybe_null=1; maybe_null=1;
m_with_subquery= true; m_with_subquery= true;
join_with_sum_func(args[1]); join_with_sum_func(args[1]);
with_window_func= args[0]->with_window_func;
// The subquery cannot have window functions aggregated in this select
DBUG_ASSERT(!args[1]->with_window_func);
with_field= with_field || args[1]->with_field; with_field= with_field || args[1]->with_field;
with_param= args[0]->with_param || args[1]->with_param; with_param= args[0]->with_param || args[1]->with_param;
used_tables_and_const_cache_join(args[1]); used_tables_and_const_cache_join(args[1]);

View File

@ -4913,7 +4913,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
int error= 0; int error= 0;
TABLE *UNINIT_VAR(table); /* inited in all loops */ TABLE *UNINIT_VAR(table); /* inited in all loops */
uint i,table_count,const_count,key; uint i,table_count,const_count,key;
table_map found_const_table_map, all_table_map, found_ref, refs; table_map found_const_table_map, all_table_map;
key_map const_ref, eq_part; key_map const_ref, eq_part;
bool has_expensive_keyparts; bool has_expensive_keyparts;
TABLE **table_vector; TABLE **table_vector;
@ -5179,7 +5179,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{ {
ref_changed = 0; ref_changed = 0;
more_const_tables_found: more_const_tables_found:
found_ref=0;
/* /*
We only have to loop from stat_vector + const_count as We only have to loop from stat_vector + const_count as
@ -5269,7 +5268,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
key=keyuse->key; key=keyuse->key;
s->keys.set_bit(key); // TODO: remove this ? s->keys.set_bit(key); // TODO: remove this ?
refs=0;
const_ref.clear_all(); const_ref.clear_all();
eq_part.clear_all(); eq_part.clear_all();
has_expensive_keyparts= false; has_expensive_keyparts= false;
@ -5285,8 +5283,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (keyuse->val->is_expensive()) if (keyuse->val->is_expensive())
has_expensive_keyparts= true; has_expensive_keyparts= true;
} }
else
refs|=keyuse->used_tables;
eq_part.set_bit(keyuse->keypart); eq_part.set_bit(keyuse->keypart);
} }
keyuse++; keyuse++;
@ -5338,8 +5334,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
found_const_table_map|= table->map; found_const_table_map|= table->map;
break; break;
} }
else
found_ref|= refs; // Table is const if all refs are const
} }
else if (base_const_ref == base_eq_part) else if (base_const_ref == base_eq_part)
s->const_keys.set_bit(key); s->const_keys.set_bit(key);
@ -28075,7 +28069,6 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
*/ */
if (tab) if (tab)
{ {
key_part_map const_parts= 0;
key_part_map map= 1; key_part_map map= 1;
uint kp; uint kp;
/* Find how many key parts would be used by ref(const) */ /* Find how many key parts would be used by ref(const) */
@ -28083,7 +28076,6 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
{ {
if (!(table->const_key_parts[keynr] & map)) if (!(table->const_key_parts[keynr] & map))
break; break;
const_parts |= map;
} }
if (kp > 0) if (kp > 0)

View File

@ -55,6 +55,9 @@ UNIV_INTERN uint srv_n_fil_crypt_threads_started = 0;
/** At this age or older a space/page will be rotated */ /** At this age or older a space/page will be rotated */
UNIV_INTERN uint srv_fil_crypt_rotate_key_age; UNIV_INTERN uint srv_fil_crypt_rotate_key_age;
/** Whether the encryption plugin does key rotation */
static bool srv_encrypt_rotate;
/** Event to signal FROM the key rotation threads. */ /** Event to signal FROM the key rotation threads. */
static os_event_t fil_crypt_event; static os_event_t fil_crypt_event;
@ -136,6 +139,14 @@ fil_space_crypt_t::key_get_latest_version(void)
if (is_key_found()) { if (is_key_found()) {
key_version = encryption_key_get_latest_version(key_id); key_version = encryption_key_get_latest_version(key_id);
/* InnoDB does dirty read of srv_fil_crypt_rotate_key_age.
It doesn't matter because srv_encrypt_rotate
can be set to true only once */
if (!srv_encrypt_rotate
&& key_version > srv_fil_crypt_rotate_key_age) {
srv_encrypt_rotate = true;
}
srv_stats.n_key_requests.inc(); srv_stats.n_key_requests.inc();
key_found = key_version; key_found = key_version;
} }
@ -1199,13 +1210,11 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space)
/* 4 - sync tablespace before publishing crypt data */ /* 4 - sync tablespace before publishing crypt data */
bool success = false; bool success = false;
ulint sum_pages = 0;
do { do {
ulint n_pages = 0; ulint n_pages = 0;
success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages); success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages);
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
sum_pages += n_pages;
} while (!success); } while (!success);
/* 5 - publish crypt data */ /* 5 - publish crypt data */
@ -1578,46 +1587,63 @@ fil_crypt_return_iops(
fil_crypt_update_total_stat(state); fil_crypt_update_total_stat(state);
} }
/** Return the next tablespace from rotation_list. bool fil_crypt_must_default_encrypt()
{
return !srv_fil_crypt_rotate_key_age || !srv_encrypt_rotate;
}
/** Return the next tablespace from default_encrypt_tables.
@param space previous tablespace (NULL to start from the start) @param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after @param recheck whether the removal condition needs to be rechecked after
the encryption parameters were changed the encryption parameters were changed
@param encrypt expected state of innodb_encrypt_tables @param encrypt expected state of innodb_encrypt_tables
@return the next tablespace to process (n_pending_ops incremented) @return the next tablespace to process (n_pending_ops incremented)
@retval NULL if this was the last */ @retval NULL if this was the last */
inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, inline fil_space_t *fil_system_t::default_encrypt_next(
bool recheck, bool encrypt) fil_space_t *space, bool recheck, bool encrypt)
{ {
ut_ad(mutex_own(&mutex)); ut_ad(mutex_own(&mutex));
sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it= sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it=
space && space->is_in_rotation_list ? space : rotation_list.begin(); space && space->is_in_default_encrypt
? space
: default_encrypt_tables.begin();
const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end= const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end=
rotation_list.end(); default_encrypt_tables.end();
if (space) if (space)
{ {
const bool released= !space->release(); const bool released= !space->release();
if (space->is_in_rotation_list) if (space->is_in_default_encrypt)
{ {
while (++it != end && while (++it != end &&
(!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); (!UT_LIST_GET_LEN(it->chain) || it->is_stopping()));
/* If one of the encryption threads already started the encryption /* If one of the encryption threads already started
of the table then don't remove the unencrypted spaces from rotation list the encryption of the table then don't remove the
unencrypted spaces from default encrypt list.
If there is a change in innodb_encrypt_tables variables value then If there is a change in innodb_encrypt_tables variables
don't remove the last processed tablespace from the rotation list. */ value then don't remove the last processed tablespace
from the default encrypt list. */
if (released && (!recheck || space->crypt_data) && if (released && (!recheck || space->crypt_data) &&
!encrypt == !srv_encrypt_tables) !encrypt == !srv_encrypt_tables)
{ {
ut_a(!rotation_list.empty()); ut_a(!default_encrypt_tables.empty());
rotation_list.remove(*space); default_encrypt_tables.remove(*space);
space->is_in_rotation_list= false; space->is_in_default_encrypt= false;
} }
} }
} }
else while (it != end &&
(!UT_LIST_GET_LEN(it->chain) || it->is_stopping()))
{
/* Find the next suitable default encrypt table if
beginning of default_encrypt_tables list has been scheduled
to be deleted */
it++;
}
while (it != end) while (it != end)
{ {
@ -1642,8 +1668,8 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck,
{ {
mutex_enter(&fil_system.mutex); mutex_enter(&fil_system.mutex);
if (!srv_fil_crypt_rotate_key_age) if (fil_crypt_must_default_encrypt())
space= fil_system.keyrotate_next(space, recheck, encrypt); space= fil_system.default_encrypt_next(space, recheck, encrypt);
else if (!space) else if (!space)
{ {
space= UT_LIST_GET_FIRST(fil_system.space_list); space= UT_LIST_GET_FIRST(fil_system.space_list);
@ -2530,9 +2556,9 @@ fil_crypt_set_thread_cnt(
} }
} }
/** Initialize the tablespace rotation_list /** Initialize the tablespace default_encrypt_tables
if innodb_encryption_rotate_key_age=0. */ if innodb_encryption_rotate_key_age=0. */
static void fil_crypt_rotation_list_fill() static void fil_crypt_default_encrypt_tables_fill()
{ {
ut_ad(mutex_own(&fil_system.mutex)); ut_ad(mutex_own(&fil_system.mutex));
@ -2540,7 +2566,7 @@ static void fil_crypt_rotation_list_fill()
space != NULL; space != NULL;
space = UT_LIST_GET_NEXT(space_list, space)) { space = UT_LIST_GET_NEXT(space_list, space)) {
if (space->purpose != FIL_TYPE_TABLESPACE if (space->purpose != FIL_TYPE_TABLESPACE
|| space->is_in_rotation_list || space->is_in_default_encrypt
|| UT_LIST_GET_LEN(space->chain) == 0 || UT_LIST_GET_LEN(space->chain) == 0
|| !space->acquire()) { || !space->acquire()) {
continue; continue;
@ -2580,8 +2606,8 @@ static void fil_crypt_rotation_list_fill()
} }
} }
fil_system.rotation_list.push_back(*space); fil_system.default_encrypt_tables.push_back(*space);
space->is_in_rotation_list = true; space->is_in_default_encrypt = true;
next: next:
space->release(); space->release();
} }
@ -2598,7 +2624,7 @@ fil_crypt_set_rotate_key_age(
mutex_enter(&fil_system.mutex); mutex_enter(&fil_system.mutex);
srv_fil_crypt_rotate_key_age = val; srv_fil_crypt_rotate_key_age = val;
if (val == 0) { if (val == 0) {
fil_crypt_rotation_list_fill(); fil_crypt_default_encrypt_tables_fill();
} }
mutex_exit(&fil_system.mutex); mutex_exit(&fil_system.mutex);
os_event_set(fil_crypt_threads_event); os_event_set(fil_crypt_threads_event);
@ -2628,8 +2654,8 @@ fil_crypt_set_encrypt_tables(
srv_encrypt_tables = val; srv_encrypt_tables = val;
if (srv_fil_crypt_rotate_key_age == 0) { if (fil_crypt_must_default_encrypt()) {
fil_crypt_rotation_list_fill(); fil_crypt_default_encrypt_tables_fill();
} }
mutex_exit(&fil_system.mutex); mutex_exit(&fil_system.mutex);

View File

@ -1083,9 +1083,9 @@ fil_space_detach(
space->is_in_unflushed_spaces = false; space->is_in_unflushed_spaces = false;
} }
if (space->is_in_rotation_list) { if (space->is_in_default_encrypt) {
fil_system.rotation_list.remove(*space); fil_system.default_encrypt_tables.remove(*space);
space->is_in_rotation_list = false; space->is_in_default_encrypt = false;
} }
UT_LIST_REMOVE(fil_system.space_list, space); UT_LIST_REMOVE(fil_system.space_list, space);
@ -1292,20 +1292,25 @@ fil_space_create(
fil_system.max_assigned_id = id; fil_system.max_assigned_id = id;
} }
const bool rotate =
(purpose == FIL_TYPE_TABLESPACE
&& (mode == FIL_ENCRYPTION_ON
|| mode == FIL_ENCRYPTION_OFF || srv_encrypt_tables)
&& fil_crypt_must_default_encrypt());
/* Inform key rotation that there could be something /* Inform key rotation that there could be something
to do */ to do */
if (purpose == FIL_TYPE_TABLESPACE if (rotate) {
&& !srv_fil_crypt_rotate_key_age && fil_crypt_threads_event &&
(mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF
|| srv_encrypt_tables)) {
/* Key rotation is not enabled, need to inform background /* Key rotation is not enabled, need to inform background
encryption threads. */ encryption threads. */
fil_system.rotation_list.push_back(*space); fil_system.default_encrypt_tables.push_back(*space);
space->is_in_rotation_list = true; space->is_in_default_encrypt = true;
}
mutex_exit(&fil_system.mutex); mutex_exit(&fil_system.mutex);
if (rotate && srv_n_fil_crypt_threads_started) {
os_event_set(fil_crypt_threads_event); os_event_set(fil_crypt_threads_event);
} else {
mutex_exit(&fil_system.mutex);
} }
return(space); return(space);

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation. Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -2524,7 +2524,6 @@ fsp_reserve_free_extents(
ulint n_free; ulint n_free;
ulint n_free_up; ulint n_free_up;
ulint reserve; ulint reserve;
size_t total_reserved = 0;
ut_ad(mtr); ut_ad(mtr);
*n_reserved = n_ext; *n_reserved = n_ext;
@ -2603,8 +2602,7 @@ try_again:
return(true); return(true);
} }
try_to_extend: try_to_extend:
if (ulint n = fsp_try_extend_data_file(space, space_header, mtr)) { if (fsp_try_extend_data_file(space, space_header, mtr)) {
total_reserved += n;
goto try_again; goto try_again;
} }

View File

@ -496,4 +496,10 @@ encrypted, or corrupted.
bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size) bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/** Add the tablespace to the rotation list if
innodb_encrypt_rotate_key_age is 0 or encryption plugin does
not do key version rotation
@return whether the tablespace should be added to rotation list */
bool fil_crypt_must_default_encrypt();
#endif /* fil0crypt_h */ #endif /* fil0crypt_h */

View File

@ -171,7 +171,7 @@ public:
bool is_in_unflushed_spaces; bool is_in_unflushed_spaces;
/** Checks that this tablespace needs key rotation. */ /** Checks that this tablespace needs key rotation. */
bool is_in_rotation_list; bool is_in_default_encrypt;
/** True if the device this filespace is on supports atomic writes */ /** True if the device this filespace is on supports atomic writes */
bool atomic_write_supported; bool atomic_write_supported;
@ -987,9 +987,9 @@ public:
record has been written since record has been written since
the latest redo log checkpoint. the latest redo log checkpoint.
Protected only by log_sys.mutex. */ Protected only by log_sys.mutex. */
ilist<fil_space_t, rotation_list_tag_t> rotation_list;
/*!< list of all file spaces needing /** List of all file spaces need key rotation */
key rotation.*/ ilist<fil_space_t, rotation_list_tag_t> default_encrypt_tables;
bool space_id_reuse_warned; bool space_id_reuse_warned;
/*!< whether fil_space_create() /*!< whether fil_space_create()
@ -1002,15 +1002,15 @@ public:
@retval NULL if the tablespace does not exist or cannot be read */ @retval NULL if the tablespace does not exist or cannot be read */
fil_space_t* read_page0(ulint id); fil_space_t* read_page0(ulint id);
/** Return the next tablespace from rotation_list. /** Return the next tablespace from default_encrypt_tables list.
@param space previous tablespace (NULL to start from the start) @param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after @param recheck whether the removal condition needs to be rechecked after
the encryption parameters were changed the encryption parameters were changed
@param encrypt expected state of innodb_encrypt_tables @param encrypt expected state of innodb_encrypt_tables
@return the next tablespace to process (n_pending_ops incremented) @return the next tablespace to process (n_pending_ops incremented)
@retval NULL if this was the last */ @retval NULL if this was the last */
inline fil_space_t* keyrotate_next(fil_space_t *space, bool recheck, inline fil_space_t* default_encrypt_next(
bool encrypt); fil_space_t *space, bool recheck, bool encrypt);
}; };
/** The tablespace memory cache. */ /** The tablespace memory cache. */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -78,20 +78,17 @@ public:
typedef trx_rsegs_t::iterator iterator; typedef trx_rsegs_t::iterator iterator;
typedef trx_rsegs_t::const_iterator const_iterator; typedef trx_rsegs_t::const_iterator const_iterator;
/** Default constructor */
TrxUndoRsegs() {} TrxUndoRsegs() {}
/** Constructor */ /** Constructor */
TrxUndoRsegs(trx_rseg_t& rseg) TrxUndoRsegs(trx_rseg_t& rseg)
: m_commit(rseg.last_commit), m_rsegs(1, &rseg) {} : trx_no(rseg.last_trx_no()), m_rsegs(1, &rseg) {}
/** Constructor */ /** Constructor */
TrxUndoRsegs(trx_id_t trx_no, trx_rseg_t& rseg) TrxUndoRsegs(trx_id_t trx_no, trx_rseg_t& rseg)
: m_commit(trx_no << 1), m_rsegs(1, &rseg) {} : trx_no(trx_no), m_rsegs(1, &rseg) {}
/** @return the transaction commit identifier */
trx_id_t trx_no() const { return m_commit >> 1; }
bool operator!=(const TrxUndoRsegs& other) const bool operator!=(const TrxUndoRsegs& other) const
{ return m_commit != other.m_commit; } { return trx_no != other.trx_no; }
bool empty() const { return m_rsegs.empty(); } bool empty() const { return m_rsegs.empty(); }
void erase(iterator& it) { m_rsegs.erase(it); } void erase(iterator& it) { m_rsegs.erase(it); }
iterator begin() { return(m_rsegs.begin()); } iterator begin() { return(m_rsegs.begin()); }
@ -105,14 +102,14 @@ public:
@return true if elem1 > elem2 else false.*/ @return true if elem1 > elem2 else false.*/
bool operator()(const TrxUndoRsegs& lhs, const TrxUndoRsegs& rhs) bool operator()(const TrxUndoRsegs& lhs, const TrxUndoRsegs& rhs)
{ {
return(lhs.m_commit > rhs.m_commit); return(lhs.trx_no > rhs.trx_no);
} }
/** Copy of trx_rseg_t::last_trx_no() */
trx_id_t trx_no= 0;
private: private:
/** Copy trx_rseg_t::last_commit */
trx_id_t m_commit;
/** Rollback segments of a transaction, scheduled for purge. */ /** Rollback segments of a transaction, scheduled for purge. */
trx_rsegs_t m_rsegs; trx_rsegs_t m_rsegs{};
}; };
typedef std::priority_queue< typedef std::priority_queue<
@ -171,17 +168,13 @@ public:
{ {
bool operator<=(const iterator& other) const bool operator<=(const iterator& other) const
{ {
if (commit < other.commit) return true; if (trx_no < other.trx_no) return true;
if (commit > other.commit) return false; if (trx_no > other.trx_no) return false;
return undo_no <= other.undo_no; return undo_no <= other.undo_no;
} }
/** @return the commit number of the transaction */ /** trx_t::no of the committed transaction */
trx_id_t trx_no() const { return commit >> 1; } trx_id_t trx_no;
void reset_trx_no(trx_id_t trx_no) { commit = trx_no << 1; }
/** 2 * trx_t::no + old_insert of the committed transaction */
trx_id_t commit;
/** The record number within the committed transaction's undo /** The record number within the committed transaction's undo
log, increasing, purged from from 0 onwards */ log, increasing, purged from from 0 onwards */
undo_no_t undo_no; undo_no_t undo_no;

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation. Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -82,9 +82,8 @@ trx_rseg_header_create(
buf_block_t* sys_header, buf_block_t* sys_header,
mtr_t* mtr); mtr_t* mtr);
/** Initialize the rollback segments in memory at database startup. */ /** Initialize or recover the rollback segments at startup. */
void dberr_t trx_rseg_array_init();
trx_rseg_array_init();
/** Free a rollback segment in memory. */ /** Free a rollback segment in memory. */
void void
@ -147,21 +146,13 @@ struct trx_rseg_t {
/** List of undo log segments cached for fast reuse */ /** List of undo log segments cached for fast reuse */
UT_LIST_BASE_NODE_T(trx_undo_t) undo_cached; UT_LIST_BASE_NODE_T(trx_undo_t) undo_cached;
/** List of recovered old insert_undo logs of incomplete
transactions (to roll back or XA COMMIT & purge) */
UT_LIST_BASE_NODE_T(trx_undo_t) old_insert_list;
/*--------------------------------------------------------*/ /*--------------------------------------------------------*/
/** Page number of the last not yet purged log header in the history /** Last not yet purged undo log header; FIL_NULL if all purged */
list; FIL_NULL if all list purged */ uint32_t last_page_no;
ulint last_page_no;
/** Byte offset of the last not yet purged log header */ /** trx_t::no | last_offset << 48 */
ulint last_offset; uint64_t last_commit_and_offset;
/** trx_t::no * 2 + old_insert of the last not yet purged log */
trx_id_t last_commit;
/** Whether the log segment needs purge */ /** Whether the log segment needs purge */
bool needs_purge; bool needs_purge;
@ -174,11 +165,15 @@ struct trx_rseg_t {
bool skip_allocation; bool skip_allocation;
/** @return the commit ID of the last committed transaction */ /** @return the commit ID of the last committed transaction */
trx_id_t last_trx_no() const { return last_commit >> 1; } trx_id_t last_trx_no() const
{ return last_commit_and_offset & ((1ULL << 48) - 1); }
/** @return header offset of the last committed transaction */
uint16_t last_offset() const
{ return static_cast<uint16_t>(last_commit_and_offset >> 48); }
void set_last_trx_no(trx_id_t trx_no, bool is_update) void set_last_commit(ulint last_offset, trx_id_t trx_no)
{ {
last_commit = trx_no << 1 | trx_id_t(is_update); last_commit_and_offset= static_cast<uint64_t>(last_offset) << 48 | trx_no;
} }
/** @return whether the rollback segment is persistent */ /** @return whether the rollback segment is persistent */

View File

@ -79,7 +79,7 @@ void trx_free_at_shutdown(trx_t *trx);
void trx_disconnect_prepared(trx_t *trx); void trx_disconnect_prepared(trx_t *trx);
/** Initialize (resurrect) transactions at startup. */ /** Initialize (resurrect) transactions at startup. */
void trx_lists_init_at_db_start(); dberr_t trx_lists_init_at_db_start();
/*************************************************************//** /*************************************************************//**
Starts the transaction if it is not yet started. */ Starts the transaction if it is not yet started. */
@ -678,10 +678,6 @@ struct trx_undo_ptr_t {
yet */ yet */
trx_undo_t* undo; /*!< pointer to the undo log, or trx_undo_t* undo; /*!< pointer to the undo log, or
NULL if nothing logged yet */ NULL if nothing logged yet */
trx_undo_t* old_insert; /*!< pointer to recovered
insert undo log, or NULL if no
INSERT transactions were
recovered from old-format undo logs */
}; };
/** An instance of temporary rollback segment. */ /** An instance of temporary rollback segment. */
@ -1035,13 +1031,6 @@ public:
return(has_logged_persistent() || rsegs.m_noredo.undo); return(has_logged_persistent() || rsegs.m_noredo.undo);
} }
/** @return whether any undo log has been generated or
recovered */
bool has_logged_or_recovered() const
{
return(has_logged() || rsegs.m_redo.old_insert);
}
/** @return rollback segment for modifying temporary tables */ /** @return rollback segment for modifying temporary tables */
trx_rseg_t* get_temp_rseg() trx_rseg_t* get_temp_rseg()
{ {

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation. Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -91,8 +91,6 @@ enum trx_dict_op_t {
struct trx_t; struct trx_t;
/** The locks and state of an active transaction */ /** The locks and state of an active transaction */
struct trx_lock_t; struct trx_lock_t;
/** Signal */
struct trx_sig_t;
/** Rollback segment */ /** Rollback segment */
struct trx_rseg_t; struct trx_rseg_t;
/** Transaction undo log */ /** Transaction undo log */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation. Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -237,22 +237,16 @@ trx_undo_set_state_at_finish(
@param[in,out] trx transaction @param[in,out] trx transaction
@param[in,out] undo undo log @param[in,out] undo undo log
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK @param[in] rollback false=XA PREPARE, true=XA ROLLBACK
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction */
@return undo log segment header page, x-latched */ void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback,
page_t* mtr_t *mtr)
trx_undo_set_state_at_prepare( MY_ATTRIBUTE((nonnull));
trx_t* trx,
trx_undo_t* undo,
bool rollback,
mtr_t* mtr);
/** Free an old insert or temporary undo log after commit or rollback. /** Free temporary undo log after commit or rollback.
The information is not needed after a commit or rollback, therefore The information is not needed after a commit or rollback, therefore
the data can be discarded. the data can be discarded.
@param[in,out] undo undo log @param undo temporary undo log */
@param[in] is_temp whether this is temporary undo log */ void trx_undo_commit_cleanup(trx_undo_t *undo);
void
trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp);
/** At shutdown, frees the undo logs of a transaction. */ /** At shutdown, frees the undo logs of a transaction. */
void void
@ -295,26 +289,21 @@ trx_undo_parse_page_header(
@param[in] id rollback segment slot @param[in] id rollback segment slot
@param[in] page_no undo log segment page number @param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID @param[in,out] max_trx_id the largest observed transaction ID
@return size of the undo log in pages */ @return the undo log
ulint @retval nullptr on error */
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no, trx_undo_t *
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
trx_id_t &max_trx_id); trx_id_t &max_trx_id);
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */
/* Types of an undo log segment */ /** the only rollback segment type since MariaDB 10.3.1 */
#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */ constexpr uint16_t TRX_UNDO_UPDATE= 2;
#define TRX_UNDO_UPDATE 2 /* contains undo entries for updates
and delete markings: in short,
modifys (the name 'UPDATE' is a
historical relic) */
/* TRX_UNDO_STATE values of an undo log segment */ /* TRX_UNDO_STATE values of an undo log segment */
/** contains an undo log of an active transaction */ /** contains an undo log of an active transaction */
constexpr uint16_t TRX_UNDO_ACTIVE = 1; constexpr uint16_t TRX_UNDO_ACTIVE = 1;
/** cached for quick reuse */ /** cached for quick reuse */
constexpr uint16_t TRX_UNDO_CACHED = 2; constexpr uint16_t TRX_UNDO_CACHED = 2;
/** old_insert undo segment that can be freed */
constexpr uint16_t TRX_UNDO_TO_FREE = 3;
/** can be freed in purge when all undo data in it is removed */ /** can be freed in purge when all undo data in it is removed */
constexpr uint16_t TRX_UNDO_TO_PURGE = 4; constexpr uint16_t TRX_UNDO_TO_PURGE = 4;
/** contains an undo log of a prepared transaction */ /** contains an undo log of a prepared transaction */
@ -377,7 +366,8 @@ struct trx_undo_t {
/** Transaction undo log page header offsets */ /** Transaction undo log page header offsets */
/* @{ */ /* @{ */
#define TRX_UNDO_PAGE_TYPE 0 /*!< unused; 0 (before MariaDB 10.3.1: #define TRX_UNDO_PAGE_TYPE 0 /*!< unused; 0 (before MariaDB 10.3.1:
TRX_UNDO_INSERT or TRX_UNDO_UPDATE) */ 1=TRX_UNDO_INSERT or
2=TRX_UNDO_UPDATE) */
#define TRX_UNDO_PAGE_START 2 /*!< Byte offset where the undo log #define TRX_UNDO_PAGE_START 2 /*!< Byte offset where the undo log
records for the LATEST transaction records for the LATEST transaction
start on this page (remember that start on this page (remember that

View File

@ -4579,7 +4579,7 @@ lock_print_info_summary(
"Purge done for trx's n:o < " TRX_ID_FMT "Purge done for trx's n:o < " TRX_ID_FMT
" undo n:o < " TRX_ID_FMT " state: %s\n" " undo n:o < " TRX_ID_FMT " state: %s\n"
"History list length %u\n", "History list length %u\n",
purge_sys.tail.trx_no(), purge_sys.tail.trx_no,
purge_sys.tail.undo_no, purge_sys.tail.undo_no,
purge_sys.enabled() purge_sys.enabled()
? (purge_sys.running() ? "running" ? (purge_sys.running() ? "running"

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2020, MariaDB Corporation. Copyright (c) 2015, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -771,7 +771,6 @@ DECLARE_THREAD(fts_parallel_tokenization)(
row_merge_block_t** crypt_block; row_merge_block_t** crypt_block;
pfs_os_file_t tmpfd[FTS_NUM_AUX_INDEX]; pfs_os_file_t tmpfd[FTS_NUM_AUX_INDEX];
ulint mycount[FTS_NUM_AUX_INDEX]; ulint mycount[FTS_NUM_AUX_INDEX];
ib_uint64_t total_rec = 0;
ulint num_doc_processed = 0; ulint num_doc_processed = 0;
doc_id_t last_doc_id = 0; doc_id_t last_doc_id = 0;
mem_heap_t* blob_heap = NULL; mem_heap_t* blob_heap = NULL;
@ -1039,7 +1038,6 @@ exit:
goto func_exit; goto func_exit;
} }
total_rec += merge_file[i]->n_rec;
os_file_close(tmpfd[i]); os_file_close(tmpfd[i]);
} }

View File

@ -524,7 +524,9 @@ row_merge_buf_add(
DBUG_ENTER("row_merge_buf_add"); DBUG_ENTER("row_merge_buf_add");
if (buf->n_tuples >= buf->max_tuples) { if (buf->n_tuples >= buf->max_tuples) {
DBUG_RETURN(0); error:
n_row_added = 0;
goto end;
} }
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF(
@ -689,7 +691,10 @@ row_merge_buf_add(
continue; continue;
} }
if (field->len != UNIV_SQL_NULL /* innobase_get_computed_value() sets the
length of the virtual column field. */
if (v_col == NULL
&& field->len != UNIV_SQL_NULL
&& col->mtype == DATA_MYSQL && col->mtype == DATA_MYSQL
&& col->len != field->len) { && col->len != field->len) {
if (conv_heap != NULL) { if (conv_heap != NULL) {
@ -845,11 +850,6 @@ end:
if (vcol_storage.innobase_record) if (vcol_storage.innobase_record)
innobase_free_row_for_vcol(&vcol_storage); innobase_free_row_for_vcol(&vcol_storage);
DBUG_RETURN(n_row_added); DBUG_RETURN(n_row_added);
error:
if (vcol_storage.innobase_record)
innobase_free_row_for_vcol(&vcol_storage);
DBUG_RETURN(0);
} }
/*************************************************************//** /*************************************************************//**
@ -2693,14 +2693,16 @@ write_buffers:
&err, &v_heap, eval_table, trx)))) { &err, &v_heap, eval_table, trx)))) {
/* An empty buffer should have enough /* An empty buffer should have enough
room for at least one record. */ room for at least one record. */
ut_error; ut_ad(err == DB_COMPUTE_VALUE_FAILED
} || err == DB_OUT_OF_MEMORY
|| err == DB_TOO_BIG_RECORD);
if (err != DB_SUCCESS) { } else if (err == DB_SUCCESS) {
break;
}
file->n_rec += rows_added; file->n_rec += rows_added;
continue;
}
trx->error_key_num = i;
break;
} }
} }

View File

@ -284,23 +284,13 @@ static bool row_undo_rec_get(undo_node_t* node)
} }
trx_undo_t* undo = NULL; trx_undo_t* undo = NULL;
trx_undo_t* insert = trx->rsegs.m_redo.old_insert;
trx_undo_t* update = trx->rsegs.m_redo.undo; trx_undo_t* update = trx->rsegs.m_redo.undo;
trx_undo_t* temp = trx->rsegs.m_noredo.undo; trx_undo_t* temp = trx->rsegs.m_noredo.undo;
const undo_no_t limit = trx->roll_limit; const undo_no_t limit = trx->roll_limit;
ut_ad(!insert || !update || insert->empty() || update->empty()
|| insert->top_undo_no != update->top_undo_no);
ut_ad(!insert || !temp || insert->empty() || temp->empty()
|| insert->top_undo_no != temp->top_undo_no);
ut_ad(!update || !temp || update->empty() || temp->empty() ut_ad(!update || !temp || update->empty() || temp->empty()
|| update->top_undo_no != temp->top_undo_no); || update->top_undo_no != temp->top_undo_no);
if (UNIV_LIKELY_NULL(insert)
&& !insert->empty() && limit <= insert->top_undo_no) {
undo = insert;
}
if (update && !update->empty() && update->top_undo_no >= limit) { if (update && !update->empty() && update->top_undo_no >= limit) {
if (!undo) { if (!undo) {
undo = update; undo = update;
@ -376,19 +366,16 @@ static bool row_undo_rec_get(undo_node_t* node)
MDEV-12288 removed the insert_undo log. There is no MDEV-12288 removed the insert_undo log. There is no
instant ADD COLUMN for temporary tables. Therefore, instant ADD COLUMN for temporary tables. Therefore,
this record can only be present in the main undo log. */ this record can only be present in the main undo log. */
ut_ad(undo == update);
/* fall through */ /* fall through */
case TRX_UNDO_RENAME_TABLE: case TRX_UNDO_RENAME_TABLE:
ut_ad(undo == insert || undo == update); ut_ad(undo == update);
/* fall through */ /* fall through */
case TRX_UNDO_INSERT_REC: case TRX_UNDO_INSERT_REC:
ut_ad(undo == insert || undo == update || undo == temp);
node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS; node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
node->state = undo == temp node->state = undo == temp
? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT; ? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT;
break; break;
default: default:
ut_ad(undo == update || undo == temp);
node->state = undo == temp node->state = undo == temp
? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT; ? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT;
break; break;

View File

@ -1310,6 +1310,16 @@ dberr_t srv_start(bool create_new_db)
|| is_mariabackup_restore_or_export()); || is_mariabackup_restore_or_export());
if (srv_force_recovery) {
ib::info() << "!!! innodb_force_recovery is set to "
<< srv_force_recovery << " !!!";
}
if (srv_force_recovery) {
ib::info() << "!!! innodb_force_recovery is set to "
<< srv_force_recovery << " !!!";
}
if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
srv_read_only_mode = true; srv_read_only_mode = true;
} }
@ -1828,7 +1838,11 @@ files_checked:
All the remaining rollback segments will be created later, All the remaining rollback segments will be created later,
after the double write buffer has been created. */ after the double write buffer has been created. */
trx_sys_create_sys_pages(); trx_sys_create_sys_pages();
trx_lists_init_at_db_start(); err = trx_lists_init_at_db_start();
if (err != DB_SUCCESS) {
return(srv_init_abort(err));
}
err = dict_create(); err = dict_create();
@ -1884,7 +1898,10 @@ files_checked:
case SRV_OPERATION_RESTORE: case SRV_OPERATION_RESTORE:
/* This must precede /* This must precede
recv_apply_hashed_log_recs(true). */ recv_apply_hashed_log_recs(true). */
trx_lists_init_at_db_start(); err = trx_lists_init_at_db_start();
if (err != DB_SUCCESS) {
return srv_init_abort(err);
}
break; break;
case SRV_OPERATION_RESTORE_DELTA: case SRV_OPERATION_RESTORE_DELTA:
case SRV_OPERATION_BACKUP: case SRV_OPERATION_BACKUP:
@ -2347,11 +2364,6 @@ skip_monitors:
<< "; transaction id " << trx_sys.get_max_trx_id(); << "; transaction id " << trx_sys.get_max_trx_id();
} }
if (srv_force_recovery > 0) {
ib::info() << "!!! innodb_force_recovery is set to "
<< srv_force_recovery << " !!!";
}
if (srv_force_recovery == 0) { if (srv_force_recovery == 0) {
/* In the insert buffer we may have even bigger tablespace /* In the insert buffer we may have even bigger tablespace
id's, because we may have dropped those tablespaces, but id's, because we may have dropped those tablespaces, but

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation. Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -87,7 +87,7 @@ inline bool TrxUndoRsegsIterator::set_next()
number shouldn't increase. Undo the increment of number shouldn't increase. Undo the increment of
expected commit done by caller assuming rollback expected commit done by caller assuming rollback
segments from given transaction are done. */ segments from given transaction are done. */
purge_sys.tail.commit = (*m_iter)->last_commit; purge_sys.tail.trx_no = (*m_iter)->last_trx_no();
} else if (!purge_sys.purge_queue.empty()) { } else if (!purge_sys.purge_queue.empty()) {
m_rsegs = purge_sys.purge_queue.top(); m_rsegs = purge_sys.purge_queue.top();
purge_sys.purge_queue.pop(); purge_sys.purge_queue.pop();
@ -108,17 +108,17 @@ inline bool TrxUndoRsegsIterator::set_next()
mutex_enter(&purge_sys.rseg->mutex); mutex_enter(&purge_sys.rseg->mutex);
ut_a(purge_sys.rseg->last_page_no != FIL_NULL); ut_a(purge_sys.rseg->last_page_no != FIL_NULL);
ut_ad(purge_sys.rseg->last_trx_no() == m_rsegs.trx_no()); ut_ad(purge_sys.rseg->last_trx_no() == m_rsegs.trx_no);
/* We assume in purge of externally stored fields that space id is /* We assume in purge of externally stored fields that space id is
in the range of UNDO tablespace space ids */ in the range of UNDO tablespace space ids */
ut_ad(purge_sys.rseg->space->id == TRX_SYS_SPACE ut_ad(purge_sys.rseg->space->id == TRX_SYS_SPACE
|| srv_is_undo_tablespace(purge_sys.rseg->space->id)); || srv_is_undo_tablespace(purge_sys.rseg->space->id));
ut_a(purge_sys.tail.commit <= purge_sys.rseg->last_commit); ut_a(purge_sys.tail.trx_no <= purge_sys.rseg->last_trx_no());
purge_sys.tail.commit = purge_sys.rseg->last_commit; purge_sys.tail.trx_no = purge_sys.rseg->last_trx_no();
purge_sys.hdr_offset = purge_sys.rseg->last_offset; purge_sys.hdr_offset = purge_sys.rseg->last_offset();
purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; purge_sys.hdr_page_no = purge_sys.rseg->last_page_no;
mutex_exit(&purge_sys.rseg->mutex); mutex_exit(&purge_sys.rseg->mutex);
@ -209,8 +209,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
{ {
DBUG_PRINT("trx", ("commit(" TRX_ID_FMT "," TRX_ID_FMT ")", DBUG_PRINT("trx", ("commit(" TRX_ID_FMT "," TRX_ID_FMT ")",
trx->id, trx->no)); trx->id, trx->no));
ut_ad(undo == trx->rsegs.m_redo.undo ut_ad(undo == trx->rsegs.m_redo.undo);
|| undo == trx->rsegs.m_redo.old_insert);
trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
ut_ad(undo->rseg == rseg); ut_ad(undo->rseg == rseg);
trx_rsegf_t* rseg_header = trx_rsegf_get( trx_rsegf_t* rseg_header = trx_rsegf_get(
@ -302,9 +301,8 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
} }
if (rseg->last_page_no == FIL_NULL) { if (rseg->last_page_no == FIL_NULL) {
rseg->last_page_no = undo->hdr_page_no; rseg->last_page_no = static_cast<uint32_t>(undo->hdr_page_no);
rseg->last_offset = undo->hdr_offset; rseg->set_last_commit(undo->hdr_offset, trx->no);
rseg->set_last_trx_no(trx->no, undo == trx->rsegs.m_redo.undo);
rseg->needs_purge = true; rseg->needs_purge = true;
} }
@ -460,8 +458,8 @@ func_exit:
undo_trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); undo_trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);
if (undo_trx_no >= limit.trx_no()) { if (undo_trx_no >= limit.trx_no) {
if (undo_trx_no == limit.trx_no()) { if (undo_trx_no == limit.trx_no) {
trx_undo_truncate_start( trx_undo_truncate_start(
&rseg, hdr_addr.page, &rseg, hdr_addr.page,
hdr_addr.boffset, limit.undo_no); hdr_addr.boffset, limit.undo_no);
@ -549,12 +547,12 @@ function is called, the caller must not have any latches on undo log pages!
static void trx_purge_truncate_history() static void trx_purge_truncate_history()
{ {
ut_ad(purge_sys.head <= purge_sys.tail); ut_ad(purge_sys.head <= purge_sys.tail);
purge_sys_t::iterator& head = purge_sys.head.commit purge_sys_t::iterator& head = purge_sys.head.trx_no
? purge_sys.head : purge_sys.tail; ? purge_sys.head : purge_sys.tail;
if (head.trx_no() >= purge_sys.view.low_limit_no()) { if (head.trx_no >= purge_sys.view.low_limit_no()) {
/* This is sometimes necessary. TODO: find out why. */ /* This is sometimes necessary. TODO: find out why. */
head.reset_trx_no(purge_sys.view.low_limit_no()); head.trx_no = purge_sys.view.low_limit_no();
head.undo_no = 0; head.undo_no = 0;
} }
@ -645,7 +643,7 @@ not_free:
undo; undo;
undo = UT_LIST_GET_NEXT(undo_list, undo = UT_LIST_GET_NEXT(undo_list,
undo)) { undo)) {
if (head.trx_no() < undo->trx_id) { if (head.trx_no < undo->trx_id) {
goto not_free; goto not_free;
} else { } else {
cached += undo->size; cached += undo->size;
@ -727,7 +725,6 @@ not_free:
free the existing structure. There can't be free the existing structure. There can't be
any active transactions. */ any active transactions. */
ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0); ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0);
ut_a(UT_LIST_GET_LEN(rseg->old_insert_list) == 0);
trx_undo_t* next_undo; trx_undo_t* next_undo;
@ -745,8 +742,6 @@ not_free:
&trx_undo_t::undo_list); &trx_undo_t::undo_list);
UT_LIST_INIT(rseg->undo_cached, UT_LIST_INIT(rseg->undo_cached,
&trx_undo_t::undo_list); &trx_undo_t::undo_list);
UT_LIST_INIT(rseg->old_insert_list,
&trx_undo_t::undo_list);
/* These were written by trx_rseg_header_create(). */ /* These were written by trx_rseg_header_create(). */
ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
@ -759,8 +754,7 @@ not_free:
rseg->curr_size = 1; rseg->curr_size = 1;
rseg->trx_ref_count = 0; rseg->trx_ref_count = 0;
rseg->last_page_no = FIL_NULL; rseg->last_page_no = FIL_NULL;
rseg->last_offset = 0; rseg->last_commit_and_offset = 0;
rseg->last_commit = 0;
rseg->needs_purge = false; rseg->needs_purge = false;
} }
@ -828,7 +822,6 @@ static void trx_purge_rseg_get_next_history_log(
handled */ handled */
{ {
page_t* undo_page; page_t* undo_page;
trx_ulogf_t* log_hdr;
fil_addr_t prev_log_addr; fil_addr_t prev_log_addr;
trx_id_t trx_no; trx_id_t trx_no;
mtr_t mtr; mtr_t mtr;
@ -837,7 +830,7 @@ static void trx_purge_rseg_get_next_history_log(
ut_a(purge_sys.rseg->last_page_no != FIL_NULL); ut_a(purge_sys.rseg->last_page_no != FIL_NULL);
purge_sys.tail.commit = purge_sys.rseg->last_commit + 1; purge_sys.tail.trx_no = purge_sys.rseg->last_trx_no() + 1;
purge_sys.tail.undo_no = 0; purge_sys.tail.undo_no = 0;
purge_sys.next_stored = false; purge_sys.next_stored = false;
@ -847,7 +840,7 @@ static void trx_purge_rseg_get_next_history_log(
page_id_t(purge_sys.rseg->space->id, page_id_t(purge_sys.rseg->space->id,
purge_sys.rseg->last_page_no), &mtr); purge_sys.rseg->last_page_no), &mtr);
log_hdr = undo_page + purge_sys.rseg->last_offset; const trx_ulogf_t* log_hdr = undo_page + purge_sys.rseg->last_offset();
/* Increase the purge page count by one for every handled log */ /* Increase the purge page count by one for every handled log */
@ -879,17 +872,16 @@ static void trx_purge_rseg_get_next_history_log(
+ prev_log_addr.boffset; + prev_log_addr.boffset;
trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);
unsigned purge = mach_read_from_2(log_hdr + TRX_UNDO_NEEDS_PURGE); ut_ad(mach_read_from_2(log_hdr + TRX_UNDO_NEEDS_PURGE) <= 1);
ut_ad(purge <= 1);
mtr_commit(&mtr); mtr_commit(&mtr);
mutex_enter(&purge_sys.rseg->mutex); mutex_enter(&purge_sys.rseg->mutex);
purge_sys.rseg->last_page_no = prev_log_addr.page; purge_sys.rseg->last_page_no = static_cast<uint32_t>(
purge_sys.rseg->last_offset = prev_log_addr.boffset; prev_log_addr.page);
purge_sys.rseg->set_last_trx_no(trx_no, purge != 0); purge_sys.rseg->set_last_commit(prev_log_addr.boffset, trx_no);
purge_sys.rseg->needs_purge = purge != 0; purge_sys.rseg->needs_purge = log_hdr[TRX_UNDO_NEEDS_PURGE + 1] != 0;
/* Purge can also produce events, however these are already ordered /* Purge can also produce events, however these are already ordered
in the rollback segment and any user generated event will be greater in the rollback segment and any user generated event will be greater
@ -906,15 +898,13 @@ static void trx_purge_rseg_get_next_history_log(
} }
/** Position the purge sys "iterator" on the undo record to use for purging. */ /** Position the purge sys "iterator" on the undo record to use for purging. */
static static void trx_purge_read_undo_rec()
void
trx_purge_read_undo_rec()
{ {
ulint offset; ulint offset;
ulint page_no; ulint page_no;
ib_uint64_t undo_no; ib_uint64_t undo_no;
purge_sys.hdr_offset = purge_sys.rseg->last_offset; purge_sys.hdr_offset = purge_sys.rseg->last_offset();
page_no = purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; page_no = purge_sys.hdr_page_no = purge_sys.rseg->last_page_no;
if (purge_sys.rseg->needs_purge) { if (purge_sys.rseg->needs_purge) {
@ -987,7 +977,7 @@ trx_purge_get_next_rec(
mtr_t mtr; mtr_t mtr;
ut_ad(purge_sys.next_stored); ut_ad(purge_sys.next_stored);
ut_ad(purge_sys.tail.trx_no() < purge_sys.view.low_limit_no()); ut_ad(purge_sys.tail.trx_no < purge_sys.view.low_limit_no());
space = purge_sys.rseg->space->id; space = purge_sys.rseg->space->id;
page_no = purge_sys.page_no; page_no = purge_sys.page_no;
@ -1080,7 +1070,7 @@ trx_purge_fetch_next_rec(
} }
} }
if (purge_sys.tail.trx_no() >= purge_sys.view.low_limit_no()) { if (purge_sys.tail.trx_no >= purge_sys.view.low_limit_no()) {
return(NULL); return(NULL);
} }

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2020, MariaDB Corporation. Copyright (c) 2016, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -66,12 +66,6 @@ static bool trx_rollback_finish(trx_t* trx)
ut_a(!srv_undo_sources); ut_a(!srv_undo_sources);
ut_ad(srv_fast_shutdown); ut_ad(srv_fast_shutdown);
ut_d(trx->in_rollback = false); ut_d(trx->in_rollback = false);
if (trx_undo_t*& undo = trx->rsegs.m_redo.old_insert) {
UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->old_insert_list,
undo);
ut_free(undo);
undo = NULL;
}
if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) { if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) {
UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->undo_list, UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->undo_list,
undo); undo);
@ -120,7 +114,7 @@ trx_rollback_to_savepoint_low(
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
if (trx->has_logged_or_recovered()) { if (trx->has_logged()) {
ut_ad(trx->rsegs.m_redo.rseg != 0 ut_ad(trx->rsegs.m_redo.rseg != 0
|| trx->rsegs.m_noredo.rseg != 0); || trx->rsegs.m_noredo.rseg != 0);
@ -242,7 +236,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
case TRX_STATE_PREPARED: case TRX_STATE_PREPARED:
case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_PREPARED_RECOVERED:
ut_ad(!trx_is_autocommit_non_locking(trx)); ut_ad(!trx_is_autocommit_non_locking(trx));
if (trx->rsegs.m_redo.undo || trx->rsegs.m_redo.old_insert) { if (trx->rsegs.m_redo.undo) {
/* The XA ROLLBACK of a XA PREPARE transaction /* The XA ROLLBACK of a XA PREPARE transaction
will consist of multiple mini-transactions. will consist of multiple mini-transactions.
@ -258,11 +252,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
killed, and finally, the transaction would be killed, and finally, the transaction would be
recovered in XA PREPARE state, with some of recovered in XA PREPARE state, with some of
the actions already having been rolled back. */ the actions already having been rolled back. */
ut_ad(!trx->rsegs.m_redo.undo ut_ad(trx->rsegs.m_redo.undo->rseg
|| trx->rsegs.m_redo.undo->rseg
== trx->rsegs.m_redo.rseg);
ut_ad(!trx->rsegs.m_redo.old_insert
|| trx->rsegs.m_redo.old_insert->rseg
== trx->rsegs.m_redo.rseg); == trx->rsegs.m_redo.rseg);
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
@ -271,10 +261,6 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
trx_undo_set_state_at_prepare(trx, undo, true, trx_undo_set_state_at_prepare(trx, undo, true,
&mtr); &mtr);
} }
if (trx_undo_t* undo = trx->rsegs.m_redo.old_insert) {
trx_undo_set_state_at_prepare(trx, undo, true,
&mtr);
}
mutex_exit(&trx->rsegs.m_redo.rseg->mutex); mutex_exit(&trx->rsegs.m_redo.rseg->mutex);
/* Write the redo log for the XA ROLLBACK /* Write the redo log for the XA ROLLBACK
state change to the global buffer. It is state change to the global buffer. It is

View File

@ -363,7 +363,6 @@ trx_rseg_mem_free(trx_rseg_t* rseg)
/* There can't be any active transactions. */ /* There can't be any active transactions. */
ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0); ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0);
ut_a(UT_LIST_GET_LEN(rseg->old_insert_list) == 0);
for (undo = UT_LIST_GET_FIRST(rseg->undo_cached); for (undo = UT_LIST_GET_FIRST(rseg->undo_cached);
undo != NULL; undo != NULL;
@ -403,7 +402,6 @@ trx_rseg_mem_create(ulint id, fil_space_t* space, ulint page_no)
&rseg->mutex); &rseg->mutex);
UT_LIST_INIT(rseg->undo_list, &trx_undo_t::undo_list); UT_LIST_INIT(rseg->undo_list, &trx_undo_t::undo_list);
UT_LIST_INIT(rseg->old_insert_list, &trx_undo_t::undo_list);
UT_LIST_INIT(rseg->undo_cached, &trx_undo_t::undo_list); UT_LIST_INIT(rseg->undo_cached, &trx_undo_t::undo_list);
return(rseg); return(rseg);
@ -413,35 +411,36 @@ trx_rseg_mem_create(ulint id, fil_space_t* space, ulint page_no)
@param[in,out] rseg rollback segment @param[in,out] rseg rollback segment
@param[in,out] max_trx_id maximum observed transaction identifier @param[in,out] max_trx_id maximum observed transaction identifier
@param[in] rseg_header rollback segment header @param[in] rseg_header rollback segment header
@return the combined size of undo log segments in pages */ @return error code */
static static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
ulint
trx_undo_lists_init(trx_rseg_t* rseg, trx_id_t& max_trx_id,
const trx_rsegf_t *rseg_header) const trx_rsegf_t *rseg_header)
{ {
ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN); ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
ulint size = 0; for (ulint i= 0; i < TRX_RSEG_N_SLOTS; i++)
{
for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) { uint32_t page_no= trx_rsegf_get_nth_undo(rseg_header, i);
ulint page_no = trx_rsegf_get_nth_undo(rseg_header, i); if (page_no != FIL_NULL)
if (page_no != FIL_NULL) { {
size += trx_undo_mem_create_at_db_start( const trx_undo_t *undo= trx_undo_mem_create_at_db_start(rseg, i, page_no,
rseg, i, page_no, max_trx_id); max_trx_id);
if (!undo)
return DB_CORRUPTION;
rseg->curr_size+= undo->size;
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED); MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
} }
} }
return(size); return DB_SUCCESS;
} }
/** Restore the state of a persistent rollback segment. /** Restore the state of a persistent rollback segment.
@param[in,out] rseg persistent rollback segment @param[in,out] rseg persistent rollback segment
@param[in,out] max_trx_id maximum observed transaction identifier @param[in,out] max_trx_id maximum observed transaction identifier
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction
static @return error code */
void static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr) mtr_t *mtr)
{ {
/* This is based on trx_rsegf_get_new(). /* This is based on trx_rsegf_get_new().
We need to access buf_block_t. */ We need to access buf_block_t. */
@ -487,13 +486,16 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
/* mariabackup --prepare only deals with /* mariabackup --prepare only deals with
the redo log and the data files, not with the redo log and the data files, not with
transactions or the data dictionary. */ transactions or the data dictionary. */
return; return DB_SUCCESS;
} }
/* Initialize the undo log lists according to the rseg header */ /* Initialize the undo log lists according to the rseg header */
rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE) rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE)
+ 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_header); + 1;
if (dberr_t err = trx_undo_lists_init(rseg, max_trx_id, rseg_header)) {
return err;
}
if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) { if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) {
trx_sys.rseg_history_len += len; trx_sys.rseg_history_len += len;
@ -501,8 +503,7 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
fil_addr_t node_addr = trx_purge_get_log_from_hist( fil_addr_t node_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr)); flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
rseg->last_page_no = node_addr.page; rseg->last_page_no = static_cast<uint32_t>(node_addr.page);
rseg->last_offset = node_addr.boffset;
const trx_ulogf_t* undo_log_hdr = trx_undo_page_get( const trx_ulogf_t* undo_log_hdr = trx_undo_page_get(
page_id_t(rseg->space->id, node_addr.page), mtr) page_id_t(rseg->space->id, node_addr.page), mtr)
@ -516,10 +517,10 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
if (id > max_trx_id) { if (id > max_trx_id) {
max_trx_id = id; max_trx_id = id;
} }
rseg->set_last_commit(node_addr.boffset, id);
unsigned purge = mach_read_from_2( unsigned purge = mach_read_from_2(
undo_log_hdr + TRX_UNDO_NEEDS_PURGE); undo_log_hdr + TRX_UNDO_NEEDS_PURGE);
ut_ad(purge <= 1); ut_ad(purge <= 1);
rseg->set_last_trx_no(id, purge != 0);
rseg->needs_purge = purge != 0; rseg->needs_purge = purge != 0;
if (rseg->last_page_no != FIL_NULL) { if (rseg->last_page_no != FIL_NULL) {
@ -529,6 +530,8 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
purge_sys.purge_queue.push(*rseg); purge_sys.purge_queue.push(*rseg);
} }
} }
return DB_SUCCESS;
} }
/** Read binlog metadata from the TRX_SYS page, in case we are upgrading /** Read binlog metadata from the TRX_SYS page, in case we are upgrading
@ -552,9 +555,8 @@ static void trx_rseg_init_binlog_info(const page_t* page)
#endif #endif
} }
/** Initialize the rollback segments in memory at database startup. */ /** Initialize or recover the rollback segments at startup. */
void dberr_t trx_rseg_array_init()
trx_rseg_array_init()
{ {
trx_id_t max_trx_id = 0; trx_id_t max_trx_id = 0;
@ -566,9 +568,9 @@ trx_rseg_array_init()
wsrep_sys_xid.null(); wsrep_sys_xid.null();
bool wsrep_xid_in_rseg_found = false; bool wsrep_xid_in_rseg_found = false;
#endif #endif
mtr_t mtr;
for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) { for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
mtr_t mtr;
mtr.start(); mtr.start();
if (const buf_block_t* sys = trx_sysf_get(&mtr, false)) { if (const buf_block_t* sys = trx_sysf_get(&mtr, false)) {
if (rseg_id == 0) { if (rseg_id == 0) {
@ -596,7 +598,11 @@ trx_rseg_array_init()
ut_ad(rseg->id == rseg_id); ut_ad(rseg->id == rseg_id);
ut_ad(!trx_sys.rseg_array[rseg_id]); ut_ad(!trx_sys.rseg_array[rseg_id]);
trx_sys.rseg_array[rseg_id] = rseg; trx_sys.rseg_array[rseg_id] = rseg;
trx_rseg_mem_restore(rseg, max_trx_id, &mtr); if (dberr_t err = trx_rseg_mem_restore(
rseg, max_trx_id, &mtr)) {
mtr.commit();
return err;
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!wsrep_sys_xid.is_null() && if (!wsrep_sys_xid.is_null() &&
!wsrep_sys_xid.eq(&trx_sys.recovered_wsrep_xid)) { !wsrep_sys_xid.eq(&trx_sys.recovered_wsrep_xid)) {
@ -623,7 +629,6 @@ trx_rseg_array_init()
If no rollback segment has a WSREP XID set, If no rollback segment has a WSREP XID set,
we must copy the XID found in TRX_SYS page we must copy the XID found in TRX_SYS page
to rollback segments. */ to rollback segments. */
mtr_t mtr;
mtr.start(); mtr.start();
if (!wsrep_xid_in_rseg_found) { if (!wsrep_xid_in_rseg_found) {
@ -639,6 +644,7 @@ trx_rseg_array_init()
#endif #endif
trx_sys.init_max_trx_id(max_trx_id + 1); trx_sys.init_max_trx_id(max_trx_id + 1);
return DB_SUCCESS;
} }
/** Create a persistent rollback segment. /** Create a persistent rollback segment.

View File

@ -668,8 +668,7 @@ trx_resurrect_table_locks(
static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg, static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
time_t start_time, ulonglong start_time_micro, time_t start_time, ulonglong start_time_micro,
uint64_t *rows_to_undo, uint64_t *rows_to_undo)
bool is_old_insert)
{ {
trx_state_t state; trx_state_t state;
/* /*
@ -692,8 +691,6 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
state= TRX_STATE_PREPARED; state= TRX_STATE_PREPARED;
break; break;
default: default:
if (is_old_insert && srv_force_recovery < SRV_FORCE_NO_TRX_UNDO)
trx_undo_commit_cleanup(undo, false);
return; return;
} }
@ -703,11 +700,7 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
ut_d(trx->start_line= __LINE__); ut_d(trx->start_line= __LINE__);
ut_ad(trx->no == TRX_ID_MAX); ut_ad(trx->no == TRX_ID_MAX);
if (is_old_insert)
trx->rsegs.m_redo.old_insert= undo;
else
trx->rsegs.m_redo.undo= undo; trx->rsegs.m_redo.undo= undo;
trx->undo_no= undo->top_undo_no + 1; trx->undo_no= undo->top_undo_no + 1;
trx->rsegs.m_redo.rseg= rseg; trx->rsegs.m_redo.rseg= rseg;
/* /*
@ -738,8 +731,7 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
/** Initialize (resurrect) transactions at startup. */ /** Initialize (resurrect) transactions at startup. */
void dberr_t trx_lists_init_at_db_start()
trx_lists_init_at_db_start()
{ {
ut_a(srv_is_being_started); ut_a(srv_is_being_started);
ut_ad(!srv_was_started); ut_ad(!srv_was_started);
@ -748,16 +740,18 @@ trx_lists_init_at_db_start()
/* mariabackup --prepare only deals with /* mariabackup --prepare only deals with
the redo log and the data files, not with the redo log and the data files, not with
transactions or the data dictionary. */ transactions or the data dictionary. */
trx_rseg_array_init(); return trx_rseg_array_init();
return;
} }
if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
return; return DB_SUCCESS;
} }
purge_sys.create(); purge_sys.create();
trx_rseg_array_init(); if (dberr_t err = trx_rseg_array_init()) {
ib::info() << "Retry with innodb_force_recovery=5";
return err;
}
/* Look from the rollback segments if there exist undo logs for /* Look from the rollback segments if there exist undo logs for
transactions. */ transactions. */
@ -775,17 +769,6 @@ trx_lists_init_at_db_start()
if (rseg == NULL) { if (rseg == NULL) {
continue; continue;
} }
/* Resurrect transactions that were doing inserts
using the old separate insert_undo log. */
undo = UT_LIST_GET_FIRST(rseg->old_insert_list);
while (undo) {
trx_undo_t* next = UT_LIST_GET_NEXT(undo_list, undo);
trx_resurrect(undo, rseg, start_time, start_time_micro,
&rows_to_undo, true);
undo = next;
}
/* Ressurrect other transactions. */ /* Ressurrect other transactions. */
for (undo = UT_LIST_GET_FIRST(rseg->undo_list); for (undo = UT_LIST_GET_FIRST(rseg->undo_list);
undo != NULL; undo != NULL;
@ -793,8 +776,7 @@ trx_lists_init_at_db_start()
trx_t *trx = trx_sys.find(0, undo->trx_id, false); trx_t *trx = trx_sys.find(0, undo->trx_id, false);
if (!trx) { if (!trx) {
trx_resurrect(undo, rseg, start_time, trx_resurrect(undo, rseg, start_time,
start_time_micro, start_time_micro, &rows_to_undo);
&rows_to_undo, false);
} else { } else {
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) ||
trx_state_eq(trx, TRX_STATE_PREPARED)); trx_state_eq(trx, TRX_STATE_PREPARED));
@ -829,6 +811,7 @@ trx_lists_init_at_db_start()
ib::info() << "Trx id counter is " << trx_sys.get_max_trx_id(); ib::info() << "Trx id counter is " << trx_sys.get_max_trx_id();
} }
trx_sys.clone_oldest_view(); trx_sys.clone_oldest_view();
return DB_SUCCESS;
} }
/** Assign a persistent rollback segment in a round-robin fashion, /** Assign a persistent rollback segment in a round-robin fashion,
@ -1117,30 +1100,22 @@ trx_write_serialisation_history(
trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
if (!rseg) { if (!rseg) {
ut_ad(!trx->rsegs.m_redo.undo); ut_ad(!trx->rsegs.m_redo.undo);
ut_ad(!trx->rsegs.m_redo.old_insert);
return; return;
} }
trx_undo_t*& undo = trx->rsegs.m_redo.undo; trx_undo_t*& undo = trx->rsegs.m_redo.undo;
trx_undo_t*& old_insert = trx->rsegs.m_redo.old_insert;
if (!undo && !old_insert) { if (!undo) {
return; return;
} }
ut_ad(!trx->read_only); ut_ad(!trx->read_only);
ut_ad(!undo || undo->rseg == rseg); ut_ad(!undo || undo->rseg == rseg);
ut_ad(!old_insert || old_insert->rseg == rseg);
mutex_enter(&rseg->mutex); mutex_enter(&rseg->mutex);
/* Assign the transaction serialisation number and add any /* Assign the transaction serialisation number and add any
undo log to the purge queue. */ undo log to the purge queue. */
trx_serialise(trx); trx_serialise(trx);
if (UNIV_LIKELY_NULL(old_insert)) {
UT_LIST_REMOVE(rseg->old_insert_list, old_insert);
trx_purge_add_undo_to_history(trx, old_insert, mtr);
}
if (undo) { if (undo) {
UT_LIST_REMOVE(rseg->undo_list, undo); UT_LIST_REMOVE(rseg->undo_list, undo);
trx_purge_add_undo_to_history(trx, undo, mtr); trx_purge_add_undo_to_history(trx, undo, mtr);
@ -1407,23 +1382,14 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
ut_ad(rseg->trx_ref_count > 0); ut_ad(rseg->trx_ref_count > 0);
--rseg->trx_ref_count; --rseg->trx_ref_count;
mutex_exit(&rseg->mutex); mutex_exit(&rseg->mutex);
if (trx_undo_t *&insert= rsegs.m_redo.old_insert)
{
ut_ad(insert->rseg == rseg);
trx_undo_commit_cleanup(insert, false);
insert= nullptr;
} }
}
ut_ad(!rsegs.m_redo.old_insert);
if (mtr) if (mtr)
{ {
if (trx_undo_t *&undo= rsegs.m_noredo.undo) if (trx_undo_t *&undo= rsegs.m_noredo.undo)
{ {
ut_ad(undo->rseg == rsegs.m_noredo.rseg); ut_ad(undo->rseg == rsegs.m_noredo.rseg);
trx_undo_commit_cleanup(undo, true); trx_undo_commit_cleanup(undo);
undo= nullptr; undo= nullptr;
} }
@ -1513,7 +1479,7 @@ void trx_t::commit_low(mtr_t *mtr)
ut_ad(!trx_state_eq(this, TRX_STATE_COMMITTED_IN_MEMORY)); ut_ad(!trx_state_eq(this, TRX_STATE_COMMITTED_IN_MEMORY));
ut_ad(!mtr || mtr->is_active()); ut_ad(!mtr || mtr->is_active());
ut_d(bool aborted = in_rollback && error_state == DB_DEADLOCK); ut_d(bool aborted = in_rollback && error_state == DB_DEADLOCK);
ut_ad(!mtr == (aborted || !has_logged_or_recovered())); ut_ad(!mtr == (aborted || !has_logged()));
ut_ad(!mtr || !aborted); ut_ad(!mtr || !aborted);
/* undo_no is non-zero if we're doing the final commit. */ /* undo_no is non-zero if we're doing the final commit. */
@ -1567,7 +1533,7 @@ void trx_t::commit()
mtr_t *mtr= nullptr; mtr_t *mtr= nullptr;
mtr_t local_mtr; mtr_t local_mtr;
if (has_logged_or_recovered()) if (has_logged())
{ {
mtr= &local_mtr; mtr= &local_mtr;
local_mtr.start(); local_mtr.start();
@ -1965,11 +1931,8 @@ trx_weight_ge(
/** Prepare a transaction. /** Prepare a transaction.
@return log sequence number that makes the XA PREPARE durable @return log sequence number that makes the XA PREPARE durable
@retval 0 if no changes needed to be made durable */ @retval 0 if no changes needed to be made durable */
static static lsn_t trx_prepare_low(trx_t *trx)
lsn_t
trx_prepare_low(trx_t* trx)
{ {
ut_ad(!trx->rsegs.m_redo.old_insert);
ut_ad(!trx->is_recovered); ut_ad(!trx->is_recovered);
mtr_t mtr; mtr_t mtr;

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2020, MariaDB Corporation. Copyright (c) 2014, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -34,6 +34,7 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0purge.h" #include "trx0purge.h"
#include "trx0rec.h" #include "trx0rec.h"
#include "trx0rseg.h" #include "trx0rseg.h"
#include "log.h"
/* How should the old versions in the history list be managed? /* How should the old versions in the history list be managed?
---------------------------------------------------------- ----------------------------------------------------------
@ -434,8 +435,7 @@ trx_undo_parse_page_header_reuse(
the space on the page */ the space on the page */
ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ undo_page) + undo_page) == 1);
== TRX_UNDO_INSERT);
byte* page_hdr = undo_page + TRX_UNDO_PAGE_HDR; byte* page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free); mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
@ -1021,13 +1021,8 @@ loop:
} }
/** Frees an undo log segment which is not in the history list. /** Frees an undo log segment which is not in the history list.
@param[in] undo undo log @param undo temporary undo log */
@param[in] noredo whether the undo tablespace is redo logged */ static void trx_undo_seg_free(const trx_undo_t *undo)
static
void
trx_undo_seg_free(
const trx_undo_t* undo,
bool noredo)
{ {
trx_rseg_t* rseg; trx_rseg_t* rseg;
fseg_header_t* file_seg; fseg_header_t* file_seg;
@ -1039,16 +1034,12 @@ trx_undo_seg_free(
rseg = undo->rseg; rseg = undo->rseg;
do { do {
mtr.start();
mtr_start(&mtr);
if (noredo) {
mtr.set_log_mode(MTR_LOG_NO_REDO); mtr.set_log_mode(MTR_LOG_NO_REDO);
}
mutex_enter(&(rseg->mutex)); mutex_enter(&(rseg->mutex));
seg_header = trx_undo_page_get(page_id_t(undo->rseg->space->id, seg_header = trx_undo_page_get(page_id_t(SRV_TMP_SPACE_ID,
undo->hdr_page_no), undo->hdr_page_no),
&mtr) &mtr)
+ TRX_UNDO_SEG_HDR; + TRX_UNDO_SEG_HDR;
@ -1079,9 +1070,10 @@ trx_undo_seg_free(
@param[in] id rollback segment slot @param[in] id rollback segment slot
@param[in] page_no undo log segment page number @param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID @param[in,out] max_trx_id the largest observed transaction ID
@return size of the undo log in pages */ @return the undo log
ulint @retval nullptr on error */
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no, trx_undo_t *
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
trx_id_t &max_trx_id) trx_id_t &max_trx_id)
{ {
mtr_t mtr; mtr_t mtr;
@ -1092,16 +1084,56 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
mtr.start(); mtr.start();
const page_t* undo_page = trx_undo_page_get( const page_t* undo_page = trx_undo_page_get(
page_id_t(rseg->space->id, page_no), &mtr); page_id_t(rseg->space->id, page_no), &mtr);
const ulint type = mach_read_from_2( const uint16_t type = mach_read_from_2(TRX_UNDO_PAGE_HDR
TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE + undo_page); + TRX_UNDO_PAGE_TYPE
ut_ad(type == 0 || type == TRX_UNDO_INSERT || type == TRX_UNDO_UPDATE);
uint state = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
+ undo_page);
uint offset = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
+ undo_page); + undo_page);
switch (type) {
case 0:
case 2: /* TRX_UNDO_UPDATE */
break;
case 1: /* TRX_UNDO_INSERT */
sql_print_error("InnoDB: upgrade from older version than"
" MariaDB 10.3 requires clean shutdown");
goto corrupted;
default:
sql_print_error("InnoDB: unsupported undo header type %u",
type);
corrupted:
mtr.commit();
return nullptr;
}
const trx_ulogf_t* undo_header = undo_page + offset; uint16_t offset = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG
+ undo_page);
if (offset < TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE ||
offset >= srv_page_size - TRX_UNDO_LOG_OLD_HDR_SIZE) {
sql_print_error("InnoDB: invalid undo header offset %u",
offset);
goto corrupted;
}
const trx_ulogf_t* const undo_header = undo_page + offset;
uint16_t state = mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
+ undo_page);
switch (state) {
case TRX_UNDO_ACTIVE:
case TRX_UNDO_PREPARED:
break;
default:
sql_print_error("InnoDB: unsupported undo header state %u",
state);
goto corrupted;
case TRX_UNDO_TO_PURGE:
case TRX_UNDO_CACHED:
trx_id_t id = mach_read_from_8(TRX_UNDO_TRX_NO + undo_header);
if (id >> 48) {
sql_print_error("InnoDB: corrupted TRX_NO %llx", id);
goto corrupted;
}
if (id > max_trx_id) {
max_trx_id = id;
}
}
/* Read X/Open XA transaction identification if it exists, or /* Read X/Open XA transaction identification if it exists, or
set it to NULL. */ set it to NULL. */
@ -1113,6 +1145,10 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
} }
trx_id_t trx_id = mach_read_from_8(undo_header + TRX_UNDO_TRX_ID); trx_id_t trx_id = mach_read_from_8(undo_header + TRX_UNDO_TRX_ID);
if (trx_id >> 48) {
sql_print_error("InnoDB: corrupted TRX_ID %llx", trx_id);
goto corrupted;
}
if (trx_id > max_trx_id) { if (trx_id > max_trx_id) {
max_trx_id = trx_id; max_trx_id = trx_id;
} }
@ -1121,30 +1157,17 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
trx_undo_t* undo = trx_undo_mem_create( trx_undo_t* undo = trx_undo_mem_create(
rseg, id, trx_id, &xid, page_no, offset); rseg, id, trx_id, &xid, page_no, offset);
mutex_exit(&rseg->mutex); mutex_exit(&rseg->mutex);
if (!undo) {
return undo;
}
undo->dict_operation = undo_header[TRX_UNDO_DICT_TRANS]; undo->dict_operation = undo_header[TRX_UNDO_DICT_TRANS];
undo->table_id = mach_read_from_8(undo_header + TRX_UNDO_TABLE_ID); undo->table_id = mach_read_from_8(undo_header + TRX_UNDO_TABLE_ID);
undo->size = flst_get_len(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST undo->size = flst_get_len(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST
+ undo_page); + undo_page);
if (UNIV_UNLIKELY(state == TRX_UNDO_TO_FREE)) {
/* This is an old-format insert_undo log segment that
is being freed. The page list is inconsistent. */
ut_ad(type == TRX_UNDO_INSERT);
state = TRX_UNDO_TO_PURGE;
} else {
if (state == TRX_UNDO_TO_PURGE
|| state == TRX_UNDO_CACHED) {
trx_id_t id = mach_read_from_8(TRX_UNDO_TRX_NO
+ undo_header);
if (id > max_trx_id) {
max_trx_id = id;
}
}
fil_addr_t last_addr = flst_get_last( fil_addr_t last_addr = flst_get_last(
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page, &mtr);
&mtr);
undo->last_page_no = last_addr.page; undo->last_page_no = last_addr.page;
undo->top_page_no = last_addr.page; undo->top_page_no = last_addr.page;
@ -1161,21 +1184,18 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
undo->top_undo_no = IB_ID_MAX; undo->top_undo_no = IB_ID_MAX;
ut_ad(undo->empty()); ut_ad(undo->empty());
} }
}
undo->state = state; undo->state = state;
if (state != TRX_UNDO_CACHED) { if (state != TRX_UNDO_CACHED) {
UT_LIST_ADD_LAST(type == TRX_UNDO_INSERT UT_LIST_ADD_LAST(rseg->undo_list, undo);
? rseg->old_insert_list
: rseg->undo_list, undo);
} else { } else {
UT_LIST_ADD_LAST(rseg->undo_cached, undo); UT_LIST_ADD_LAST(rseg->undo_cached, undo);
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_CACHED); MONITOR_INC(MONITOR_NUM_UNDO_SLOT_CACHED);
} }
mtr.commit(); mtr.commit();
return undo->size; return undo;
} }
/********************************************************************//** /********************************************************************//**
@ -1361,7 +1381,7 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo,
if (ut_d(ulint type =) UNIV_UNLIKELY( if (ut_d(ulint type =) UNIV_UNLIKELY(
mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ block->frame))) { + block->frame))) {
ut_ad(type == TRX_UNDO_INSERT || type == TRX_UNDO_UPDATE); ut_ad(type == 1 || type == 2);
mlog_write_ulint(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE mlog_write_ulint(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ block->frame, 0, MLOG_2BYTES, mtr); + block->frame, 0, MLOG_2BYTES, mtr);
} }
@ -1537,9 +1557,8 @@ trx_undo_set_state_at_finish(
@param[in,out] trx transaction @param[in,out] trx transaction
@param[in,out] undo undo log @param[in,out] undo undo log
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK @param[in] rollback false=XA PREPARE, true=XA ROLLBACK
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction */
@return undo log segment header page, x-latched */ void
page_t*
trx_undo_set_state_at_prepare( trx_undo_set_state_at_prepare(
trx_t* trx, trx_t* trx,
trx_undo_t* undo, trx_undo_t* undo,
@ -1551,8 +1570,6 @@ trx_undo_set_state_at_prepare(
page_t* undo_page; page_t* undo_page;
ulint offset; ulint offset;
ut_ad(trx && undo && mtr);
ut_a(undo->id < TRX_RSEG_N_SLOTS); ut_a(undo->id < TRX_RSEG_N_SLOTS);
undo_page = trx_undo_page_get( undo_page = trx_undo_page_get(
@ -1564,7 +1581,7 @@ trx_undo_set_state_at_prepare(
ut_ad(undo->state == TRX_UNDO_PREPARED); ut_ad(undo->state == TRX_UNDO_PREPARED);
mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE, mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE,
MLOG_2BYTES, mtr); MLOG_2BYTES, mtr);
return(undo_page); return;
} }
/*------------------------------*/ /*------------------------------*/
@ -1583,26 +1600,20 @@ trx_undo_set_state_at_prepare(
TRUE, MLOG_1BYTE, mtr); TRUE, MLOG_1BYTE, mtr);
trx_undo_write_xid(undo_header, &undo->xid, mtr); trx_undo_write_xid(undo_header, &undo->xid, mtr);
return(undo_page);
} }
/** Free an old insert or temporary undo log after commit or rollback. /** Free temporary undo log after commit or rollback.
The information is not needed after a commit or rollback, therefore The information is not needed after a commit or rollback, therefore
the data can be discarded. the data can be discarded.
@param[in,out] undo undo log @param undo temporary undo log */
@param[in] is_temp whether this is temporary undo log */ void trx_undo_commit_cleanup(trx_undo_t *undo)
void
trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
{ {
trx_rseg_t* rseg = undo->rseg; trx_rseg_t* rseg = undo->rseg;
ut_ad(is_temp == !rseg->is_persistent()); ut_ad(rseg->space == fil_system.temp_space);
ut_ad(!is_temp || 0 == UT_LIST_GET_LEN(rseg->old_insert_list));
mutex_enter(&rseg->mutex); mutex_enter(&rseg->mutex);
UT_LIST_REMOVE(is_temp ? rseg->undo_list : rseg->old_insert_list, UT_LIST_REMOVE(rseg->undo_list, undo);
undo);
if (undo->state == TRX_UNDO_CACHED) { if (undo->state == TRX_UNDO_CACHED) {
UT_LIST_ADD_FIRST(rseg->undo_cached, undo); UT_LIST_ADD_FIRST(rseg->undo_cached, undo);
@ -1612,7 +1623,7 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
/* Delete first the undo log segment in the file */ /* Delete first the undo log segment in the file */
mutex_exit(&rseg->mutex); mutex_exit(&rseg->mutex);
trx_undo_seg_free(undo, is_temp); trx_undo_seg_free(undo);
mutex_enter(&rseg->mutex); mutex_enter(&rseg->mutex);
ut_ad(rseg->curr_size > undo->size); ut_ad(rseg->curr_size > undo->size);
@ -1625,15 +1636,13 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
} }
/** At shutdown, frees the undo logs of a transaction. */ /** At shutdown, frees the undo logs of a transaction. */
void void trx_undo_free_at_shutdown(trx_t *trx)
trx_undo_free_at_shutdown(trx_t *trx)
{ {
if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) { if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) {
switch (undo->state) { switch (undo->state) {
case TRX_UNDO_PREPARED: case TRX_UNDO_PREPARED:
break; break;
case TRX_UNDO_CACHED: case TRX_UNDO_CACHED:
case TRX_UNDO_TO_FREE:
case TRX_UNDO_TO_PURGE: case TRX_UNDO_TO_PURGE:
ut_ad(trx_state_eq(trx, ut_ad(trx_state_eq(trx,
TRX_STATE_COMMITTED_IN_MEMORY)); TRX_STATE_COMMITTED_IN_MEMORY));
@ -1654,34 +1663,6 @@ trx_undo_free_at_shutdown(trx_t *trx)
ut_free(undo); ut_free(undo);
undo = NULL; undo = NULL;
} }
if (trx_undo_t*& undo = trx->rsegs.m_redo.old_insert) {
switch (undo->state) {
case TRX_UNDO_PREPARED:
break;
case TRX_UNDO_CACHED:
case TRX_UNDO_TO_FREE:
case TRX_UNDO_TO_PURGE:
ut_ad(trx_state_eq(trx,
TRX_STATE_COMMITTED_IN_MEMORY));
/* fall through */
case TRX_UNDO_ACTIVE:
/* trx_t::commit_state() assigns
trx->state = TRX_STATE_COMMITTED_IN_MEMORY. */
ut_a(!srv_was_started
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
|| srv_fast_shutdown);
break;
default:
ut_error;
}
UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->old_insert_list, undo);
ut_free(undo);
undo = NULL;
}
if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) { if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) {
ut_a(undo->state == TRX_UNDO_PREPARED); ut_a(undo->state == TRX_UNDO_PREPARED);

View File

@ -4212,7 +4212,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
const char * name, my_bool rep_quick) const char * name, my_bool rep_quick)
{ {
int got_error; int got_error;
uint i,key, total_key_length, istep; uint i,key, istep;
ha_rows start_records; ha_rows start_records;
my_off_t new_header_length,del; my_off_t new_header_length,del;
File new_file; File new_file;
@ -4374,7 +4374,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
_ma_check_print_error(param,"Not enough memory for key!"); _ma_check_print_error(param,"Not enough memory for key!");
goto err; goto err;
} }
total_key_length=0; #ifdef USING_SECOND_APPROACH
uint total_key_length=0;
#endif
rec_per_key_part= param->new_rec_per_key_part; rec_per_key_part= param->new_rec_per_key_part;
share->state.state.records=share->state.state.del=share->state.split=0; share->state.state.records=share->state.state.del=share->state.split=0;
share->state.state.empty=0; share->state.state.empty=0;
@ -4443,7 +4445,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (keyseg->flag & HA_NULL_PART) if (keyseg->flag & HA_NULL_PART)
sort_param[i].key_length++; sort_param[i].key_length++;
} }
#ifdef USING_SECOND_APPROACH
total_key_length+=sort_param[i].key_length; total_key_length+=sort_param[i].key_length;
#endif
if (sort_param[i].keyinfo->flag & HA_FULLTEXT) if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
{ {

View File

@ -2616,7 +2616,7 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
const char * name, int rep_quick) const char * name, int rep_quick)
{ {
int got_error; int got_error;
uint i,key, total_key_length, istep; uint i,key, istep;
ulong rec_length; ulong rec_length;
ha_rows start_records; ha_rows start_records;
my_off_t new_header_length,del; my_off_t new_header_length,del;
@ -2802,7 +2802,9 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Not enough memory for key!"); mi_check_print_error(param,"Not enough memory for key!");
goto err; goto err;
} }
total_key_length=0; #ifdef USING_SECOND_APPROACH
uint total_key_length=0;
#endif
rec_per_key_part= param->rec_per_key_part; rec_per_key_part= param->rec_per_key_part;
info->state->records=info->state->del=share->state.split=0; info->state->records=info->state->del=share->state.split=0;
info->state->empty=0; info->state->empty=0;
@ -2871,7 +2873,9 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
if (keyseg->flag & HA_NULL_PART) if (keyseg->flag & HA_NULL_PART)
sort_param[i].key_length++; sort_param[i].key_length++;
} }
#ifdef USING_SECOND_APPROACH
total_key_length+=sort_param[i].key_length; total_key_length+=sort_param[i].key_length;
#endif
if (sort_param[i].keyinfo->flag & HA_FULLTEXT) if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
{ {

View File

@ -4,7 +4,6 @@ package My::Suite::Spider;
return "No Spider engine" unless $ENV{HA_SPIDER_SO}; return "No Spider engine" unless $ENV{HA_SPIDER_SO};
return "Not run for embedded server" if $::opt_embedded_server; return "Not run for embedded server" if $::opt_embedded_server;
return "Test needs --big-test" unless $::opt_big_test;
sub is_default { 1 } sub is_default { 1 }

View File

@ -4,7 +4,6 @@ package My::Suite::Spider;
return "No Spider engine" unless $ENV{HA_SPIDER_SO}; return "No Spider engine" unless $ENV{HA_SPIDER_SO};
return "Not run for embedded server" if $::opt_embedded_server; return "Not run for embedded server" if $::opt_embedded_server;
return "Test needs --big-test" unless $::opt_big_test;
sub is_default { 1 } sub is_default { 1 }

View File

@ -22,7 +22,9 @@ USE auto_test_remote;
--connection child2_1 --connection child2_1
--disable_query_log --disable_query_log
echo CHILD2_1_CREATE_TABLES; echo CHILD2_1_CREATE_TABLES;
--disable_ps_protocol
eval $CHILD2_1_CREATE_TABLES; eval $CHILD2_1_CREATE_TABLES;
--enable_ps_protocol
--enable_query_log --enable_query_log
TRUNCATE TABLE mysql.general_log; TRUNCATE TABLE mysql.general_log;
@ -66,7 +68,9 @@ SELECT a, b, c FROM tbl_a PARTITION (pt2,pt3);
--connection child2_1 --connection child2_1
eval $CHILD2_1_SELECT_ARGUMENT1; eval $CHILD2_1_SELECT_ARGUMENT1;
--disable_ps_protocol
eval $CHILD2_1_SELECT_TABLES; eval $CHILD2_1_SELECT_TABLES;
--enable_ps_protocol
--echo --echo
--echo deinit --echo deinit

View File

@ -22,7 +22,9 @@ USE auto_test_remote;
--connection child2_1 --connection child2_1
--disable_query_log --disable_query_log
echo CHILD2_1_CREATE_TABLES; echo CHILD2_1_CREATE_TABLES;
--disable_ps_protocol
eval $CHILD2_1_CREATE_TABLES; eval $CHILD2_1_CREATE_TABLES;
--enable_ps_protocol
--enable_query_log --enable_query_log
TRUNCATE TABLE mysql.general_log; TRUNCATE TABLE mysql.general_log;
@ -78,7 +80,9 @@ SELECT STRAIGHT_JOIN b.a, b.b FROM tb_l a, tbl_a b WHERE a.a = b.a;
--connection child2_1 --connection child2_1
SET NAMES utf8; SET NAMES utf8;
eval $CHILD2_1_SELECT_ARGUMENT1; eval $CHILD2_1_SELECT_ARGUMENT1;
--disable_ps_protocol
eval $CHILD2_1_SELECT_TABLES; eval $CHILD2_1_SELECT_TABLES;
--enable_ps_protocol
--echo --echo
--echo deinit --echo deinit

View File

@ -49,6 +49,8 @@ TRUNCATE TABLE mysql.general_log;
SELECT * FROM tbl_a ORDER BY pkey; SELECT * FROM tbl_a ORDER BY pkey;
--connection child2_1 --connection child2_1
# in --ps a query is logged differently in a general log
replace_regex /order by t0.`pkey`/order by `pkey`/;
eval $CHILD2_1_SELECT_ARGUMENT1; eval $CHILD2_1_SELECT_ARGUMENT1;
eval $CHILD2_1_SELECT_TABLES; eval $CHILD2_1_SELECT_TABLES;

View File

@ -4,7 +4,6 @@ package My::Suite::Spider;
return "No Spider engine" unless $ENV{HA_SPIDER_SO}; return "No Spider engine" unless $ENV{HA_SPIDER_SO};
return "Not run for embedded server" if $::opt_embedded_server; return "Not run for embedded server" if $::opt_embedded_server;
return "Test needs --big-test" unless $::opt_big_test;
sub is_default { 1 } sub is_default { 1 }

View File

@ -4,7 +4,6 @@ package My::Suite::Spider;
return "No Spider engine" unless $ENV{HA_SPIDER_SO}; return "No Spider engine" unless $ENV{HA_SPIDER_SO};
return "Not run for embedded server" if $::opt_embedded_server; return "Not run for embedded server" if $::opt_embedded_server;
return "Test needs --big-test" unless $::opt_big_test;
sub is_default { 1 } sub is_default { 1 }

View File

@ -1,3 +1,4 @@
--source include/no_protocol.inc
--source ../include/partition_mrr_init.inc --source ../include/partition_mrr_init.inc
if (!$HAVE_PARTITION) if (!$HAVE_PARTITION)
{ {

View File

@ -3,7 +3,7 @@ if [ -r %{restart_flag} ] ; then
# only restart the server if it was already running # only restart the server if it was already running
if [ -x /usr/bin/systemctl ] ; then if [ -x /usr/bin/systemctl ] ; then
/usr/bin/systemctl daemon-reload > /dev/null 2>&1 /usr/bin/systemctl daemon-reload > /dev/null 2>&1
if [ /usr/bin/systemctl is-active mysql ]; then if /usr/bin/systemctl is-active mysql; then
/usr/bin/systemctl restart mysql > /dev/null 2>&1 /usr/bin/systemctl restart mysql > /dev/null 2>&1
else else
/usr/bin/systemctl try-restart mariadb.service > /dev/null 2>&1 /usr/bin/systemctl try-restart mariadb.service > /dev/null 2>&1