mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.6 into 10.9
This commit is contained in:
2
debian/mariadb-server.mariadb.init
vendored
2
debian/mariadb-server.mariadb.init
vendored
@@ -86,7 +86,7 @@ sanity_checks() {
|
|||||||
datadir=`mariadbd_get_param datadir`
|
datadir=`mariadbd_get_param datadir`
|
||||||
# As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024
|
# As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024
|
||||||
# 4096 blocks is then lower than 4 MB
|
# 4096 blocks is then lower than 4 MB
|
||||||
df_available_blocks=`LC_ALL=C BLOCKSIZE= df --output=avail "$datadir" | tail -n 1`
|
df_available_blocks="$(LC_ALL=C BLOCKSIZE='' df --output=avail "$datadir" | tail -n 1)"
|
||||||
if [ "$df_available_blocks" -lt "4096" ]; then
|
if [ "$df_available_blocks" -lt "4096" ]; then
|
||||||
log_failure_msg "$0: ERROR: The partition with $datadir is too full!"
|
log_failure_msg "$0: ERROR: The partition with $datadir is too full!"
|
||||||
echo "ERROR: The partition with $datadir is too full!" | $ERR_LOGGER
|
echo "ERROR: The partition with $datadir is too full!" | $ERR_LOGGER
|
||||||
|
23
debian/mariadb-server.preinst
vendored
23
debian/mariadb-server.preinst
vendored
@@ -223,14 +223,23 @@ then
|
|||||||
mkdir -Z $mysql_datadir
|
mkdir -Z $mysql_datadir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024
|
# Check if MariaDB datadir is available if not fails.
|
||||||
# 4096 blocks is then lower than 4 MB
|
# There should be symlink or directory available or something will fail.
|
||||||
df_available_blocks=`LC_ALL=C BLOCKSIZE= df --output=avail "$datadir" | tail -n 1`
|
if [ -d "$mysql_datadir" ] || [ -L "$mysql_datadir" ]
|
||||||
if [ "$df_available_blocks" -lt "4096" ]
|
|
||||||
then
|
then
|
||||||
echo "ERROR: There's not enough space in $mysql_datadir/" 1>&2
|
# As preset blocksize of GNU df is 1024 then available bytes is $df_available_blocks * 1024
|
||||||
db_stop
|
# 4096 blocks is then lower than 4 MB
|
||||||
exit 1
|
df_available_blocks="$(LC_ALL=C BLOCKSIZE='' df --output=avail "$mysql_datadir" | tail -n 1)"
|
||||||
|
if [ "$df_available_blocks" -lt "4096" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: There's not enough space in $mysql_datadir/" 1>&2
|
||||||
|
db_stop
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "ERROR: There's no directory or symlink available: $mysql_datadir/" 1>&2
|
||||||
|
db_stop
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Since the home directory was created before putting the user into
|
# Since the home directory was created before putting the user into
|
||||||
|
@@ -26,4 +26,60 @@ UPDATE mysql.innodb_table_stats SET last_update=NULL WHERE table_name='t1';
|
|||||||
XA END 'test';
|
XA END 'test';
|
||||||
XA ROLLBACK 'test';
|
XA ROLLBACK 'test';
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-30483 After upgrade to 10.6 from Mysql 5.7 seeing "InnoDB: Column last_update in table mysql.innodb_table_stats is BINARY(4) NOT NULL but should be INT UNSIGNED NOT NULL"
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Testing a non-default format: Field_timestamp0 - UINT4 based
|
||||||
|
#
|
||||||
|
SET @@global.mysql56_temporal_format=0;
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_table_stats LIKE 'last_update';
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
last_update timestamp /* mariadb-5.3 */ NO current_timestamp() on update current_timestamp()
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_index_stats LIKE 'last_update';
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
last_update timestamp /* mariadb-5.3 */ NO current_timestamp() on update current_timestamp()
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=1;
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
TIMESTAMPDIFF(DAY,last_update,now())<=1
|
||||||
|
1
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
TIMESTAMPDIFF(DAY,last_update,now())<=1
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Now as the table t1 is dropped, expect no statistics
|
||||||
|
#
|
||||||
|
SELECT * FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
database_name table_name last_update n_rows clustered_index_size sum_of_other_index_sizes
|
||||||
|
SELECT * FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
database_name table_name index_name last_update stat_name stat_value sample_size stat_description
|
||||||
|
#
|
||||||
|
# Testing with the default format: Field_timestampf - BINARY(4) based with the UNSIGNED_FLAG
|
||||||
|
#
|
||||||
|
SET @@global.mysql56_temporal_format=1;
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_table_stats LIKE 'last_update';
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
last_update timestamp NO current_timestamp() on update current_timestamp()
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_index_stats LIKE 'last_update';
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
last_update timestamp NO current_timestamp() on update current_timestamp()
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=1;
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
TIMESTAMPDIFF(DAY,last_update,now())<=1
|
||||||
|
1
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
TIMESTAMPDIFF(DAY,last_update,now())<=1
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
# End of 10.6 tests
|
# End of 10.6 tests
|
||||||
|
@@ -28,4 +28,57 @@ XA END 'test';
|
|||||||
XA ROLLBACK 'test';
|
XA ROLLBACK 'test';
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-30483 After upgrade to 10.6 from Mysql 5.7 seeing "InnoDB: Column last_update in table mysql.innodb_table_stats is BINARY(4) NOT NULL but should be INT UNSIGNED NOT NULL"
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# The following tests demonstrate that these columns:
|
||||||
|
# - innodb_table_stats.last_update
|
||||||
|
# - innodb_index_stats.last_update
|
||||||
|
# have sane values close to NOW(), rather than any garbage,
|
||||||
|
# with all TIMESTAMP formats.
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing a non-default format: Field_timestamp0 - UINT4 based
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET @@global.mysql56_temporal_format=0;
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_table_stats LIKE 'last_update';
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_index_stats LIKE 'last_update';
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=1;
|
||||||
|
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Now as the table t1 is dropped, expect no statistics
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SELECT * FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
SELECT * FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing with the default format: Field_timestampf - BINARY(4) based with the UNSIGNED_FLAG
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET @@global.mysql56_temporal_format=1;
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_table_stats LIKE 'last_update';
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_index_stats LIKE 'last_update';
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=1;
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo # End of 10.6 tests
|
--echo # End of 10.6 tests
|
||||||
|
26
mysql-test/suite/parts/r/partition_purge.result
Normal file
26
mysql-test/suite/parts/r/partition_purge.result
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
CREATE TABLE t1(f1 INT, f2 INT, INDEX(f1))ENGINE=InnoDB
|
||||||
|
PARTITION BY LIST(f1) (
|
||||||
|
PARTITION p1 VALUES in (1, 2, 3),
|
||||||
|
PARTITION p2 VALUES in (4, 5, 6));
|
||||||
|
INSERT INTO t1 VALUES(1, 1), (1, 1), (6, 1);
|
||||||
|
connect con1,localhost,root,,,;
|
||||||
|
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||||
|
connect con2,localhost,root,,,;
|
||||||
|
SET DEBUG_SYNC="innodb_rollback_inplace_alter_table SIGNAL default_resume WAIT_FOR alter_resume";
|
||||||
|
ALTER TABLE t1 ADD UNIQUE INDEX(f1);
|
||||||
|
connection default;
|
||||||
|
set DEBUG_SYNC="now WAIT_FOR default_resume";
|
||||||
|
SET DEBUG_SYNC="innodb_row_update_for_mysql_begin SIGNAL alter_resume WAIT_FOR alter_finish";
|
||||||
|
DELETE FROM t1;
|
||||||
|
connection con2;
|
||||||
|
ERROR 23000: Duplicate entry '1' for key 'f1_2'
|
||||||
|
SET DEBUG_SYNC="now SIGNAL alter_finish";
|
||||||
|
connection default;
|
||||||
|
connection con1;
|
||||||
|
commit;
|
||||||
|
connection default;
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
InnoDB 0 transactions not purged
|
||||||
|
drop table t1;
|
||||||
|
SET DEBUG_SYNC=reset;
|
1
mysql-test/suite/parts/t/partition_purge.opt
Normal file
1
mysql-test/suite/parts/t/partition_purge.opt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
--innodb_purge_threads=1
|
37
mysql-test/suite/parts/t/partition_purge.test
Normal file
37
mysql-test/suite/parts/t/partition_purge.test
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_partition.inc
|
||||||
|
--source include/have_debug.inc
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1(f1 INT, f2 INT, INDEX(f1))ENGINE=InnoDB
|
||||||
|
PARTITION BY LIST(f1) (
|
||||||
|
PARTITION p1 VALUES in (1, 2, 3),
|
||||||
|
PARTITION p2 VALUES in (4, 5, 6));
|
||||||
|
INSERT INTO t1 VALUES(1, 1), (1, 1), (6, 1);
|
||||||
|
connect(con1,localhost,root,,,);
|
||||||
|
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||||
|
|
||||||
|
connect(con2,localhost,root,,,);
|
||||||
|
SET DEBUG_SYNC="innodb_rollback_inplace_alter_table SIGNAL default_resume WAIT_FOR alter_resume";
|
||||||
|
send ALTER TABLE t1 ADD UNIQUE INDEX(f1);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
set DEBUG_SYNC="now WAIT_FOR default_resume";
|
||||||
|
SET DEBUG_SYNC="innodb_row_update_for_mysql_begin SIGNAL alter_resume WAIT_FOR alter_finish";
|
||||||
|
send DELETE FROM t1;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC="now SIGNAL alter_finish";
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
connection con1;
|
||||||
|
commit;
|
||||||
|
connection default;
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
--source ../../innodb/include/wait_all_purged.inc
|
||||||
|
drop table t1;
|
||||||
|
SET DEBUG_SYNC=reset;
|
@@ -13,7 +13,7 @@ innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
|||||||
`sum_of_other_index_sizes` bigint(20) unsigned NOT NULL,
|
`sum_of_other_index_sizes` bigint(20) unsigned NOT NULL,
|
||||||
PRIMARY KEY (`database_name`,`table_name`)
|
PRIMARY KEY (`database_name`,`table_name`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
||||||
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP;
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_table_stats;
|
SHOW CREATE TABLE mysql.innodb_table_stats;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
||||||
@@ -25,7 +25,7 @@ innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
|||||||
`sum_of_other_index_sizes` bigint(20) unsigned NOT NULL,
|
`sum_of_other_index_sizes` bigint(20) unsigned NOT NULL,
|
||||||
PRIMARY KEY (`database_name`,`table_name`)
|
PRIMARY KEY (`database_name`,`table_name`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
||||||
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP;
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_index_stats;
|
SHOW CREATE TABLE mysql.innodb_index_stats;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
innodb_index_stats CREATE TABLE `innodb_index_stats` (
|
innodb_index_stats CREATE TABLE `innodb_index_stats` (
|
||||||
@@ -44,7 +44,7 @@ CREATE TABLE t1 (a INT, KEY(a)) ENGINE=InnoDB;
|
|||||||
INSERT INTO t1 VALUES (10);
|
INSERT INTO t1 VALUES (10);
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET @@global.innodb_stats_persistent=0;
|
SET @@global.innodb_stats_persistent=0;
|
||||||
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP;
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_table_stats;
|
SHOW CREATE TABLE mysql.innodb_table_stats;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
||||||
@@ -56,7 +56,7 @@ innodb_table_stats CREATE TABLE `innodb_table_stats` (
|
|||||||
`sum_of_other_index_sizes` bigint(20) unsigned NOT NULL,
|
`sum_of_other_index_sizes` bigint(20) unsigned NOT NULL,
|
||||||
PRIMARY KEY (`database_name`,`table_name`)
|
PRIMARY KEY (`database_name`,`table_name`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
||||||
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP;
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_index_stats;
|
SHOW CREATE TABLE mysql.innodb_index_stats;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
innodb_index_stats CREATE TABLE `innodb_index_stats` (
|
innodb_index_stats CREATE TABLE `innodb_index_stats` (
|
||||||
@@ -71,3 +71,38 @@ innodb_index_stats CREATE TABLE `innodb_index_stats` (
|
|||||||
PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`)
|
PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0
|
||||||
SET @@global.innodb_stats_persistent=1;
|
SET @@global.innodb_stats_persistent=1;
|
||||||
|
#
|
||||||
|
# Testing MySQL-5.6-alike Field_timestampf: BINARY(4) based, without UNSIGNED_FLAG
|
||||||
|
#
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_table_stats LIKE 'last_update';
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
last_update type_mysql_timestamp NO current_timestamp() on update current_timestamp()
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_index_stats LIKE 'last_update';
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
last_update type_mysql_timestamp NO current_timestamp() on update current_timestamp()
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=1;
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
TIMESTAMPDIFF(DAY,last_update,now())<=1
|
||||||
|
1
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
TIMESTAMPDIFF(DAY,last_update,now())<=1
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Now as the table t1 is dropped, expect no statistics
|
||||||
|
#
|
||||||
|
SELECT * FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
database_name table_name last_update n_rows clustered_index_size sum_of_other_index_sizes
|
||||||
|
SELECT * FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
database_name table_name index_name last_update stat_name stat_value sample_size stat_description
|
||||||
|
#
|
||||||
|
# Restore the structure of the tables
|
||||||
|
#
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
SET @@global.innodb_stats_persistent=0;
|
SET @@global.innodb_stats_persistent=0;
|
||||||
SHOW CREATE TABLE mysql.innodb_table_stats;
|
SHOW CREATE TABLE mysql.innodb_table_stats;
|
||||||
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP;
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_table_stats;
|
SHOW CREATE TABLE mysql.innodb_table_stats;
|
||||||
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP;
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_index_stats;
|
SHOW CREATE TABLE mysql.innodb_index_stats;
|
||||||
SET @@global.innodb_stats_persistent=1;
|
SET @@global.innodb_stats_persistent=1;
|
||||||
|
|
||||||
@@ -17,8 +17,46 @@ INSERT INTO t1 VALUES (10);
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
SET @@global.innodb_stats_persistent=0;
|
SET @@global.innodb_stats_persistent=0;
|
||||||
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP;
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_table_stats;
|
SHOW CREATE TABLE mysql.innodb_table_stats;
|
||||||
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP;
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
SHOW CREATE TABLE mysql.innodb_index_stats;
|
SHOW CREATE TABLE mysql.innodb_index_stats;
|
||||||
SET @@global.innodb_stats_persistent=1;
|
SET @@global.innodb_stats_persistent=1;
|
||||||
|
|
||||||
|
|
||||||
|
# The following test demonstrate that these columns:
|
||||||
|
# - innodb_table_stats.last_update
|
||||||
|
# - innodb_index_stats.last_update
|
||||||
|
# have sane values close to NOW(), rather than any garbage,
|
||||||
|
# with MySQL-alike Field_timestampf
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing MySQL-5.6-alike Field_timestampf: BINARY(4) based, without UNSIGNED_FLAG
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TYPE_MYSQL_TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_table_stats LIKE 'last_update';
|
||||||
|
SHOW COLUMNS FROM mysql.innodb_index_stats LIKE 'last_update';
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=1;
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
SELECT TIMESTAMPDIFF(DAY,last_update,now())<=1 FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Now as the table t1 is dropped, expect no statistics
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SELECT * FROM mysql.innodb_table_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1';
|
||||||
|
SELECT * FROM mysql.innodb_index_stats
|
||||||
|
WHERE database_name='test' AND table_name='t1' AND stat_name='size';
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Restore the structure of the tables
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
ALTER TABLE mysql.innodb_table_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
ALTER TABLE mysql.innodb_index_stats MODIFY last_update TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp();
|
||||||
|
@@ -2140,6 +2140,8 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
block->page.lock.x_lock();
|
block->page.lock.x_lock();
|
||||||
|
if (block->page.is_ibuf_exist())
|
||||||
|
ibuf_merge_or_delete_for_page(nullptr, page_id, block->page.zip_size());
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
if (block->index)
|
if (block->index)
|
||||||
btr_search_drop_page_hash_index(block, false);
|
btr_search_drop_page_hash_index(block, false);
|
||||||
|
@@ -2438,6 +2438,7 @@ static void buf_flush_page_cleaner()
|
|||||||
else if (buf_pool.ran_out())
|
else if (buf_pool.ran_out())
|
||||||
{
|
{
|
||||||
buf_pool.page_cleaner_set_idle(false);
|
buf_pool.page_cleaner_set_idle(false);
|
||||||
|
buf_pool.get_oldest_modification(0);
|
||||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||||
n= srv_max_io_capacity;
|
n= srv_max_io_capacity;
|
||||||
mysql_mutex_lock(&buf_pool.mutex);
|
mysql_mutex_lock(&buf_pool.mutex);
|
||||||
|
@@ -1955,8 +1955,8 @@ err_exit:
|
|||||||
FIL_TYPE_TABLESPACE,
|
FIL_TYPE_TABLESPACE,
|
||||||
crypt_data, mode, true)) {
|
crypt_data, mode, true)) {
|
||||||
fil_node_t* node = space->add(path, file, size, false, true);
|
fil_node_t* node = space->add(path, file, size, false, true);
|
||||||
mysql_mutex_unlock(&fil_system.mutex);
|
|
||||||
IF_WIN(node->find_metadata(), node->find_metadata(file, true));
|
IF_WIN(node->find_metadata(), node->find_metadata(file, true));
|
||||||
|
mysql_mutex_unlock(&fil_system.mutex);
|
||||||
mtr.start();
|
mtr.start();
|
||||||
mtr.set_named_space(space);
|
mtr.set_named_space(space);
|
||||||
ut_a(fsp_header_init(space, size, &mtr) == DB_SUCCESS);
|
ut_a(fsp_header_init(space, size, &mtr) == DB_SUCCESS);
|
||||||
|
@@ -2364,6 +2364,7 @@ tablespace_deleted:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ulint zip_size = s->zip_size(), size = s->size;
|
const ulint zip_size = s->zip_size(), size = s->size;
|
||||||
|
s->x_lock();
|
||||||
s->release();
|
s->release();
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
@@ -2381,13 +2382,17 @@ tablespace_deleted:
|
|||||||
|| !page_is_leaf(block->page.frame);
|
|| !page_is_leaf(block->page.frame);
|
||||||
mtr.commit();
|
mtr.commit();
|
||||||
if (err == DB_TABLESPACE_DELETED) {
|
if (err == DB_TABLESPACE_DELETED) {
|
||||||
|
s->x_unlock();
|
||||||
goto tablespace_deleted;
|
goto tablespace_deleted;
|
||||||
}
|
}
|
||||||
if (!remove) {
|
if (!remove) {
|
||||||
|
s->x_unlock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->x_unlock();
|
||||||
|
|
||||||
if (srv_shutdown_state == SRV_SHUTDOWN_NONE
|
if (srv_shutdown_state == SRV_SHUTDOWN_NONE
|
||||||
|| srv_fast_shutdown) {
|
|| srv_fast_shutdown) {
|
||||||
continue;
|
continue;
|
||||||
@@ -2416,7 +2421,7 @@ tablespace_deleted:
|
|||||||
/* Prevent an infinite loop, by removing entries from
|
/* Prevent an infinite loop, by removing entries from
|
||||||
the change buffer in the case the bitmap bits were
|
the change buffer in the case the bitmap bits were
|
||||||
wrongly clear even though buffered changes exist. */
|
wrongly clear even though buffered changes exist. */
|
||||||
ibuf_delete_recs(page_id_t(space_ids[i], page_nos[i]));
|
ibuf_delete_recs(page_id_t(space_id, page_nos[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4194,25 +4199,26 @@ dberr_t ibuf_merge_or_delete_for_page(buf_block_t *block,
|
|||||||
|
|
||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
|
|
||||||
if (bitmap_bits
|
if (!bitmap_bits) {
|
||||||
&& DB_SUCCESS
|
done:
|
||||||
|
/* No changes are buffered for this page. */
|
||||||
|
space->release();
|
||||||
|
return DB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block
|
||||||
|
|| DB_SUCCESS
|
||||||
== fseg_page_is_allocated(space, page_id.page_no())) {
|
== fseg_page_is_allocated(space, page_id.page_no())) {
|
||||||
ibuf_mtr_start(&mtr);
|
ibuf_mtr_start(&mtr);
|
||||||
mtr.set_named_space(space);
|
mtr.set_named_space(space);
|
||||||
ibuf_reset_bitmap(block, page_id, zip_size, &mtr);
|
ibuf_reset_bitmap(block, page_id, zip_size, &mtr);
|
||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
bitmap_bits = 0;
|
|
||||||
if (!block
|
if (!block
|
||||||
|| btr_page_get_index_id(block->page.frame)
|
|| btr_page_get_index_id(block->page.frame)
|
||||||
!= DICT_IBUF_ID_MIN + IBUF_SPACE_ID) {
|
!= DICT_IBUF_ID_MIN + IBUF_SPACE_ID) {
|
||||||
ibuf_delete_recs(page_id);
|
ibuf_delete_recs(page_id);
|
||||||
}
|
}
|
||||||
}
|
goto done;
|
||||||
|
|
||||||
if (!bitmap_bits) {
|
|
||||||
/* No changes are buffered for this page. */
|
|
||||||
space->release();
|
|
||||||
return DB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -216,14 +216,6 @@ buf_block_t*
|
|||||||
trx_undo_assign_low(trx_t *trx, trx_rseg_t *rseg, trx_undo_t **undo,
|
trx_undo_assign_low(trx_t *trx, trx_rseg_t *rseg, trx_undo_t **undo,
|
||||||
mtr_t *mtr, dberr_t *err)
|
mtr_t *mtr, dberr_t *err)
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
/******************************************************************//**
|
|
||||||
Sets the state of the undo log segment at a transaction finish.
|
|
||||||
@return undo log segment header page, x-latched */
|
|
||||||
buf_block_t*
|
|
||||||
trx_undo_set_state_at_finish(
|
|
||||||
/*=========================*/
|
|
||||||
trx_undo_t* undo, /*!< in: undo log memory copy */
|
|
||||||
mtr_t* mtr); /*!< in: mtr */
|
|
||||||
|
|
||||||
/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK.
|
/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK.
|
||||||
@param[in,out] trx transaction
|
@param[in,out] trx transaction
|
||||||
|
@@ -2491,7 +2491,7 @@ inline
|
|||||||
recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
|
recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
restart:
|
restart:
|
||||||
#ifndef SUX_LOCK_GENERIC
|
#ifndef SUX_LOCK_GENERIC
|
||||||
ut_ad(log_sys.latch.is_write_locked() ||
|
ut_ad(log_sys.latch.is_write_locked() ||
|
||||||
srv_operation == SRV_OPERATION_BACKUP ||
|
srv_operation == SRV_OPERATION_BACKUP ||
|
||||||
@@ -3279,9 +3279,6 @@ set_start_lsn:
|
|||||||
|| recv_sys.is_corrupt_log()) && !srv_force_recovery) {
|
|| recv_sys.is_corrupt_log()) && !srv_force_recovery) {
|
||||||
if (init) {
|
if (init) {
|
||||||
init->created = false;
|
init->created = false;
|
||||||
if (space || block->page.id().page_no()) {
|
|
||||||
block->page.lock.x_lock_recursive();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr.discard_modifications();
|
mtr.discard_modifications();
|
||||||
@@ -3847,10 +3844,12 @@ void recv_sys_t::apply(bool last_batch)
|
|||||||
if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start))
|
if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start))
|
||||||
{
|
{
|
||||||
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
|
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
|
||||||
|
ut_ad(space->recv_size >= t.pages);
|
||||||
fil_node_t *file= UT_LIST_GET_FIRST(space->chain);
|
fil_node_t *file= UT_LIST_GET_FIRST(space->chain);
|
||||||
ut_ad(file->is_open());
|
ut_ad(file->is_open());
|
||||||
os_file_truncate(file->name, file->handle,
|
os_file_truncate(file->name, file->handle,
|
||||||
os_offset_t{t.pages} << srv_page_size_shift, true);
|
os_offset_t{space->recv_size} <<
|
||||||
|
srv_page_size_shift, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -214,14 +214,14 @@ row_ins_sec_index_entry_by_modify(
|
|||||||
made to the clustered index, and completed the
|
made to the clustered index, and completed the
|
||||||
secondary index creation before we got here. In this
|
secondary index creation before we got here. In this
|
||||||
case, the change would already be there. The CREATE
|
case, the change would already be there. The CREATE
|
||||||
INDEX should be waiting for a MySQL meta-data lock
|
INDEX should be in wait_while_table_is_used() at least
|
||||||
upgrade at least until this INSERT or UPDATE
|
until this INSERT or UPDATE returns. After that point,
|
||||||
returns. After that point, set_committed(true)
|
set_committed(true) would be invoked in
|
||||||
would be invoked in commit_inplace_alter_table(). */
|
commit_inplace_alter_table(). */
|
||||||
ut_a(update->n_fields == 0);
|
ut_a(update->n_fields == 0);
|
||||||
ut_a(!cursor->index()->is_committed());
|
|
||||||
ut_ad(!dict_index_is_online_ddl(cursor->index()));
|
ut_ad(!dict_index_is_online_ddl(cursor->index()));
|
||||||
return(DB_SUCCESS);
|
return cursor->index()->is_committed()
|
||||||
|
? DB_CORRUPTION : DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == BTR_MODIFY_LEAF) {
|
if (mode == BTR_MODIFY_LEAF) {
|
||||||
|
@@ -615,6 +615,8 @@ row_purge_del_mark(
|
|||||||
const auto type= node->index->type;
|
const auto type= node->index->type;
|
||||||
if (type & (DICT_FTS | DICT_CORRUPT))
|
if (type & (DICT_FTS | DICT_CORRUPT))
|
||||||
continue;
|
continue;
|
||||||
|
if (node->index->online_status > ONLINE_INDEX_CREATION)
|
||||||
|
continue;
|
||||||
if (UNIV_UNLIKELY(DICT_VIRTUAL & type) && !node->index->is_committed() &&
|
if (UNIV_UNLIKELY(DICT_VIRTUAL & type) && !node->index->is_committed() &&
|
||||||
node->index->has_new_v_col())
|
node->index->has_new_v_col())
|
||||||
continue;
|
continue;
|
||||||
@@ -767,6 +769,11 @@ row_purge_upd_exist_or_extern_func(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->index->online_status
|
||||||
|
> ONLINE_INDEX_CREATION) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (row_upd_changes_ord_field_binary(node->index, node->update,
|
if (row_upd_changes_ord_field_binary(node->index, node->update,
|
||||||
thr, NULL, NULL)) {
|
thr, NULL, NULL)) {
|
||||||
/* Build the older version of the index entry */
|
/* Build the older version of the index entry */
|
||||||
|
@@ -246,127 +246,121 @@ Remove the undo log segment from the rseg slot if it is too big for reuse.
|
|||||||
void
|
void
|
||||||
trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|
trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("trx", ("commit(" TRX_ID_FMT "," TRX_ID_FMT ")",
|
DBUG_PRINT("trx", ("commit(" TRX_ID_FMT "," TRX_ID_FMT ")",
|
||||||
trx->id, trx_id_t{trx->rw_trx_hash_element->no}));
|
trx->id, trx_id_t{trx->rw_trx_hash_element->no}));
|
||||||
ut_ad(undo == trx->rsegs.m_redo.undo);
|
ut_ad(undo->id < TRX_RSEG_N_SLOTS);
|
||||||
trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
|
ut_ad(undo == trx->rsegs.m_redo.undo);
|
||||||
ut_ad(undo->rseg == rseg);
|
trx_rseg_t *rseg= trx->rsegs.m_redo.rseg;
|
||||||
buf_block_t* rseg_header = rseg->get(mtr, nullptr);
|
ut_ad(undo->rseg == rseg);
|
||||||
/* We are in transaction commit; we cannot return an error. If the
|
buf_block_t *rseg_header= rseg->get(mtr, nullptr);
|
||||||
database is corrupted, it is better to crash it than to
|
/* We are in transaction commit; we cannot return an error. If the
|
||||||
intentionally violate ACID by committing something that is known to
|
database is corrupted, it is better to crash it than to
|
||||||
be corrupted. */
|
intentionally violate ACID by committing something that is known to
|
||||||
ut_ad(rseg_header);
|
be corrupted. */
|
||||||
buf_block_t* undo_page = trx_undo_set_state_at_finish(
|
ut_ad(rseg_header);
|
||||||
undo, mtr);
|
buf_block_t *undo_page=
|
||||||
trx_ulogf_t* undo_header = undo_page->page.frame
|
buf_page_get(page_id_t(rseg->space->id, undo->hdr_page_no), 0,
|
||||||
+ undo->hdr_offset;
|
RW_X_LATCH, mtr);
|
||||||
|
/* This function is invoked during transaction commit, which is not
|
||||||
|
allowed to fail. If we get a corrupted undo header, we will crash here. */
|
||||||
|
ut_a(undo_page);
|
||||||
|
trx_ulogf_t *undo_header= undo_page->page.frame + undo->hdr_offset;
|
||||||
|
|
||||||
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
|
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
|
||||||
ut_ad(rseg->needs_purge > trx->id);
|
ut_ad(rseg->needs_purge > trx->id);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
|
if (rseg->last_page_no == FIL_NULL)
|
||||||
+ rseg_header->page.frame))) {
|
{
|
||||||
/* This database must have been upgraded from
|
rseg->last_page_no= undo->hdr_page_no;
|
||||||
before MariaDB 10.3.5. */
|
rseg->set_last_commit(undo->hdr_offset, trx->rw_trx_hash_element->no);
|
||||||
trx_rseg_format_upgrade(rseg_header, mtr);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (undo->state != TRX_UNDO_CACHED) {
|
rseg->history_size++;
|
||||||
/* The undo log segment will not be reused */
|
|
||||||
ut_a(undo->id < TRX_RSEG_N_SLOTS);
|
|
||||||
static_assert(FIL_NULL == 0xffffffff, "");
|
|
||||||
mtr->memset(rseg_header,
|
|
||||||
TRX_RSEG + TRX_RSEG_UNDO_SLOTS
|
|
||||||
+ undo->id * TRX_RSEG_SLOT_SIZE, 4, 0xff);
|
|
||||||
|
|
||||||
uint32_t hist_size = mach_read_from_4(
|
if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT +
|
||||||
TRX_RSEG_HISTORY_SIZE + TRX_RSEG
|
rseg_header->page.frame)))
|
||||||
+ rseg_header->page.frame);
|
/* This database must have been upgraded from before MariaDB 10.3.5. */
|
||||||
|
trx_rseg_format_upgrade(rseg_header, mtr);
|
||||||
|
|
||||||
ut_ad(undo->size == flst_get_len(TRX_UNDO_SEG_HDR
|
uint16_t undo_state;
|
||||||
+ TRX_UNDO_PAGE_LIST
|
|
||||||
+ undo_page->page.frame));
|
|
||||||
|
|
||||||
mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_HISTORY_SIZE
|
if (undo->size == 1 &&
|
||||||
+ rseg_header->page.frame,
|
TRX_UNDO_PAGE_REUSE_LIMIT >
|
||||||
hist_size + undo->size);
|
mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
|
||||||
mtr->write<8>(*rseg_header, TRX_RSEG + TRX_RSEG_MAX_TRX_ID
|
undo_page->page.frame))
|
||||||
+ rseg_header->page.frame,
|
{
|
||||||
trx_sys.get_max_trx_id());
|
undo->state= undo_state= TRX_UNDO_CACHED;
|
||||||
}
|
UT_LIST_ADD_FIRST(rseg->undo_cached, undo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ut_ad(undo->size == flst_get_len(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST +
|
||||||
|
undo_page->page.frame));
|
||||||
|
/* The undo log segment will not be reused */
|
||||||
|
static_assert(FIL_NULL == 0xffffffff, "");
|
||||||
|
mtr->memset(rseg_header, TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
|
||||||
|
undo->id * TRX_RSEG_SLOT_SIZE, 4, 0xff);
|
||||||
|
uint32_t hist_size= mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG +
|
||||||
|
rseg_header->page.frame);
|
||||||
|
mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_HISTORY_SIZE +
|
||||||
|
rseg_header->page.frame, hist_size + undo->size);
|
||||||
|
mtr->write<8>(*rseg_header, TRX_RSEG + TRX_RSEG_MAX_TRX_ID +
|
||||||
|
rseg_header->page.frame, trx_sys.get_max_trx_id());
|
||||||
|
ut_free(undo);
|
||||||
|
undo_state= TRX_UNDO_TO_PURGE;
|
||||||
|
}
|
||||||
|
|
||||||
/* After the purge thread has been given permission to exit,
|
undo= nullptr;
|
||||||
we may roll back transactions (trx->undo_no==0)
|
|
||||||
in THD::cleanup() invoked from unlink_thd() in fast shutdown,
|
|
||||||
or in trx_rollback_recovered() in slow shutdown.
|
|
||||||
|
|
||||||
Before any transaction-generating background threads or the
|
/* After the purge thread has been given permission to exit,
|
||||||
purge have been started, we can
|
we may roll back transactions (trx->undo_no==0)
|
||||||
start transactions in row_merge_drop_temp_indexes(),
|
in THD::cleanup() invoked from unlink_thd() in fast shutdown,
|
||||||
and roll back recovered transactions.
|
or in trx_rollback_recovered() in slow shutdown.
|
||||||
|
|
||||||
Arbitrary user transactions may be executed when all the undo log
|
Before any transaction-generating background threads or the purge
|
||||||
related background processes (including purge) are disabled due to
|
have been started, we can start transactions in
|
||||||
innodb_force_recovery=2 or innodb_force_recovery=3.
|
row_merge_drop_temp_indexes(), and roll back recovered transactions.
|
||||||
DROP TABLE may be executed at any innodb_force_recovery level.
|
|
||||||
|
|
||||||
During fast shutdown, we may also continue to execute
|
Arbitrary user transactions may be executed when all the undo log
|
||||||
user transactions. */
|
related background processes (including purge) are disabled due to
|
||||||
ut_ad(srv_undo_sources
|
innodb_force_recovery=2 or innodb_force_recovery=3. DROP TABLE may
|
||||||
|| trx->undo_no == 0
|
be executed at any innodb_force_recovery level.
|
||||||
|| (!purge_sys.enabled()
|
|
||||||
&& (srv_is_being_started
|
|
||||||
|| trx_rollback_is_active
|
|
||||||
|| srv_force_recovery >= SRV_FORCE_NO_BACKGROUND))
|
|
||||||
|| srv_fast_shutdown);
|
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
During fast shutdown, we may also continue to execute user
|
||||||
if (wsrep_is_wsrep_xid(&trx->xid)) {
|
transactions. */
|
||||||
trx_rseg_update_wsrep_checkpoint(rseg_header, &trx->xid, mtr);
|
ut_ad(srv_undo_sources || trx->undo_no == 0 ||
|
||||||
}
|
(!purge_sys.enabled() &&
|
||||||
|
(srv_is_being_started ||
|
||||||
|
trx_rollback_is_active ||
|
||||||
|
srv_force_recovery >= SRV_FORCE_NO_BACKGROUND)) ||
|
||||||
|
srv_fast_shutdown);
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
if (wsrep_is_wsrep_xid(&trx->xid))
|
||||||
|
trx_rseg_update_wsrep_checkpoint(rseg_header, &trx->xid, mtr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (trx->mysql_log_file_name && *trx->mysql_log_file_name) {
|
if (trx->mysql_log_file_name && *trx->mysql_log_file_name)
|
||||||
/* Update the latest MySQL binlog name and offset info
|
/* Update the latest binlog name and offset if log_bin=ON or this
|
||||||
in rollback segment header if MySQL binlogging is on
|
is a replica. */
|
||||||
or the database server is a MySQL replication save. */
|
trx_rseg_update_binlog_offset(rseg_header, trx, mtr);
|
||||||
trx_rseg_update_binlog_offset(rseg_header, trx, mtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the log as the first in the history list */
|
/* Add the log as the first in the history list */
|
||||||
|
|
||||||
/* We are in transaction commit; we cannot return an error
|
/* We are in transaction commit; we cannot return an error
|
||||||
when detecting corruption. It is better to crash the server
|
when detecting corruption. It is better to crash the server
|
||||||
than to intentionally violate ACID by committing something
|
than to intentionally violate ACID by committing something
|
||||||
that is known to be corrupted. */
|
that is known to be corrupted. */
|
||||||
ut_a(flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY, undo_page,
|
ut_a(flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY, undo_page,
|
||||||
static_cast<uint16_t>(undo->hdr_offset
|
uint16_t(page_offset(undo_header) +
|
||||||
+ TRX_UNDO_HISTORY_NODE),
|
TRX_UNDO_HISTORY_NODE), mtr) == DB_SUCCESS);
|
||||||
mtr) == DB_SUCCESS);
|
|
||||||
|
|
||||||
mtr->write<8,mtr_t::MAYBE_NOP>(*undo_page,
|
mtr->write<2>(*undo_page, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE +
|
||||||
undo_header + TRX_UNDO_TRX_NO,
|
undo_page->page.frame, undo_state);
|
||||||
trx->rw_trx_hash_element->no);
|
mtr->write<8,mtr_t::MAYBE_NOP>(*undo_page, undo_header + TRX_UNDO_TRX_NO,
|
||||||
mtr->write<2,mtr_t::MAYBE_NOP>(*undo_page, undo_header
|
trx->rw_trx_hash_element->no);
|
||||||
+ TRX_UNDO_NEEDS_PURGE, 1U);
|
mtr->write<2,mtr_t::MAYBE_NOP>(*undo_page, undo_header +
|
||||||
|
TRX_UNDO_NEEDS_PURGE, 1U);
|
||||||
if (rseg->last_page_no == FIL_NULL) {
|
|
||||||
rseg->last_page_no = undo->hdr_page_no;
|
|
||||||
rseg->set_last_commit(undo->hdr_offset,
|
|
||||||
trx->rw_trx_hash_element->no);
|
|
||||||
}
|
|
||||||
|
|
||||||
rseg->history_size++;
|
|
||||||
|
|
||||||
if (undo->state == TRX_UNDO_CACHED) {
|
|
||||||
UT_LIST_ADD_FIRST(rseg->undo_cached, undo);
|
|
||||||
} else {
|
|
||||||
ut_ad(undo->state == TRX_UNDO_TO_PURGE);
|
|
||||||
ut_free(undo);
|
|
||||||
}
|
|
||||||
|
|
||||||
undo = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Free an undo log segment.
|
/** Free an undo log segment.
|
||||||
@@ -685,6 +679,7 @@ not_free:
|
|||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
mtr.start();
|
mtr.start();
|
||||||
mtr.x_lock_space(&space);
|
mtr.x_lock_space(&space);
|
||||||
|
const auto space_id= space.id;
|
||||||
|
|
||||||
/* Lock all modified pages of the tablespace.
|
/* Lock all modified pages of the tablespace.
|
||||||
|
|
||||||
@@ -694,8 +689,8 @@ not_free:
|
|||||||
mini-transaction commit and the server was killed, then
|
mini-transaction commit and the server was killed, then
|
||||||
discarding the to-be-trimmed pages without flushing would
|
discarding the to-be-trimmed pages without flushing would
|
||||||
break crash recovery. */
|
break crash recovery. */
|
||||||
|
rescan:
|
||||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||||
|
|
||||||
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
|
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
|
||||||
{
|
{
|
||||||
ut_ad(bpage->oldest_modification());
|
ut_ad(bpage->oldest_modification());
|
||||||
@@ -703,46 +698,47 @@ not_free:
|
|||||||
|
|
||||||
buf_page_t *prev= UT_LIST_GET_PREV(list, bpage);
|
buf_page_t *prev= UT_LIST_GET_PREV(list, bpage);
|
||||||
|
|
||||||
if (bpage->id().space() == space.id &&
|
if (bpage->oldest_modification() > 2 && bpage->id().space() == space_id)
|
||||||
bpage->oldest_modification() != 1)
|
|
||||||
{
|
{
|
||||||
ut_ad(bpage->frame);
|
ut_ad(bpage->frame);
|
||||||
auto block= reinterpret_cast<buf_block_t*>(bpage);
|
bpage->fix();
|
||||||
if (!bpage->lock.x_lock_try())
|
|
||||||
{
|
{
|
||||||
rescan:
|
/* Try to acquire an exclusive latch while the cache line is
|
||||||
/* Let buf_pool_t::release_freed_page() proceed. */
|
fresh after fix(). */
|
||||||
|
const bool got_lock{bpage->lock.x_lock_try()};
|
||||||
|
buf_pool.flush_hp.set(prev);
|
||||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||||
mysql_mutex_lock(&buf_pool.mutex);
|
if (!got_lock)
|
||||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
bpage->lock.x_lock();
|
||||||
mysql_mutex_unlock(&buf_pool.mutex);
|
|
||||||
bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
buf_pool.flush_hp.set(prev);
|
|
||||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
|
||||||
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
ut_ad(!block->index); /* There is no AHI on undo tablespaces. */
|
/* There is no AHI on undo tablespaces. */
|
||||||
|
ut_ad(!reinterpret_cast<buf_block_t*>(bpage)->index);
|
||||||
#endif
|
#endif
|
||||||
bpage->fix();
|
|
||||||
ut_ad(!bpage->is_io_fixed());
|
ut_ad(!bpage->is_io_fixed());
|
||||||
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
ut_ad(bpage->id().space() == space_id);
|
||||||
|
|
||||||
if (bpage->oldest_modification() > 1)
|
if (bpage->oldest_modification() > 2)
|
||||||
{
|
{
|
||||||
|
mtr.memo_push(reinterpret_cast<buf_block_t*>(bpage),
|
||||||
|
MTR_MEMO_PAGE_X_FIX);
|
||||||
|
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||||
|
ut_ad(bpage->oldest_modification() > 2);
|
||||||
bpage->reset_oldest_modification();
|
bpage->reset_oldest_modification();
|
||||||
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bpage->unfix();
|
bpage->unfix();
|
||||||
bpage->lock.x_unlock();
|
bpage->lock.x_unlock();
|
||||||
|
mysql_mutex_lock(&buf_pool.flush_list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev != buf_pool.flush_hp.get())
|
if (prev != buf_pool.flush_hp.get())
|
||||||
/* Rescan, because we may have lost the position. */
|
{
|
||||||
|
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||||
goto rescan;
|
goto rescan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bpage= prev;
|
bpage= prev;
|
||||||
|
@@ -1463,37 +1463,6 @@ template buf_block_t*
|
|||||||
trx_undo_assign_low<true>(trx_t *trx, trx_rseg_t *rseg, trx_undo_t **undo,
|
trx_undo_assign_low<true>(trx_t *trx, trx_rseg_t *rseg, trx_undo_t **undo,
|
||||||
mtr_t *mtr, dberr_t *err);
|
mtr_t *mtr, dberr_t *err);
|
||||||
|
|
||||||
/******************************************************************//**
|
|
||||||
Sets the state of the undo log segment at a transaction finish.
|
|
||||||
@return undo log segment header page, x-latched */
|
|
||||||
buf_block_t*
|
|
||||||
trx_undo_set_state_at_finish(
|
|
||||||
/*=========================*/
|
|
||||||
trx_undo_t* undo, /*!< in: undo log memory copy */
|
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
|
||||||
{
|
|
||||||
ut_ad(undo->id < TRX_RSEG_N_SLOTS);
|
|
||||||
ut_ad(undo->rseg->is_persistent());
|
|
||||||
|
|
||||||
buf_block_t *block=
|
|
||||||
buf_page_get(page_id_t(undo->rseg->space->id, undo->hdr_page_no), 0,
|
|
||||||
RW_X_LATCH, mtr);
|
|
||||||
/* This function is invoked during transaction commit, which is not
|
|
||||||
allowed to fail. If we get a corrupted undo header, we will crash here. */
|
|
||||||
ut_a(block);
|
|
||||||
const uint16_t state = undo->size == 1 &&
|
|
||||||
TRX_UNDO_PAGE_REUSE_LIMIT >
|
|
||||||
mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
|
|
||||||
block->page.frame)
|
|
||||||
? TRX_UNDO_CACHED
|
|
||||||
: TRX_UNDO_TO_PURGE;
|
|
||||||
|
|
||||||
undo->state= state;
|
|
||||||
mtr->write<2>(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + block->page.frame,
|
|
||||||
state);
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK.
|
/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK.
|
||||||
@param[in,out] trx transaction
|
@param[in,out] trx transaction
|
||||||
@param[in,out] undo undo log
|
@param[in,out] undo undo log
|
||||||
|
Reference in New Issue
Block a user