Merge 10.3 into 10.4
This commit is contained in:
commit
d3e4fae797
@ -1,7 +1,6 @@
|
||||
Code status:
|
||||
------------
|
||||
|
||||
* [](https://travis-ci.org/MariaDB/server) travis-ci.org (10.4 branch)
|
||||
* [](https://ci.appveyor.com/project/rasmushoj/server) ci.appveyor.com
|
||||
|
||||
## 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:
|
||||
https://github.com/MariaDB/server
|
||||
|
||||
***************************************************************************
|
||||
|
@ -90,6 +90,8 @@ static my_bool non_blocking_api_enabled= 0;
|
||||
|
||||
#define QUERY_PRINT_ORIGINAL_FLAG 4
|
||||
|
||||
#define CLOSED_CONNECTION "-closed_connection-"
|
||||
|
||||
#ifndef HAVE_SETENV
|
||||
static int setenv(const char *name, const char *value, int overwrite);
|
||||
#endif
|
||||
@ -5582,11 +5584,12 @@ void do_close_connection(struct st_command *command)
|
||||
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.
|
||||
*/
|
||||
if (!(con->name = my_strdup("-closed_connection-", MYF(MY_WME))))
|
||||
if (!(con->name = my_strdup(CLOSED_CONNECTION, MYF(MY_WME))))
|
||||
die("Out of memory");
|
||||
con->name_len= sizeof(CLOSED_CONNECTION)-1;
|
||||
|
||||
if (con == cur_con)
|
||||
{
|
||||
@ -5959,7 +5962,7 @@ void do_connect(struct st_command *command)
|
||||
con_slot= next_con;
|
||||
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",
|
||||
opt_max_connections);
|
||||
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();
|
||||
dynstr_set(&ds_res, 0);
|
||||
|
||||
if (view_protocol_enabled &&
|
||||
if (view_protocol_enabled && mysql &&
|
||||
complete_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);
|
||||
}
|
||||
|
||||
if (sp_protocol_enabled &&
|
||||
if (sp_protocol_enabled && mysql &&
|
||||
complete_query &&
|
||||
match_re(&sp_re, query))
|
||||
{
|
||||
@ -8961,7 +8964,7 @@ static void dump_backtrace(void)
|
||||
struct st_connection *conn= cur_con;
|
||||
|
||||
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);
|
||||
|
||||
if (conn)
|
||||
|
@ -74,7 +74,9 @@ FOREACH(file ${ABI_HEADERS})
|
||||
FILE(REMOVE ${tmpfile})
|
||||
EXECUTE_PROCESS(
|
||||
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)
|
||||
EXECUTE_PROCESS(COMMAND mv -v ${abi_check_out} ${file}.pp)
|
||||
ELSE(ABI_UPDATE)
|
||||
@ -84,4 +86,3 @@ FOREACH(file ${ABI_HEADERS})
|
||||
ENDIF()
|
||||
FILE(REMOVE ${abi_check_out})
|
||||
ENDFOREACH()
|
||||
|
||||
|
22
cmake/os/OpenBSD.cmake
Normal file
22
cmake/os/OpenBSD.cmake
Normal 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()
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
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
|
||||
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 {
|
||||
int n_undo_state_active;
|
||||
int n_undo_state_cached;
|
||||
int n_undo_state_to_free;
|
||||
int n_undo_state_to_purge;
|
||||
int n_undo_state_prepared;
|
||||
int n_undo_state_other;
|
||||
int n_undo_insert;
|
||||
int n_undo_update;
|
||||
int n_undo_other;
|
||||
int n_undo;
|
||||
int n_fil_page_index;
|
||||
int n_fil_page_undo_log;
|
||||
int n_fil_page_inode;
|
||||
@ -938,21 +935,7 @@ parse_page(
|
||||
fprintf(file, "#::%llu\t\t|\t\tUndo log page\t\t\t|",
|
||||
cur_page_num);
|
||||
}
|
||||
if (undo_page_type == TRX_UNDO_INSERT) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
page_type.n_undo++;
|
||||
undo_page_type = mach_read_from_2(page + TRX_UNDO_SEG_HDR +
|
||||
TRX_UNDO_STATE);
|
||||
switch (undo_page_type) {
|
||||
@ -972,14 +955,6 @@ parse_page(
|
||||
}
|
||||
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:
|
||||
page_type.n_undo_state_to_purge++;
|
||||
if (page_type_dump) {
|
||||
@ -1203,15 +1178,11 @@ print_summary(
|
||||
|
||||
fprintf(fil_out, "\n===============================================\n");
|
||||
fprintf(fil_out, "Additional information:\n");
|
||||
fprintf(fil_out, "Undo page type: %d insert, %d update, %d other\n",
|
||||
page_type.n_undo_insert,
|
||||
page_type.n_undo_update,
|
||||
page_type.n_undo_other);
|
||||
fprintf(fil_out, "Undo page state: %d active, %d cached, %d to_free, %d"
|
||||
fprintf(fil_out, "Undo page type: %d\n", page_type.n_undo);
|
||||
fprintf(fil_out, "Undo page state: %d active, %d cached, %d"
|
||||
" to_purge, %d prepared, %d other\n",
|
||||
page_type.n_undo_state_active,
|
||||
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_prepared,
|
||||
page_type.n_undo_state_other);
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 180c543704d627a50a52aaf60e24ca14e0ec4686
|
||||
Subproject commit 802ce584a26fdc0ba67fcf35e277bf3c7440956a
|
@ -3892,6 +3892,25 @@ id rn
|
||||
1 1
|
||||
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
|
||||
#
|
||||
#
|
||||
|
@ -2542,6 +2542,20 @@ order by rn desc;
|
||||
|
||||
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 # End of 10.2 tests
|
||||
--echo #
|
||||
|
@ -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_compression_algorithm = 1;
|
||||
create database enctests;
|
||||
|
20
mysql-test/suite/encryption/r/key_version_rotation.result
Normal file
20
mysql-test/suite/encryption/r/key_version_rotation.result
Normal 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;
|
@ -3898,6 +3898,25 @@ id rn
|
||||
1 1
|
||||
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
|
||||
#
|
||||
#
|
||||
|
@ -3,9 +3,6 @@
|
||||
# not embedded because of restarts
|
||||
-- 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`;
|
||||
SET GLOBAL innodb_file_per_table = ON;
|
||||
# zlib
|
||||
|
2
mysql-test/suite/encryption/t/key_version_rotation.opt
Normal file
2
mysql-test/suite/encryption/t/key_version_rotation.opt
Normal file
@ -0,0 +1,2 @@
|
||||
--innodb-tablespaces-encryption
|
||||
--plugin-load-add=$DEBUG_KEY_MANAGEMENT_SO
|
41
mysql-test/suite/encryption/t/key_version_rotation.test
Normal file
41
mysql-test/suite/encryption/t/key_version_rotation.test
Normal 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;
|
@ -262,3 +262,37 @@ CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
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;
|
||||
|
1
mysql-test/suite/gcol/t/innodb_virtual_index.opt
Normal file
1
mysql-test/suite/gcol/t/innodb_virtual_index.opt
Normal file
@ -0,0 +1 @@
|
||||
--innodb_sort_buffer_size=64k
|
@ -1,4 +1,5 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_sequence.inc
|
||||
|
||||
# Ensure that the history list length will actually be decremented by purge.
|
||||
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
@ -281,3 +282,35 @@ ROLLBACK;
|
||||
SELECT * FROM t1;
|
||||
CHECK 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;
|
||||
|
@ -1052,10 +1052,13 @@ a
|
||||
10
|
||||
DROP TABLE t1;
|
||||
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);
|
||||
ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
SET GLOBAL innodb_instant_alter_column_allowed=@save_allowed;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
10 2001-01-01
|
||||
|
@ -652,10 +652,13 @@ DROP TABLE t1;
|
||||
|
||||
# DATETIME-to-DATE truncation is OK
|
||||
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);
|
||||
--enable_info
|
||||
ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
|
||||
--disable_info
|
||||
SET GLOBAL innodb_instant_alter_column_allowed=@save_allowed;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -31,19 +31,17 @@ DROP TABLE t2, t1;
|
||||
#
|
||||
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
|
||||
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';
|
||||
ALTER TABLE t1 ADD FULLTEXT(c);
|
||||
connection default;
|
||||
SET DEBUG_SYNC='now WAIT_FOR s1';
|
||||
KILL QUERY @id;
|
||||
SET DEBUG_SYNC='now SIGNAL g1 WAIT_FOR s2';
|
||||
SET DEBUG_SYNC='now WAIT_FOR s2';
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1;
|
||||
a b c
|
||||
SET DEBUG_SYNC='now SIGNAL s2';
|
||||
SET DEBUG_SYNC='now SIGNAL g2';
|
||||
connection con1;
|
||||
ERROR 70100: Query execution was interrupted
|
||||
ERROR HY000: Out of memory.
|
||||
disconnect con1;
|
||||
connection default;
|
||||
SET DEBUG_SYNC=RESET;
|
||||
|
@ -60,20 +60,16 @@ DROP TABLE t2, t1;
|
||||
--echo #
|
||||
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
|
||||
connect(con1,localhost,root,,test);
|
||||
let $ID= `SELECT @id := CONNECTION_ID()`;
|
||||
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';
|
||||
send ALTER TABLE t1 ADD FULLTEXT(c);
|
||||
connection default;
|
||||
SET DEBUG_SYNC='now WAIT_FOR s1';
|
||||
let $ignore= `SELECT @id := $ID`;
|
||||
KILL QUERY @id;
|
||||
SET DEBUG_SYNC='now SIGNAL g1 WAIT_FOR s2';
|
||||
SET DEBUG_SYNC='now WAIT_FOR s2';
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1;
|
||||
SET DEBUG_SYNC='now SIGNAL s2';
|
||||
SET DEBUG_SYNC='now SIGNAL g2';
|
||||
connection con1;
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
--error ER_OUT_OF_RESOURCES
|
||||
reap;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
@ -112,8 +112,8 @@ File::tab#.ibd
|
||||
|
||||
===============================================
|
||||
Additional information:
|
||||
Undo page type: # insert, # update, # other
|
||||
Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other
|
||||
Undo page type: #
|
||||
Undo page state: # active, # cached, # to_purge, # prepared, # other
|
||||
index_id #pages #leaf_pages #recs_per_page #bytes_per_page
|
||||
# # # # #
|
||||
# # # # #
|
||||
@ -147,8 +147,8 @@ File::tab#.ibd
|
||||
|
||||
===============================================
|
||||
Additional information:
|
||||
Undo page type: # insert, # update, # other
|
||||
Undo page state: # active, # cached, # to_free, # to_purge, # prepared, # other
|
||||
Undo page type: #
|
||||
Undo page state: # active, # cached, # to_purge, # prepared, # other
|
||||
index_id #pages #leaf_pages #recs_per_page #bytes_per_page
|
||||
# # # # #
|
||||
# # # # #
|
||||
|
@ -1,5 +1,5 @@
|
||||
INSTALL SONAME 'auth_named_pipe';
|
||||
CREATE USER 'USERNAME' IDENTIFIED WITH named_pipe;
|
||||
GRANT ALL PRIVILEGES ON *.* to USERNAME;
|
||||
GRANT ALL PRIVILEGES ON *.* to 'USERNAME';
|
||||
DROP USER 'USERNAME';
|
||||
UNINSTALL SONAME 'auth_named_pipe';
|
||||
|
@ -18,7 +18,7 @@ INSTALL SONAME 'auth_named_pipe';
|
||||
--replace_result $USERNAME USERNAME
|
||||
eval CREATE USER '$USERNAME' IDENTIFIED WITH named_pipe;
|
||||
--replace_result $USERNAME USERNAME
|
||||
eval GRANT ALL PRIVILEGES ON *.* to $USERNAME;
|
||||
eval GRANT ALL PRIVILEGES ON *.* to '$USERNAME';
|
||||
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# with named user
|
||||
#
|
||||
create user USER identified via unix_socket;
|
||||
create user 'USER' identified via unix_socket;
|
||||
#
|
||||
# name match = ok
|
||||
#
|
||||
@ -11,7 +11,7 @@ USER@localhost USER@% test
|
||||
#
|
||||
# name does not match = failure
|
||||
#
|
||||
drop user USER;
|
||||
drop user 'USER';
|
||||
#
|
||||
# and now with anonymous user
|
||||
#
|
||||
|
@ -4,9 +4,9 @@
|
||||
--echo # with named user
|
||||
--echo #
|
||||
|
||||
--let $replace=create user $USER
|
||||
--replace_result $replace "create user USER"
|
||||
eval create user $USER identified via unix_socket;
|
||||
--let $replace=create user '$USER'
|
||||
--replace_result $replace "create user 'USER'"
|
||||
eval create user '$USER' identified via unix_socket;
|
||||
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
--let $replace1=$USER@localhost
|
||||
@ -26,9 +26,9 @@ EOF
|
||||
--error 1
|
||||
--exec $MYSQL_TEST -u foobar < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
|
||||
--let $replace=drop user $USER
|
||||
--replace_result $replace "drop user USER"
|
||||
eval drop user $USER;
|
||||
--let $replace=drop user '$USER'
|
||||
--replace_result $replace "drop user 'USER'"
|
||||
eval drop user '$USER';
|
||||
|
||||
--echo #
|
||||
--echo # and now with anonymous user
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
left_length+=length;
|
||||
diff_length=0;
|
||||
}
|
||||
|
||||
|
@ -1190,7 +1190,6 @@ trim_string()
|
||||
check_pid()
|
||||
{
|
||||
local pid_file="$1"
|
||||
local remove=${2:-0}
|
||||
if [ -r "$pid_file" ]; then
|
||||
local pid=$(cat "$pid_file" 2>/dev/null)
|
||||
if [ -n "$pid" ]; then
|
||||
@ -1201,6 +1200,7 @@ check_pid()
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
local remove=${2:-0}
|
||||
if [ $remove -eq 1 ]; then
|
||||
rm -f "$pid_file"
|
||||
fi
|
||||
@ -1223,7 +1223,7 @@ check_pid()
|
||||
#
|
||||
cleanup_pid()
|
||||
{
|
||||
local pid="$1"
|
||||
local pid=$1
|
||||
local pid_file="${2:-}"
|
||||
local config="${3:-}"
|
||||
|
||||
@ -1241,8 +1241,9 @@ cleanup_pid()
|
||||
round=8
|
||||
force=1
|
||||
kill -9 $pid >/dev/null 2>&1
|
||||
sleep 0.5
|
||||
else
|
||||
return 1;
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@ -1254,7 +1255,7 @@ cleanup_pid()
|
||||
fi
|
||||
|
||||
[ -n "$pid_file" ] && [ -f "$pid_file" ] && rm -f "$pid_file"
|
||||
[ -n "$config" ] && [ -f "$config" ] && rm -f "$config"
|
||||
[ -n "$config" ] && [ -f "$config" ] && rm -f "$config"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
@ -741,15 +741,15 @@ recv_joiner()
|
||||
fi
|
||||
|
||||
# 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
|
||||
wsrep_log_error "Donor does not know my secret!"
|
||||
wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'"
|
||||
exit 32
|
||||
fi
|
||||
|
||||
# remove secret from magic file
|
||||
grep -v -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new"
|
||||
# remove secret from the magic file
|
||||
grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new"
|
||||
mv "$MAGIC_FILE.new" "$MAGIC_FILE"
|
||||
fi
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ cleanup_joiner()
|
||||
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
|
||||
wsrep_cleanup_progress_file
|
||||
fi
|
||||
|
||||
[ -f "$SST_PID" ] && rm -f "$SST_PID"
|
||||
}
|
||||
|
||||
check_pid_and_port()
|
||||
@ -281,6 +283,7 @@ then
|
||||
*)
|
||||
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
|
||||
exit 22 # EINVAL
|
||||
;;
|
||||
esac
|
||||
if [ -z "$CAFILE_OPT" ]; then
|
||||
wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file"
|
||||
@ -426,7 +429,7 @@ EOF
|
||||
exit 255 # unknown error
|
||||
fi
|
||||
|
||||
# second, we transfer InnoDB log files
|
||||
# second, we transfer InnoDB and Aria log files
|
||||
rsync ${STUNNEL:+--rsh="$STUNNEL"} \
|
||||
--owner --group --perms --links --specials \
|
||||
--ignore-times --inplace --dirs --delete --quiet \
|
||||
@ -499,7 +502,22 @@ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
|
||||
then
|
||||
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
|
||||
while check_pid "$STUNNEL_PID" 1
|
||||
do
|
||||
@ -516,7 +534,7 @@ then
|
||||
RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid"
|
||||
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
|
||||
while check_pid "$RSYNC_PID" 1
|
||||
do
|
||||
@ -583,12 +601,14 @@ EOF
|
||||
RSYNC_ADDR="*"
|
||||
fi
|
||||
|
||||
echo $$ > "$SST_PID"
|
||||
|
||||
if [ -z "$STUNNEL" ]
|
||||
then
|
||||
rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS &
|
||||
RSYNC_REAL_PID=$!
|
||||
TRANSFER_REAL_PID="$RSYNC_REAL_PID"
|
||||
TRANSFER_PID=$RSYNC_PID
|
||||
TRANSFER_REAL_PID=$RSYNC_REAL_PID
|
||||
TRANSFER_PID="$RSYNC_PID"
|
||||
else
|
||||
# Let's check if the path to the config file contains a space?
|
||||
if [ "${RSYNC_CONF#* }" = "$RSYNC_CONF" ]; then
|
||||
@ -631,8 +651,8 @@ EOF
|
||||
fi
|
||||
stunnel "$STUNNEL_CONF" &
|
||||
STUNNEL_REAL_PID=$!
|
||||
TRANSFER_REAL_PID="$STUNNEL_REAL_PID"
|
||||
TRANSFER_PID=$STUNNEL_PID
|
||||
TRANSFER_REAL_PID=$STUNNEL_REAL_PID
|
||||
TRANSFER_PID="$STUNNEL_PID"
|
||||
fi
|
||||
|
||||
if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]
|
||||
@ -691,35 +711,49 @@ EOF
|
||||
|
||||
# Clean up old binlog files first
|
||||
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:"
|
||||
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
|
||||
echo "$BINLOG_DIRNAME/$bin_file" >> "$binlog_index"
|
||||
done < _binlog_tmp_files_$!
|
||||
rm -f _binlog_tmp_files_$!
|
||||
done < "$tmpfile"
|
||||
rm -f "$tmpfile"
|
||||
|
||||
cd "$OLD_PWD"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -r "$MAGIC_FILE" ]
|
||||
then
|
||||
# check donor supplied secret
|
||||
SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2)
|
||||
if [ "$SECRET" != "$MY_SECRET" ]; then
|
||||
wsrep_log_error "Donor does not know my secret!"
|
||||
wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'"
|
||||
exit 32
|
||||
if [ -r "$MAGIC_FILE" ]; then
|
||||
if [ -n "$MY_SECRET" ]; then
|
||||
# check donor supplied secret
|
||||
SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2)
|
||||
if [ "$SECRET" != "$MY_SECRET" ]; then
|
||||
wsrep_log_error "Donor does not know my secret!"
|
||||
wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'"
|
||||
exit 32
|
||||
fi
|
||||
# remove secret from the magic file, and output
|
||||
# the UUID:seqno & wsrep_gtid_domain_id:
|
||||
grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE"
|
||||
else
|
||||
# Output the UUID:seqno and wsrep_gtid_domain_id:
|
||||
cat "$MAGIC_FILE"
|
||||
fi
|
||||
|
||||
# remove secret from magic file
|
||||
grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new"
|
||||
|
||||
mv "$MAGIC_FILE.new" "$MAGIC_FILE"
|
||||
# UUID:seqno & wsrep_gtid_domain_id is received here.
|
||||
cat "$MAGIC_FILE" # Output : UUID:seqno wsrep_gtid_domain_id
|
||||
else
|
||||
# this message should cause joiner to abort
|
||||
echo "rsync process ended without creating '$MAGIC_FILE'"
|
||||
|
@ -434,7 +434,7 @@ Event_scheduler::start(int *err_no)
|
||||
scheduler_thd= NULL;
|
||||
deinit_event_thread(new_thd);
|
||||
|
||||
delete scheduler_param_value;
|
||||
my_free(scheduler_param_value);
|
||||
ret= true;
|
||||
}
|
||||
|
||||
|
@ -8470,6 +8470,7 @@ Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg):
|
||||
with_field= orig_item->with_field;
|
||||
name= item_arg->name;
|
||||
m_with_subquery= orig_item->with_subquery();
|
||||
with_window_func= orig_item->with_window_func;
|
||||
|
||||
if ((expr_value= orig_item->get_cache(thd)))
|
||||
expr_value->setup(thd, orig_item);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
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;
|
||||
m_with_subquery= true;
|
||||
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_param= args[0]->with_param || args[1]->with_param;
|
||||
used_tables_and_const_cache_join(args[1]);
|
||||
|
@ -4913,7 +4913,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
|
||||
int error= 0;
|
||||
TABLE *UNINIT_VAR(table); /* inited in all loops */
|
||||
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;
|
||||
bool has_expensive_keyparts;
|
||||
TABLE **table_vector;
|
||||
@ -5179,7 +5179,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
|
||||
{
|
||||
ref_changed = 0;
|
||||
more_const_tables_found:
|
||||
found_ref=0;
|
||||
|
||||
/*
|
||||
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;
|
||||
s->keys.set_bit(key); // TODO: remove this ?
|
||||
|
||||
refs=0;
|
||||
const_ref.clear_all();
|
||||
eq_part.clear_all();
|
||||
has_expensive_keyparts= false;
|
||||
@ -5285,8 +5283,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
|
||||
if (keyuse->val->is_expensive())
|
||||
has_expensive_keyparts= true;
|
||||
}
|
||||
else
|
||||
refs|=keyuse->used_tables;
|
||||
eq_part.set_bit(keyuse->keypart);
|
||||
}
|
||||
keyuse++;
|
||||
@ -5338,8 +5334,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
|
||||
found_const_table_map|= table->map;
|
||||
break;
|
||||
}
|
||||
else
|
||||
found_ref|= refs; // Table is const if all refs are const
|
||||
}
|
||||
else if (base_const_ref == base_eq_part)
|
||||
s->const_keys.set_bit(key);
|
||||
@ -28075,7 +28069,6 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
|
||||
*/
|
||||
if (tab)
|
||||
{
|
||||
key_part_map const_parts= 0;
|
||||
key_part_map map= 1;
|
||||
uint kp;
|
||||
/* 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))
|
||||
break;
|
||||
const_parts |= map;
|
||||
}
|
||||
|
||||
if (kp > 0)
|
||||
|
@ -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 */
|
||||
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. */
|
||||
static os_event_t fil_crypt_event;
|
||||
|
||||
@ -136,6 +139,14 @@ fil_space_crypt_t::key_get_latest_version(void)
|
||||
|
||||
if (is_key_found()) {
|
||||
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();
|
||||
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 */
|
||||
|
||||
bool success = false;
|
||||
ulint sum_pages = 0;
|
||||
|
||||
do {
|
||||
ulint n_pages = 0;
|
||||
success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages);
|
||||
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
|
||||
sum_pages += n_pages;
|
||||
} while (!success);
|
||||
|
||||
/* 5 - publish crypt data */
|
||||
@ -1578,46 +1587,63 @@ fil_crypt_return_iops(
|
||||
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 recheck whether the removal condition needs to be rechecked after
|
||||
the encryption parameters were changed
|
||||
@param encrypt expected state of innodb_encrypt_tables
|
||||
@return the next tablespace to process (n_pending_ops incremented)
|
||||
@retval NULL if this was the last */
|
||||
inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
|
||||
bool recheck, bool encrypt)
|
||||
inline fil_space_t *fil_system_t::default_encrypt_next(
|
||||
fil_space_t *space, bool recheck, bool encrypt)
|
||||
{
|
||||
ut_ad(mutex_own(&mutex));
|
||||
|
||||
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=
|
||||
rotation_list.end();
|
||||
default_encrypt_tables.end();
|
||||
|
||||
if (space)
|
||||
{
|
||||
const bool released= !space->release();
|
||||
|
||||
if (space->is_in_rotation_list)
|
||||
if (space->is_in_default_encrypt)
|
||||
{
|
||||
while (++it != end &&
|
||||
(!UT_LIST_GET_LEN(it->chain) || it->is_stopping()));
|
||||
|
||||
/* If one of the encryption threads already started the encryption
|
||||
of the table then don't remove the unencrypted spaces from rotation list
|
||||
/* If one of the encryption threads already started
|
||||
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
|
||||
don't remove the last processed tablespace from the rotation list. */
|
||||
If there is a change in innodb_encrypt_tables variables
|
||||
value then don't remove the last processed tablespace
|
||||
from the default encrypt list. */
|
||||
if (released && (!recheck || space->crypt_data) &&
|
||||
!encrypt == !srv_encrypt_tables)
|
||||
{
|
||||
ut_a(!rotation_list.empty());
|
||||
rotation_list.remove(*space);
|
||||
space->is_in_rotation_list= false;
|
||||
ut_a(!default_encrypt_tables.empty());
|
||||
default_encrypt_tables.remove(*space);
|
||||
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)
|
||||
{
|
||||
@ -1642,8 +1668,8 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck,
|
||||
{
|
||||
mutex_enter(&fil_system.mutex);
|
||||
|
||||
if (!srv_fil_crypt_rotate_key_age)
|
||||
space= fil_system.keyrotate_next(space, recheck, encrypt);
|
||||
if (fil_crypt_must_default_encrypt())
|
||||
space= fil_system.default_encrypt_next(space, recheck, encrypt);
|
||||
else if (!space)
|
||||
{
|
||||
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. */
|
||||
static void fil_crypt_rotation_list_fill()
|
||||
static void fil_crypt_default_encrypt_tables_fill()
|
||||
{
|
||||
ut_ad(mutex_own(&fil_system.mutex));
|
||||
|
||||
@ -2540,7 +2566,7 @@ static void fil_crypt_rotation_list_fill()
|
||||
space != NULL;
|
||||
space = UT_LIST_GET_NEXT(space_list, space)) {
|
||||
if (space->purpose != FIL_TYPE_TABLESPACE
|
||||
|| space->is_in_rotation_list
|
||||
|| space->is_in_default_encrypt
|
||||
|| UT_LIST_GET_LEN(space->chain) == 0
|
||||
|| !space->acquire()) {
|
||||
continue;
|
||||
@ -2580,8 +2606,8 @@ static void fil_crypt_rotation_list_fill()
|
||||
}
|
||||
}
|
||||
|
||||
fil_system.rotation_list.push_back(*space);
|
||||
space->is_in_rotation_list = true;
|
||||
fil_system.default_encrypt_tables.push_back(*space);
|
||||
space->is_in_default_encrypt = true;
|
||||
next:
|
||||
space->release();
|
||||
}
|
||||
@ -2598,7 +2624,7 @@ fil_crypt_set_rotate_key_age(
|
||||
mutex_enter(&fil_system.mutex);
|
||||
srv_fil_crypt_rotate_key_age = val;
|
||||
if (val == 0) {
|
||||
fil_crypt_rotation_list_fill();
|
||||
fil_crypt_default_encrypt_tables_fill();
|
||||
}
|
||||
mutex_exit(&fil_system.mutex);
|
||||
os_event_set(fil_crypt_threads_event);
|
||||
@ -2628,8 +2654,8 @@ fil_crypt_set_encrypt_tables(
|
||||
|
||||
srv_encrypt_tables = val;
|
||||
|
||||
if (srv_fil_crypt_rotate_key_age == 0) {
|
||||
fil_crypt_rotation_list_fill();
|
||||
if (fil_crypt_must_default_encrypt()) {
|
||||
fil_crypt_default_encrypt_tables_fill();
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system.mutex);
|
||||
|
@ -1083,9 +1083,9 @@ fil_space_detach(
|
||||
space->is_in_unflushed_spaces = false;
|
||||
}
|
||||
|
||||
if (space->is_in_rotation_list) {
|
||||
fil_system.rotation_list.remove(*space);
|
||||
space->is_in_rotation_list = false;
|
||||
if (space->is_in_default_encrypt) {
|
||||
fil_system.default_encrypt_tables.remove(*space);
|
||||
space->is_in_default_encrypt = false;
|
||||
}
|
||||
|
||||
UT_LIST_REMOVE(fil_system.space_list, space);
|
||||
@ -1292,20 +1292,25 @@ fil_space_create(
|
||||
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
|
||||
to do */
|
||||
if (purpose == FIL_TYPE_TABLESPACE
|
||||
&& !srv_fil_crypt_rotate_key_age && fil_crypt_threads_event &&
|
||||
(mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF
|
||||
|| srv_encrypt_tables)) {
|
||||
if (rotate) {
|
||||
/* Key rotation is not enabled, need to inform background
|
||||
encryption threads. */
|
||||
fil_system.rotation_list.push_back(*space);
|
||||
space->is_in_rotation_list = true;
|
||||
mutex_exit(&fil_system.mutex);
|
||||
fil_system.default_encrypt_tables.push_back(*space);
|
||||
space->is_in_default_encrypt = true;
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system.mutex);
|
||||
|
||||
if (rotate && srv_n_fil_crypt_threads_started) {
|
||||
os_event_set(fil_crypt_threads_event);
|
||||
} else {
|
||||
mutex_exit(&fil_system.mutex);
|
||||
}
|
||||
|
||||
return(space);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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_up;
|
||||
ulint reserve;
|
||||
size_t total_reserved = 0;
|
||||
|
||||
ut_ad(mtr);
|
||||
*n_reserved = n_ext;
|
||||
@ -2603,8 +2602,7 @@ try_again:
|
||||
return(true);
|
||||
}
|
||||
try_to_extend:
|
||||
if (ulint n = fsp_try_extend_data_file(space, space_header, mtr)) {
|
||||
total_reserved += n;
|
||||
if (fsp_try_extend_data_file(space, space_header, mtr)) {
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
|
@ -496,4 +496,10 @@ encrypted, or corrupted.
|
||||
bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
|
||||
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 */
|
||||
|
@ -171,7 +171,7 @@ public:
|
||||
bool is_in_unflushed_spaces;
|
||||
|
||||
/** 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 */
|
||||
bool atomic_write_supported;
|
||||
@ -987,9 +987,9 @@ public:
|
||||
record has been written since
|
||||
the latest redo log checkpoint.
|
||||
Protected only by log_sys.mutex. */
|
||||
ilist<fil_space_t, rotation_list_tag_t> rotation_list;
|
||||
/*!< list of all file spaces needing
|
||||
key rotation.*/
|
||||
|
||||
/** List of all file spaces need key rotation */
|
||||
ilist<fil_space_t, rotation_list_tag_t> default_encrypt_tables;
|
||||
|
||||
bool space_id_reuse_warned;
|
||||
/*!< whether fil_space_create()
|
||||
@ -1002,15 +1002,15 @@ public:
|
||||
@retval NULL if the tablespace does not exist or cannot be read */
|
||||
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 recheck whether the removal condition needs to be rechecked after
|
||||
the encryption parameters were changed
|
||||
@param encrypt expected state of innodb_encrypt_tables
|
||||
@return the next tablespace to process (n_pending_ops incremented)
|
||||
@retval NULL if this was the last */
|
||||
inline fil_space_t* keyrotate_next(fil_space_t *space, bool recheck,
|
||||
bool encrypt);
|
||||
inline fil_space_t* default_encrypt_next(
|
||||
fil_space_t *space, bool recheck, bool encrypt);
|
||||
};
|
||||
|
||||
/** The tablespace memory cache. */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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::const_iterator const_iterator;
|
||||
|
||||
/** Default constructor */
|
||||
TrxUndoRsegs() {}
|
||||
|
||||
/** Constructor */
|
||||
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 */
|
||||
TrxUndoRsegs(trx_id_t trx_no, trx_rseg_t& rseg)
|
||||
: m_commit(trx_no << 1), m_rsegs(1, &rseg) {}
|
||||
|
||||
/** @return the transaction commit identifier */
|
||||
trx_id_t trx_no() const { return m_commit >> 1; }
|
||||
: trx_no(trx_no), m_rsegs(1, &rseg) {}
|
||||
|
||||
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(); }
|
||||
void erase(iterator& it) { m_rsegs.erase(it); }
|
||||
iterator begin() { return(m_rsegs.begin()); }
|
||||
@ -105,14 +102,14 @@ public:
|
||||
@return true if elem1 > elem2 else false.*/
|
||||
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:
|
||||
/** Copy trx_rseg_t::last_commit */
|
||||
trx_id_t m_commit;
|
||||
/** Rollback segments of a transaction, scheduled for purge. */
|
||||
trx_rsegs_t m_rsegs;
|
||||
trx_rsegs_t m_rsegs{};
|
||||
};
|
||||
|
||||
typedef std::priority_queue<
|
||||
@ -171,17 +168,13 @@ public:
|
||||
{
|
||||
bool operator<=(const iterator& other) const
|
||||
{
|
||||
if (commit < other.commit) return true;
|
||||
if (commit > other.commit) return false;
|
||||
if (trx_no < other.trx_no) return true;
|
||||
if (trx_no > other.trx_no) return false;
|
||||
return undo_no <= other.undo_no;
|
||||
}
|
||||
|
||||
/** @return the commit number of the transaction */
|
||||
trx_id_t trx_no() const { return commit >> 1; }
|
||||
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;
|
||||
/** trx_t::no of the committed transaction */
|
||||
trx_id_t trx_no;
|
||||
/** The record number within the committed transaction's undo
|
||||
log, increasing, purged from from 0 onwards */
|
||||
undo_no_t undo_no;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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,
|
||||
mtr_t* mtr);
|
||||
|
||||
/** Initialize the rollback segments in memory at database startup. */
|
||||
void
|
||||
trx_rseg_array_init();
|
||||
/** Initialize or recover the rollback segments at startup. */
|
||||
dberr_t trx_rseg_array_init();
|
||||
|
||||
/** Free a rollback segment in memory. */
|
||||
void
|
||||
@ -147,21 +146,13 @@ struct trx_rseg_t {
|
||||
/** List of undo log segments cached for fast reuse */
|
||||
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
|
||||
list; FIL_NULL if all list purged */
|
||||
ulint last_page_no;
|
||||
/** Last not yet purged undo log header; FIL_NULL if all purged */
|
||||
uint32_t last_page_no;
|
||||
|
||||
/** Byte offset of the last not yet purged log header */
|
||||
ulint last_offset;
|
||||
|
||||
/** trx_t::no * 2 + old_insert of the last not yet purged log */
|
||||
trx_id_t last_commit;
|
||||
/** trx_t::no | last_offset << 48 */
|
||||
uint64_t last_commit_and_offset;
|
||||
|
||||
/** Whether the log segment needs purge */
|
||||
bool needs_purge;
|
||||
@ -173,13 +164,17 @@ struct trx_rseg_t {
|
||||
UNDO-tablespace marked for truncate. */
|
||||
bool skip_allocation;
|
||||
|
||||
/** @return the commit ID of the last committed transaction */
|
||||
trx_id_t last_trx_no() const { return last_commit >> 1; }
|
||||
/** @return the commit ID of the last committed transaction */
|
||||
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)
|
||||
{
|
||||
last_commit = trx_no << 1 | trx_id_t(is_update);
|
||||
}
|
||||
void set_last_commit(ulint last_offset, trx_id_t trx_no)
|
||||
{
|
||||
last_commit_and_offset= static_cast<uint64_t>(last_offset) << 48 | trx_no;
|
||||
}
|
||||
|
||||
/** @return whether the rollback segment is persistent */
|
||||
bool is_persistent() const
|
||||
|
@ -79,7 +79,7 @@ void trx_free_at_shutdown(trx_t *trx);
|
||||
void trx_disconnect_prepared(trx_t *trx);
|
||||
|
||||
/** 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. */
|
||||
@ -678,10 +678,6 @@ struct trx_undo_ptr_t {
|
||||
yet */
|
||||
trx_undo_t* undo; /*!< pointer to the undo log, or
|
||||
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. */
|
||||
@ -1035,13 +1031,6 @@ public:
|
||||
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 */
|
||||
trx_rseg_t* get_temp_rseg()
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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;
|
||||
/** The locks and state of an active transaction */
|
||||
struct trx_lock_t;
|
||||
/** Signal */
|
||||
struct trx_sig_t;
|
||||
/** Rollback segment */
|
||||
struct trx_rseg_t;
|
||||
/** Transaction undo log */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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] undo undo log
|
||||
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK
|
||||
@param[in,out] mtr mini-transaction
|
||||
@return undo log segment header page, x-latched */
|
||||
page_t*
|
||||
trx_undo_set_state_at_prepare(
|
||||
trx_t* trx,
|
||||
trx_undo_t* undo,
|
||||
bool rollback,
|
||||
mtr_t* mtr);
|
||||
@param[in,out] mtr mini-transaction */
|
||||
void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback,
|
||||
mtr_t *mtr)
|
||||
MY_ATTRIBUTE((nonnull));
|
||||
|
||||
/** 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 data can be discarded.
|
||||
@param[in,out] undo undo log
|
||||
@param[in] is_temp whether this is temporary undo log */
|
||||
void
|
||||
trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp);
|
||||
@param undo temporary undo log */
|
||||
void trx_undo_commit_cleanup(trx_undo_t *undo);
|
||||
|
||||
/** At shutdown, frees the undo logs of a transaction. */
|
||||
void
|
||||
@ -295,26 +289,21 @@ trx_undo_parse_page_header(
|
||||
@param[in] id rollback segment slot
|
||||
@param[in] page_no undo log segment page number
|
||||
@param[in,out] max_trx_id the largest observed transaction ID
|
||||
@return size of the undo log in pages */
|
||||
ulint
|
||||
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
|
||||
trx_id_t& max_trx_id);
|
||||
@return the undo log
|
||||
@retval nullptr on error */
|
||||
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);
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/* Types of an undo log segment */
|
||||
#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */
|
||||
#define TRX_UNDO_UPDATE 2 /* contains undo entries for updates
|
||||
and delete markings: in short,
|
||||
modifys (the name 'UPDATE' is a
|
||||
historical relic) */
|
||||
/** the only rollback segment type since MariaDB 10.3.1 */
|
||||
constexpr uint16_t TRX_UNDO_UPDATE= 2;
|
||||
/* TRX_UNDO_STATE values of an undo log segment */
|
||||
/** contains an undo log of an active transaction */
|
||||
constexpr uint16_t TRX_UNDO_ACTIVE = 1;
|
||||
/** cached for quick reuse */
|
||||
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 */
|
||||
constexpr uint16_t TRX_UNDO_TO_PURGE = 4;
|
||||
/** contains an undo log of a prepared transaction */
|
||||
@ -377,7 +366,8 @@ struct trx_undo_t {
|
||||
/** Transaction undo log page header offsets */
|
||||
/* @{ */
|
||||
#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
|
||||
records for the LATEST transaction
|
||||
start on this page (remember that
|
||||
|
@ -4579,7 +4579,7 @@ lock_print_info_summary(
|
||||
"Purge done for trx's n:o < " TRX_ID_FMT
|
||||
" undo n:o < " TRX_ID_FMT " state: %s\n"
|
||||
"History list length %u\n",
|
||||
purge_sys.tail.trx_no(),
|
||||
purge_sys.tail.trx_no,
|
||||
purge_sys.tail.undo_no,
|
||||
purge_sys.enabled()
|
||||
? (purge_sys.running() ? "running"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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;
|
||||
pfs_os_file_t tmpfd[FTS_NUM_AUX_INDEX];
|
||||
ulint mycount[FTS_NUM_AUX_INDEX];
|
||||
ib_uint64_t total_rec = 0;
|
||||
ulint num_doc_processed = 0;
|
||||
doc_id_t last_doc_id = 0;
|
||||
mem_heap_t* blob_heap = NULL;
|
||||
@ -1039,7 +1038,6 @@ exit:
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
total_rec += merge_file[i]->n_rec;
|
||||
os_file_close(tmpfd[i]);
|
||||
}
|
||||
|
||||
|
@ -524,7 +524,9 @@ row_merge_buf_add(
|
||||
DBUG_ENTER("row_merge_buf_add");
|
||||
|
||||
if (buf->n_tuples >= buf->max_tuples) {
|
||||
DBUG_RETURN(0);
|
||||
error:
|
||||
n_row_added = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
@ -689,7 +691,10 @@ row_merge_buf_add(
|
||||
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->len != field->len) {
|
||||
if (conv_heap != NULL) {
|
||||
@ -845,11 +850,6 @@ end:
|
||||
if (vcol_storage.innobase_record)
|
||||
innobase_free_row_for_vcol(&vcol_storage);
|
||||
DBUG_RETURN(n_row_added);
|
||||
|
||||
error:
|
||||
if (vcol_storage.innobase_record)
|
||||
innobase_free_row_for_vcol(&vcol_storage);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
@ -2691,16 +2691,18 @@ write_buffers:
|
||||
new_table, psort_info, row, ext,
|
||||
&doc_id, conv_heap,
|
||||
&err, &v_heap, eval_table, trx)))) {
|
||||
/* An empty buffer should have enough
|
||||
room for at least one record. */
|
||||
ut_error;
|
||||
/* An empty buffer should have enough
|
||||
room for at least one record. */
|
||||
ut_ad(err == DB_COMPUTE_VALUE_FAILED
|
||||
|| err == DB_OUT_OF_MEMORY
|
||||
|| err == DB_TOO_BIG_RECORD);
|
||||
} else if (err == DB_SUCCESS) {
|
||||
file->n_rec += rows_added;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
file->n_rec += rows_added;
|
||||
trx->error_key_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,23 +284,13 @@ static bool row_undo_rec_get(undo_node_t* node)
|
||||
}
|
||||
|
||||
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* temp = trx->rsegs.m_noredo.undo;
|
||||
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()
|
||||
|| 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 (!undo) {
|
||||
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
|
||||
instant ADD COLUMN for temporary tables. Therefore,
|
||||
this record can only be present in the main undo log. */
|
||||
ut_ad(undo == update);
|
||||
/* fall through */
|
||||
case TRX_UNDO_RENAME_TABLE:
|
||||
ut_ad(undo == insert || undo == update);
|
||||
ut_ad(undo == update);
|
||||
/* fall through */
|
||||
case TRX_UNDO_INSERT_REC:
|
||||
ut_ad(undo == insert || undo == update || undo == temp);
|
||||
node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
|
||||
node->state = undo == temp
|
||||
? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT;
|
||||
break;
|
||||
default:
|
||||
ut_ad(undo == update || undo == temp);
|
||||
node->state = undo == temp
|
||||
? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT;
|
||||
break;
|
||||
|
@ -1310,6 +1310,16 @@ dberr_t srv_start(bool create_new_db)
|
||||
|| 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) {
|
||||
srv_read_only_mode = true;
|
||||
}
|
||||
@ -1828,7 +1838,11 @@ files_checked:
|
||||
All the remaining rollback segments will be created later,
|
||||
after the double write buffer has been created. */
|
||||
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();
|
||||
|
||||
@ -1884,7 +1898,10 @@ files_checked:
|
||||
case SRV_OPERATION_RESTORE:
|
||||
/* This must precede
|
||||
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;
|
||||
case SRV_OPERATION_RESTORE_DELTA:
|
||||
case SRV_OPERATION_BACKUP:
|
||||
@ -2347,11 +2364,6 @@ skip_monitors:
|
||||
<< "; 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) {
|
||||
/* In the insert buffer we may have even bigger tablespace
|
||||
id's, because we may have dropped those tablespaces, but
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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
|
||||
expected commit done by caller assuming rollback
|
||||
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()) {
|
||||
m_rsegs = purge_sys.purge_queue.top();
|
||||
purge_sys.purge_queue.pop();
|
||||
@ -108,17 +108,17 @@ inline bool TrxUndoRsegsIterator::set_next()
|
||||
mutex_enter(&purge_sys.rseg->mutex);
|
||||
|
||||
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
|
||||
in the range of UNDO tablespace space ids */
|
||||
ut_ad(purge_sys.rseg->space->id == TRX_SYS_SPACE
|
||||
|| 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.hdr_offset = purge_sys.rseg->last_offset;
|
||||
purge_sys.tail.trx_no = purge_sys.rseg->last_trx_no();
|
||||
purge_sys.hdr_offset = purge_sys.rseg->last_offset();
|
||||
purge_sys.hdr_page_no = purge_sys.rseg->last_page_no;
|
||||
|
||||
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 ")",
|
||||
trx->id, trx->no));
|
||||
ut_ad(undo == trx->rsegs.m_redo.undo
|
||||
|| undo == trx->rsegs.m_redo.old_insert);
|
||||
ut_ad(undo == trx->rsegs.m_redo.undo);
|
||||
trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
|
||||
ut_ad(undo->rseg == rseg);
|
||||
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) {
|
||||
rseg->last_page_no = undo->hdr_page_no;
|
||||
rseg->last_offset = undo->hdr_offset;
|
||||
rseg->set_last_trx_no(trx->no, undo == trx->rsegs.m_redo.undo);
|
||||
rseg->last_page_no = static_cast<uint32_t>(undo->hdr_page_no);
|
||||
rseg->set_last_commit(undo->hdr_offset, trx->no);
|
||||
rseg->needs_purge = true;
|
||||
}
|
||||
|
||||
@ -460,8 +458,8 @@ func_exit:
|
||||
|
||||
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(
|
||||
&rseg, hdr_addr.page,
|
||||
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()
|
||||
{
|
||||
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;
|
||||
|
||||
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. */
|
||||
head.reset_trx_no(purge_sys.view.low_limit_no());
|
||||
head.trx_no = purge_sys.view.low_limit_no();
|
||||
head.undo_no = 0;
|
||||
}
|
||||
|
||||
@ -645,7 +643,7 @@ not_free:
|
||||
undo;
|
||||
undo = UT_LIST_GET_NEXT(undo_list,
|
||||
undo)) {
|
||||
if (head.trx_no() < undo->trx_id) {
|
||||
if (head.trx_no < undo->trx_id) {
|
||||
goto not_free;
|
||||
} else {
|
||||
cached += undo->size;
|
||||
@ -727,7 +725,6 @@ not_free:
|
||||
free the existing structure. There can't be
|
||||
any active transactions. */
|
||||
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;
|
||||
|
||||
@ -745,8 +742,6 @@ not_free:
|
||||
&trx_undo_t::undo_list);
|
||||
UT_LIST_INIT(rseg->undo_cached,
|
||||
&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(). */
|
||||
ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
|
||||
@ -759,8 +754,7 @@ not_free:
|
||||
rseg->curr_size = 1;
|
||||
rseg->trx_ref_count = 0;
|
||||
rseg->last_page_no = FIL_NULL;
|
||||
rseg->last_offset = 0;
|
||||
rseg->last_commit = 0;
|
||||
rseg->last_commit_and_offset = 0;
|
||||
rseg->needs_purge = false;
|
||||
}
|
||||
|
||||
@ -828,7 +822,6 @@ static void trx_purge_rseg_get_next_history_log(
|
||||
handled */
|
||||
{
|
||||
page_t* undo_page;
|
||||
trx_ulogf_t* log_hdr;
|
||||
fil_addr_t prev_log_addr;
|
||||
trx_id_t trx_no;
|
||||
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);
|
||||
|
||||
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.next_stored = false;
|
||||
|
||||
@ -847,7 +840,7 @@ static void trx_purge_rseg_get_next_history_log(
|
||||
page_id_t(purge_sys.rseg->space->id,
|
||||
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 */
|
||||
|
||||
@ -879,17 +872,16 @@ static void trx_purge_rseg_get_next_history_log(
|
||||
+ prev_log_addr.boffset;
|
||||
|
||||
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(purge <= 1);
|
||||
ut_ad(mach_read_from_2(log_hdr + TRX_UNDO_NEEDS_PURGE) <= 1);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_enter(&purge_sys.rseg->mutex);
|
||||
|
||||
purge_sys.rseg->last_page_no = prev_log_addr.page;
|
||||
purge_sys.rseg->last_offset = prev_log_addr.boffset;
|
||||
purge_sys.rseg->set_last_trx_no(trx_no, purge != 0);
|
||||
purge_sys.rseg->needs_purge = purge != 0;
|
||||
purge_sys.rseg->last_page_no = static_cast<uint32_t>(
|
||||
prev_log_addr.page);
|
||||
purge_sys.rseg->set_last_commit(prev_log_addr.boffset, trx_no);
|
||||
purge_sys.rseg->needs_purge = log_hdr[TRX_UNDO_NEEDS_PURGE + 1] != 0;
|
||||
|
||||
/* Purge can also produce events, however these are already ordered
|
||||
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. */
|
||||
static
|
||||
void
|
||||
trx_purge_read_undo_rec()
|
||||
static void trx_purge_read_undo_rec()
|
||||
{
|
||||
ulint offset;
|
||||
ulint page_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;
|
||||
|
||||
if (purge_sys.rseg->needs_purge) {
|
||||
@ -987,7 +977,7 @@ trx_purge_get_next_rec(
|
||||
mtr_t mtr;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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_ad(srv_fast_shutdown);
|
||||
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) {
|
||||
UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->undo_list,
|
||||
undo);
|
||||
@ -120,7 +114,7 @@ trx_rollback_to_savepoint_low(
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
if (trx->has_logged_or_recovered()) {
|
||||
if (trx->has_logged()) {
|
||||
|
||||
ut_ad(trx->rsegs.m_redo.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_RECOVERED:
|
||||
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
|
||||
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
|
||||
recovered in XA PREPARE state, with some of
|
||||
the actions already having been rolled back. */
|
||||
ut_ad(!trx->rsegs.m_redo.undo
|
||||
|| 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
|
||||
ut_ad(trx->rsegs.m_redo.undo->rseg
|
||||
== trx->rsegs.m_redo.rseg);
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
@ -271,10 +261,6 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
|
||||
trx_undo_set_state_at_prepare(trx, undo, true,
|
||||
&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);
|
||||
/* Write the redo log for the XA ROLLBACK
|
||||
state change to the global buffer. It is
|
||||
|
@ -363,7 +363,6 @@ trx_rseg_mem_free(trx_rseg_t* rseg)
|
||||
|
||||
/* There can't be any active transactions. */
|
||||
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);
|
||||
undo != NULL;
|
||||
@ -403,45 +402,45 @@ trx_rseg_mem_create(ulint id, fil_space_t* space, ulint page_no)
|
||||
&rseg->mutex);
|
||||
|
||||
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);
|
||||
|
||||
return(rseg);
|
||||
}
|
||||
|
||||
/** Read the undo log lists.
|
||||
@param[in,out] rseg rollback segment
|
||||
@param[in,out] max_trx_id maximum observed transaction identifier
|
||||
@param[in] rseg_header rollback segment header
|
||||
@return the combined size of undo log segments in pages */
|
||||
static
|
||||
ulint
|
||||
trx_undo_lists_init(trx_rseg_t* rseg, trx_id_t& max_trx_id,
|
||||
const trx_rsegf_t* rseg_header)
|
||||
@param[in,out] rseg rollback segment
|
||||
@param[in,out] max_trx_id maximum observed transaction identifier
|
||||
@param[in] rseg_header rollback segment header
|
||||
@return error code */
|
||||
static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
|
||||
const trx_rsegf_t *rseg_header)
|
||||
{
|
||||
ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
|
||||
|
||||
ulint size = 0;
|
||||
for (ulint i= 0; i < TRX_RSEG_N_SLOTS; i++)
|
||||
{
|
||||
uint32_t page_no= trx_rsegf_get_nth_undo(rseg_header, i);
|
||||
if (page_no != FIL_NULL)
|
||||
{
|
||||
const trx_undo_t *undo= trx_undo_mem_create_at_db_start(rseg, i, page_no,
|
||||
max_trx_id);
|
||||
if (!undo)
|
||||
return DB_CORRUPTION;
|
||||
rseg->curr_size+= undo->size;
|
||||
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
|
||||
}
|
||||
}
|
||||
|
||||
for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) {
|
||||
ulint page_no = trx_rsegf_get_nth_undo(rseg_header, i);
|
||||
if (page_no != FIL_NULL) {
|
||||
size += trx_undo_mem_create_at_db_start(
|
||||
rseg, i, page_no, max_trx_id);
|
||||
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
|
||||
}
|
||||
}
|
||||
|
||||
return(size);
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/** Restore the state of a persistent rollback segment.
|
||||
@param[in,out] rseg persistent rollback segment
|
||||
@param[in,out] max_trx_id maximum observed transaction identifier
|
||||
@param[in,out] mtr mini-transaction */
|
||||
static
|
||||
void
|
||||
trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
|
||||
@param[in,out] mtr mini-transaction
|
||||
@return error code */
|
||||
static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
|
||||
mtr_t *mtr)
|
||||
{
|
||||
/* This is based on trx_rsegf_get_new().
|
||||
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
|
||||
the redo log and the data files, not with
|
||||
transactions or the data dictionary. */
|
||||
return;
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/* Initialize the undo log lists according to the rseg header */
|
||||
|
||||
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)) {
|
||||
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(
|
||||
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
|
||||
|
||||
rseg->last_page_no = node_addr.page;
|
||||
rseg->last_offset = node_addr.boffset;
|
||||
rseg->last_page_no = static_cast<uint32_t>(node_addr.page);
|
||||
|
||||
const trx_ulogf_t* undo_log_hdr = trx_undo_page_get(
|
||||
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) {
|
||||
max_trx_id = id;
|
||||
}
|
||||
rseg->set_last_commit(node_addr.boffset, id);
|
||||
unsigned purge = mach_read_from_2(
|
||||
undo_log_hdr + TRX_UNDO_NEEDS_PURGE);
|
||||
ut_ad(purge <= 1);
|
||||
rseg->set_last_trx_no(id, purge != 0);
|
||||
rseg->needs_purge = purge != 0;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/** 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
|
||||
}
|
||||
|
||||
/** Initialize the rollback segments in memory at database startup. */
|
||||
void
|
||||
trx_rseg_array_init()
|
||||
/** Initialize or recover the rollback segments at startup. */
|
||||
dberr_t trx_rseg_array_init()
|
||||
{
|
||||
trx_id_t max_trx_id = 0;
|
||||
|
||||
@ -566,9 +568,9 @@ trx_rseg_array_init()
|
||||
wsrep_sys_xid.null();
|
||||
bool wsrep_xid_in_rseg_found = false;
|
||||
#endif
|
||||
mtr_t mtr;
|
||||
|
||||
for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
if (const buf_block_t* sys = trx_sysf_get(&mtr, false)) {
|
||||
if (rseg_id == 0) {
|
||||
@ -596,7 +598,11 @@ trx_rseg_array_init()
|
||||
ut_ad(rseg->id == rseg_id);
|
||||
ut_ad(!trx_sys.rseg_array[rseg_id]);
|
||||
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
|
||||
if (!wsrep_sys_xid.is_null() &&
|
||||
!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,
|
||||
we must copy the XID found in TRX_SYS page
|
||||
to rollback segments. */
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
|
||||
if (!wsrep_xid_in_rseg_found) {
|
||||
@ -639,6 +644,7 @@ trx_rseg_array_init()
|
||||
#endif
|
||||
|
||||
trx_sys.init_max_trx_id(max_trx_id + 1);
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create a persistent rollback segment.
|
||||
|
@ -668,8 +668,7 @@ trx_resurrect_table_locks(
|
||||
|
||||
static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
|
||||
time_t start_time, ulonglong start_time_micro,
|
||||
uint64_t *rows_to_undo,
|
||||
bool is_old_insert)
|
||||
uint64_t *rows_to_undo)
|
||||
{
|
||||
trx_state_t state;
|
||||
/*
|
||||
@ -692,8 +691,6 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
|
||||
state= TRX_STATE_PREPARED;
|
||||
break;
|
||||
default:
|
||||
if (is_old_insert && srv_force_recovery < SRV_FORCE_NO_TRX_UNDO)
|
||||
trx_undo_commit_cleanup(undo, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -703,11 +700,7 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
|
||||
ut_d(trx->start_line= __LINE__);
|
||||
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->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. */
|
||||
void
|
||||
trx_lists_init_at_db_start()
|
||||
dberr_t trx_lists_init_at_db_start()
|
||||
{
|
||||
ut_a(srv_is_being_started);
|
||||
ut_ad(!srv_was_started);
|
||||
@ -748,16 +740,18 @@ trx_lists_init_at_db_start()
|
||||
/* mariabackup --prepare only deals with
|
||||
the redo log and the data files, not with
|
||||
transactions or the data dictionary. */
|
||||
trx_rseg_array_init();
|
||||
return;
|
||||
return trx_rseg_array_init();
|
||||
}
|
||||
|
||||
if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
|
||||
return;
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
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
|
||||
transactions. */
|
||||
@ -775,17 +769,6 @@ trx_lists_init_at_db_start()
|
||||
if (rseg == NULL) {
|
||||
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. */
|
||||
for (undo = UT_LIST_GET_FIRST(rseg->undo_list);
|
||||
undo != NULL;
|
||||
@ -793,8 +776,7 @@ trx_lists_init_at_db_start()
|
||||
trx_t *trx = trx_sys.find(0, undo->trx_id, false);
|
||||
if (!trx) {
|
||||
trx_resurrect(undo, rseg, start_time,
|
||||
start_time_micro,
|
||||
&rows_to_undo, false);
|
||||
start_time_micro, &rows_to_undo);
|
||||
} else {
|
||||
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) ||
|
||||
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();
|
||||
}
|
||||
trx_sys.clone_oldest_view();
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
if (!rseg) {
|
||||
ut_ad(!trx->rsegs.m_redo.undo);
|
||||
ut_ad(!trx->rsegs.m_redo.old_insert);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ut_ad(!trx->read_only);
|
||||
ut_ad(!undo || undo->rseg == rseg);
|
||||
ut_ad(!old_insert || old_insert->rseg == rseg);
|
||||
mutex_enter(&rseg->mutex);
|
||||
|
||||
/* Assign the transaction serialisation number and add any
|
||||
undo log to the purge queue. */
|
||||
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) {
|
||||
UT_LIST_REMOVE(rseg->undo_list, undo);
|
||||
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);
|
||||
--rseg->trx_ref_count;
|
||||
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 (trx_undo_t *&undo= rsegs.m_noredo.undo)
|
||||
{
|
||||
ut_ad(undo->rseg == rsegs.m_noredo.rseg);
|
||||
trx_undo_commit_cleanup(undo, true);
|
||||
trx_undo_commit_cleanup(undo);
|
||||
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(!mtr || mtr->is_active());
|
||||
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);
|
||||
|
||||
/* 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 local_mtr;
|
||||
|
||||
if (has_logged_or_recovered())
|
||||
if (has_logged())
|
||||
{
|
||||
mtr= &local_mtr;
|
||||
local_mtr.start();
|
||||
@ -1965,11 +1931,8 @@ trx_weight_ge(
|
||||
/** Prepare a transaction.
|
||||
@return log sequence number that makes the XA PREPARE durable
|
||||
@retval 0 if no changes needed to be made durable */
|
||||
static
|
||||
lsn_t
|
||||
trx_prepare_low(trx_t* trx)
|
||||
static lsn_t trx_prepare_low(trx_t *trx)
|
||||
{
|
||||
ut_ad(!trx->rsegs.m_redo.old_insert);
|
||||
ut_ad(!trx->is_recovered);
|
||||
|
||||
mtr_t mtr;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
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 "trx0rec.h"
|
||||
#include "trx0rseg.h"
|
||||
#include "log.h"
|
||||
|
||||
/* 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 */
|
||||
|
||||
ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
|
||||
+ undo_page)
|
||||
== TRX_UNDO_INSERT);
|
||||
+ undo_page) == 1);
|
||||
|
||||
byte* page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
|
||||
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.
|
||||
@param[in] undo undo log
|
||||
@param[in] noredo whether the undo tablespace is redo logged */
|
||||
static
|
||||
void
|
||||
trx_undo_seg_free(
|
||||
const trx_undo_t* undo,
|
||||
bool noredo)
|
||||
@param undo temporary undo log */
|
||||
static void trx_undo_seg_free(const trx_undo_t *undo)
|
||||
{
|
||||
trx_rseg_t* rseg;
|
||||
fseg_header_t* file_seg;
|
||||
@ -1039,16 +1034,12 @@ trx_undo_seg_free(
|
||||
rseg = undo->rseg;
|
||||
|
||||
do {
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
if (noredo) {
|
||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
||||
}
|
||||
mtr.start();
|
||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
||||
|
||||
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),
|
||||
&mtr)
|
||||
+ TRX_UNDO_SEG_HDR;
|
||||
@ -1079,10 +1070,11 @@ trx_undo_seg_free(
|
||||
@param[in] id rollback segment slot
|
||||
@param[in] page_no undo log segment page number
|
||||
@param[in,out] max_trx_id the largest observed transaction ID
|
||||
@return size of the undo log in pages */
|
||||
ulint
|
||||
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
|
||||
trx_id_t& max_trx_id)
|
||||
@return the undo log
|
||||
@retval nullptr on error */
|
||||
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)
|
||||
{
|
||||
mtr_t mtr;
|
||||
XID xid;
|
||||
@ -1092,16 +1084,56 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
|
||||
mtr.start();
|
||||
const page_t* undo_page = trx_undo_page_get(
|
||||
page_id_t(rseg->space->id, page_no), &mtr);
|
||||
const ulint type = mach_read_from_2(
|
||||
TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE + undo_page);
|
||||
ut_ad(type == 0 || type == TRX_UNDO_INSERT || type == TRX_UNDO_UPDATE);
|
||||
const uint16_t type = mach_read_from_2(TRX_UNDO_PAGE_HDR
|
||||
+ TRX_UNDO_PAGE_TYPE
|
||||
+ 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;
|
||||
}
|
||||
|
||||
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);
|
||||
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* undo_header = undo_page + offset;
|
||||
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
|
||||
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);
|
||||
if (trx_id >> 48) {
|
||||
sql_print_error("InnoDB: corrupted TRX_ID %llx", trx_id);
|
||||
goto corrupted;
|
||||
}
|
||||
if (trx_id > max_trx_id) {
|
||||
max_trx_id = trx_id;
|
||||
}
|
||||
@ -1121,61 +1157,45 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
|
||||
trx_undo_t* undo = trx_undo_mem_create(
|
||||
rseg, id, trx_id, &xid, page_no, offset);
|
||||
mutex_exit(&rseg->mutex);
|
||||
if (!undo) {
|
||||
return undo;
|
||||
}
|
||||
|
||||
undo->dict_operation = undo_header[TRX_UNDO_DICT_TRANS];
|
||||
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_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;
|
||||
fil_addr_t last_addr = flst_get_last(
|
||||
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page, &mtr);
|
||||
|
||||
undo->last_page_no = last_addr.page;
|
||||
undo->top_page_no = last_addr.page;
|
||||
|
||||
page_t* last_page = trx_undo_page_get(
|
||||
page_id_t(rseg->space->id, undo->last_page_no), &mtr);
|
||||
|
||||
if (const trx_undo_rec_t* rec = trx_undo_page_get_last_rec(
|
||||
last_page, page_no, offset)) {
|
||||
undo->top_offset = ulint(rec - last_page);
|
||||
undo->top_undo_no = trx_undo_rec_get_undo_no(rec);
|
||||
ut_ad(!undo->empty());
|
||||
} 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(
|
||||
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page,
|
||||
&mtr);
|
||||
|
||||
undo->last_page_no = last_addr.page;
|
||||
undo->top_page_no = last_addr.page;
|
||||
|
||||
page_t* last_page = trx_undo_page_get(
|
||||
page_id_t(rseg->space->id, undo->last_page_no), &mtr);
|
||||
|
||||
if (const trx_undo_rec_t* rec = trx_undo_page_get_last_rec(
|
||||
last_page, page_no, offset)) {
|
||||
undo->top_offset = ulint(rec - last_page);
|
||||
undo->top_undo_no = trx_undo_rec_get_undo_no(rec);
|
||||
ut_ad(!undo->empty());
|
||||
} else {
|
||||
undo->top_undo_no = IB_ID_MAX;
|
||||
ut_ad(undo->empty());
|
||||
}
|
||||
undo->top_undo_no = IB_ID_MAX;
|
||||
ut_ad(undo->empty());
|
||||
}
|
||||
|
||||
undo->state = state;
|
||||
|
||||
if (state != TRX_UNDO_CACHED) {
|
||||
UT_LIST_ADD_LAST(type == TRX_UNDO_INSERT
|
||||
? rseg->old_insert_list
|
||||
: rseg->undo_list, undo);
|
||||
UT_LIST_ADD_LAST(rseg->undo_list, undo);
|
||||
} else {
|
||||
UT_LIST_ADD_LAST(rseg->undo_cached, undo);
|
||||
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_CACHED);
|
||||
}
|
||||
|
||||
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(
|
||||
mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
|
||||
+ 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
|
||||
+ block->frame, 0, MLOG_2BYTES, mtr);
|
||||
}
|
||||
@ -1537,9 +1557,8 @@ trx_undo_set_state_at_finish(
|
||||
@param[in,out] trx transaction
|
||||
@param[in,out] undo undo log
|
||||
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK
|
||||
@param[in,out] mtr mini-transaction
|
||||
@return undo log segment header page, x-latched */
|
||||
page_t*
|
||||
@param[in,out] mtr mini-transaction */
|
||||
void
|
||||
trx_undo_set_state_at_prepare(
|
||||
trx_t* trx,
|
||||
trx_undo_t* undo,
|
||||
@ -1551,8 +1570,6 @@ trx_undo_set_state_at_prepare(
|
||||
page_t* undo_page;
|
||||
ulint offset;
|
||||
|
||||
ut_ad(trx && undo && mtr);
|
||||
|
||||
ut_a(undo->id < TRX_RSEG_N_SLOTS);
|
||||
|
||||
undo_page = trx_undo_page_get(
|
||||
@ -1564,7 +1581,7 @@ trx_undo_set_state_at_prepare(
|
||||
ut_ad(undo->state == TRX_UNDO_PREPARED);
|
||||
mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, TRX_UNDO_ACTIVE,
|
||||
MLOG_2BYTES, mtr);
|
||||
return(undo_page);
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------*/
|
||||
@ -1583,26 +1600,20 @@ trx_undo_set_state_at_prepare(
|
||||
TRUE, MLOG_1BYTE, 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 data can be discarded.
|
||||
@param[in,out] undo undo log
|
||||
@param[in] is_temp whether this is temporary undo log */
|
||||
void
|
||||
trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
|
||||
@param undo temporary undo log */
|
||||
void trx_undo_commit_cleanup(trx_undo_t *undo)
|
||||
{
|
||||
trx_rseg_t* rseg = undo->rseg;
|
||||
ut_ad(is_temp == !rseg->is_persistent());
|
||||
ut_ad(!is_temp || 0 == UT_LIST_GET_LEN(rseg->old_insert_list));
|
||||
ut_ad(rseg->space == fil_system.temp_space);
|
||||
|
||||
mutex_enter(&rseg->mutex);
|
||||
|
||||
UT_LIST_REMOVE(is_temp ? rseg->undo_list : rseg->old_insert_list,
|
||||
undo);
|
||||
UT_LIST_REMOVE(rseg->undo_list, undo);
|
||||
|
||||
if (undo->state == TRX_UNDO_CACHED) {
|
||||
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 */
|
||||
mutex_exit(&rseg->mutex);
|
||||
trx_undo_seg_free(undo, is_temp);
|
||||
trx_undo_seg_free(undo);
|
||||
mutex_enter(&rseg->mutex);
|
||||
|
||||
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. */
|
||||
void
|
||||
trx_undo_free_at_shutdown(trx_t *trx)
|
||||
void trx_undo_free_at_shutdown(trx_t *trx)
|
||||
{
|
||||
if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) {
|
||||
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));
|
||||
@ -1654,34 +1663,6 @@ trx_undo_free_at_shutdown(trx_t *trx)
|
||||
ut_free(undo);
|
||||
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) {
|
||||
ut_a(undo->state == TRX_UNDO_PREPARED);
|
||||
|
||||
|
@ -4212,7 +4212,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
||||
const char * name, my_bool rep_quick)
|
||||
{
|
||||
int got_error;
|
||||
uint i,key, total_key_length, istep;
|
||||
uint i,key, istep;
|
||||
ha_rows start_records;
|
||||
my_off_t new_header_length,del;
|
||||
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!");
|
||||
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;
|
||||
share->state.state.records=share->state.state.del=share->state.split=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)
|
||||
sort_param[i].key_length++;
|
||||
}
|
||||
#ifdef USING_SECOND_APPROACH
|
||||
total_key_length+=sort_param[i].key_length;
|
||||
#endif
|
||||
|
||||
if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
|
||||
{
|
||||
|
@ -2616,7 +2616,7 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
|
||||
const char * name, int rep_quick)
|
||||
{
|
||||
int got_error;
|
||||
uint i,key, total_key_length, istep;
|
||||
uint i,key, istep;
|
||||
ulong rec_length;
|
||||
ha_rows start_records;
|
||||
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!");
|
||||
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;
|
||||
info->state->records=info->state->del=share->state.split=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)
|
||||
sort_param[i].key_length++;
|
||||
}
|
||||
#ifdef USING_SECOND_APPROACH
|
||||
total_key_length+=sort_param[i].key_length;
|
||||
#endif
|
||||
|
||||
if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@ package My::Suite::Spider;
|
||||
|
||||
return "No Spider engine" unless $ENV{HA_SPIDER_SO};
|
||||
return "Not run for embedded server" if $::opt_embedded_server;
|
||||
return "Test needs --big-test" unless $::opt_big_test;
|
||||
|
||||
sub is_default { 1 }
|
||||
|
||||
|
@ -4,7 +4,6 @@ package My::Suite::Spider;
|
||||
|
||||
return "No Spider engine" unless $ENV{HA_SPIDER_SO};
|
||||
return "Not run for embedded server" if $::opt_embedded_server;
|
||||
return "Test needs --big-test" unless $::opt_big_test;
|
||||
|
||||
sub is_default { 1 }
|
||||
|
||||
|
@ -22,7 +22,9 @@ USE auto_test_remote;
|
||||
--connection child2_1
|
||||
--disable_query_log
|
||||
echo CHILD2_1_CREATE_TABLES;
|
||||
--disable_ps_protocol
|
||||
eval $CHILD2_1_CREATE_TABLES;
|
||||
--enable_ps_protocol
|
||||
--enable_query_log
|
||||
TRUNCATE TABLE mysql.general_log;
|
||||
|
||||
@ -66,7 +68,9 @@ SELECT a, b, c FROM tbl_a PARTITION (pt2,pt3);
|
||||
|
||||
--connection child2_1
|
||||
eval $CHILD2_1_SELECT_ARGUMENT1;
|
||||
--disable_ps_protocol
|
||||
eval $CHILD2_1_SELECT_TABLES;
|
||||
--enable_ps_protocol
|
||||
|
||||
--echo
|
||||
--echo deinit
|
||||
|
@ -22,7 +22,9 @@ USE auto_test_remote;
|
||||
--connection child2_1
|
||||
--disable_query_log
|
||||
echo CHILD2_1_CREATE_TABLES;
|
||||
--disable_ps_protocol
|
||||
eval $CHILD2_1_CREATE_TABLES;
|
||||
--enable_ps_protocol
|
||||
--enable_query_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
|
||||
SET NAMES utf8;
|
||||
eval $CHILD2_1_SELECT_ARGUMENT1;
|
||||
--disable_ps_protocol
|
||||
eval $CHILD2_1_SELECT_TABLES;
|
||||
--enable_ps_protocol
|
||||
|
||||
--echo
|
||||
--echo deinit
|
||||
|
@ -49,6 +49,8 @@ TRUNCATE TABLE mysql.general_log;
|
||||
SELECT * FROM tbl_a ORDER BY pkey;
|
||||
|
||||
--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_TABLES;
|
||||
|
||||
|
@ -4,7 +4,6 @@ package My::Suite::Spider;
|
||||
|
||||
return "No Spider engine" unless $ENV{HA_SPIDER_SO};
|
||||
return "Not run for embedded server" if $::opt_embedded_server;
|
||||
return "Test needs --big-test" unless $::opt_big_test;
|
||||
|
||||
sub is_default { 1 }
|
||||
|
||||
|
@ -4,7 +4,6 @@ package My::Suite::Spider;
|
||||
|
||||
return "No Spider engine" unless $ENV{HA_SPIDER_SO};
|
||||
return "Not run for embedded server" if $::opt_embedded_server;
|
||||
return "Test needs --big-test" unless $::opt_big_test;
|
||||
|
||||
sub is_default { 1 }
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
--source include/no_protocol.inc
|
||||
--source ../include/partition_mrr_init.inc
|
||||
if (!$HAVE_PARTITION)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ if [ -r %{restart_flag} ] ; then
|
||||
# only restart the server if it was already running
|
||||
if [ -x /usr/bin/systemctl ] ; then
|
||||
/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
|
||||
else
|
||||
/usr/bin/systemctl try-restart mariadb.service > /dev/null 2>&1
|
||||
|
Loading…
x
Reference in New Issue
Block a user