mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
MDEV-15528 Punch holes when pages are freed
The following parameters are deprecated: innodb-background-scrub-data-uncompressed innodb-background-scrub-data-compressed innodb-background-scrub-data-interval innodb-background-scrub-data-check-interval Removed scrubbing code completely(btr0scrub.h, btr0scrub.cc) Removed information_schema.innodb_tablespaces_scrubbing tables Removed the scrubbing logic from fil_crypt_thread()
This commit is contained in:
parent
a35b4ae898
commit
a5584b13d1
26 changed files with 160 additions and 1823 deletions
|
@ -39,7 +39,6 @@ INNODB_SYS_TABLES
|
|||
INNODB_SYS_TABLESTATS
|
||||
INNODB_SYS_VIRTUAL
|
||||
INNODB_TABLESPACES_ENCRYPTION
|
||||
INNODB_TABLESPACES_SCRUBBING
|
||||
INNODB_TRX
|
||||
KEY_CACHES
|
||||
KEY_COLUMN_USAGE
|
||||
|
@ -120,7 +119,6 @@ INNODB_SYS_TABLES TABLE_ID
|
|||
INNODB_SYS_TABLESTATS TABLE_ID
|
||||
INNODB_SYS_VIRTUAL TABLE_ID
|
||||
INNODB_TABLESPACES_ENCRYPTION SPACE
|
||||
INNODB_TABLESPACES_SCRUBBING SPACE
|
||||
INNODB_TRX trx_id
|
||||
KEY_CACHES KEY_CACHE_NAME
|
||||
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
|
||||
|
@ -201,7 +199,6 @@ INNODB_SYS_TABLES TABLE_ID
|
|||
INNODB_SYS_TABLESTATS TABLE_ID
|
||||
INNODB_SYS_VIRTUAL TABLE_ID
|
||||
INNODB_TABLESPACES_ENCRYPTION SPACE
|
||||
INNODB_TABLESPACES_SCRUBBING SPACE
|
||||
INNODB_TRX trx_id
|
||||
KEY_CACHES KEY_CACHE_NAME
|
||||
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
|
||||
|
@ -287,7 +284,6 @@ INNODB_SYS_TABLES information_schema.INNODB_SYS_TABLES 1
|
|||
INNODB_SYS_TABLESTATS information_schema.INNODB_SYS_TABLESTATS 1
|
||||
INNODB_SYS_VIRTUAL information_schema.INNODB_SYS_VIRTUAL 1
|
||||
INNODB_TABLESPACES_ENCRYPTION information_schema.INNODB_TABLESPACES_ENCRYPTION 1
|
||||
INNODB_TABLESPACES_SCRUBBING information_schema.INNODB_TABLESPACES_SCRUBBING 1
|
||||
INNODB_TRX information_schema.INNODB_TRX 1
|
||||
KEY_CACHES information_schema.KEY_CACHES 1
|
||||
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
|
||||
|
@ -358,7 +354,6 @@ Database: information_schema
|
|||
| INNODB_SYS_TABLESTATS |
|
||||
| INNODB_SYS_VIRTUAL |
|
||||
| INNODB_TABLESPACES_ENCRYPTION |
|
||||
| INNODB_TABLESPACES_SCRUBBING |
|
||||
| INNODB_TRX |
|
||||
| KEY_CACHES |
|
||||
| KEY_COLUMN_USAGE |
|
||||
|
@ -429,7 +424,6 @@ Database: INFORMATION_SCHEMA
|
|||
| INNODB_SYS_TABLESTATS |
|
||||
| INNODB_SYS_VIRTUAL |
|
||||
| INNODB_TABLESPACES_ENCRYPTION |
|
||||
| INNODB_TABLESPACES_SCRUBBING |
|
||||
| INNODB_TRX |
|
||||
| KEY_CACHES |
|
||||
| KEY_COLUMN_USAGE |
|
||||
|
@ -465,5 +459,5 @@ Wildcard: inf_rmation_schema
|
|||
| information_schema |
|
||||
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
|
||||
table_schema count(*)
|
||||
information_schema 66
|
||||
information_schema 65
|
||||
mysql 31
|
||||
|
|
|
@ -66,8 +66,6 @@ create sql security invoker view i_sys_virtual as select * from information_sche
|
|||
create sql security definer view d_sys_virtual as select * from information_schema.innodb_sys_virtual;
|
||||
create sql security invoker view i_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
|
||||
create sql security definer view d_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
|
||||
create sql security invoker view i_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
|
||||
create sql security definer view d_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
|
||||
create sql security invoker view i_trx as select * from information_schema.innodb_trx;
|
||||
create sql security definer view d_trx as select * from information_schema.innodb_trx;
|
||||
connection select_only;
|
||||
|
@ -284,13 +282,6 @@ ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) fo
|
|||
select count(*) > -1 from d_tablespaces_encryption;
|
||||
count(*) > -1
|
||||
1
|
||||
select count(*) > -1 from information_schema.innodb_tablespaces_scrubbing;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
|
||||
select count(*) > -1 from i_tablespaces_scrubbing;
|
||||
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
|
||||
select count(*) > -1 from d_tablespaces_scrubbing;
|
||||
count(*) > -1
|
||||
1
|
||||
select count(*) > -1 from information_schema.innodb_trx;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
select count(*) > -1 from i_trx;
|
||||
|
|
|
@ -393,10 +393,6 @@ select * from information_schema.innodb_tablespaces_encryption;
|
|||
SPACE NAME ENCRYPTION_SCHEME KEYSERVER_REQUESTS MIN_KEY_VERSION CURRENT_KEY_VERSION KEY_ROTATION_PAGE_NUMBER KEY_ROTATION_MAX_PAGE_NUMBER CURRENT_KEY_ID ROTATING_OR_FLUSHING
|
||||
Warnings:
|
||||
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_tablespaces_encryption but the InnoDB storage engine is not installed
|
||||
select * from information_schema.innodb_tablespaces_scrubbing;
|
||||
SPACE NAME COMPRESSED LAST_SCRUB_COMPLETED CURRENT_SCRUB_STARTED CURRENT_SCRUB_ACTIVE_THREADS CURRENT_SCRUB_PAGE_NUMBER CURRENT_SCRUB_MAX_PAGE_NUMBER ON_SSD
|
||||
Warnings:
|
||||
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_tablespaces_scrubbing but the InnoDB storage engine is not installed
|
||||
select * from information_schema.innodb_mutexes;
|
||||
NAME CREATE_FILE CREATE_LINE OS_WAITS
|
||||
Warnings:
|
||||
|
|
|
@ -30,4 +30,3 @@
|
|||
--enable-plugin-innodb-mutexes
|
||||
--enable-plugin-innodb-sys-semaphore-waits
|
||||
--enable-plugin-innodb-tablespaces-encryption
|
||||
--enable-plugin-innodb-tablespaces-scrubbing
|
||||
|
|
|
@ -103,9 +103,6 @@ create sql security definer view d_sys_virtual as select * from information_sche
|
|||
create sql security invoker view i_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
|
||||
create sql security definer view d_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
|
||||
|
||||
create sql security invoker view i_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
|
||||
create sql security definer view d_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
|
||||
|
||||
create sql security invoker view i_trx as select * from information_schema.innodb_trx;
|
||||
create sql security definer view d_trx as select * from information_schema.innodb_trx;
|
||||
|
||||
|
@ -293,12 +290,6 @@ select count(*) > -1 from information_schema.innodb_tablespaces_encryption;
|
|||
select count(*) > -1 from i_tablespaces_encryption;
|
||||
select count(*) > -1 from d_tablespaces_encryption;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
select count(*) > -1 from information_schema.innodb_tablespaces_scrubbing;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
select count(*) > -1 from i_tablespaces_scrubbing;
|
||||
select count(*) > -1 from d_tablespaces_scrubbing;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
select count(*) > -1 from information_schema.innodb_trx;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
|
|
|
@ -32,6 +32,5 @@ select * from information_schema.innodb_sys_datafiles;
|
|||
--error 0,1109
|
||||
select * from information_schema.innodb_changed_pages;
|
||||
select * from information_schema.innodb_tablespaces_encryption;
|
||||
select * from information_schema.innodb_tablespaces_scrubbing;
|
||||
select * from information_schema.innodb_mutexes;
|
||||
select * from information_schema.innodb_sys_semaphore_waits;
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
--innodb_tablespaces_scrubbing
|
|
@ -1,13 +0,0 @@
|
|||
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING;
|
||||
Table Create Table
|
||||
INNODB_TABLESPACES_SCRUBBING CREATE TEMPORARY TABLE `INNODB_TABLESPACES_SCRUBBING` (
|
||||
`SPACE` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`NAME` varchar(655) DEFAULT NULL,
|
||||
`COMPRESSED` int(1) unsigned NOT NULL DEFAULT 0,
|
||||
`LAST_SCRUB_COMPLETED` datetime DEFAULT NULL,
|
||||
`CURRENT_SCRUB_STARTED` datetime DEFAULT NULL,
|
||||
`CURRENT_SCRUB_ACTIVE_THREADS` int(11) unsigned DEFAULT NULL,
|
||||
`CURRENT_SCRUB_PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`CURRENT_SCRUB_MAX_PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`ON_SSD` int(1) unsigned NOT NULL DEFAULT 0
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8
|
|
@ -1,3 +0,0 @@
|
|||
--source include/have_innodb.inc
|
||||
|
||||
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING;
|
|
@ -4,60 +4,74 @@ SET @start_global_value = @@global.innodb_background_scrub_data_check_interval;
|
|||
#
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
3600
|
||||
0
|
||||
set global innodb_background_scrub_data_check_interval=10;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
10
|
||||
0
|
||||
set global innodb_background_scrub_data_check_interval=DEFAULT;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
3600
|
||||
0
|
||||
set global innodb_background_scrub_data_check_interval=20;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
20
|
||||
0
|
||||
set global innodb_background_scrub_data_check_interval=DEFAULT;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
3600
|
||||
0
|
||||
#
|
||||
# exists as global only
|
||||
#
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
3600
|
||||
0
|
||||
select @@session.innodb_background_scrub_data_check_interval;
|
||||
ERROR HY000: Variable 'innodb_background_scrub_data_check_interval' is a GLOBAL variable
|
||||
show global variables like 'innodb_background_scrub_data_check_interval';
|
||||
Variable_name Value
|
||||
innodb_background_scrub_data_check_interval 3600
|
||||
innodb_background_scrub_data_check_interval 0
|
||||
show session variables like 'innodb_background_scrub_data_check_interval';
|
||||
Variable_name Value
|
||||
innodb_background_scrub_data_check_interval 3600
|
||||
innodb_background_scrub_data_check_interval 0
|
||||
select * from information_schema.global_variables
|
||||
where variable_name='innodb_background_scrub_data_check_interval';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 3600
|
||||
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 0
|
||||
select * from information_schema.session_variables
|
||||
where variable_name='innodb_background_scrub_data_check_interval';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 3600
|
||||
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 0
|
||||
#
|
||||
# show that it's writable
|
||||
#
|
||||
set global innodb_background_scrub_data_check_interval=10;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
10
|
||||
0
|
||||
set global innodb_background_scrub_data_check_interval=20;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
20
|
||||
0
|
||||
set global innodb_background_scrub_data_check_interval=1;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_check_interval;
|
||||
@@global.innodb_background_scrub_data_check_interval
|
||||
1
|
||||
0
|
||||
set session innodb_background_scrub_data_check_interval=1;
|
||||
ERROR HY000: Variable 'innodb_background_scrub_data_check_interval' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
#
|
||||
|
@ -70,3 +84,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_c
|
|||
set global innodb_background_scrub_data_check_interval="foo";
|
||||
ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_check_interval'
|
||||
SET @@global.innodb_background_scrub_data_check_interval = @start_global_value;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
|
||||
|
|
|
@ -25,17 +25,23 @@ INNODB_BACKGROUND_SCRUB_DATA_COMPRESSED OFF
|
|||
# show that it's writable
|
||||
#
|
||||
set global innodb_background_scrub_data_compressed=ON;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_compressed;
|
||||
@@global.innodb_background_scrub_data_compressed
|
||||
1
|
||||
0
|
||||
set global innodb_background_scrub_data_compressed=OFF;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_compressed;
|
||||
@@global.innodb_background_scrub_data_compressed
|
||||
0
|
||||
set global innodb_background_scrub_data_compressed=1;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_compressed;
|
||||
@@global.innodb_background_scrub_data_compressed
|
||||
1
|
||||
0
|
||||
set session innodb_background_scrub_data_compressed=1;
|
||||
ERROR HY000: Variable 'innodb_background_scrub_data_compressed' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
#
|
||||
|
@ -48,3 +54,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_c
|
|||
set global innodb_background_scrub_data_compressed="foo";
|
||||
ERROR 42000: Variable 'innodb_background_scrub_data_compressed' can't be set to the value of 'foo'
|
||||
SET @@global.innodb_background_scrub_data_compressed = @start_global_value;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
|
||||
|
|
|
@ -4,38 +4,44 @@ SET @start_global_value = @@global.innodb_background_scrub_data_interval;
|
|||
#
|
||||
select @@global.innodb_background_scrub_data_interval;
|
||||
@@global.innodb_background_scrub_data_interval
|
||||
604800
|
||||
0
|
||||
select @@session.innodb_background_scrub_data_interval;
|
||||
ERROR HY000: Variable 'innodb_background_scrub_data_interval' is a GLOBAL variable
|
||||
show global variables like 'innodb_background_scrub_data_interval';
|
||||
Variable_name Value
|
||||
innodb_background_scrub_data_interval 604800
|
||||
innodb_background_scrub_data_interval 0
|
||||
show session variables like 'innodb_background_scrub_data_interval';
|
||||
Variable_name Value
|
||||
innodb_background_scrub_data_interval 604800
|
||||
innodb_background_scrub_data_interval 0
|
||||
select * from information_schema.global_variables
|
||||
where variable_name='innodb_background_scrub_data_interval';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 604800
|
||||
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 0
|
||||
select * from information_schema.session_variables
|
||||
where variable_name='innodb_background_scrub_data_interval';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 604800
|
||||
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 0
|
||||
#
|
||||
# show that it's writable
|
||||
#
|
||||
set global innodb_background_scrub_data_interval=100;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_interval;
|
||||
@@global.innodb_background_scrub_data_interval
|
||||
100
|
||||
0
|
||||
set global innodb_background_scrub_data_interval=200;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_interval;
|
||||
@@global.innodb_background_scrub_data_interval
|
||||
200
|
||||
0
|
||||
set global innodb_background_scrub_data_interval=300;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_interval;
|
||||
@@global.innodb_background_scrub_data_interval
|
||||
300
|
||||
0
|
||||
set session innodb_background_scrub_data_interval=400;
|
||||
ERROR HY000: Variable 'innodb_background_scrub_data_interval' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
#
|
||||
|
@ -48,3 +54,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_i
|
|||
set global innodb_background_scrub_data_interval="foo";
|
||||
ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_interval'
|
||||
SET @@global.innodb_background_scrub_data_interval = @start_global_value;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
|
||||
|
|
|
@ -25,17 +25,23 @@ INNODB_BACKGROUND_SCRUB_DATA_UNCOMPRESSED OFF
|
|||
# show that it's writable
|
||||
#
|
||||
set global innodb_background_scrub_data_uncompressed=ON;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_uncompressed;
|
||||
@@global.innodb_background_scrub_data_uncompressed
|
||||
1
|
||||
0
|
||||
set global innodb_background_scrub_data_uncompressed=OFF;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_uncompressed;
|
||||
@@global.innodb_background_scrub_data_uncompressed
|
||||
0
|
||||
set global innodb_background_scrub_data_uncompressed=1;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
|
||||
select @@global.innodb_background_scrub_data_uncompressed;
|
||||
@@global.innodb_background_scrub_data_uncompressed
|
||||
1
|
||||
0
|
||||
set session innodb_background_scrub_data_uncompressed=1;
|
||||
ERROR HY000: Variable 'innodb_background_scrub_data_uncompressed' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
#
|
||||
|
@ -48,3 +54,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_u
|
|||
set global innodb_background_scrub_data_uncompressed="foo";
|
||||
ERROR 42000: Variable 'innodb_background_scrub_data_uncompressed' can't be set to the value of 'foo'
|
||||
SET @@global.innodb_background_scrub_data_uncompressed = @start_global_value;
|
||||
Warnings:
|
||||
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
SET @start_global_value = @@global.innodb_debug_force_scrubbing;
|
||||
#
|
||||
# exists as global only
|
||||
#
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
@@global.innodb_debug_force_scrubbing
|
||||
0
|
||||
select @@session.innodb_debug_force_scrubbing;
|
||||
ERROR HY000: Variable 'innodb_debug_force_scrubbing' is a GLOBAL variable
|
||||
show global variables like 'innodb_debug_force_scrubbing';
|
||||
Variable_name Value
|
||||
innodb_debug_force_scrubbing OFF
|
||||
show session variables like 'innodb_debug_force_scrubbing';
|
||||
Variable_name Value
|
||||
innodb_debug_force_scrubbing OFF
|
||||
select * from information_schema.global_variables
|
||||
where variable_name='innodb_debug_force_scrubbing';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_DEBUG_FORCE_SCRUBBING OFF
|
||||
select * from information_schema.session_variables
|
||||
where variable_name='innodb_debug_force_scrubbing';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_DEBUG_FORCE_SCRUBBING OFF
|
||||
#
|
||||
# show that it's writable
|
||||
#
|
||||
set global innodb_debug_force_scrubbing=ON;
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
@@global.innodb_debug_force_scrubbing
|
||||
1
|
||||
set global innodb_debug_force_scrubbing=OFF;
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
@@global.innodb_debug_force_scrubbing
|
||||
0
|
||||
set global innodb_debug_force_scrubbing=1;
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
@@global.innodb_debug_force_scrubbing
|
||||
1
|
||||
set session innodb_debug_force_scrubbing=1;
|
||||
ERROR HY000: Variable 'innodb_debug_force_scrubbing' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
#
|
||||
# incorrect types
|
||||
#
|
||||
set global innodb_debug_force_scrubbing=1.1;
|
||||
ERROR 42000: Incorrect argument type to variable 'innodb_debug_force_scrubbing'
|
||||
set global innodb_debug_force_scrubbing=1e1;
|
||||
ERROR 42000: Incorrect argument type to variable 'innodb_debug_force_scrubbing'
|
||||
set global innodb_debug_force_scrubbing="foo";
|
||||
ERROR 42000: Variable 'innodb_debug_force_scrubbing' can't be set to the value of 'foo'
|
||||
SET @@global.innodb_debug_force_scrubbing = @start_global_value;
|
|
@ -107,12 +107,12 @@ READ_ONLY NO
|
|||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE 3600
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT check if spaces needs scrubbing every innodb_background_scrub_data_check_interval seconds
|
||||
NUMERIC_MIN_VALUE 1
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
VARIABLE_COMMENT Deprecated parameter with no effect.
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 0
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
|
@ -122,21 +122,21 @@ SESSION_VALUE NULL
|
|||
DEFAULT_VALUE OFF
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BOOLEAN
|
||||
VARIABLE_COMMENT Enable scrubbing of compressed data by background threads (same as encryption_threads)
|
||||
VARIABLE_COMMENT Deprecated parameter with no effect.
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME INNODB_BACKGROUND_SCRUB_DATA_INTERVAL
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE 604800
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT scrub spaces that were last scrubbed longer than innodb_background_scrub_data_interval seconds ago
|
||||
NUMERIC_MIN_VALUE 1
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
VARIABLE_COMMENT Deprecated parameter with no effect.
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 0
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
|
@ -146,13 +146,13 @@ SESSION_VALUE NULL
|
|||
DEFAULT_VALUE OFF
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BOOLEAN
|
||||
VARIABLE_COMMENT Enable scrubbing of uncompressed data by background threads (same as encryption_threads)
|
||||
VARIABLE_COMMENT Deprecated parameter with no effect.
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME INNODB_BUFFER_POOL_CHUNK_SIZE
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE 134217728
|
||||
|
@ -513,18 +513,6 @@ NUMERIC_BLOCK_SIZE NULL
|
|||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT NONE
|
||||
VARIABLE_NAME INNODB_DEBUG_FORCE_SCRUBBING
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE OFF
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BOOLEAN
|
||||
VARIABLE_COMMENT Perform extra scrubbing to increase test exposure
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME INNODB_DEFAULT_ENCRYPTION_KEY_ID
|
||||
SESSION_VALUE 1
|
||||
DEFAULT_VALUE 1
|
||||
|
@ -710,7 +698,7 @@ SESSION_VALUE NULL
|
|||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT Number of threads performing background key rotation and scrubbing
|
||||
VARIABLE_COMMENT Number of threads performing background key rotation
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
# bool global
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
SET @start_global_value = @@global.innodb_debug_force_scrubbing;
|
||||
|
||||
--echo #
|
||||
--echo # exists as global only
|
||||
--echo #
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
select @@session.innodb_debug_force_scrubbing;
|
||||
show global variables like 'innodb_debug_force_scrubbing';
|
||||
show session variables like 'innodb_debug_force_scrubbing';
|
||||
select * from information_schema.global_variables
|
||||
where variable_name='innodb_debug_force_scrubbing';
|
||||
select * from information_schema.session_variables
|
||||
where variable_name='innodb_debug_force_scrubbing';
|
||||
|
||||
--echo #
|
||||
--echo # show that it's writable
|
||||
--echo #
|
||||
set global innodb_debug_force_scrubbing=ON;
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
set global innodb_debug_force_scrubbing=OFF;
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
set global innodb_debug_force_scrubbing=1;
|
||||
select @@global.innodb_debug_force_scrubbing;
|
||||
--error ER_GLOBAL_VARIABLE
|
||||
set session innodb_debug_force_scrubbing=1;
|
||||
|
||||
--echo #
|
||||
--echo # incorrect types
|
||||
--echo #
|
||||
--error ER_WRONG_TYPE_FOR_VAR
|
||||
set global innodb_debug_force_scrubbing=1.1;
|
||||
--error ER_WRONG_TYPE_FOR_VAR
|
||||
set global innodb_debug_force_scrubbing=1e1;
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
set global innodb_debug_force_scrubbing="foo";
|
||||
|
||||
SET @@global.innodb_debug_force_scrubbing = @start_global_value;
|
|
@ -26,7 +26,6 @@ SET(INNOBASE_SOURCES
|
|||
btr/btr0bulk.cc
|
||||
btr/btr0cur.cc
|
||||
btr/btr0pcur.cc
|
||||
btr/btr0scrub.cc
|
||||
btr/btr0sea.cc
|
||||
btr/btr0defragment.cc
|
||||
buf/buf0buddy.cc
|
||||
|
|
|
@ -1,909 +0,0 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// Copyright (c) 2017, 2020, MariaDB Corporation.
|
||||
|
||||
/**************************************************//**
|
||||
@file btr/btr0scrub.cc
|
||||
Scrubbing of btree pages
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include "btr0btr.h"
|
||||
#include "btr0cur.h"
|
||||
#include "btr0scrub.h"
|
||||
#include "ibuf0ibuf.h"
|
||||
#include "fsp0fsp.h"
|
||||
#include "dict0dict.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
/* used when trying to acquire dict-lock */
|
||||
UNIV_INTERN bool fil_crypt_is_closing(ulint space);
|
||||
|
||||
/**
|
||||
* scrub data at delete time (e.g purge thread)
|
||||
*/
|
||||
my_bool srv_immediate_scrub_data_uncompressed = false;
|
||||
|
||||
/**
|
||||
* background scrub uncompressed data
|
||||
*
|
||||
* if srv_immediate_scrub_data_uncompressed is enabled
|
||||
* this is only needed to handle "old" data
|
||||
*/
|
||||
my_bool srv_background_scrub_data_uncompressed = false;
|
||||
|
||||
/**
|
||||
* backgrounds scrub compressed data
|
||||
*
|
||||
* reorganize compressed page for scrubbing
|
||||
* (only way to scrub compressed data)
|
||||
*/
|
||||
my_bool srv_background_scrub_data_compressed = false;
|
||||
|
||||
/* check spaces once per hour */
|
||||
UNIV_INTERN uint srv_background_scrub_data_check_interval = (60 * 60);
|
||||
|
||||
/* default to scrub spaces that hasn't been scrubbed in a week */
|
||||
UNIV_INTERN uint srv_background_scrub_data_interval = (7 * 24 * 60 * 60);
|
||||
|
||||
/**
|
||||
* statistics for scrubbing by background threads
|
||||
*/
|
||||
static btr_scrub_stat_t scrub_stat;
|
||||
static ib_mutex_t scrub_stat_mutex;
|
||||
#ifdef UNIV_PFS_MUTEX
|
||||
UNIV_INTERN mysql_pfs_key_t scrub_stat_mutex_key;
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**
|
||||
* srv_scrub_force_testing
|
||||
*
|
||||
* - force scrubbing using background threads even for uncompressed tables
|
||||
* - force pessimistic scrubbing (page split) even if not needed
|
||||
* (see test_pessimistic_scrub_pct)
|
||||
*/
|
||||
my_bool srv_scrub_force_testing = true;
|
||||
|
||||
/**
|
||||
* Force pessimistic scrubbing in 50% of the cases (UNIV_DEBUG only)
|
||||
*/
|
||||
static int test_pessimistic_scrub_pct = 50;
|
||||
|
||||
#endif
|
||||
static uint scrub_compression_level = page_zip_level;
|
||||
|
||||
/**************************************************************//**
|
||||
Log a scrubbing failure */
|
||||
static
|
||||
void
|
||||
log_scrub_failure(
|
||||
/*===============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
btr_scrub_t* scrub_data, /*!< in: data to store statistics on */
|
||||
buf_block_t* block, /*!< in: block */
|
||||
dberr_t err) /*!< in: error */
|
||||
{
|
||||
const char* reason = "unknown";
|
||||
switch(err) {
|
||||
case DB_UNDERFLOW:
|
||||
reason = "too few records on page";
|
||||
scrub_data->scrub_stat.page_split_failures_underflow++;
|
||||
break;
|
||||
case DB_INDEX_CORRUPT:
|
||||
reason = "unable to find index!";
|
||||
scrub_data->scrub_stat.page_split_failures_missing_index++;
|
||||
break;
|
||||
case DB_OUT_OF_FILE_SPACE:
|
||||
reason = "out of filespace";
|
||||
scrub_data->scrub_stat.page_split_failures_out_of_filespace++;
|
||||
break;
|
||||
default:
|
||||
ut_ad(0);
|
||||
reason = "unknown";
|
||||
scrub_data->scrub_stat.page_split_failures_unknown++;
|
||||
}
|
||||
|
||||
ib::warn() << "Failed to scrub index " << index->name
|
||||
<< " of table " << index->table->name
|
||||
<< " page " << block->page.id << ": " << reason;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Lock dict mutexes */
|
||||
static
|
||||
bool
|
||||
btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table,
|
||||
const char * file, uint line)
|
||||
{
|
||||
time_t start = time(0);
|
||||
time_t last = start;
|
||||
|
||||
/* FIXME: this is not the proper way of doing things. The
|
||||
dict_sys.mutex should not be held by any thread for longer
|
||||
than a few microseconds. It must not be held during I/O,
|
||||
for example. So, what is the purpose for this busy-waiting?
|
||||
This function should be rewritten as part of MDEV-8139:
|
||||
Fix scrubbing tests. */
|
||||
|
||||
while (mutex_enter_nowait(&dict_sys.mutex)) {
|
||||
/* if we lock to close a table, we wait forever
|
||||
* if we don't lock to close a table, we check if space
|
||||
* is closing, and then instead give up
|
||||
*/
|
||||
if (lock_to_close_table) {
|
||||
} else if (fil_space_t* space = fil_space_acquire(space_id)) {
|
||||
bool stopping = space->is_stopping();
|
||||
space->release();
|
||||
if (stopping) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
os_thread_sleep(250000);
|
||||
|
||||
time_t now = time(0);
|
||||
|
||||
if (now >= last + 30) {
|
||||
fprintf(stderr,
|
||||
"WARNING: %s:%u waited %ld seconds for"
|
||||
" dict_sys lock, space: " ULINTPF
|
||||
" lock_to_close_table: %d\n",
|
||||
file, line, long(now - start), space_id,
|
||||
lock_to_close_table);
|
||||
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(mutex_own(&dict_sys.mutex));
|
||||
return true;
|
||||
}
|
||||
|
||||
#define btr_scrub_lock_dict(space, lock_to_close_table) \
|
||||
btr_scrub_lock_dict_func(space, lock_to_close_table, __FILE__, __LINE__)
|
||||
|
||||
/****************************************************************
|
||||
Unlock dict mutexes */
|
||||
static
|
||||
void
|
||||
btr_scrub_unlock_dict()
|
||||
{
|
||||
dict_mutex_exit_for_mysql();
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Release reference to table
|
||||
*/
|
||||
static
|
||||
void
|
||||
btr_scrub_table_close(
|
||||
/*==================*/
|
||||
dict_table_t* table) /*!< in: table */
|
||||
{
|
||||
bool dict_locked = true;
|
||||
bool try_drop = false;
|
||||
table->stats_bg_flag &= ~BG_SCRUB_IN_PROGRESS;
|
||||
dict_table_close(table, dict_locked, try_drop);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Release reference to table
|
||||
*/
|
||||
static
|
||||
void
|
||||
btr_scrub_table_close_for_thread(
|
||||
btr_scrub_t *scrub_data)
|
||||
{
|
||||
if (scrub_data->current_table == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fil_space_t* space = fil_space_acquire(scrub_data->space)) {
|
||||
/* If tablespace is not marked as stopping perform
|
||||
the actual close. */
|
||||
if (!space->is_stopping()) {
|
||||
mutex_enter(&dict_sys.mutex);
|
||||
/* perform the actual closing */
|
||||
btr_scrub_table_close(scrub_data->current_table);
|
||||
mutex_exit(&dict_sys.mutex);
|
||||
}
|
||||
space->release();
|
||||
}
|
||||
|
||||
scrub_data->current_table = NULL;
|
||||
scrub_data->current_index = NULL;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Check if scrubbing is turned ON or OFF */
|
||||
static
|
||||
bool
|
||||
check_scrub_setting(
|
||||
/*=====================*/
|
||||
btr_scrub_t* scrub_data) /*!< in: scrub data */
|
||||
{
|
||||
if (scrub_data->compressed)
|
||||
return srv_background_scrub_data_compressed;
|
||||
else
|
||||
return srv_background_scrub_data_uncompressed;
|
||||
}
|
||||
|
||||
#define IBUF_INDEX_ID (DICT_IBUF_ID_MIN + IBUF_SPACE_ID)
|
||||
|
||||
/**************************************************************//**
|
||||
Check if a page needs scrubbing */
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_page_needs_scrubbing(
|
||||
/*=====================*/
|
||||
btr_scrub_t* scrub_data, /*!< in: scrub data */
|
||||
buf_block_t* block, /*!< in: block to check, latched */
|
||||
btr_scrub_page_allocation_status_t allocated) /*!< in: is block known
|
||||
to be allocated */
|
||||
{
|
||||
/**
|
||||
* Check if scrubbing has been turned OFF.
|
||||
*
|
||||
* at start of space, we check if scrubbing is ON or OFF
|
||||
* here we only check if scrubbing is turned OFF.
|
||||
*
|
||||
* Motivation is that it's only valueable to have a full table (space)
|
||||
* scrubbed.
|
||||
*/
|
||||
if (!check_scrub_setting(scrub_data)) {
|
||||
bool before_value = scrub_data->scrubbing;
|
||||
scrub_data->scrubbing = false;
|
||||
|
||||
if (before_value == true) {
|
||||
/* we toggle scrubbing from on to off */
|
||||
return BTR_SCRUB_TURNED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (scrub_data->scrubbing == false) {
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
const page_t* page = buf_block_get_frame(block);
|
||||
|
||||
if (allocated == BTR_SCRUB_PAGE_ALLOCATED) {
|
||||
if (fil_page_get_type(page) != FIL_PAGE_INDEX) {
|
||||
/* this function is called from fil-crypt-threads.
|
||||
* these threads iterate all pages of all tablespaces
|
||||
* and don't know about fil_page_type.
|
||||
* But scrubbing is only needed for index-pages. */
|
||||
|
||||
/**
|
||||
* NOTE: scrubbing is also needed for UNDO pages,
|
||||
* but they are scrubbed at purge-time, since they are
|
||||
* uncompressed
|
||||
*/
|
||||
|
||||
/* if encountering page type not needing scrubbing
|
||||
release reference to table object */
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
if (!page_has_garbage(page)) {
|
||||
/* no garbage (from deleted/shrunken records) */
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
} else if (allocated == BTR_SCRUB_PAGE_FREE ||
|
||||
allocated == BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN) {
|
||||
|
||||
switch (fil_page_get_type(page)) {
|
||||
case FIL_PAGE_INDEX:
|
||||
case FIL_PAGE_TYPE_ZBLOB:
|
||||
case FIL_PAGE_TYPE_ZBLOB2:
|
||||
break;
|
||||
default:
|
||||
/**
|
||||
* If this is a dropped page, we also need to scrub
|
||||
* BLOB pages
|
||||
*/
|
||||
|
||||
/* if encountering page type not needing scrubbing
|
||||
release reference to table object */
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (block->page.id.space() == TRX_SYS_SPACE
|
||||
&& btr_page_get_index_id(page) == IBUF_INDEX_ID) {
|
||||
/* skip ibuf */
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
return BTR_SCRUB_PAGE;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Handle a skipped page
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_skip_page(
|
||||
/*==================*/
|
||||
btr_scrub_t* scrub_data, /*!< in: data with scrub state */
|
||||
int needs_scrubbing) /*!< in: return code from
|
||||
btr_page_needs_scrubbing */
|
||||
{
|
||||
switch(needs_scrubbing) {
|
||||
case BTR_SCRUB_SKIP_PAGE:
|
||||
/* nothing todo */
|
||||
return;
|
||||
case BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE:
|
||||
btr_scrub_table_close_for_thread(scrub_data);
|
||||
return;
|
||||
case BTR_SCRUB_TURNED_OFF:
|
||||
case BTR_SCRUB_SKIP_PAGE_AND_COMPLETE_SPACE:
|
||||
btr_scrub_complete_space(scrub_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* unknown value. should not happen */
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Try to scrub a page.
|
||||
return DB_SUCCESS on success or DB_OVERFLOW on failure */
|
||||
static
|
||||
dberr_t
|
||||
btr_optimistic_scrub(
|
||||
/*==================*/
|
||||
btr_scrub_t* scrub_data, /*!< in: data with scrub state */
|
||||
buf_block_t* block, /*!< in: block to scrub */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
#ifdef UNIV_DEBUG
|
||||
if (srv_scrub_force_testing &&
|
||||
page_get_n_recs(buf_block_get_frame(block)) > 2 &&
|
||||
(rand() % 100) < test_pessimistic_scrub_pct) {
|
||||
|
||||
log_scrub_failure(index, scrub_data, block, DB_OVERFLOW);
|
||||
return DB_OVERFLOW;
|
||||
}
|
||||
#endif
|
||||
if (!btr_page_reorganize_block(scrub_compression_level, block,
|
||||
index, mtr)) {
|
||||
return DB_OVERFLOW;
|
||||
}
|
||||
|
||||
/* We play safe and reset the free bits */
|
||||
if (!dict_index_is_clust(index) &&
|
||||
block != NULL) {
|
||||
buf_frame_t* frame = buf_block_get_frame(block);
|
||||
if (frame &&
|
||||
page_is_leaf(frame)) {
|
||||
|
||||
ibuf_reset_free_bits(block);
|
||||
}
|
||||
}
|
||||
|
||||
scrub_data->scrub_stat.page_reorganizations++;
|
||||
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Try to scrub a page by splitting it
|
||||
return DB_SUCCESS on success
|
||||
DB_UNDERFLOW if page has too few records
|
||||
DB_OUT_OF_FILE_SPACE if we can't find space for split */
|
||||
static
|
||||
dberr_t
|
||||
btr_pessimistic_scrub(
|
||||
/*==================*/
|
||||
btr_scrub_t* scrub_data, /*!< in: data with scrub state */
|
||||
buf_block_t* block, /*!< in: block to scrub */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
page_t* page = buf_block_get_frame(block);
|
||||
|
||||
if (page_get_n_recs(page) < 2) {
|
||||
/**
|
||||
* There is no way we can split a page with < 2 records
|
||||
*/
|
||||
log_scrub_failure(index, scrub_data, block, DB_UNDERFLOW);
|
||||
return DB_UNDERFLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splitting page needs new space, allocate it here
|
||||
* so that splitting won't fail due to this */
|
||||
ulint n_extents = 3;
|
||||
ulint n_reserved = 0;
|
||||
if (!fsp_reserve_free_extents(&n_reserved, index->table->space,
|
||||
n_extents, FSP_NORMAL, mtr)) {
|
||||
log_scrub_failure(index, scrub_data, block,
|
||||
DB_OUT_OF_FILE_SPACE);
|
||||
return DB_OUT_OF_FILE_SPACE;
|
||||
}
|
||||
|
||||
/* read block variables */
|
||||
const uint32_t page_no = block->page.id.page_no();
|
||||
const uint32_t left_page_no = btr_page_get_prev(page);
|
||||
const uint32_t right_page_no = btr_page_get_next(page);
|
||||
|
||||
/**
|
||||
* When splitting page, we need X-latches on left/right brothers
|
||||
* see e.g btr_cur_latch_leaves
|
||||
*/
|
||||
|
||||
if (left_page_no != FIL_NULL) {
|
||||
/**
|
||||
* pages needs to be locked left-to-right, release block
|
||||
* and re-lock. We still have x-lock on index
|
||||
* so this should be safe
|
||||
*/
|
||||
mtr->release_block_at_savepoint(scrub_data->savepoint, block);
|
||||
|
||||
btr_block_get(*index, left_page_no, RW_X_LATCH,
|
||||
page_is_leaf(page), mtr);
|
||||
|
||||
/**
|
||||
* Refetch block and re-initialize page
|
||||
*/
|
||||
block = btr_block_get(*index, page_no, RW_X_LATCH,
|
||||
page_is_leaf(page), mtr);
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
/**
|
||||
* structure should be unchanged
|
||||
*/
|
||||
ut_a(left_page_no == btr_page_get_prev(page));
|
||||
ut_a(right_page_no == btr_page_get_next(page));
|
||||
}
|
||||
|
||||
if (right_page_no != FIL_NULL) {
|
||||
btr_block_get(*index, right_page_no, RW_X_LATCH,
|
||||
page_is_leaf(page), mtr);
|
||||
}
|
||||
|
||||
/* arguments to btr_page_split_and_insert */
|
||||
mem_heap_t* heap = NULL;
|
||||
dtuple_t* entry = NULL;
|
||||
offset_t* offsets = NULL;
|
||||
ulint n_ext = 0;
|
||||
ulint flags = BTR_MODIFY_TREE;
|
||||
|
||||
/**
|
||||
* position a cursor on first record on page
|
||||
*/
|
||||
rec_t* rec = page_rec_get_next(page_get_infimum_rec(page));
|
||||
btr_cur_t cursor;
|
||||
btr_cur_position(index, rec, block, &cursor);
|
||||
|
||||
/**
|
||||
* call split page with NULL as argument for entry to insert
|
||||
*/
|
||||
if (dict_index_get_page(index) == page_no) {
|
||||
/* The page is the root page
|
||||
* NOTE: ibuf_reset_free_bits is called inside
|
||||
* btr_root_raise_and_insert */
|
||||
rec = btr_root_raise_and_insert(
|
||||
flags, &cursor, &offsets, &heap, entry, n_ext, mtr);
|
||||
} else {
|
||||
/* We play safe and reset the free bits
|
||||
* NOTE: need to call this prior to btr_page_split_and_insert */
|
||||
if (!dict_index_is_clust(index) &&
|
||||
block != NULL) {
|
||||
buf_frame_t* frame = buf_block_get_frame(block);
|
||||
if (frame &&
|
||||
page_is_leaf(frame)) {
|
||||
|
||||
ibuf_reset_free_bits(block);
|
||||
}
|
||||
}
|
||||
|
||||
rec = btr_page_split_and_insert(
|
||||
flags, &cursor, &offsets, &heap, entry, n_ext, mtr);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
index->table->space->release_free_extents(n_reserved);
|
||||
scrub_data->scrub_stat.page_splits++;
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Location index by id for a table
|
||||
return index or NULL */
|
||||
static
|
||||
dict_index_t*
|
||||
find_index(
|
||||
/*========*/
|
||||
dict_table_t* table, /*!< in: table */
|
||||
index_id_t index_id) /*!< in: index id */
|
||||
{
|
||||
if (table != NULL) {
|
||||
dict_index_t* index = dict_table_get_first_index(table);
|
||||
while (index != NULL) {
|
||||
if (index->id == index_id)
|
||||
return index;
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Check if table should be scrubbed
|
||||
*/
|
||||
static
|
||||
bool
|
||||
btr_scrub_table_needs_scrubbing(
|
||||
/*============================*/
|
||||
dict_table_t* table) /*!< in: table */
|
||||
{
|
||||
if (table == NULL)
|
||||
return false;
|
||||
|
||||
if (table->stats_bg_flag & BG_STAT_SHOULD_QUIT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (table->to_be_dropped) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!table->is_readable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Check if index should be scrubbed
|
||||
*/
|
||||
static
|
||||
bool
|
||||
btr_scrub_index_needs_scrubbing(
|
||||
/*============================*/
|
||||
dict_index_t* index) /*!< in: index */
|
||||
{
|
||||
if (index == NULL)
|
||||
return false;
|
||||
|
||||
if (dict_index_is_ibuf(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dict_index_is_online_ddl(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Get table and index and store it on scrub_data
|
||||
*/
|
||||
static
|
||||
void
|
||||
btr_scrub_get_table_and_index(
|
||||
/*=========================*/
|
||||
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
|
||||
index_id_t index_id) /*!< in: index id */
|
||||
{
|
||||
/* first check if it's an index to current table */
|
||||
scrub_data->current_index = find_index(scrub_data->current_table,
|
||||
index_id);
|
||||
|
||||
if (scrub_data->current_index != NULL) {
|
||||
/* yes it was */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!btr_scrub_lock_dict(scrub_data->space, false)) {
|
||||
btr_scrub_complete_space(scrub_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* close current table (if any) */
|
||||
if (scrub_data->current_table != NULL) {
|
||||
btr_scrub_table_close(scrub_data->current_table);
|
||||
scrub_data->current_table = NULL;
|
||||
}
|
||||
|
||||
/* open table based on index_id */
|
||||
dict_table_t* table = dict_table_open_on_index_id(index_id);
|
||||
|
||||
if (table != NULL) {
|
||||
/* mark table as being scrubbed */
|
||||
table->stats_bg_flag |= BG_SCRUB_IN_PROGRESS;
|
||||
|
||||
if (!btr_scrub_table_needs_scrubbing(table)) {
|
||||
btr_scrub_table_close(table);
|
||||
btr_scrub_unlock_dict();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
btr_scrub_unlock_dict();
|
||||
scrub_data->current_table = table;
|
||||
scrub_data->current_index = find_index(table, index_id);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Handle free page */
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_scrub_free_page(
|
||||
/*====================*/
|
||||
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
|
||||
buf_block_t* block, /*!< in: block to scrub */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
// TODO(jonaso): scrub only what is actually needed
|
||||
|
||||
{
|
||||
/* note: perform both the memset and setting of FIL_PAGE_TYPE
|
||||
* wo/ logging. so that if we crash before page is flushed
|
||||
* it will be found by scrubbing thread again
|
||||
*/
|
||||
memset(buf_block_get_frame(block) + PAGE_HEADER, 0,
|
||||
srv_page_size - PAGE_HEADER);
|
||||
|
||||
mach_write_to_2(buf_block_get_frame(block) + FIL_PAGE_TYPE,
|
||||
FIL_PAGE_TYPE_ALLOCATED);
|
||||
}
|
||||
|
||||
page_create(block, mtr,
|
||||
dict_table_is_comp(scrub_data->current_table));
|
||||
|
||||
mtr_commit(mtr);
|
||||
|
||||
/* page doesn't need further processing => SKIP
|
||||
* and close table/index so that we don't keep references too long */
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Recheck if a page needs scrubbing, and if it does load appropriate
|
||||
table and index */
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_scrub_recheck_page(
|
||||
/*====================*/
|
||||
btr_scrub_t* scrub_data, /*!< inut: scrub data */
|
||||
buf_block_t* block, /*!< in: block */
|
||||
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
|
||||
allocated or free */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
/* recheck if page needs scrubbing (knowing allocation status) */
|
||||
int needs_scrubbing = btr_page_needs_scrubbing(
|
||||
scrub_data, block, allocated);
|
||||
|
||||
if (needs_scrubbing != BTR_SCRUB_PAGE) {
|
||||
mtr_commit(mtr);
|
||||
return needs_scrubbing;
|
||||
}
|
||||
|
||||
if (allocated == BTR_SCRUB_PAGE_FREE) {
|
||||
/** we don't need to load table/index for free pages
|
||||
* so scrub directly here */
|
||||
/* mtr is committed inside btr_scrub_page_free */
|
||||
return btr_scrub_free_page(scrub_data,
|
||||
block,
|
||||
mtr);
|
||||
}
|
||||
|
||||
page_t* page = buf_block_get_frame(block);
|
||||
index_id_t index_id = btr_page_get_index_id(page);
|
||||
|
||||
if (scrub_data->current_index == NULL ||
|
||||
scrub_data->current_index->id != index_id) {
|
||||
|
||||
/**
|
||||
* commit mtr (i.e release locks on block)
|
||||
* and try to get table&index potentially loading it
|
||||
* from disk
|
||||
*/
|
||||
mtr_commit(mtr);
|
||||
btr_scrub_get_table_and_index(scrub_data, index_id);
|
||||
} else {
|
||||
/* we already have correct index
|
||||
* commit mtr so that we can lock index before fetching page
|
||||
*/
|
||||
mtr_commit(mtr);
|
||||
}
|
||||
|
||||
/* check if table is about to be dropped */
|
||||
if (!btr_scrub_table_needs_scrubbing(scrub_data->current_table)) {
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
/* check if index is scrubbable */
|
||||
if (!btr_scrub_index_needs_scrubbing(scrub_data->current_index)) {
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
mtr_start(mtr);
|
||||
mtr_x_lock_index(scrub_data->current_index, mtr);
|
||||
/** set savepoint for X-latch of block */
|
||||
scrub_data->savepoint = mtr_set_savepoint(mtr);
|
||||
return BTR_SCRUB_PAGE;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Perform actual scrubbing of page */
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_scrub_page(
|
||||
/*============*/
|
||||
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
|
||||
buf_block_t* block, /*!< in: block */
|
||||
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
|
||||
allocated or free */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
/* recheck if page needs scrubbing (knowing allocation status) */
|
||||
int needs_scrubbing = BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
|
||||
if (block) {
|
||||
btr_page_needs_scrubbing(scrub_data, block, allocated);
|
||||
}
|
||||
|
||||
if (!block || needs_scrubbing != BTR_SCRUB_PAGE) {
|
||||
mtr_commit(mtr);
|
||||
return needs_scrubbing;
|
||||
}
|
||||
|
||||
if (allocated == BTR_SCRUB_PAGE_FREE) {
|
||||
/* mtr is committed inside btr_scrub_page_free */
|
||||
return btr_scrub_free_page(scrub_data,
|
||||
block,
|
||||
mtr);
|
||||
}
|
||||
|
||||
/* check that table/index still match now that they are loaded */
|
||||
|
||||
if (!scrub_data->current_table->space
|
||||
|| scrub_data->current_table->space_id != scrub_data->space) {
|
||||
/* this is truncate table */
|
||||
mtr_commit(mtr);
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
if (scrub_data->current_index->table != scrub_data->current_table) {
|
||||
/* this is truncate table */
|
||||
mtr_commit(mtr);
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
if (scrub_data->current_index->page == FIL_NULL) {
|
||||
/* this is truncate table */
|
||||
mtr_commit(mtr);
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
buf_frame_t* frame = buf_block_get_frame(block);
|
||||
|
||||
if (!frame || btr_page_get_index_id(frame) !=
|
||||
scrub_data->current_index->id) {
|
||||
/* page has been reallocated to new index */
|
||||
mtr_commit(mtr);
|
||||
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
|
||||
}
|
||||
|
||||
/* check if I can scrub (reorganize) page wo/ overflow */
|
||||
if (btr_optimistic_scrub(scrub_data,
|
||||
block,
|
||||
scrub_data->current_index,
|
||||
mtr) != DB_SUCCESS) {
|
||||
|
||||
/**
|
||||
* Can't reorganize page...need to split it
|
||||
*/
|
||||
btr_pessimistic_scrub(scrub_data,
|
||||
block,
|
||||
scrub_data->current_index,
|
||||
mtr);
|
||||
}
|
||||
mtr_commit(mtr);
|
||||
|
||||
return BTR_SCRUB_SKIP_PAGE; // no further action needed
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Start iterating a space */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
btr_scrub_start_space(
|
||||
/*===================*/
|
||||
ulint space, /*!< in: space */
|
||||
btr_scrub_t* scrub_data) /*!< in/out: scrub data */
|
||||
{
|
||||
scrub_data->space = space;
|
||||
scrub_data->current_table = NULL;
|
||||
scrub_data->current_index = NULL;
|
||||
if (fil_space_t* s = fil_space_acquire_silent(space)) {
|
||||
scrub_data->compressed = s->zip_size();
|
||||
s->release();
|
||||
} else {
|
||||
scrub_data->compressed = 0;
|
||||
}
|
||||
scrub_data->scrubbing = check_scrub_setting(scrub_data);
|
||||
return scrub_data->scrubbing;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Update global statistics with thread statistics */
|
||||
static
|
||||
void
|
||||
btr_scrub_update_total_stat(btr_scrub_t *scrub_data)
|
||||
{
|
||||
mutex_enter(&scrub_stat_mutex);
|
||||
scrub_stat.page_reorganizations +=
|
||||
scrub_data->scrub_stat.page_reorganizations;
|
||||
scrub_stat.page_splits +=
|
||||
scrub_data->scrub_stat.page_splits;
|
||||
scrub_stat.page_split_failures_underflow +=
|
||||
scrub_data->scrub_stat.page_split_failures_underflow;
|
||||
scrub_stat.page_split_failures_out_of_filespace +=
|
||||
scrub_data->scrub_stat.page_split_failures_out_of_filespace;
|
||||
scrub_stat.page_split_failures_missing_index +=
|
||||
scrub_data->scrub_stat.page_split_failures_missing_index;
|
||||
scrub_stat.page_split_failures_unknown +=
|
||||
scrub_data->scrub_stat.page_split_failures_unknown;
|
||||
mutex_exit(&scrub_stat_mutex);
|
||||
|
||||
// clear stat
|
||||
memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat));
|
||||
}
|
||||
|
||||
/** Complete iterating a space.
|
||||
@param[in,out] scrub_data scrub data */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_complete_space(btr_scrub_t* scrub_data)
|
||||
{
|
||||
ut_ad(scrub_data->scrubbing);
|
||||
btr_scrub_table_close_for_thread(scrub_data);
|
||||
btr_scrub_update_total_stat(scrub_data);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Return scrub statistics */
|
||||
void
|
||||
btr_scrub_total_stat(btr_scrub_stat_t *stat)
|
||||
{
|
||||
mutex_enter(&scrub_stat_mutex);
|
||||
*stat = scrub_stat;
|
||||
mutex_exit(&scrub_stat_mutex);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Init global variables */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_init()
|
||||
{
|
||||
mutex_create(LATCH_ID_SCRUB_STAT_MUTEX, &scrub_stat_mutex);
|
||||
|
||||
memset(&scrub_stat, 0, sizeof(scrub_stat));
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Cleanup globals */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_cleanup()
|
||||
{
|
||||
mutex_free(&scrub_stat_mutex);
|
||||
}
|
||||
|
|
@ -37,7 +37,6 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
|
|||
#include "mtr0mtr.h"
|
||||
#include "mtr0log.h"
|
||||
#include "ut0ut.h"
|
||||
#include "btr0scrub.h"
|
||||
#include "fsp0fsp.h"
|
||||
#include "fil0pagecompress.h"
|
||||
#include <my_crypt.h>
|
||||
|
@ -79,20 +78,12 @@ UNIV_INTERN uint srv_n_fil_crypt_iops = 100; // 10ms per iop
|
|||
static uint srv_alloc_time = 3; // allocate iops for 3s at a time
|
||||
static uint n_fil_crypt_iops_allocated = 0;
|
||||
|
||||
/** Variables for scrubbing */
|
||||
extern uint srv_background_scrub_data_interval;
|
||||
extern uint srv_background_scrub_data_check_interval;
|
||||
|
||||
#define DEBUG_KEYROTATION_THROTTLING 0
|
||||
|
||||
/** Statistics variables */
|
||||
static fil_crypt_stat_t crypt_stat;
|
||||
static ib_mutex_t crypt_stat_mutex;
|
||||
|
||||
/** Is background scrubbing enabled, defined on btr0scrub.cc */
|
||||
extern my_bool srv_background_scrub_data_uncompressed;
|
||||
extern my_bool srv_background_scrub_data_compressed;
|
||||
|
||||
/***********************************************************************
|
||||
Check if a key needs rotation given a key_state
|
||||
@param[in] crypt_data Encryption information
|
||||
|
@ -1165,9 +1156,6 @@ struct rotate_thread_t {
|
|||
|
||||
fil_crypt_stat_t crypt_stat; // statistics
|
||||
|
||||
btr_scrub_t scrub_data; /* thread local data used by btr_scrub-functions
|
||||
* when iterating pages of tablespace */
|
||||
|
||||
/** @return whether this thread should terminate */
|
||||
bool should_shutdown() const {
|
||||
switch (srv_shutdown_state) {
|
||||
|
@ -1266,20 +1254,7 @@ fil_crypt_space_needs_rotation(
|
|||
key_state->key_version,
|
||||
key_state->rotate_key_age);
|
||||
|
||||
crypt_data->rotate_state.scrubbing.is_active =
|
||||
btr_scrub_start_space(space->id, &state->scrub_data);
|
||||
|
||||
time_t diff = time(0) - crypt_data->rotate_state.scrubbing.
|
||||
last_scrub_completed;
|
||||
|
||||
bool need_scrubbing =
|
||||
(srv_background_scrub_data_uncompressed ||
|
||||
srv_background_scrub_data_compressed) &&
|
||||
crypt_data->rotate_state.scrubbing.is_active
|
||||
&& diff >= 0
|
||||
&& ulint(diff) >= srv_background_scrub_data_interval;
|
||||
|
||||
if (need_key_rotation == false && need_scrubbing == false) {
|
||||
if (need_key_rotation == false) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1728,69 +1703,6 @@ fil_crypt_get_page_throttle_func(
|
|||
return block;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Get block and allocation status
|
||||
|
||||
note: innodb locks fil_space_latch and then block when allocating page
|
||||
but locks block and then fil_space_latch when freeing page.
|
||||
|
||||
@param[in,out] state Rotation state
|
||||
@param[in] offset Page offset
|
||||
@param[in,out] mtr Minitransaction
|
||||
@param[out] allocation_status Allocation status
|
||||
@param[out] sleeptime_ms Sleep time
|
||||
@return block or NULL
|
||||
*/
|
||||
static
|
||||
buf_block_t*
|
||||
btr_scrub_get_block_and_allocation_status(
|
||||
rotate_thread_t* state,
|
||||
ulint offset,
|
||||
mtr_t* mtr,
|
||||
btr_scrub_page_allocation_status_t *allocation_status,
|
||||
ulint* sleeptime_ms)
|
||||
{
|
||||
mtr_t local_mtr;
|
||||
buf_block_t *block = NULL;
|
||||
fil_space_t* space = state->space;
|
||||
|
||||
ut_ad(space->referenced());
|
||||
|
||||
mtr_start(&local_mtr);
|
||||
|
||||
*allocation_status = fseg_page_is_free(space, (uint32_t)offset) ?
|
||||
BTR_SCRUB_PAGE_FREE :
|
||||
BTR_SCRUB_PAGE_ALLOCATED;
|
||||
|
||||
if (*allocation_status == BTR_SCRUB_PAGE_FREE) {
|
||||
/* this is easy case, we lock fil_space_latch first and
|
||||
then block */
|
||||
block = fil_crypt_get_page_throttle(state,
|
||||
offset, mtr,
|
||||
sleeptime_ms);
|
||||
mtr_commit(&local_mtr);
|
||||
} else {
|
||||
/* page is allocated according to xdes */
|
||||
|
||||
/* release fil_space_latch *before* fetching block */
|
||||
mtr_commit(&local_mtr);
|
||||
|
||||
/* NOTE: when we have locked dict_index_get_lock(),
|
||||
* it's safe to release fil_space_latch and then fetch block
|
||||
* as dict_index_get_lock() is needed to make tree modifications
|
||||
* such as free-ing a page
|
||||
*/
|
||||
|
||||
block = fil_crypt_get_page_throttle(state,
|
||||
offset, mtr,
|
||||
sleeptime_ms);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Rotate one page
|
||||
@param[in,out] key_state Key state
|
||||
|
@ -1829,7 +1741,6 @@ fil_crypt_rotate_page(
|
|||
offset, &mtr,
|
||||
&sleeptime_ms)) {
|
||||
bool modified = false;
|
||||
int needs_scrubbing = BTR_SCRUB_SKIP_PAGE;
|
||||
byte* frame = buf_block_get_frame(block);
|
||||
const lsn_t block_lsn = mach_read_from_8(FIL_PAGE_LSN + frame);
|
||||
uint kv = buf_page_get_key_version(frame, space->flags);
|
||||
|
@ -1885,74 +1796,11 @@ fil_crypt_rotate_page(
|
|||
state->min_key_version_found = kv;
|
||||
}
|
||||
}
|
||||
|
||||
needs_scrubbing = btr_page_needs_scrubbing(
|
||||
&state->scrub_data, block,
|
||||
BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN);
|
||||
}
|
||||
|
||||
mtr.commit();
|
||||
lsn_t end_lsn = mtr.commit_lsn();
|
||||
|
||||
if (needs_scrubbing == BTR_SCRUB_PAGE) {
|
||||
mtr.start();
|
||||
/*
|
||||
* refetch page and allocation status
|
||||
*/
|
||||
btr_scrub_page_allocation_status_t allocated;
|
||||
|
||||
block = btr_scrub_get_block_and_allocation_status(
|
||||
state, offset, &mtr,
|
||||
&allocated,
|
||||
&sleeptime_ms);
|
||||
|
||||
if (block) {
|
||||
mtr.set_named_space(space);
|
||||
|
||||
/* get required table/index and index-locks */
|
||||
needs_scrubbing = btr_scrub_recheck_page(
|
||||
&state->scrub_data, block, allocated, &mtr);
|
||||
|
||||
if (needs_scrubbing == BTR_SCRUB_PAGE) {
|
||||
/* we need to refetch it once more now that we have
|
||||
* index locked */
|
||||
block = btr_scrub_get_block_and_allocation_status(
|
||||
state, offset, &mtr,
|
||||
&allocated,
|
||||
&sleeptime_ms);
|
||||
|
||||
needs_scrubbing = btr_scrub_page(&state->scrub_data,
|
||||
block, allocated,
|
||||
&mtr);
|
||||
}
|
||||
|
||||
/* NOTE: mtr is committed inside btr_scrub_recheck_page()
|
||||
* and/or btr_scrub_page. This is to make sure that
|
||||
* locks & pages are latched in corrected order,
|
||||
* the mtr is in some circumstances restarted.
|
||||
* (mtr_commit() + mtr_start())
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_scrubbing != BTR_SCRUB_PAGE) {
|
||||
/* if page didn't need scrubbing it might be that cleanups
|
||||
are needed. do those outside of any mtr to prevent deadlocks.
|
||||
|
||||
the information what kinds of cleanups that are needed are
|
||||
encoded inside the needs_scrubbing, but this is opaque to
|
||||
this function (except the value BTR_SCRUB_PAGE) */
|
||||
btr_scrub_skip_page(&state->scrub_data, needs_scrubbing);
|
||||
}
|
||||
|
||||
if (needs_scrubbing == BTR_SCRUB_TURNED_OFF) {
|
||||
/* if we just detected that scrubbing was turned off
|
||||
* update global state to reflect this */
|
||||
ut_ad(crypt_data);
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
crypt_data->rotate_state.scrubbing.is_active = false;
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
/* if we modified page, we take lsn from mtr */
|
||||
|
@ -2137,31 +1985,14 @@ static void fil_crypt_complete_rotate_space(rotate_thread_t* state)
|
|||
crypt_data->rotate_state.flushing = true;
|
||||
crypt_data->min_key_version =
|
||||
crypt_data->rotate_state.min_key_version_found;
|
||||
}
|
||||
|
||||
/* inform scrubbing */
|
||||
crypt_data->rotate_state.scrubbing.is_active = false;
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
|
||||
/* all threads must call btr_scrub_complete_space wo/ mutex held */
|
||||
if (state->scrub_data.scrubbing) {
|
||||
btr_scrub_complete_space(&state->scrub_data);
|
||||
if (should_flush) {
|
||||
/* only last thread updates last_scrub_completed */
|
||||
ut_ad(crypt_data);
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
crypt_data->rotate_state.scrubbing.
|
||||
last_scrub_completed = time(0);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
if (should_flush) {
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
fil_crypt_flush_space(state);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
crypt_data->rotate_state.flushing = false;
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
} else {
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
} else {
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
@ -2194,8 +2025,6 @@ DECLARE_THREAD(fil_crypt_thread)(void*)
|
|||
|
||||
key_state_t new_state;
|
||||
|
||||
time_t wait_start = time(0);
|
||||
|
||||
while (!thr.should_shutdown()) {
|
||||
|
||||
/* wait for key state changes
|
||||
|
@ -2213,17 +2042,6 @@ DECLARE_THREAD(fil_crypt_thread)(void*)
|
|||
* a space*/
|
||||
break;
|
||||
}
|
||||
|
||||
time_t waited = time(0) - wait_start;
|
||||
|
||||
/* Break if we have waited the background scrub
|
||||
internal and background scrubbing is enabled */
|
||||
if (waited >= 0
|
||||
&& ulint(waited) >= srv_background_scrub_data_check_interval
|
||||
&& (srv_background_scrub_data_uncompressed
|
||||
|| srv_background_scrub_data_compressed)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
recheck = false;
|
||||
|
@ -2604,45 +2422,6 @@ fil_crypt_total_stat(
|
|||
mutex_exit(&crypt_stat_mutex);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Get scrub status for a space (used by information_schema)
|
||||
|
||||
@param[in] space Tablespace
|
||||
@param[out] status Scrub status */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_space_get_scrub_status(
|
||||
const fil_space_t* space,
|
||||
struct fil_space_scrub_status_t* status)
|
||||
{
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
ut_ad(space->referenced());
|
||||
fil_space_crypt_t* crypt_data = space->crypt_data;
|
||||
|
||||
status->space = space->id;
|
||||
|
||||
if (crypt_data != NULL) {
|
||||
status->compressed = FSP_FLAGS_GET_ZIP_SSIZE(space->flags) > 0;
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
status->last_scrub_completed =
|
||||
crypt_data->rotate_state.scrubbing.last_scrub_completed;
|
||||
if (crypt_data->rotate_state.active_threads > 0 &&
|
||||
crypt_data->rotate_state.scrubbing.is_active) {
|
||||
status->scrubbing = true;
|
||||
status->current_scrub_started =
|
||||
crypt_data->rotate_state.start_time;
|
||||
status->current_scrub_active_threads =
|
||||
crypt_data->rotate_state.active_threads;
|
||||
status->current_scrub_page_number =
|
||||
crypt_data->rotate_state.next_offset;
|
||||
status->current_scrub_max_page_number =
|
||||
crypt_data->rotate_state.max_offset;
|
||||
}
|
||||
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
}
|
||||
#endif /* UNIV_INNOCHECKSUM */
|
||||
|
||||
/**
|
||||
|
|
|
@ -213,14 +213,8 @@ static char* innodb_version_str = (char*) INNODB_VERSION_STR;
|
|||
extern uint srv_fil_crypt_rotate_key_age;
|
||||
extern uint srv_n_fil_crypt_iops;
|
||||
|
||||
extern my_bool srv_immediate_scrub_data_uncompressed;
|
||||
extern my_bool srv_background_scrub_data_uncompressed;
|
||||
extern my_bool srv_background_scrub_data_compressed;
|
||||
extern uint srv_background_scrub_data_interval;
|
||||
extern uint srv_background_scrub_data_check_interval;
|
||||
#ifdef UNIV_DEBUG
|
||||
my_bool innodb_evict_tables_on_commit_debug;
|
||||
extern my_bool srv_scrub_force_testing;
|
||||
#endif
|
||||
|
||||
/** Note we cannot use rec_format_enum because we do not allow
|
||||
|
@ -1081,22 +1075,6 @@ static SHOW_VAR innodb_status_variables[]= {
|
|||
{"encryption_n_temp_blocks_decrypted",
|
||||
&export_vars.innodb_n_temp_blocks_decrypted, SHOW_LONGLONG},
|
||||
|
||||
/* scrubing */
|
||||
{"scrub_background_page_reorganizations",
|
||||
&export_vars.innodb_scrub_page_reorganizations, SHOW_SIZE_T},
|
||||
{"scrub_background_page_splits", &export_vars.innodb_scrub_page_splits,
|
||||
SHOW_SIZE_T},
|
||||
{"scrub_background_page_split_failures_underflow",
|
||||
&export_vars.innodb_scrub_page_split_failures_underflow, SHOW_SIZE_T},
|
||||
{"scrub_background_page_split_failures_out_of_filespace",
|
||||
&export_vars.innodb_scrub_page_split_failures_out_of_filespace,SHOW_SIZE_T},
|
||||
{"scrub_background_page_split_failures_missing_index",
|
||||
&export_vars.innodb_scrub_page_split_failures_missing_index, SHOW_SIZE_T},
|
||||
{"scrub_background_page_split_failures_unknown",
|
||||
&export_vars.innodb_scrub_page_split_failures_unknown, SHOW_SIZE_T},
|
||||
{"encryption_num_key_requests", &export_vars.innodb_encryption_key_requests,
|
||||
SHOW_LONGLONG},
|
||||
|
||||
{NullS, NullS, SHOW_LONG}
|
||||
};
|
||||
|
||||
|
@ -3454,6 +3432,26 @@ static const char* innodb_page_cleaners_msg
|
|||
= "The parameter innodb_page_cleaners is deprecated and has no effect.";
|
||||
|
||||
ulong srv_n_log_files;
|
||||
|
||||
static my_bool innodb_background_scrub_data_uncompressed;
|
||||
|
||||
static const char* innodb_background_scrub_data_uncompressed_msg
|
||||
= "The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.";
|
||||
|
||||
static my_bool innodb_background_scrub_data_compressed;
|
||||
|
||||
static const char* innodb_background_scrub_data_compressed_msg
|
||||
= "The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.";
|
||||
|
||||
static uint innodb_background_scrub_data_check_interval;
|
||||
|
||||
static const char* innodb_background_scrub_data_check_interval_msg
|
||||
= "The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.";
|
||||
|
||||
static uint innodb_background_scrub_data_interval;
|
||||
|
||||
static const char* innodb_background_scrub_data_interval_msg
|
||||
= "The parameter innodb_background_scrub_data_interval is deprecated and has no effect.";
|
||||
} // namespace deprecated
|
||||
|
||||
/** Initialize, validate and normalize the InnoDB startup parameters.
|
||||
|
@ -18934,6 +18932,46 @@ innodb_scrub_log_speed_warn(THD* thd, st_mysql_sys_var*, void*, const void*)
|
|||
deprecated::innodb_scrub_log_speed_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
innodb_background_scrub_data_uncompressed_warn(THD* thd, st_mysql_sys_var*,
|
||||
void*, const void*)
|
||||
{
|
||||
push_warning_printf(
|
||||
thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
HA_ERR_UNSUPPORTED,
|
||||
deprecated::innodb_background_scrub_data_uncompressed_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
innodb_background_scrub_data_compressed_warn(THD* thd, st_mysql_sys_var*,
|
||||
void*, const void*)
|
||||
{
|
||||
push_warning_printf(
|
||||
thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
HA_ERR_UNSUPPORTED,
|
||||
deprecated::innodb_background_scrub_data_compressed_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
innodb_background_scrub_data_check_interval_warn(
|
||||
THD* thd, st_mysql_sys_var*, void*, const void*)
|
||||
{
|
||||
push_warning_printf(
|
||||
thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
HA_ERR_UNSUPPORTED,
|
||||
deprecated::innodb_background_scrub_data_check_interval_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
innodb_background_scrub_data_interval_warn(
|
||||
THD* thd, st_mysql_sys_var*, void*, const void*)
|
||||
{
|
||||
push_warning_printf(
|
||||
thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
HA_ERR_UNSUPPORTED,
|
||||
deprecated::innodb_background_scrub_data_interval_msg);
|
||||
}
|
||||
|
||||
static SHOW_VAR innodb_status_variables_export[]= {
|
||||
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
|
||||
{NullS, NullS, SHOW_LONG}
|
||||
|
@ -20151,8 +20189,7 @@ static MYSQL_SYSVAR_ENUM(encrypt_tables, srv_encrypt_tables,
|
|||
|
||||
static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Number of threads performing background key rotation and "
|
||||
"scrubbing",
|
||||
"Number of threads performing background key rotation ",
|
||||
NULL,
|
||||
innodb_encryption_threads_update,
|
||||
srv_n_fil_crypt_threads, 0, UINT_MAX32, 0);
|
||||
|
@ -20197,47 +20234,24 @@ static MYSQL_SYSVAR_BOOL(immediate_scrub_data_uncompressed,
|
|||
NULL, NULL, FALSE);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(background_scrub_data_uncompressed,
|
||||
srv_background_scrub_data_uncompressed,
|
||||
0,
|
||||
"Enable scrubbing of uncompressed data by "
|
||||
"background threads (same as encryption_threads)",
|
||||
NULL, NULL, FALSE);
|
||||
deprecated::innodb_background_scrub_data_uncompressed,
|
||||
PLUGIN_VAR_OPCMDARG, innodb_deprecated_ignored, NULL,
|
||||
innodb_background_scrub_data_uncompressed_warn, FALSE);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(background_scrub_data_compressed,
|
||||
srv_background_scrub_data_compressed,
|
||||
0,
|
||||
"Enable scrubbing of compressed data by "
|
||||
"background threads (same as encryption_threads)",
|
||||
NULL, NULL, FALSE);
|
||||
deprecated::innodb_background_scrub_data_compressed,
|
||||
PLUGIN_VAR_OPCMDARG, innodb_deprecated_ignored, NULL,
|
||||
innodb_background_scrub_data_compressed_warn, FALSE);
|
||||
|
||||
static MYSQL_SYSVAR_UINT(background_scrub_data_check_interval,
|
||||
srv_background_scrub_data_check_interval,
|
||||
0,
|
||||
"check if spaces needs scrubbing every "
|
||||
"innodb_background_scrub_data_check_interval "
|
||||
"seconds",
|
||||
NULL, NULL,
|
||||
srv_background_scrub_data_check_interval,
|
||||
1,
|
||||
UINT_MAX32, 0);
|
||||
deprecated::innodb_background_scrub_data_check_interval,
|
||||
0, innodb_deprecated_ignored, NULL,
|
||||
innodb_background_scrub_data_check_interval_warn, 0, 0, 0, 0);
|
||||
|
||||
static MYSQL_SYSVAR_UINT(background_scrub_data_interval,
|
||||
srv_background_scrub_data_interval,
|
||||
0,
|
||||
"scrub spaces that were last scrubbed longer than "
|
||||
" innodb_background_scrub_data_interval seconds ago",
|
||||
NULL, NULL,
|
||||
srv_background_scrub_data_interval,
|
||||
1,
|
||||
UINT_MAX32, 0);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
static MYSQL_SYSVAR_BOOL(debug_force_scrubbing,
|
||||
srv_scrub_force_testing,
|
||||
0,
|
||||
"Perform extra scrubbing to increase test exposure",
|
||||
NULL, NULL, FALSE);
|
||||
#endif /* UNIV_DEBUG */
|
||||
deprecated::innodb_background_scrub_data_interval,
|
||||
0, innodb_deprecated_ignored, NULL,
|
||||
innodb_background_scrub_data_interval_warn, 0, 0, 0, 0);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(encrypt_temporary_tables, innodb_encrypt_temporary_tables,
|
||||
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
|
||||
|
@ -20442,9 +20456,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(background_scrub_data_compressed),
|
||||
MYSQL_SYSVAR(background_scrub_data_interval),
|
||||
MYSQL_SYSVAR(background_scrub_data_check_interval),
|
||||
#ifdef UNIV_DEBUG
|
||||
MYSQL_SYSVAR(debug_force_scrubbing),
|
||||
#endif
|
||||
MYSQL_SYSVAR(buf_dump_status_frequency),
|
||||
MYSQL_SYSVAR(background_thread),
|
||||
MYSQL_SYSVAR(encrypt_temporary_tables),
|
||||
|
@ -20499,8 +20510,7 @@ i_s_innodb_sys_datafiles,
|
|||
i_s_innodb_sys_virtual,
|
||||
i_s_innodb_mutexes,
|
||||
i_s_innodb_sys_semaphore_waits,
|
||||
i_s_innodb_tablespaces_encryption,
|
||||
i_s_innodb_tablespaces_scrubbing
|
||||
i_s_innodb_tablespaces_encryption
|
||||
maria_declare_plugin_end;
|
||||
|
||||
/** @brief Initialize the default value of innodb_commit_concurrency.
|
||||
|
|
|
@ -7159,228 +7159,6 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_encryption =
|
|||
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
|
||||
};
|
||||
|
||||
namespace Show {
|
||||
/** TABLESPACES_SCRUBBING ********************************************/
|
||||
/* Fields of the table INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING */
|
||||
static ST_FIELD_INFO innodb_tablespaces_scrubbing_fields_info[] =
|
||||
{
|
||||
#define TABLESPACES_SCRUBBING_SPACE 0
|
||||
Column("SPACE", ULonglong(), NOT_NULL),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_NAME 1
|
||||
Column("NAME", Varchar(MAX_FULL_NAME_LEN + 1), NULLABLE),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_COMPRESSED 2
|
||||
Column("COMPRESSED", ULong(1), NOT_NULL),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED 3
|
||||
Column("LAST_SCRUB_COMPLETED", Datetime(0), NULLABLE),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_STARTED 4
|
||||
Column("CURRENT_SCRUB_STARTED", Datetime(0), NULLABLE),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_ACTIVE_THREADS 5
|
||||
Column("CURRENT_SCRUB_ACTIVE_THREADS", ULong(), NULLABLE),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_PAGE_NUMBER 6
|
||||
Column("CURRENT_SCRUB_PAGE_NUMBER", ULonglong(),NOT_NULL),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_MAX_PAGE_NUMBER 7
|
||||
Column("CURRENT_SCRUB_MAX_PAGE_NUMBER", ULonglong(), NOT_NULL),
|
||||
|
||||
#define TABLESPACES_SCRUBBING_ON_SSD 8
|
||||
Column("ON_SSD", ULong(1), NOT_NULL),
|
||||
|
||||
CEnd()
|
||||
};
|
||||
} // namespace Show
|
||||
|
||||
/**********************************************************************//**
|
||||
Function to fill INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING
|
||||
with information collected by scanning SYS_TABLESPACES table and
|
||||
fil_space.
|
||||
@param[in] thd Thread handle
|
||||
@param[in] space Tablespace
|
||||
@param[in] table_to_fill I_S table
|
||||
@return 0 on success */
|
||||
static
|
||||
int
|
||||
i_s_dict_fill_tablespaces_scrubbing(
|
||||
THD* thd,
|
||||
fil_space_t* space,
|
||||
TABLE* table_to_fill)
|
||||
{
|
||||
Field** fields;
|
||||
struct fil_space_scrub_status_t status;
|
||||
|
||||
DBUG_ENTER("i_s_dict_fill_tablespaces_scrubbing");
|
||||
|
||||
fields = table_to_fill->field;
|
||||
|
||||
fil_space_get_scrub_status(space, &status);
|
||||
|
||||
OK(fields[TABLESPACES_SCRUBBING_SPACE]->store(space->id, true));
|
||||
|
||||
OK(field_store_string(fields[TABLESPACES_SCRUBBING_NAME],
|
||||
space->name));
|
||||
|
||||
OK(fields[TABLESPACES_SCRUBBING_COMPRESSED]->store(
|
||||
status.compressed ? 1 : 0, true));
|
||||
|
||||
if (status.last_scrub_completed == 0) {
|
||||
fields[TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED]->set_null();
|
||||
} else {
|
||||
fields[TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED]
|
||||
->set_notnull();
|
||||
OK(field_store_time_t(
|
||||
fields[TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED],
|
||||
status.last_scrub_completed));
|
||||
}
|
||||
|
||||
int field_numbers[] = {
|
||||
TABLESPACES_SCRUBBING_CURRENT_SCRUB_STARTED,
|
||||
TABLESPACES_SCRUBBING_CURRENT_SCRUB_ACTIVE_THREADS,
|
||||
TABLESPACES_SCRUBBING_CURRENT_SCRUB_PAGE_NUMBER,
|
||||
TABLESPACES_SCRUBBING_CURRENT_SCRUB_MAX_PAGE_NUMBER };
|
||||
|
||||
if (status.scrubbing) {
|
||||
for (uint i = 0; i < array_elements(field_numbers); i++) {
|
||||
fields[field_numbers[i]]->set_notnull();
|
||||
}
|
||||
|
||||
OK(field_store_time_t(
|
||||
fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_STARTED],
|
||||
status.current_scrub_started));
|
||||
OK(fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_ACTIVE_THREADS]
|
||||
->store(status.current_scrub_active_threads, true));
|
||||
OK(fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_PAGE_NUMBER]
|
||||
->store(status.current_scrub_page_number, true));
|
||||
OK(fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_MAX_PAGE_NUMBER]
|
||||
->store(status.current_scrub_max_page_number, true));
|
||||
} else {
|
||||
for (uint i = 0; i < array_elements(field_numbers); i++) {
|
||||
fields[field_numbers[i]]->set_null();
|
||||
}
|
||||
}
|
||||
|
||||
OK(fields[TABLESPACES_SCRUBBING_ON_SSD]->store(!space->is_rotational(),
|
||||
true));
|
||||
OK(schema_table_store_record(thd, table_to_fill));
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/*******************************************************************//**
|
||||
Function to populate INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING table.
|
||||
Loop through each record in TABLESPACES_SCRUBBING, and extract the column
|
||||
information and fill the INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING table.
|
||||
@return 0 on success */
|
||||
static
|
||||
int
|
||||
i_s_tablespaces_scrubbing_fill_table(
|
||||
/*===========================*/
|
||||
THD* thd, /*!< in: thread */
|
||||
TABLE_LIST* tables, /*!< in/out: tables to fill */
|
||||
Item* ) /*!< in: condition (not used) */
|
||||
{
|
||||
DBUG_ENTER("i_s_tablespaces_scrubbing_fill_table");
|
||||
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
|
||||
|
||||
/* deny access to user without SUPER_ACL privilege */
|
||||
if (check_global_access(thd, SUPER_ACL)) {
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
mutex_enter(&fil_system.mutex);
|
||||
|
||||
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
|
||||
space; space = UT_LIST_GET_NEXT(space_list, space)) {
|
||||
if (space->purpose == FIL_TYPE_TABLESPACE
|
||||
&& !space->is_stopping()) {
|
||||
space->acquire();
|
||||
mutex_exit(&fil_system.mutex);
|
||||
if (int err = i_s_dict_fill_tablespaces_scrubbing(
|
||||
thd, space, tables->table)) {
|
||||
space->release();
|
||||
DBUG_RETURN(err);
|
||||
}
|
||||
mutex_enter(&fil_system.mutex);
|
||||
space->release();
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system.mutex);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/*******************************************************************//**
|
||||
Bind the dynamic table INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING
|
||||
@return 0 on success */
|
||||
static
|
||||
int
|
||||
innodb_tablespaces_scrubbing_init(
|
||||
/*========================*/
|
||||
void* p) /*!< in/out: table schema object */
|
||||
{
|
||||
ST_SCHEMA_TABLE* schema;
|
||||
|
||||
DBUG_ENTER("innodb_tablespaces_scrubbing_init");
|
||||
|
||||
schema = (ST_SCHEMA_TABLE*) p;
|
||||
|
||||
schema->fields_info = Show::innodb_tablespaces_scrubbing_fields_info;
|
||||
schema->fill_table = i_s_tablespaces_scrubbing_fill_table;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing =
|
||||
{
|
||||
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
|
||||
/* int */
|
||||
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
|
||||
|
||||
/* pointer to type-specific plugin descriptor */
|
||||
/* void* */
|
||||
STRUCT_FLD(info, &i_s_info),
|
||||
|
||||
/* plugin name */
|
||||
/* const char* */
|
||||
STRUCT_FLD(name, "INNODB_TABLESPACES_SCRUBBING"),
|
||||
|
||||
/* plugin author (for SHOW PLUGINS) */
|
||||
/* const char* */
|
||||
STRUCT_FLD(author, "Google Inc"),
|
||||
|
||||
/* general descriptive text (for SHOW PLUGINS) */
|
||||
/* const char* */
|
||||
STRUCT_FLD(descr, "InnoDB TABLESPACES_SCRUBBING"),
|
||||
|
||||
/* the plugin license (PLUGIN_LICENSE_XXX) */
|
||||
/* int */
|
||||
STRUCT_FLD(license, PLUGIN_LICENSE_BSD),
|
||||
|
||||
/* the function to invoke when plugin is loaded */
|
||||
/* int (*)(void*); */
|
||||
STRUCT_FLD(init, innodb_tablespaces_scrubbing_init),
|
||||
|
||||
/* the function to invoke when plugin is unloaded */
|
||||
/* int (*)(void*); */
|
||||
STRUCT_FLD(deinit, i_s_common_deinit),
|
||||
|
||||
/* plugin version (for SHOW PLUGINS) */
|
||||
/* unsigned int */
|
||||
STRUCT_FLD(version, INNODB_VERSION_SHORT),
|
||||
|
||||
/* struct st_mysql_show_var* */
|
||||
STRUCT_FLD(status_vars, NULL),
|
||||
|
||||
/* struct st_mysql_sys_var** */
|
||||
STRUCT_FLD(system_vars, NULL),
|
||||
|
||||
/* Maria extension */
|
||||
STRUCT_FLD(version_info, INNODB_VERSION_STR),
|
||||
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
|
||||
};
|
||||
|
||||
namespace Show {
|
||||
/** INNODB_MUTEXES *********************************************/
|
||||
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
// Copyright 2014 Google
|
||||
|
||||
#ifndef btr0scrub_h
|
||||
#define btr0scrub_h
|
||||
|
||||
#include "dict0dict.h"
|
||||
|
||||
/**
|
||||
* enum describing page allocation status
|
||||
*/
|
||||
enum btr_scrub_page_allocation_status_t {
|
||||
BTR_SCRUB_PAGE_FREE,
|
||||
BTR_SCRUB_PAGE_ALLOCATED,
|
||||
BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN
|
||||
};
|
||||
|
||||
/**
|
||||
* constants returned by btr_page_needs_scrubbing & btr_scrub_recheck_page
|
||||
*/
|
||||
#define BTR_SCRUB_PAGE 1 /* page should be scrubbed */
|
||||
#define BTR_SCRUB_SKIP_PAGE 2 /* no scrub & no action */
|
||||
#define BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE 3 /* no scrub & close table */
|
||||
#define BTR_SCRUB_SKIP_PAGE_AND_COMPLETE_SPACE 4 /* no scrub & complete space */
|
||||
#define BTR_SCRUB_TURNED_OFF 5 /* we detected that scrubbing
|
||||
was disabled by global
|
||||
variable */
|
||||
|
||||
/**************************************************************//**
|
||||
struct for keeping scrub statistics. */
|
||||
struct btr_scrub_stat_t {
|
||||
/* page reorganizations */
|
||||
ulint page_reorganizations;
|
||||
/* page splits */
|
||||
ulint page_splits;
|
||||
/* scrub failures */
|
||||
ulint page_split_failures_underflow;
|
||||
ulint page_split_failures_out_of_filespace;
|
||||
ulint page_split_failures_missing_index;
|
||||
ulint page_split_failures_unknown;
|
||||
};
|
||||
|
||||
/**************************************************************//**
|
||||
struct for thread local scrub state. */
|
||||
struct btr_scrub_t {
|
||||
|
||||
/* current space */
|
||||
ulint space;
|
||||
|
||||
/* is scrubbing enabled for this space */
|
||||
bool scrubbing;
|
||||
|
||||
/* is current space compressed */
|
||||
bool compressed;
|
||||
|
||||
dict_table_t* current_table;
|
||||
dict_index_t* current_index;
|
||||
/* savepoint for X_LATCH of block */
|
||||
ulint savepoint;
|
||||
|
||||
/* statistic counters */
|
||||
btr_scrub_stat_t scrub_stat;
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
Init scrub global variables */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_init();
|
||||
|
||||
/*********************************************************************
|
||||
Cleanup scrub globals */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_cleanup();
|
||||
|
||||
/***********************************************************************
|
||||
Return crypt statistics */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_total_stat(
|
||||
/*==================*/
|
||||
btr_scrub_stat_t *stat); /*!< out: stats to update */
|
||||
|
||||
/**************************************************************//**
|
||||
Check if a page needs scrubbing
|
||||
* @return BTR_SCRUB_PAGE if page should be scrubbed
|
||||
* else btr_scrub_skip_page should be called
|
||||
* with this return value (and without any latches held)
|
||||
*/
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_page_needs_scrubbing(
|
||||
/*=====================*/
|
||||
btr_scrub_t* scrub_data, /*!< in: scrub data */
|
||||
buf_block_t* block, /*!< in: block to check, latched */
|
||||
btr_scrub_page_allocation_status_t allocated); /*!< in: is block
|
||||
allocated, free or
|
||||
unknown */
|
||||
|
||||
/****************************************************************
|
||||
Recheck if a page needs scrubbing, and if it does load appropriate
|
||||
table and index
|
||||
* @return BTR_SCRUB_PAGE if page should be scrubbed
|
||||
* else btr_scrub_skip_page should be called
|
||||
* with this return value (and without any latches held)
|
||||
*/
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_scrub_recheck_page(
|
||||
/*====================*/
|
||||
btr_scrub_t* scrub_data, /*!< inut: scrub data */
|
||||
buf_block_t* block, /*!< in: block */
|
||||
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
|
||||
allocated or free */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
|
||||
/****************************************************************
|
||||
Perform actual scrubbing of page */
|
||||
UNIV_INTERN
|
||||
int
|
||||
btr_scrub_page(
|
||||
/*============*/
|
||||
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
|
||||
buf_block_t* block, /*!< in: block */
|
||||
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
|
||||
allocated or free */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
|
||||
/****************************************************************
|
||||
Perform cleanup needed for a page not needing scrubbing */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_skip_page(
|
||||
/*============*/
|
||||
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
|
||||
int needs_scrubbing); /*!< in: return value from
|
||||
btr_page_needs_scrubbing or
|
||||
btr_scrub_recheck_page which encodes what kind
|
||||
of cleanup is needed */
|
||||
|
||||
/****************************************************************
|
||||
Start iterating a space
|
||||
* @return true if scrubbing is turned on */
|
||||
UNIV_INTERN
|
||||
bool
|
||||
btr_scrub_start_space(
|
||||
/*===================*/
|
||||
ulint space, /*!< in: space */
|
||||
btr_scrub_t* scrub_data); /*!< in/out: scrub data */
|
||||
|
||||
/** Complete iterating a space.
|
||||
@param[in,out] scrub_data scrub data */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_scrub_complete_space(btr_scrub_t* scrub_data);
|
||||
|
||||
#endif
|
|
@ -93,11 +93,6 @@ struct fil_space_rotate_state_t
|
|||
space */
|
||||
bool starting; /*!< initial write of IV */
|
||||
bool flushing; /*!< space is being flushed at end of rotate */
|
||||
struct {
|
||||
bool is_active; /*!< is scrubbing active in this space */
|
||||
time_t last_scrub_completed; /*!< when was last scrub
|
||||
completed */
|
||||
} scrubbing;
|
||||
};
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
@ -226,18 +221,6 @@ struct fil_crypt_stat_t {
|
|||
ulint estimated_iops;
|
||||
};
|
||||
|
||||
/** Status info about scrubbing */
|
||||
struct fil_space_scrub_status_t {
|
||||
ulint space; /*!< tablespace id */
|
||||
bool compressed; /*!< is space compressed */
|
||||
time_t last_scrub_completed; /*!< when was last scrub completed */
|
||||
bool scrubbing; /*!< is scrubbing ongoing */
|
||||
time_t current_scrub_started; /*!< when started current scrubbing */
|
||||
ulint current_scrub_active_threads; /*!< current scrub active threads */
|
||||
ulint current_scrub_page_number; /*!< current scrub page no */
|
||||
ulint current_scrub_max_page_number; /*!< current scrub max page no */
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
Init space crypt */
|
||||
UNIV_INTERN
|
||||
|
@ -449,18 +432,6 @@ void
|
|||
fil_crypt_total_stat(
|
||||
fil_crypt_stat_t *stat);
|
||||
|
||||
/**
|
||||
Get scrub status for a space (used by information_schema)
|
||||
|
||||
@param[in] space Tablespace
|
||||
@param[out] status Scrub status
|
||||
return 0 if data found */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_space_get_scrub_status(
|
||||
const fil_space_t* space,
|
||||
fil_space_scrub_status_t* status);
|
||||
|
||||
#include "fil0crypt.ic"
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
|
|
|
@ -454,6 +454,7 @@ extern ulong srv_replication_delay;
|
|||
|
||||
extern my_bool innodb_encrypt_temporary_tables;
|
||||
|
||||
extern my_bool srv_immediate_scrub_data_uncompressed;
|
||||
/*-------------------------------------------*/
|
||||
|
||||
/** Modes of operation */
|
||||
|
@ -958,13 +959,6 @@ struct export_var_t{
|
|||
ulint innodb_encryption_rotation_estimated_iops;
|
||||
int64_t innodb_encryption_key_requests;
|
||||
int64_t innodb_key_rotation_list_length;
|
||||
|
||||
ulint innodb_scrub_page_reorganizations;
|
||||
ulint innodb_scrub_page_splits;
|
||||
ulint innodb_scrub_page_split_failures_underflow;
|
||||
ulint innodb_scrub_page_split_failures_out_of_filespace;
|
||||
ulint innodb_scrub_page_split_failures_missing_index;
|
||||
ulint innodb_scrub_page_split_failures_unknown;
|
||||
};
|
||||
|
||||
/** Thread slot in the thread table. */
|
||||
|
|
|
@ -72,7 +72,6 @@ Created 10/8/1995 Heikki Tuuri
|
|||
#include "fil0fil.h"
|
||||
#include "fil0crypt.h"
|
||||
#include "fil0pagecompress.h"
|
||||
#include "btr0scrub.h"
|
||||
|
||||
|
||||
#include <my_service_manager.h>
|
||||
|
@ -403,6 +402,8 @@ my_bool srv_force_primary_key;
|
|||
/** Key version to encrypt the temporary tablespace */
|
||||
my_bool innodb_encrypt_temporary_tables;
|
||||
|
||||
my_bool srv_immediate_scrub_data_uncompressed;
|
||||
|
||||
/* Array of English strings describing the current state of an
|
||||
i/o handler thread */
|
||||
|
||||
|
@ -1113,11 +1114,9 @@ srv_export_innodb_status(void)
|
|||
/*==========================*/
|
||||
{
|
||||
fil_crypt_stat_t crypt_stat;
|
||||
btr_scrub_stat_t scrub_stat;
|
||||
|
||||
if (!srv_read_only_mode) {
|
||||
fil_crypt_total_stat(&crypt_stat);
|
||||
btr_scrub_total_stat(&scrub_stat);
|
||||
}
|
||||
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
|
@ -1346,19 +1345,6 @@ srv_export_innodb_status(void)
|
|||
srv_stats.n_key_requests;
|
||||
export_vars.innodb_key_rotation_list_length =
|
||||
srv_stats.key_rotation_list_length;
|
||||
|
||||
export_vars.innodb_scrub_page_reorganizations =
|
||||
scrub_stat.page_reorganizations;
|
||||
export_vars.innodb_scrub_page_splits =
|
||||
scrub_stat.page_splits;
|
||||
export_vars.innodb_scrub_page_split_failures_underflow =
|
||||
scrub_stat.page_split_failures_underflow;
|
||||
export_vars.innodb_scrub_page_split_failures_out_of_filespace =
|
||||
scrub_stat.page_split_failures_out_of_filespace;
|
||||
export_vars.innodb_scrub_page_split_failures_missing_index =
|
||||
scrub_stat.page_split_failures_missing_index;
|
||||
export_vars.innodb_scrub_page_split_failures_unknown =
|
||||
scrub_stat.page_split_failures_unknown;
|
||||
}
|
||||
|
||||
mutex_exit(&srv_innodb_monitor_mutex);
|
||||
|
|
|
@ -100,7 +100,6 @@ Created 2/16/1996 Heikki Tuuri
|
|||
#include "os0event.h"
|
||||
#include "zlib.h"
|
||||
#include "ut0crc32.h"
|
||||
#include "btr0scrub.h"
|
||||
|
||||
/** Log sequence number at shutdown */
|
||||
lsn_t srv_shutdown_lsn;
|
||||
|
@ -2028,7 +2027,6 @@ skip_monitors:
|
|||
will flush dirty pages and that might need e.g.
|
||||
fil_crypt_threads_event. */
|
||||
fil_system_enter();
|
||||
btr_scrub_init();
|
||||
fil_crypt_threads_init();
|
||||
fil_system_exit();
|
||||
|
||||
|
@ -2136,7 +2134,6 @@ void innodb_shutdown()
|
|||
fts_optimize_shutdown(); dict_stats_shutdown(); */
|
||||
|
||||
fil_crypt_threads_cleanup();
|
||||
btr_scrub_cleanup();
|
||||
btr_defragment_shutdown();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue