diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 8590acfc060..7a10e401fa7 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1905,8 +1905,6 @@ static bool innodb_init_param() srv_buf_pool_size = (ulint) xtrabackup_use_memory; srv_buf_pool_chunk_unit = (ulong)srv_buf_pool_size; - srv_buf_pool_instances = 1; - srv_n_page_cleaners = 1; srv_n_file_io_threads = (ulint) innobase_file_io_threads; srv_n_read_io_threads = (ulint) innobase_read_io_threads; diff --git a/mysql-test/main/information_schema_all_engines.result b/mysql-test/main/information_schema_all_engines.result index 9ba4d20c76d..52bb151384d 100644 --- a/mysql-test/main/information_schema_all_engines.result +++ b/mysql-test/main/information_schema_all_engines.result @@ -99,9 +99,9 @@ GEOMETRY_COLUMNS F_TABLE_SCHEMA GLOBAL_STATUS VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME INDEX_STATISTICS TABLE_SCHEMA -INNODB_BUFFER_PAGE POOL_ID -INNODB_BUFFER_PAGE_LRU POOL_ID -INNODB_BUFFER_POOL_STATS POOL_ID +INNODB_BUFFER_PAGE BLOCK_ID +INNODB_BUFFER_PAGE_LRU LRU_POSITION +INNODB_BUFFER_POOL_STATS POOL_SIZE INNODB_CMP page_size INNODB_CMPMEM page_size INNODB_CMPMEM_RESET page_size @@ -180,9 +180,9 @@ GEOMETRY_COLUMNS F_TABLE_SCHEMA GLOBAL_STATUS VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME INDEX_STATISTICS TABLE_SCHEMA -INNODB_BUFFER_PAGE POOL_ID -INNODB_BUFFER_PAGE_LRU POOL_ID -INNODB_BUFFER_POOL_STATS POOL_ID +INNODB_BUFFER_PAGE BLOCK_ID +INNODB_BUFFER_PAGE_LRU LRU_POSITION +INNODB_BUFFER_POOL_STATS POOL_SIZE INNODB_CMP page_size INNODB_CMPMEM page_size INNODB_CMPMEM_RESET page_size diff --git a/mysql-test/main/sp-group.result b/mysql-test/main/sp-group.result index ce8dccfa2c9..9f370ff03fe 100644 --- a/mysql-test/main/sp-group.result +++ b/mysql-test/main/sp-group.result @@ -22,9 +22,9 @@ ORDER BY table1.NUMBER_RECORDS LIMIT 0 ; CALL s1; -POOL_ID LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK pk f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 +LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK pk f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 CALL s1; -POOL_ID LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK pk f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 +LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK pk f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 drop table t1; drop view view_t1; drop procedure s1; diff --git a/mysql-test/suite/innodb/r/innodb-page-cleaners.result b/mysql-test/suite/innodb/r/innodb-page-cleaners.result deleted file mode 100644 index 0954e42cf9f..00000000000 --- a/mysql-test/suite/innodb/r/innodb-page-cleaners.result +++ /dev/null @@ -1,45 +0,0 @@ -SET @saved_page_cleaners = @@GLOBAL.innodb_page_cleaners; -create table t1 (a int not null primary key auto_increment, -b bigint, -c varchar(200), -d int, -key b (b), -key d (d)) engine=INNODB; -set GLOBAL innodb_page_cleaners = 4; -connect con1,localhost,root,,; -connection con1; -update t1 set b = b + 5, d = d + 1 where a between 1 and 2000; -connect con2,localhost,root,,; -connection con2; -update t1 set b = b + 5, d = d + 1 where a between 3000 and 5000; -connect con3,localhost,root,,; -connection con3; -update t1 set b = b + 5, d = d + 1 where a between 8000 and 12000; -connection default; -set GLOBAL innodb_page_cleaners = 2; -set GLOBAL innodb_page_cleaners = 4; -set GLOBAL innodb_page_cleaners = 6; -connection con1; -connection con2; -connection con3; -connection default; -set GLOBAL innodb_page_cleaners = 4; -connection con1; -update t1 set b = b + 5, d = d + 1 where a between 1 and 2000; -connection con2; -update t1 set b = b + 5, d = d + 1 where a between 3000 and 5000; -connection con3; -update t1 set b = b + 5, d = d + 1 where a between 8000 and 12000; -connection default; -set GLOBAL innodb_page_cleaners = 3; -set GLOBAL innodb_page_cleaners = 2; -set GLOBAL innodb_page_cleaners = 1; -connection con1; -connection con2; -connection con3; -connection default; -disconnect con1; -disconnect con2; -disconnect con3; -DROP TABLE t1; -SET GLOBAL innodb_page_cleaners=@saved_page_cleaners; diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 1120fe25bb6..91b5a0284ac 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -27,11 +27,11 @@ database_name table_name index_name compress_ops compress_ops_ok compress_time u Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_cmp_per_index_reset but the InnoDB storage engine is not installed select * from information_schema.innodb_cmpmem; -page_size buffer_pool_instance pages_used pages_free relocation_ops relocation_time +page_size pages_used pages_free relocation_ops relocation_time Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_cmpmem but the InnoDB storage engine is not installed select * from information_schema.innodb_cmpmem_reset; -page_size buffer_pool_instance pages_used pages_free relocation_ops relocation_time +page_size pages_used pages_free relocation_ops relocation_time Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_cmpmem_reset but the InnoDB storage engine is not installed select * from information_schema.innodb_metrics; @@ -344,11 +344,11 @@ KEY VALUE Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_ft_config but the InnoDB storage engine is not installed select * from information_schema.innodb_buffer_page; -POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK +BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_buffer_page but the InnoDB storage engine is not installed select * from information_schema.innodb_buffer_page_lru; -POOL_ID LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK +LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_buffer_page_lru but the InnoDB storage engine is not installed select * from information_schema.innodb_buffer_stats; diff --git a/mysql-test/suite/innodb/t/innodb-page-cleaners.test b/mysql-test/suite/innodb/t/innodb-page-cleaners.test deleted file mode 100644 index 6f8accec30f..00000000000 --- a/mysql-test/suite/innodb/t/innodb-page-cleaners.test +++ /dev/null @@ -1,100 +0,0 @@ ---source include/have_innodb.inc -# This test is slow on buildbot. ---source include/big_test.inc - -SET @saved_page_cleaners = @@GLOBAL.innodb_page_cleaners; - -create table t1 (a int not null primary key auto_increment, -b bigint, -c varchar(200), -d int, -key b (b), -key d (d)) engine=INNODB; - -let $rows = 15000; ---disable_query_log -begin; -while ($rows) -{ - eval insert into t1 values(NULL, $rows, 'testing...', $rows+1000); - dec $rows; -} -commit; ---enable_query_log - -# -# We want 4 connections: (1) - (3) to create dirty pages -# and default to modify the number of page cleaner threads -# - -set GLOBAL innodb_page_cleaners = 4; - -connect (con1,localhost,root,,); -connection con1; -send update t1 set b = b + 5, d = d + 1 where a between 1 and 2000; - -connect (con2,localhost,root,,); -connection con2; -send update t1 set b = b + 5, d = d + 1 where a between 3000 and 5000; - - -connect (con3,localhost,root,,); -connection con3; -send update t1 set b = b + 5, d = d + 1 where a between 8000 and 12000; - -# -# Page cleaners are increased -# - -connection default; -set GLOBAL innodb_page_cleaners = 2; -set GLOBAL innodb_page_cleaners = 4; -set GLOBAL innodb_page_cleaners = 6; - -connection con1; -reap; - -connection con2; -reap; - -connection con3; -reap; - -connection default; -set GLOBAL innodb_page_cleaners = 4; - -# -# Page cleaners are decreased -# - -connection con1; -send update t1 set b = b + 5, d = d + 1 where a between 1 and 2000; - -connection con2; -send update t1 set b = b + 5, d = d + 1 where a between 3000 and 5000; - -connection con3; -send update t1 set b = b + 5, d = d + 1 where a between 8000 and 12000; - -connection default; -set GLOBAL innodb_page_cleaners = 3; -set GLOBAL innodb_page_cleaners = 2; -set GLOBAL innodb_page_cleaners = 1; - -connection con1; -reap; - -connection con2; -reap; - -connection con3; -reap; - -connection default; -disconnect con1; -disconnect con2; -disconnect con3; - -DROP TABLE t1; - -SET GLOBAL innodb_page_cleaners=@saved_page_cleaners; diff --git a/mysql-test/suite/innodb_i_s/innodb_buffer_page.result b/mysql-test/suite/innodb_i_s/innodb_buffer_page.result index 3ef5608e155..a212460457c 100644 --- a/mysql-test/suite/innodb_i_s/innodb_buffer_page.result +++ b/mysql-test/suite/innodb_i_s/innodb_buffer_page.result @@ -1,7 +1,6 @@ SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; Table Create Table INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` ( - `POOL_ID` int(11) unsigned NOT NULL DEFAULT 0, `BLOCK_ID` bigint(21) unsigned NOT NULL DEFAULT 0, `SPACE` int(11) unsigned NOT NULL DEFAULT 0, `PAGE_NUMBER` int(11) unsigned NOT NULL DEFAULT 0, diff --git a/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result b/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result index 73871eb2eda..cfdb526663b 100644 --- a/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result +++ b/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result @@ -1,7 +1,6 @@ SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU; Table Create Table INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` ( - `POOL_ID` int(11) unsigned NOT NULL DEFAULT 0, `LRU_POSITION` bigint(21) unsigned NOT NULL DEFAULT 0, `SPACE` int(11) unsigned NOT NULL DEFAULT 0, `PAGE_NUMBER` int(11) unsigned NOT NULL DEFAULT 0, diff --git a/mysql-test/suite/innodb_i_s/innodb_buffer_pool_stats.result b/mysql-test/suite/innodb_i_s/innodb_buffer_pool_stats.result index be5c31a6b57..7282b8e97d7 100644 --- a/mysql-test/suite/innodb_i_s/innodb_buffer_pool_stats.result +++ b/mysql-test/suite/innodb_i_s/innodb_buffer_pool_stats.result @@ -1,7 +1,6 @@ SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; Table Create Table INNODB_BUFFER_POOL_STATS CREATE TEMPORARY TABLE `INNODB_BUFFER_POOL_STATS` ( - `POOL_ID` int(11) unsigned NOT NULL DEFAULT 0, `POOL_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `FREE_BUFFERS` bigint(21) unsigned NOT NULL DEFAULT 0, `DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT 0, diff --git a/mysql-test/suite/innodb_i_s/innodb_cmpmem.result b/mysql-test/suite/innodb_i_s/innodb_cmpmem.result index e1dd5d0a314..adb80fe4c39 100644 --- a/mysql-test/suite/innodb_i_s/innodb_cmpmem.result +++ b/mysql-test/suite/innodb_i_s/innodb_cmpmem.result @@ -2,7 +2,6 @@ SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_CMPMEM; Table Create Table INNODB_CMPMEM CREATE TEMPORARY TABLE `INNODB_CMPMEM` ( `page_size` int(5) NOT NULL DEFAULT 0, - `buffer_pool_instance` int(11) NOT NULL DEFAULT 0, `pages_used` int(11) NOT NULL DEFAULT 0, `pages_free` int(11) NOT NULL DEFAULT 0, `relocation_ops` bigint(21) NOT NULL DEFAULT 0, diff --git a/mysql-test/suite/innodb_i_s/innodb_cmpmem_reset.result b/mysql-test/suite/innodb_i_s/innodb_cmpmem_reset.result index 178cd244f9a..3eea4c2e265 100644 --- a/mysql-test/suite/innodb_i_s/innodb_cmpmem_reset.result +++ b/mysql-test/suite/innodb_i_s/innodb_cmpmem_reset.result @@ -2,7 +2,6 @@ SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_CMPMEM_RESET; Table Create Table INNODB_CMPMEM_RESET CREATE TEMPORARY TABLE `INNODB_CMPMEM_RESET` ( `page_size` int(5) NOT NULL DEFAULT 0, - `buffer_pool_instance` int(11) NOT NULL DEFAULT 0, `pages_used` int(11) NOT NULL DEFAULT 0, `pages_free` int(11) NOT NULL DEFAULT 0, `relocation_ops` bigint(21) NOT NULL DEFAULT 0, diff --git a/mysql-test/suite/sys_vars/r/innodb_page_cleaners_basic.result b/mysql-test/suite/sys_vars/r/innodb_page_cleaners_basic.result index 3113d77668c..db9d94c5fac 100644 --- a/mysql-test/suite/sys_vars/r/innodb_page_cleaners_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_page_cleaners_basic.result @@ -7,32 +7,40 @@ SELECT @@innodb_page_cleaners; 1 1 Expected SET @@GLOBAL.innodb_page_cleaners=2; +Warnings: +Warning 138 The parameter innodb_page_cleaners is deprecated and has no effect. Expected to pass SELECT @@innodb_page_cleaners; @@innodb_page_cleaners -2 +1 2 Expected SET @@GLOBAL.innodb_page_cleaners=1; +Warnings: +Warning 138 The parameter innodb_page_cleaners is deprecated and has no effect. Expected to pass SELECT @@innodb_page_cleaners; @@innodb_page_cleaners 1 1 Expected SET @@GLOBAL.innodb_page_cleaners=6; +Warnings: +Warning 138 The parameter innodb_page_cleaners is deprecated and has no effect. Expected to pass SELECT @@innodb_page_cleaners; @@innodb_page_cleaners -6 +1 6 Expected SET @@GLOBAL.innodb_page_cleaners=4; +Warnings: +Warning 138 The parameter innodb_page_cleaners is deprecated and has no effect. Expected to pass SELECT @@innodb_page_cleaners; @@innodb_page_cleaners -4 +1 4 Expected SET @@GLOBAL.innodb_page_cleaners=0; Warnings: -Warning 1292 Truncated incorrect innodb_page_cleaners value: '0' +Warning 138 The parameter innodb_page_cleaners is deprecated and has no effect. Warning expected SELECT @@innodb_page_cleaners; @@innodb_page_cleaners diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff index 60be1dc78a0..b8400fbcea7 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff @@ -42,7 +42,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Size of a single memory chunk within each buffer pool instance for resizing buffer pool. Online buffer pool resizing happens at this granularity. 0 means disable resizing buffer pool. + VARIABLE_COMMENT Size of a single memory chunk for resizing buffer pool. Online buffer pool resizing happens at this granularity. 0 means disable resizing buffer pool. NUMERIC_MIN_VALUE 1048576 -NUMERIC_MAX_VALUE 9223372036854775807 +NUMERIC_MAX_VALUE 2147483647 @@ -64,7 +64,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Number of buffer pool instances, set to higher value on high-end machines to increase scalability + VARIABLE_COMMENT Deprecated parameter with no effect. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 64 @@ -289,7 +289,7 @@ @@ -377,8 +377,8 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Page cleaner threads can be from 1 to 64. Default is 4. - NUMERIC_MIN_VALUE 1 + VARIABLE_COMMENT Deprecated parameter with no effect. + NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 64 @@ -1513,7 +1513,7 @@ SESSION_VALUE NULL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 4c77e964aad..4afe97d80f3 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -158,7 +158,7 @@ SESSION_VALUE NULL DEFAULT_VALUE 134217728 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Size of a single memory chunk within each buffer pool instance for resizing buffer pool. Online buffer pool resizing happens at this granularity. 0 means disable resizing buffer pool. +VARIABLE_COMMENT Size of a single memory chunk for resizing buffer pool. Online buffer pool resizing happens at this granularity. 0 means disable resizing buffer pool. NUMERIC_MIN_VALUE 1048576 NUMERIC_MAX_VALUE 9223372036854775807 NUMERIC_BLOCK_SIZE 1048576 @@ -230,7 +230,7 @@ SESSION_VALUE NULL DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Number of buffer pool instances, set to higher value on high-end machines to increase scalability +VARIABLE_COMMENT Deprecated parameter with no effect. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 64 NUMERIC_BLOCK_SIZE 0 @@ -1487,11 +1487,11 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT NONE VARIABLE_NAME INNODB_PAGE_CLEANERS SESSION_VALUE NULL -DEFAULT_VALUE 4 +DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Page cleaner threads can be from 1 to 64. Default is 4. -NUMERIC_MIN_VALUE 1 +VARIABLE_COMMENT Deprecated parameter with no effect. +NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 64 NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL diff --git a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_pct_function.opt b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_pct_function.opt index 8d74d91426a..787f6ce532d 100644 --- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_pct_function.opt +++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_pct_function.opt @@ -2,5 +2,4 @@ --loose-innodb_buffer_pool_load_at_startup=0 --loose-innodb_buffer_pool_dump_at_shutdown=0 --loose-innodb-buffer-pool-size=8M ---loose-innodb-buffer-pool-instances=1 --loose-innodb-page-size=16k diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 88af5003d25..3414e05ffb8 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1391,7 +1391,6 @@ btr_page_reorganize_low( mtr_t* mtr) /*!< in/out: mini-transaction */ { buf_block_t* block = page_cur_get_block(cursor); - buf_pool_t* buf_pool = buf_pool_from_bpage(&block->page); page_t* page = buf_block_get_frame(block); page_zip_des_t* page_zip = buf_block_get_page_zip(block); buf_block_t* temp_block; @@ -1420,7 +1419,7 @@ btr_page_reorganize_low( /* Turn logging off */ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); - temp_block = buf_block_alloc(buf_pool); + temp_block = buf_block_alloc(); MONITOR_INC(MONITOR_INDEX_REORG_ATTEMPTS); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 2842600cdf6..6f20ae7ff44 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1461,7 +1461,7 @@ btr_cur_search_to_nth_level_func( for them, when the history list is glowing huge. */ if (lock_intention == BTR_INTENTION_DELETE && trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH - && buf_get_n_pending_read_ios()) { + && buf_pool->n_pend_reads) { x_latch_index: mtr_x_lock_index(index, mtr); } else if (index->is_spatial() @@ -2590,7 +2590,7 @@ btr_cur_open_at_index_side_func( for them, when the history list is glowing huge. */ if (lock_intention == BTR_INTENTION_DELETE && trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH - && buf_get_n_pending_read_ios()) { + && buf_pool->n_pend_reads) { mtr_x_lock_index(index, mtr); } else { mtr_sx_lock_index(index, mtr); @@ -2917,7 +2917,7 @@ btr_cur_open_at_rnd_pos_func( for them, when the history list is glowing huge. */ if (lock_intention == BTR_INTENTION_DELETE && trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH - && buf_get_n_pending_read_ios()) { + && buf_pool->n_pend_reads) { mtr_x_lock_index(index, mtr); } else { mtr_sx_lock_index(index, mtr); @@ -7267,7 +7267,6 @@ btr_blob_free( if there is one */ mtr_t* mtr) /*!< in: mini-transaction to commit */ { - buf_pool_t* buf_pool = buf_pool_from_block(block); ulint space = block->page.id.space(); ulint page_no = block->page.id.page_no(); @@ -7275,7 +7274,7 @@ btr_blob_free( mtr_commit(mtr); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); /* Only free the block if it is still allocated to the same file page. */ @@ -7294,7 +7293,7 @@ btr_blob_free( } } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } /** Helper class used while writing blob pages, during insert or update. */ diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index ae30dec61ca..5522ba54b96 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -206,7 +206,7 @@ btr_search_check_free_space_in_heap(const dict_index_t* index) be enough free space in the hash table. */ if (heap->free_block == NULL) { - buf_block_t* block = buf_block_alloc(NULL); + buf_block_t* block = buf_block_alloc(); rw_lock_t* ahi_latch = btr_get_search_latch(index); rw_lock_x_lock(ahi_latch); @@ -408,12 +408,12 @@ void btr_search_disable(bool need_mutex) /** Enable the adaptive hash search system. */ void btr_search_enable() { - buf_pool_mutex_enter_all(); + mutex_enter(&buf_pool->mutex); if (srv_buf_pool_old_size != srv_buf_pool_size) { - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); return; } - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); btr_search_x_lock_all(); btr_search_enabled = true; @@ -949,7 +949,6 @@ fail: } buf_block_t* block = buf_block_from_ahi(rec); - buf_pool_t* buf_pool = buf_pool_from_block(block); if (use_latch) { mutex_enter(&block->mutex); @@ -968,7 +967,7 @@ fail: buf_block_buf_fix_inc(block, __FILE__, __LINE__); mutex_exit(&block->mutex); - buf_page_make_young_if_needed(buf_pool, &block->page); + buf_page_make_young_if_needed(&block->page); mtr_memo_type_t fix_type; if (latch_mode == BTR_SEARCH_LEAF) { if (!rw_lock_s_lock_nowait(&block->lock, @@ -1081,7 +1080,7 @@ got_no_latch: ++buf_pool->stat.n_page_gets; if (!ahi_latch) { - buf_page_make_young_if_needed(buf_pool, &block->page); + buf_page_make_young_if_needed(&block->page); } return true; @@ -1994,23 +1993,23 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs_init(offsets_); btr_search_x_lock_all(); - buf_pool_mutex_enter_all(); + mutex_enter(&buf_pool->mutex); cell_count = hash_get_n_cells( - btr_search_sys->hash_tables[hash_table_id]); + btr_search_sys->hash_tables[hash_table_id]); for (i = 0; i < cell_count; i++) { /* We release search latches every once in a while to give other queries a chance to run. */ if ((i != 0) && ((i % chunk_size) == 0)) { - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); btr_search_x_unlock_all(); os_thread_yield(); btr_search_x_lock_all(); - buf_pool_mutex_enter_all(); + mutex_enter(&buf_pool->mutex); ulint curr_cell_count = hash_get_n_cells( btr_search_sys->hash_tables[hash_table_id]); @@ -2032,11 +2031,8 @@ btr_search_hash_table_validate(ulint hash_table_id) const buf_block_t* block = buf_block_from_ahi((byte*) node->data); const buf_block_t* hash_block; - buf_pool_t* buf_pool; index_id_t page_index_id; - buf_pool = buf_pool_from_bpage((buf_page_t*) block); - if (UNIV_LIKELY(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE)) { @@ -2046,7 +2042,6 @@ btr_search_hash_table_validate(ulint hash_table_id) (BUF_BLOCK_REMOVE_HASH, see the assertion and the comment below) */ hash_block = buf_block_hash_get( - buf_pool, block->page.id); } else { hash_block = NULL; @@ -2120,14 +2115,13 @@ btr_search_hash_table_validate(ulint hash_table_id) /* We release search latches every once in a while to give other queries a chance to run. */ if (i != 0) { - - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); btr_search_x_unlock_all(); os_thread_yield(); btr_search_x_lock_all(); - buf_pool_mutex_enter_all(); + mutex_enter(&buf_pool->mutex); ulint curr_cell_count = hash_get_n_cells( btr_search_sys->hash_tables[hash_table_id]); @@ -2150,7 +2144,7 @@ btr_search_hash_table_validate(ulint hash_table_id) } } - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); btr_search_x_unlock_all(); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index 0942a962b4d..7e3c06892a0 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2019, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -181,13 +181,8 @@ struct CheckZipFree { }; /** Validate a buddy list. -@param[in] buf_pool buffer pool instance @param[in] i buddy size to validate */ -static -void -buf_buddy_list_validate( - const buf_pool_t* buf_pool, - ulint i) +static void buf_buddy_list_validate(ulint i) { ut_list_validate(buf_pool->zip_free[i], CheckZipFree(i)); } @@ -195,18 +190,14 @@ buf_buddy_list_validate( /**********************************************************************//** Debug function to validate that a buffer is indeed free i.e.: in the zip_free[]. +@param[in] buf block to check +@param[in] i index of buf_pool->zip_free[] @return true if free */ -UNIV_INLINE -bool -buf_buddy_check_free( -/*=================*/ - buf_pool_t* buf_pool,/*!< in: buffer pool instance */ - const buf_buddy_free_t* buf, /*!< in: block to check */ - ulint i) /*!< in: index of buf_pool->zip_free[] */ +static bool buf_buddy_check_free(const buf_buddy_free_t* buf, ulint i) { const ulint size = BUF_BUDDY_LOW << i; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!ut_align_offset(buf, size)); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); @@ -268,90 +259,75 @@ buf_buddy_is_free( : BUF_BUDDY_STATE_PARTIALLY_USED); } -/**********************************************************************//** -Add a block to the head of the appropriate buddy free list. */ +/** Add a block to the head of the appropriate buddy free list. +@param[in,out] buf block to be freed +@param[in] i index of buf_pool->zip_free[] */ UNIV_INLINE void -buf_buddy_add_to_free( -/*==================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_buddy_free_t* buf, /*!< in,own: block to be freed */ - ulint i) /*!< in: index of - buf_pool->zip_free[] */ +buf_buddy_add_to_free(buf_buddy_free_t* buf, ulint i) { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_pool->zip_free[i].start != buf); buf_buddy_stamp_free(buf, i); UT_LIST_ADD_FIRST(buf_pool->zip_free[i], buf); - ut_d(buf_buddy_list_validate(buf_pool, i)); + ut_d(buf_buddy_list_validate(i)); } -/**********************************************************************//** -Remove a block from the appropriate buddy free list. */ +/** Remove a block from the appropriate buddy free list. +@param[in,out] buf block to be freed +@param[in] i index of buf_pool->zip_free[] */ UNIV_INLINE void -buf_buddy_remove_from_free( -/*=======================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_buddy_free_t* buf, /*!< in,own: block to be - freed */ - ulint i) /*!< in: index of - buf_pool->zip_free[] */ +buf_buddy_remove_from_free(buf_buddy_free_t* buf, ulint i) { - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(buf_buddy_check_free(buf_pool, buf, i)); + ut_ad(mutex_own(&buf_pool->mutex)); + ut_ad(buf_buddy_check_free(buf, i)); UT_LIST_REMOVE(buf_pool->zip_free[i], buf); buf_buddy_stamp_nonfree(buf, i); } -/**********************************************************************//** -Try to allocate a block from buf_pool->zip_free[]. +/** Try to allocate a block from buf_pool->zip_free[]. +@param[in] i index of buf_pool->zip_free[] @return allocated block, or NULL if buf_pool->zip_free[] was empty */ -static -buf_buddy_free_t* -buf_buddy_alloc_zip( -/*================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint i) /*!< in: index of buf_pool->zip_free[] */ +static buf_buddy_free_t* buf_buddy_alloc_zip(ulint i) { buf_buddy_free_t* buf; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_a(i < BUF_BUDDY_SIZES); ut_a(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); - ut_d(buf_buddy_list_validate(buf_pool, i)); + ut_d(buf_buddy_list_validate(i)); buf = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); if (buf_pool->curr_size < buf_pool->old_size && UT_LIST_GET_LEN(buf_pool->withdraw) - < buf_pool->withdraw_target) { + < buf_pool->withdraw_target) { while (buf != NULL - && buf_frame_will_withdrawn( - buf_pool, reinterpret_cast(buf))) { + && buf_frame_will_be_withdrawn( + reinterpret_cast(buf))) { /* This should be withdrawn, not to be allocated */ buf = UT_LIST_GET_NEXT(list, buf); } } if (buf) { - buf_buddy_remove_from_free(buf_pool, buf, i); + buf_buddy_remove_from_free(buf, i); } else if (i + 1 < BUF_BUDDY_SIZES) { /* Attempt to split. */ - buf = buf_buddy_alloc_zip(buf_pool, i + 1); + buf = buf_buddy_alloc_zip(i + 1); if (buf) { buf_buddy_free_t* buddy = reinterpret_cast( buf->stamp.bytes + (BUF_BUDDY_LOW << i)); - - ut_ad(!buf_pool_contains_zip(buf_pool, buddy)); - buf_buddy_add_to_free(buf_pool, buddy, i); + ut_ad(!buf_pool_contains_zip(buddy)); + buf_buddy_add_to_free(buddy, i); } } @@ -370,20 +346,17 @@ buf_buddy_alloc_zip( return(buf); } -/**********************************************************************//** -Deallocate a buffer frame of srv_page_size. */ +/** Deallocate a buffer frame of srv_page_size. +@param[in] buf buffer frame to deallocate */ static void -buf_buddy_block_free( -/*=================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* buf) /*!< in: buffer frame to deallocate */ +buf_buddy_block_free(void* buf) { const ulint fold = BUF_POOL_ZIP_FOLD_PTR(buf); buf_page_t* bpage; buf_block_t* block; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_a(!ut_align_offset(buf, srv_page_size)); @@ -418,9 +391,8 @@ buf_buddy_block_register( /*=====================*/ buf_block_t* block) /*!< in: buffer frame to allocate */ { - buf_pool_t* buf_pool = buf_pool_from_block(block); const ulint fold = BUF_POOL_ZIP_FOLD(block); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE); @@ -437,19 +409,14 @@ buf_buddy_block_register( ut_d(buf_pool->buddy_n_frames++); } -/**********************************************************************//** -Allocate a block from a bigger object. +/** Allocate a block from a bigger object. +@param[in] buf a block that is free to use +@param[in] i index of buf_pool->zip_free[] +@param[in] j size of buf as an index of buf_pool->zip_free[] @return allocated block */ static void* -buf_buddy_alloc_from( -/*=================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* buf, /*!< in: a block that is free to use */ - ulint i, /*!< in: index of - buf_pool->zip_free[] */ - ulint j) /*!< in: size of buf as an index - of buf_pool->zip_free[] */ +buf_buddy_alloc_from(void* buf, ulint i, ulint j) { ulint offs = BUF_BUDDY_LOW << j; ut_ad(j <= BUF_BUDDY_SIZES); @@ -466,39 +433,28 @@ buf_buddy_alloc_from( zip_buf = reinterpret_cast( reinterpret_cast(buf) + offs); - buf_buddy_add_to_free(buf_pool, zip_buf, j); + buf_buddy_add_to_free(zip_buf, j); } buf_buddy_stamp_nonfree(reinterpret_cast(buf), i); return(buf); } -/**********************************************************************//** -Allocate a block. The thread calling this function must hold -buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex. -The buf_pool_mutex may be released and reacquired. +/** Allocate a block. +@param[in] i index of buf_pool->zip_free[] or BUF_BUDDY_SIZES +@param[out] lru whether buf_pool->mutex was temporarily released @return allocated block, never NULL */ -void* -buf_buddy_alloc_low( -/*================*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ - ulint i, /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ - bool* lru) /*!< in: pointer to a variable that - will be assigned true if storage was - allocated from the LRU list and - buf_pool->mutex was temporarily - released */ +byte *buf_buddy_alloc_low(ulint i, bool *lru) { buf_block_t* block; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); if (i < BUF_BUDDY_SIZES) { /* Try to allocate from the buddy system. */ - block = (buf_block_t*) buf_buddy_alloc_zip(buf_pool, i); + block = (buf_block_t*) buf_buddy_alloc_zip(i); if (block) { goto func_exit; @@ -506,51 +462,46 @@ buf_buddy_alloc_low( } /* Try allocating from the buf_pool->free list. */ - block = buf_LRU_get_free_only(buf_pool); + block = buf_LRU_get_free_only(); if (block) { - goto alloc_big; } /* Try replacing an uncompressed page in the buffer pool. */ - buf_pool_mutex_exit(buf_pool); - block = buf_LRU_get_free_block(buf_pool); - *lru = true; - buf_pool_mutex_enter(buf_pool); + mutex_exit(&buf_pool->mutex); + block = buf_LRU_get_free_block(); + mutex_enter(&buf_pool->mutex); + if (lru) { + *lru = true; + } alloc_big: buf_buddy_block_register(block); block = (buf_block_t*) buf_buddy_alloc_from( - buf_pool, block->frame, i, BUF_BUDDY_SIZES); + block->frame, i, BUF_BUDDY_SIZES); func_exit: buf_pool->buddy_stat[i].used++; - return(block); + return reinterpret_cast(block); } -/**********************************************************************//** -Try to relocate a block. +/** Try to relocate a block. The caller must hold zip_free_mutex, and this +function will release and lock it again. +@param[in] src block to relocate +@param[in] dst free block to relocated to +@param[in] i index of buf_pool->zip_free[] +@param[in] force true if we must relocated always @return true if relocated */ -static -bool -buf_buddy_relocate( -/*===============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* src, /*!< in: block to relocate */ - void* dst, /*!< in: free block to relocate to */ - ulint i, /*!< in: index of - buf_pool->zip_free[] */ - bool force) /*!< in: true if we must relocate - always */ +static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) { buf_page_t* bpage; const ulint size = BUF_BUDDY_LOW << i; ulint space; ulint offset; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(!ut_align_offset(src, size)); ut_ad(!ut_align_offset(dst, size)); @@ -571,17 +522,11 @@ buf_buddy_relocate( const page_id_t page_id(space, offset); - /* If space,offset is bogus, then we know that the - buf_page_hash_get_low() call below will return NULL. */ - if (!force && buf_pool != buf_pool_get(page_id)) { - return(false); - } - - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + rw_lock_t* hash_lock = buf_page_hash_lock_get(page_id); rw_lock_x_lock(hash_lock); - bpage = buf_page_hash_get_low(buf_pool, page_id); + bpage = buf_page_hash_get_low(page_id); if (!bpage || bpage->zip.data != src) { /* The block has probably been freshly @@ -601,8 +546,7 @@ buf_buddy_relocate( bpage = UT_LIST_GET_FIRST(buf_pool->LRU); while (bpage != NULL) { if (bpage->zip.data == src) { - hash_lock = buf_page_hash_lock_get( - buf_pool, bpage->id); + hash_lock = buf_page_hash_lock_get(bpage->id); rw_lock_x_lock(hash_lock); break; } @@ -661,20 +605,15 @@ buf_buddy_relocate( return(false); } -/**********************************************************************//** -Deallocate a block. */ -void -buf_buddy_free_low( -/*===============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* buf, /*!< in: block to be freed, must not be - pointed to by the buffer pool */ - ulint i) /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ +/** Deallocate a block. +@param[in] buf block to be freed, must not be pointed to + by the buffer pool +@param[in] i index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ +void buf_buddy_free_low(void* buf, ulint i) { buf_buddy_free_t* buddy; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(i <= BUF_BUDDY_SIZES); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); @@ -685,13 +624,13 @@ recombine: UNIV_MEM_ALLOC(buf, BUF_BUDDY_LOW << i); if (i == BUF_BUDDY_SIZES) { - buf_buddy_block_free(buf_pool, buf); + buf_buddy_block_free(buf); return; } ut_ad(i < BUF_BUDDY_SIZES); ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i)); - ut_ad(!buf_pool_contains_zip(buf_pool, buf)); + ut_ad(!buf_pool_contains_zip(buf)); /* Do not recombine blocks if there are few free blocks. We may waste up to 15360*max_len bytes to free blocks @@ -709,16 +648,16 @@ recombine: switch (buf_buddy_is_free(buddy, i)) { case BUF_BUDDY_STATE_FREE: /* The buddy is free: recombine */ - buf_buddy_remove_from_free(buf_pool, buddy, i); + buf_buddy_remove_from_free(buddy, i); buddy_is_free: - ut_ad(!buf_pool_contains_zip(buf_pool, buddy)); + ut_ad(!buf_pool_contains_zip(buddy)); i++; buf = ut_align_down(buf, BUF_BUDDY_LOW << i); goto recombine; case BUF_BUDDY_STATE_USED: - ut_d(buf_buddy_list_validate(buf_pool, i)); + ut_d(buf_buddy_list_validate(i)); /* The buddy is not free. Is there a free block of this size? */ @@ -728,17 +667,15 @@ buddy_is_free: /* Remove the block from the free list, because a successful buf_buddy_relocate() will overwrite zip_free->list. */ - buf_buddy_remove_from_free(buf_pool, zip_buf, i); + buf_buddy_remove_from_free(zip_buf, i); /* Try to relocate the buddy of buf to the free block. */ - if (buf_buddy_relocate(buf_pool, buddy, zip_buf, i, - false)) { - + if (buf_buddy_relocate(buddy, zip_buf, i, false)) { goto buddy_is_free; } - buf_buddy_add_to_free(buf_pool, zip_buf, i); + buf_buddy_add_to_free(zip_buf, i); } break; @@ -750,40 +687,32 @@ buddy_is_free: func_exit: /* Free the block to the buddy list. */ - buf_buddy_add_to_free(buf_pool, - reinterpret_cast(buf), - i); + buf_buddy_add_to_free(reinterpret_cast(buf), i); } -/** Reallocate a block. -@param[in] buf_pool buffer pool instance -@param[in] buf block to be reallocated, must be pointed -to by the buffer pool -@param[in] size block size, up to srv_page_size -@retval false if failed because of no free blocks. */ +/** Try to reallocate a block. +@param[in] buf buf_pool block to be reallocated +@param[in] size block size, up to srv_page_size +@return whether the reallocation succeeded */ bool -buf_buddy_realloc( - buf_pool_t* buf_pool, - void* buf, - ulint size) +buf_buddy_realloc(void* buf, ulint size) { buf_block_t* block = NULL; ulint i = buf_buddy_get_slot(size); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(i <= BUF_BUDDY_SIZES); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); if (i < BUF_BUDDY_SIZES) { /* Try to allocate from the buddy system. */ - block = reinterpret_cast( - buf_buddy_alloc_zip(buf_pool, i)); + block = reinterpret_cast(buf_buddy_alloc_zip(i)); } if (block == NULL) { /* Try allocating from the buf_pool->free list. */ - block = buf_LRU_get_free_only(buf_pool); + block = buf_LRU_get_free_only(); if (block == NULL) { return(false); /* free_list was not enough */ @@ -793,30 +722,27 @@ buf_buddy_realloc( block = reinterpret_cast( buf_buddy_alloc_from( - buf_pool, block->frame, i, BUF_BUDDY_SIZES)); + block->frame, i, BUF_BUDDY_SIZES)); } buf_pool->buddy_stat[i].used++; /* Try to relocate the buddy of buf to the free block. */ - if (buf_buddy_relocate(buf_pool, buf, block, i, true)) { + if (buf_buddy_relocate(buf, block, i, true)) { /* succeeded */ - buf_buddy_free_low(buf_pool, buf, i); + buf_buddy_free_low(buf, i); } else { /* failed */ - buf_buddy_free_low(buf_pool, block, i); + buf_buddy_free_low(block, i); } return(true); /* free_list was enough */ } -/** Combine all pairs of free buddies. -@param[in] buf_pool buffer pool instance */ -void -buf_buddy_condense_free( - buf_pool_t* buf_pool) +/** Combine all pairs of free buddies. */ +void buf_buddy_condense_free() { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_pool->curr_size < buf_pool->old_size); for (ulint i = 0; i < UT_ARR_SIZE(buf_pool->zip_free); ++i) { @@ -825,8 +751,8 @@ buf_buddy_condense_free( /* seek to withdraw target */ while (buf != NULL - && !buf_frame_will_withdrawn( - buf_pool, reinterpret_cast(buf))) { + && !buf_frame_will_be_withdrawn( + reinterpret_cast(buf))) { buf = UT_LIST_GET_NEXT(list, buf); } @@ -843,8 +769,7 @@ buf_buddy_condense_free( /* seek to the next withdraw target */ while (true) { while (next != NULL - && !buf_frame_will_withdrawn( - buf_pool, + && !buf_frame_will_be_withdrawn( reinterpret_cast(next))) { next = UT_LIST_GET_NEXT(list, next); } @@ -860,10 +785,10 @@ buf_buddy_condense_free( == BUF_BUDDY_STATE_FREE) { /* Both buf and buddy are free. Try to combine them. */ - buf_buddy_remove_from_free(buf_pool, buf, i); + buf_buddy_remove_from_free(buf, i); buf_pool->buddy_stat[i].used++; - buf_buddy_free_low(buf_pool, buf, i); + buf_buddy_free_low(buf, i); } buf = next; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index c8497b7b884..71078622486 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -311,8 +311,8 @@ static const ulint BUF_READ_AHEAD_PAGES = 64; read-ahead buffer. (Divide buf_pool size by this amount) */ static const ulint BUF_READ_AHEAD_PORTION = 32; -/** The buffer pools of the database */ -buf_pool_t* buf_pool_ptr; +/** The buffer pool of the database */ +buf_pool_t* buf_pool; /** true when resizing buffer pool is in the critical path. */ volatile bool buf_pool_resizing; @@ -443,7 +443,6 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space) ((buf_block_t*) bpage)->frame; bool page_compressed = space->is_compressed() && buf_page_is_compressed(dst_frame, space->flags); - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); if (bpage->id.page_no() == 0) { /* File header pages are not encrypted/compressed */ @@ -541,53 +540,28 @@ decrypt_failed: return true; } -/********************************************************************//** -Gets the smallest oldest_modification lsn for any page in the pool. Returns -zero if all modified pages have been flushed to disk. -@return oldest modification in pool, zero if none */ +/** +@return the smallest oldest_modification lsn for any page. +@retval 0 if all modified persistent pages have been flushed */ lsn_t -buf_pool_get_oldest_modification(void) -/*==================================*/ +buf_pool_get_oldest_modification() { - lsn_t lsn = 0; - lsn_t oldest_lsn = 0; + mutex_enter(&buf_pool->flush_list_mutex); - /* When we traverse all the flush lists we don't want another - thread to add a dirty page to any flush list. */ - log_flush_order_mutex_enter(); + buf_page_t* bpage; - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_flush_list_mutex_enter(buf_pool); - - buf_page_t* bpage; - - /* We don't let log-checkpoint halt because pages from system - temporary are not yet flushed to the disk. Anyway, object - residing in system temporary doesn't generate REDO logging. */ - for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); - bpage != NULL - && fsp_is_system_temporary(bpage->id.space()); - bpage = UT_LIST_GET_PREV(list, bpage)) { - /* Do nothing. */ - } - - if (bpage != NULL) { - ut_ad(bpage->in_flush_list); - lsn = bpage->oldest_modification; - } - - buf_flush_list_mutex_exit(buf_pool); - - if (!oldest_lsn || oldest_lsn > lsn) { - oldest_lsn = lsn; - } + /* FIXME: Keep temporary tablespace pages in a separate flush + list. We would only need to write out temporary pages if the + page is about to be evicted from the buffer pool, and the page + contents is still needed (the page has not been freed). */ + for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); + bpage != NULL && fsp_is_system_temporary(bpage->id.space()); + bpage = UT_LIST_GET_PREV(list, bpage)) { + ut_ad(bpage->in_flush_list); } - log_flush_order_mutex_exit(); + lsn_t oldest_lsn = bpage ? bpage->oldest_modification : 0; + mutex_exit(&buf_pool->flush_list_mutex); /* The returned answer may be out of date: the flush_list can change after the mutex has been released. */ @@ -595,115 +569,13 @@ buf_pool_get_oldest_modification(void) return(oldest_lsn); } -/********************************************************************//** -Get total buffer pool statistics. */ -void -buf_get_total_list_len( -/*===================*/ - ulint* LRU_len, /*!< out: length of all LRU lists */ - ulint* free_len, /*!< out: length of all free lists */ - ulint* flush_list_len) /*!< out: length of all flush lists */ -{ - ulint i; - - *LRU_len = 0; - *free_len = 0; - *flush_list_len = 0; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - *LRU_len += UT_LIST_GET_LEN(buf_pool->LRU); - *free_len += UT_LIST_GET_LEN(buf_pool->free); - *flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list); - } -} - -/********************************************************************//** -Get total list size in bytes from all buffer pools. */ -void -buf_get_total_list_size_in_bytes( -/*=============================*/ - buf_pools_list_size_t* buf_pools_list_size) /*!< out: list sizes - in all buffer pools */ -{ - ut_ad(buf_pools_list_size); - memset(buf_pools_list_size, 0, sizeof(*buf_pools_list_size)); - - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - /* We don't need mutex protection since this is - for statistics purpose */ - buf_pools_list_size->LRU_bytes += buf_pool->stat.LRU_bytes; - buf_pools_list_size->unzip_LRU_bytes += - UT_LIST_GET_LEN(buf_pool->unzip_LRU) - << srv_page_size_shift; - buf_pools_list_size->flush_list_bytes += - buf_pool->stat.flush_list_bytes; - } -} - -/********************************************************************//** -Get total buffer pool statistics. */ -void -buf_get_total_stat( -/*===============*/ - buf_pool_stat_t* tot_stat) /*!< out: buffer pool stats */ -{ - ulint i; - - memset(tot_stat, 0, sizeof(*tot_stat)); - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_stat_t*buf_stat; - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_stat = &buf_pool->stat; - tot_stat->n_page_gets += buf_stat->n_page_gets; - tot_stat->n_pages_read += buf_stat->n_pages_read; - tot_stat->n_pages_written += buf_stat->n_pages_written; - tot_stat->n_pages_created += buf_stat->n_pages_created; - tot_stat->n_ra_pages_read_rnd += buf_stat->n_ra_pages_read_rnd; - tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read; - tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted; - tot_stat->n_pages_made_young += buf_stat->n_pages_made_young; - - tot_stat->n_pages_not_made_young += - buf_stat->n_pages_not_made_young; - } -} - -/********************************************************************//** -Allocates a buffer block. +/** Allocate a buffer block. @return own: the allocated block, in state BUF_BLOCK_MEMORY */ buf_block_t* -buf_block_alloc( -/*============*/ - buf_pool_t* buf_pool) /*!< in/out: buffer pool instance, - or NULL for round-robin selection - of the buffer pool */ +buf_block_alloc() { - buf_block_t* block; - ulint index; - static ulint buf_pool_index; - - if (buf_pool == NULL) { - /* We are allocating memory from any buffer pool, ensure - we spread the grace on all buffer pool instances. */ - index = buf_pool_index++ % srv_buf_pool_instances; - buf_pool = buf_pool_from_array(index); - } - - block = buf_LRU_get_free_block(buf_pool); - + buf_block_t* block = buf_LRU_get_free_block(); buf_block_set_state(block, BUF_BLOCK_MEMORY); - return(block); } #endif /* !UNIV_INNOCHECKSUM */ @@ -1215,8 +1087,6 @@ int buf_madvise_do_dump() { int ret= 0; - buf_pool_t* buf_pool; - buf_chunk_t* chunk; /* mirrors allocation in log_t::create() */ if (log_sys.buf) { @@ -1232,21 +1102,14 @@ buf_madvise_do_dump() ret+= madvise(recv_sys.buf, recv_sys.len, MADV_DODUMP); } - buf_pool_mutex_enter_all(); + mutex_enter(&buf_pool->mutex); + buf_chunk_t* chunk = buf_pool->chunks; - for (ulong i= 0; i < srv_buf_pool_instances; i++) - { - buf_pool = buf_pool_from_array(i); - chunk = buf_pool->chunks; - - for (int n = buf_pool->n_chunks; n--; chunk++) - { - ret+= madvise(chunk->mem, chunk->mem_size(), MADV_DODUMP); - } + for (ulint n = buf_pool->n_chunks; n--; chunk++) { + ret+= madvise(chunk->mem, chunk->mem_size(), MADV_DODUMP); } - buf_pool_mutex_exit_all(); - + mutex_exit(&buf_pool->mutex); return ret; } #endif @@ -1473,15 +1336,12 @@ pfs_register_buffer_block( } # endif /* PFS_GROUP_BUFFER_SYNC */ -/********************************************************************//** -Initializes a buffer control block when the buf_pool is created. */ +/** Initialize a buffer page descriptor. +@param[in,out] block buffer page descriptor +@param[in] frame buffer page frame */ static void -buf_block_init( -/*===========*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_block_t* block, /*!< in: pointer to control block */ - byte* frame) /*!< in: pointer to buffer frame */ +buf_block_init(buf_block_t* block, byte* frame) { UNIV_MEM_DESC(frame, srv_page_size); @@ -1491,7 +1351,6 @@ buf_block_init( block->frame = frame; - block->page.buf_pool_index = buf_pool_index(buf_pool); block->page.flush_type = BUF_FLUSH_LRU; block->page.state = BUF_BLOCK_NOT_USED; block->page.buf_fix_count = 0; @@ -1549,16 +1408,12 @@ buf_block_init( ut_ad(rw_lock_validate(&(block->lock))); } -/********************************************************************//** -Allocates a chunk of buffer frames. -@return chunk, or NULL on failure */ -static -buf_chunk_t* -buf_chunk_init( -/*===========*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_chunk_t* chunk, /*!< out: chunk of buffers */ - ulint mem_size) /*!< in: requested size in bytes */ +/** Allocate a chunk of buffer frames. +@param[in,out] chunk chunk of buffers +@param[in] mem_size requested size in bytes +@return chunk +@retval NULL on failure */ +static buf_chunk_t* buf_chunk_init(buf_chunk_t* chunk, ulint mem_size) { buf_block_t* block; byte* frame; @@ -1631,14 +1486,13 @@ buf_chunk_init( for (i = chunk->size; i--; ) { - buf_block_init(buf_pool, block, frame); + buf_block_init(block, frame); UNIV_MEM_INVALID(block->frame, srv_page_size); /* Add the block to the free list */ UT_LIST_ADD_LAST(buf_pool->free, &block->page); ut_d(block->page.in_free_list = TRUE); - ut_ad(buf_pool_from_block(block) == buf_pool); block++; frame += srv_page_size; @@ -1679,26 +1533,17 @@ buf_chunk_contains_zip( return(NULL); } -/*********************************************************************//** -Finds a block in the buffer pool that points to a -given compressed page. -@return buffer block pointing to the compressed page, or NULL */ -buf_block_t* -buf_pool_contains_zip( -/*==================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - const void* data) /*!< in: pointer to compressed page */ +/** Finds a block in the buffer pool that points to a given compressed page. +@param[in] data pointer to compressed page +@return buffer block pointing to the compressed page +@retval NULL if not found */ +buf_block_t* buf_pool_contains_zip(const void* data) { - ulint n; buf_chunk_t* chunk = buf_pool->chunks; - ut_ad(buf_pool); - ut_ad(buf_pool_mutex_own(buf_pool)); - for (n = buf_pool->n_chunks; n--; chunk++) { - - buf_block_t* block = buf_chunk_contains_zip(chunk, data); - - if (block) { + ut_ad(mutex_own(&buf_pool->mutex)); + for (ulint n = buf_pool->n_chunks; n--; chunk++) { + if (buf_block_t* block = buf_chunk_contains_zip(chunk, data)) { return(block); } } @@ -1769,32 +1614,6 @@ buf_chunk_not_freed( return(NULL); } -/********************************************************************//** -Set buffer pool size variables after resizing it */ -static -void -buf_pool_set_sizes(void) -/*====================*/ -{ - ulint i; - ulint curr_size = 0; - - buf_pool_mutex_enter_all(); - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - curr_size += buf_pool->curr_pool_size; - } - - srv_buf_pool_curr_size = curr_size; - srv_buf_pool_old_size = srv_buf_pool_size; - srv_buf_pool_base_size = srv_buf_pool_size; - - buf_pool_mutex_exit_all(); -} - /** Free the synchronization objects of a buffer pool block descriptor @param[in,out] block buffer pool block descriptor */ static void buf_block_free_mutexes(buf_block_t* block) @@ -1805,22 +1624,24 @@ static void buf_block_free_mutexes(buf_block_t* block) ut_d(ut_free(block->debug_latch)); } -/********************************************************************//** -Initialize a buffer pool instance. -@return DB_SUCCESS if all goes well. */ -static -ulint -buf_pool_init_instance( -/*===================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint buf_pool_size, /*!< in: size in bytes */ - ulint instance_no) /*!< in: id of the instance */ +/** Create the buffer pool. +@return whether the creation failed */ +bool buf_pool_init() { ulint i; ulint chunk_size; buf_chunk_t* chunk; - ut_ad(buf_pool_size % srv_buf_pool_chunk_unit == 0); + ut_ad(srv_buf_pool_size % srv_buf_pool_chunk_unit == 0); + ut_ad(!buf_pool); + + NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE; + + buf_pool_resizing = false; + buf_pool_withdrawing = false; + buf_withdraw_clock = 0; + buf_chunk_map_reg = UT_NEW_NOKEY(buf_pool_chunk_map_t()); + buf_pool = (buf_pool_t*) ut_zalloc_nokey(sizeof *buf_pool); /* 1. Initialize general fields ------------------------------- */ @@ -1831,11 +1652,11 @@ buf_pool_init_instance( new(&buf_pool->allocator) ut_allocator(mem_key_buf_buf_pool); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - if (buf_pool_size > 0) { + if (srv_buf_pool_size > 0) { buf_pool->n_chunks - = buf_pool_size / srv_buf_pool_chunk_unit; + = srv_buf_pool_size / srv_buf_pool_chunk_unit; chunk_size = srv_buf_pool_chunk_unit; buf_pool->chunks = @@ -1863,7 +1684,7 @@ buf_pool_init_instance( chunk = buf_pool->chunks; do { - if (!buf_chunk_init(buf_pool, chunk, chunk_size)) { + if (!buf_chunk_init(chunk, chunk_size)) { while (--chunk >= buf_pool->chunks) { buf_block_t* block = chunk->blocks; @@ -1875,20 +1696,19 @@ buf_pool_init_instance( chunk->mem, &chunk->mem_pfx, chunk->mem_size()); } ut_free(buf_pool->chunks); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); - return(DB_ERROR); + return true; } buf_pool->curr_size += chunk->size; } while (++chunk < buf_pool->chunks + buf_pool->n_chunks); - buf_pool->instance_no = instance_no; buf_pool->read_ahead_area = ut_min(BUF_READ_AHEAD_PAGES, ut_2_power_up(buf_pool->curr_size / BUF_READ_AHEAD_PORTION)); - buf_pool->curr_pool_size = buf_pool_size; + buf_pool->curr_pool_size = srv_buf_pool_size; buf_pool->old_size = buf_pool->curr_size; buf_pool->n_chunks_new = buf_pool->n_chunks; @@ -1922,49 +1742,45 @@ buf_pool_init_instance( buf_pool->watch = (buf_page_t*) ut_zalloc_nokey( sizeof(*buf_pool->watch) * BUF_POOL_WATCH_SIZE); - for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) { - buf_pool->watch[i].buf_pool_index - = unsigned(buf_pool->instance_no); - } /* All fields are initialized by ut_zalloc_nokey(). */ buf_pool->try_LRU_scan = TRUE; /* Initialize the hazard pointer for flush_list batches */ - new(&buf_pool->flush_hp) - FlushHp(buf_pool, &buf_pool->flush_list_mutex); + new(&buf_pool->flush_hp) FlushHp(&buf_pool->flush_list_mutex); /* Initialize the hazard pointer for LRU batches */ - new(&buf_pool->lru_hp) LRUHp(buf_pool, &buf_pool->mutex); + new(&buf_pool->lru_hp) LRUHp(&buf_pool->mutex); /* Initialize the iterator for LRU scan search */ - new(&buf_pool->lru_scan_itr) LRUItr(buf_pool, &buf_pool->mutex); + new(&buf_pool->lru_scan_itr) LRUItr(&buf_pool->mutex); /* Initialize the iterator for single page scan search */ - new(&buf_pool->single_scan_itr) LRUItr(buf_pool, &buf_pool->mutex); + new(&buf_pool->single_scan_itr) LRUItr(&buf_pool->mutex); /* Initialize the temporal memory array and slots */ new(&buf_pool->io_buf) buf_pool_t::io_buf_t( (srv_n_read_io_threads + srv_n_write_io_threads) * OS_AIO_N_PENDING_IOS_PER_THREAD); - buf_pool_mutex_exit(buf_pool); + /* FIXME: remove some of these variables */ + srv_buf_pool_curr_size = buf_pool->curr_pool_size; + srv_buf_pool_old_size = srv_buf_pool_size; + srv_buf_pool_base_size = srv_buf_pool_size; - DBUG_EXECUTE_IF("buf_pool_init_instance_force_oom", - return(DB_ERROR); ); + mutex_exit(&buf_pool->mutex); + DBUG_EXECUTE_IF("buf_pool_init_instance_force_oom", return true;); - return(DB_SUCCESS); + buf_chunk_map_ref = buf_chunk_map_reg; + buf_LRU_old_ratio_update(100 * 3 / 8, false); + btr_search_sys_create(srv_buf_pool_curr_size / sizeof(void*) / 64); + return false; } -/********************************************************************//** -free one buffer pool instance */ -static -void -buf_pool_free_instance( -/*===================*/ - buf_pool_t* buf_pool) /* in,own: buffer pool instance - to free */ +/** Free the buffer pool at shutdown. +This must not be invoked before freeing all mutexes. */ +void buf_pool_free() { buf_chunk_t* chunk; buf_chunk_t* chunks; @@ -2027,100 +1843,31 @@ buf_pool_free_instance( buf_pool->io_buf.~io_buf_t(); buf_pool->allocator.~ut_allocator(); -} - -/********************************************************************//** -Creates the buffer pool. -@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */ -dberr_t -buf_pool_init( -/*==========*/ - ulint total_size, /*!< in: size of the total pool in bytes */ - ulint n_instances) /*!< in: number of instances */ -{ - ulint i; - const ulint size = total_size / n_instances; - - ut_ad(n_instances > 0); - ut_ad(n_instances <= MAX_BUFFER_POOLS); - ut_ad(n_instances == srv_buf_pool_instances); - - NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE; - - buf_pool_resizing = false; - buf_pool_withdrawing = false; - buf_withdraw_clock = 0; - - buf_pool_ptr = (buf_pool_t*) ut_zalloc_nokey( - n_instances * sizeof *buf_pool_ptr); - - buf_chunk_map_reg = UT_NEW_NOKEY(buf_pool_chunk_map_t()); - - for (i = 0; i < n_instances; i++) { - buf_pool_t* ptr = &buf_pool_ptr[i]; - - if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) { - - /* Free all the instances created so far. */ - buf_pool_free(i); - - return(DB_ERROR); - } - } - - buf_chunk_map_ref = buf_chunk_map_reg; - - buf_pool_set_sizes(); - buf_LRU_old_ratio_update(100 * 3/ 8, FALSE); - - btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64); - - return(DB_SUCCESS); -} - -/********************************************************************//** -Frees the buffer pool at shutdown. This must not be invoked before -freeing all mutexes. */ -void -buf_pool_free( -/*==========*/ - ulint n_instances) /*!< in: numbere of instances to free */ -{ - for (ulint i = 0; i < n_instances; i++) { - buf_pool_free_instance(buf_pool_from_array(i)); - } - UT_DELETE(buf_chunk_map_reg); buf_chunk_map_reg = buf_chunk_map_ref = NULL; - ut_free(buf_pool_ptr); - buf_pool_ptr = NULL; + ut_free(buf_pool); + buf_pool = NULL; } /** Reallocate a control block. -@param[in] buf_pool buffer pool instance @param[in] block pointer to control block @retval false if failed because of no free blocks. */ -static -bool -buf_page_realloc( - buf_pool_t* buf_pool, - buf_block_t* block) +static bool buf_page_realloc(buf_block_t* block) { buf_block_t* new_block; ut_ad(buf_pool_withdrawing); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - new_block = buf_LRU_get_free_only(buf_pool); + new_block = buf_LRU_get_free_only(); if (new_block == NULL) { - return(false); /* free_list was not enough */ + return(false); /* buf_pool->free list was not enough */ } - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, block->page.id); - + rw_lock_t* hash_lock = buf_page_hash_lock_get(block->page.id); rw_lock_x_lock(hash_lock); mutex_enter(&block->mutex); @@ -2136,7 +1883,7 @@ buf_page_realloc( ut_ad(!block->page.in_zip_hash); ut_d(block->page.in_LRU_list = FALSE); - buf_LRU_adjust_hp(buf_pool, &block->page); + buf_LRU_adjust_hp(&block->page); buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, &block->page); UT_LIST_REMOVE(buf_pool->LRU, &block->page); @@ -2179,8 +1926,7 @@ buf_page_realloc( /* relocate buf_pool->page_hash */ ut_ad(block->page.in_page_hash); - ut_ad(&block->page == buf_page_hash_get_low(buf_pool, - block->page.id)); + ut_ad(&block->page == buf_page_hash_get_low(block->page.id)); ut_d(block->page.in_page_hash = FALSE); ulint fold = block->page.id.fold(); ut_ad(fold == new_block->page.id.fold()); @@ -2273,16 +2019,12 @@ buf_resize_status( } /** Determines if a block is intended to be withdrawn. -@param[in] buf_pool buffer pool instance @param[in] block pointer to control block @retval true if will be withdrawn */ -bool -buf_block_will_withdrawn( - buf_pool_t* buf_pool, - const buf_block_t* block) +bool buf_block_will_be_withdrawn(const buf_block_t* block) { ut_ad(buf_pool->curr_size < buf_pool->old_size); - ut_ad(!buf_pool_resizing || buf_pool_mutex_own(buf_pool)); + ut_ad(!buf_pool_resizing || mutex_own(&buf_pool->mutex)); const buf_chunk_t* chunk = buf_pool->chunks + buf_pool->n_chunks_new; @@ -2301,16 +2043,13 @@ buf_block_will_withdrawn( } /** Determines if a frame is intended to be withdrawn. -@param[in] buf_pool buffer pool instance @param[in] ptr pointer to a frame @retval true if will be withdrawn */ bool -buf_frame_will_withdrawn( - buf_pool_t* buf_pool, - const byte* ptr) +buf_frame_will_be_withdrawn(const byte* ptr) { ut_ad(buf_pool->curr_size < buf_pool->old_size); - ut_ad(!buf_pool_resizing || buf_pool_mutex_own(buf_pool)); + ut_ad(!buf_pool_resizing || mutex_own(&buf_pool->mutex)); const buf_chunk_t* chunk = buf_pool->chunks + buf_pool->n_chunks_new; @@ -2329,27 +2068,21 @@ buf_frame_will_withdrawn( return(false); } -/** Withdraw the buffer pool blocks from end of the buffer pool instance +/** Withdraw the buffer pool blocks from the end of the buffer pool until withdrawn by buf_pool->withdraw_target. -@param[in] buf_pool buffer pool instance @retval true if retry is needed */ -static -bool -buf_pool_withdraw_blocks( - buf_pool_t* buf_pool) +static bool buf_pool_withdraw_blocks() { buf_block_t* block; ulint loop_count = 0; - ulint i = buf_pool_index(buf_pool); - ib::info() << "buffer pool " << i - << " : start to withdraw the last " - << buf_pool->withdraw_target << " blocks."; + ib::info() << "start to withdraw the last " + << buf_pool->withdraw_target << " blocks"; /* Minimize buf_pool->zip_free[i] lists */ - buf_pool_mutex_enter(buf_pool); - buf_buddy_condense_free(buf_pool); - buf_pool_mutex_exit(buf_pool); + mutex_enter(&buf_pool->mutex); + buf_buddy_condense_free(); + mutex_exit(&buf_pool->mutex); while (UT_LIST_GET_LEN(buf_pool->withdraw) < buf_pool->withdraw_target) { @@ -2357,7 +2090,7 @@ buf_pool_withdraw_blocks( /* try to withdraw from free_list */ ulint count1 = 0; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); block = reinterpret_cast( UT_LIST_GET_FIRST(buf_pool->free)); while (block != NULL @@ -2373,7 +2106,7 @@ buf_pool_withdraw_blocks( UT_LIST_GET_NEXT( list, &block->page)); - if (buf_block_will_withdrawn(buf_pool, block)) { + if (buf_block_will_be_withdrawn(block)) { /* This should be withdrawn */ UT_LIST_REMOVE( buf_pool->free, @@ -2387,7 +2120,7 @@ buf_pool_withdraw_blocks( block = next_block; } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* reserve free_list length */ if (UT_LIST_GET_LEN(buf_pool->withdraw) @@ -2396,9 +2129,9 @@ buf_pool_withdraw_blocks( flush_counters_t n; /* cap scan_depth with current LRU size. */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); scan_depth = UT_LIST_GET_LEN(buf_pool->LRU); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); scan_depth = ut_min( ut_max(buf_pool->withdraw_target @@ -2406,9 +2139,8 @@ buf_pool_withdraw_blocks( static_cast(srv_LRU_scan_depth)), scan_depth); - buf_flush_do_batch(buf_pool, BUF_FLUSH_LRU, - scan_depth, 0, &n); - buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU); + buf_flush_do_batch(BUF_FLUSH_LRU, scan_depth, 0, &n); + buf_flush_wait_batch_end(BUF_FLUSH_LRU); if (n.flushed) { MONITOR_INC_VALUE_CUMULATIVE( @@ -2422,7 +2154,7 @@ buf_pool_withdraw_blocks( /* relocate blocks/buddies in withdrawn area */ ulint count2 = 0; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); buf_page_t* bpage; bpage = UT_LIST_GET_FIRST(buf_pool->LRU); while (bpage != NULL) { @@ -2435,81 +2167,68 @@ buf_pool_withdraw_blocks( next_bpage = UT_LIST_GET_NEXT(LRU, bpage); if (bpage->zip.data != NULL - && buf_frame_will_withdrawn( - buf_pool, - static_cast(bpage->zip.data))) { - - if (buf_page_can_relocate(bpage)) { - mutex_exit(block_mutex); - buf_pool_mutex_exit_forbid(buf_pool); - if(!buf_buddy_realloc( - buf_pool, bpage->zip.data, - page_zip_get_size( - &bpage->zip))) { - - /* failed to allocate block */ - buf_pool_mutex_exit_allow( - buf_pool); - break; - } - buf_pool_mutex_exit_allow(buf_pool); - mutex_enter(block_mutex); - count2++; + && buf_frame_will_be_withdrawn(bpage->zip.data) + && buf_page_can_relocate(bpage)) { + mutex_exit(block_mutex); + buf_pool_mutex_exit_forbid(); + if (!buf_buddy_realloc( + bpage->zip.data, + page_zip_get_size(&bpage->zip))) { + /* failed to allocate block */ + buf_pool_mutex_exit_allow(); + break; } - /* NOTE: if the page is in use, - not reallocated yet */ + buf_pool_mutex_exit_allow(); + mutex_enter(block_mutex); + count2++; } if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE - && buf_block_will_withdrawn( - buf_pool, - reinterpret_cast(bpage))) { + && buf_block_will_be_withdrawn( + reinterpret_cast(bpage))) { if (buf_page_can_relocate(bpage)) { mutex_exit(block_mutex); - buf_pool_mutex_exit_forbid(buf_pool); + buf_pool_mutex_exit_forbid(); if(!buf_page_realloc( - buf_pool, reinterpret_cast( bpage))) { /* failed to allocate block */ - buf_pool_mutex_exit_allow( - buf_pool); + buf_pool_mutex_exit_allow(); break; } - buf_pool_mutex_exit_allow(buf_pool); + buf_pool_mutex_exit_allow(); count2++; } else { mutex_exit(block_mutex); } /* NOTE: if the page is in use, - not reallocated yet */ + not relocated yet */ } else { mutex_exit(block_mutex); } bpage = next_bpage; } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); buf_resize_status( - "buffer pool %lu : withdrawing blocks. (%lu/%lu)", - i, UT_LIST_GET_LEN(buf_pool->withdraw), + "withdrawing blocks. (" ULINTPF "/" ULINTPF ")", + UT_LIST_GET_LEN(buf_pool->withdraw), buf_pool->withdraw_target); - ib::info() << "buffer pool " << i << " : withdrew " + ib::info() << "withdrew " << count1 << " blocks from free list." << " Tried to relocate " << count2 << " pages (" << UT_LIST_GET_LEN(buf_pool->withdraw) << "/" - << buf_pool->withdraw_target << ")."; + << buf_pool->withdraw_target << ")"; if (++loop_count >= 10) { /* give up for now. retried after user threads paused. */ - ib::info() << "buffer pool " << i - << " : will retry to withdraw later."; + ib::info() << "will retry to withdraw later"; /* need retry later */ return(true); @@ -2535,8 +2254,8 @@ buf_pool_withdraw_blocks( ++chunk; } - ib::info() << "buffer pool " << i << " : withdrawn target " - << UT_LIST_GET_LEN(buf_pool->withdraw) << " blocks."; + ib::info() << "withdrawn target: " + << UT_LIST_GET_LEN(buf_pool->withdraw) << " blocks"; /* retry is not needed */ ++buf_withdraw_clock; @@ -2544,12 +2263,8 @@ buf_pool_withdraw_blocks( return(false); } -/** resize page_hash and zip_hash for a buffer pool instance. -@param[in] buf_pool buffer pool instance */ -static -void -buf_pool_resize_hash( - buf_pool_t* buf_pool) +/** resize page_hash and zip_hash */ +static void buf_pool_resize_hash() { hash_table_t* new_hash_table; @@ -2643,12 +2358,8 @@ buf_pool_resize_chunk_make_null(buf_chunk_t** new_chunks) /** Resize the buffer pool based on srv_buf_pool_size from srv_buf_pool_old_size. */ -static -void -buf_pool_resize() +static void buf_pool_resize() { - buf_pool_t* buf_pool; - ulint new_instance_size; bool warning = false; NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE; @@ -2657,32 +2368,24 @@ buf_pool_resize() ut_ad(!buf_pool_withdrawing); ut_ad(srv_buf_pool_chunk_unit > 0); - new_instance_size = srv_buf_pool_size / srv_buf_pool_instances; - new_instance_size >>= srv_page_size_shift; + ulint new_instance_size = srv_buf_pool_size >> srv_page_size_shift; buf_resize_status("Resizing buffer pool from " ULINTPF " to " ULINTPF " (unit=" ULINTPF ").", srv_buf_pool_old_size, srv_buf_pool_size, srv_buf_pool_chunk_unit); - /* set new limit for all buffer pool for resizing */ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool = buf_pool_from_array(i); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); + ut_ad(buf_pool->curr_size == buf_pool->old_size); + ut_ad(buf_pool->n_chunks_new == buf_pool->n_chunks); + ut_ad(UT_LIST_GET_LEN(buf_pool->withdraw) == 0); + ut_ad(buf_pool->flush_rbt == NULL); - ut_ad(buf_pool->curr_size == buf_pool->old_size); - ut_ad(buf_pool->n_chunks_new == buf_pool->n_chunks); - ut_ad(UT_LIST_GET_LEN(buf_pool->withdraw) == 0); - ut_ad(buf_pool->flush_rbt == NULL); + buf_pool->n_chunks_new = (new_instance_size << srv_page_size_shift) + / srv_buf_pool_chunk_unit; + buf_pool->curr_size = buf_pool->n_chunks_new * buf_pool->chunks->size; + mutex_exit(&buf_pool->mutex); - buf_pool->n_chunks_new = - (new_instance_size << srv_page_size_shift) - / srv_buf_pool_chunk_unit; - - buf_pool->curr_size = buf_pool->n_chunks_new * buf_pool->chunks->size; - - buf_pool_mutex_exit(buf_pool); - } #ifdef BTR_CUR_HASH_ADAPT /* disable AHI if needed */ bool btr_search_disabled = false; @@ -2704,26 +2407,23 @@ buf_pool_resize() } #endif /* BTR_CUR_HASH_ADAPT */ - /* set withdraw target */ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool = buf_pool_from_array(i); - if (buf_pool->curr_size < buf_pool->old_size) { - ulint withdraw_target = 0; + if (buf_pool->curr_size < buf_pool->old_size) { + /* set withdraw target */ + ulint withdraw_target = 0; - const buf_chunk_t* chunk - = buf_pool->chunks + buf_pool->n_chunks_new; - const buf_chunk_t* echunk - = buf_pool->chunks + buf_pool->n_chunks; + const buf_chunk_t* chunk + = buf_pool->chunks + buf_pool->n_chunks_new; + const buf_chunk_t* echunk + = buf_pool->chunks + buf_pool->n_chunks; - while (chunk < echunk) { - withdraw_target += chunk->size; - ++chunk; - } - - ut_ad(buf_pool->withdraw_target == 0); - buf_pool->withdraw_target = withdraw_target; - buf_pool_withdrawing = true; + while (chunk < echunk) { + withdraw_target += chunk->size; + ++chunk; } + + ut_ad(buf_pool->withdraw_target == 0); + buf_pool->withdraw_target = withdraw_target; + buf_pool_withdrawing = true; } buf_resize_status("Withdrawing blocks to be shrunken."); @@ -2733,17 +2433,10 @@ buf_pool_resize() ulint retry_interval = 1; withdraw_retry: - bool should_retry_withdraw = false; - /* wait for the number of blocks fit to the new size (if needed)*/ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool = buf_pool_from_array(i); - if (buf_pool->curr_size < buf_pool->old_size) { - - should_retry_withdraw |= - buf_pool_withdraw_blocks(buf_pool); - } - } + bool should_retry_withdraw + = buf_pool->curr_size < buf_pool->old_size + && buf_pool_withdraw_blocks(); if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { /* abort to resize for shutdown. */ @@ -2833,191 +2526,147 @@ withdraw_retry: /* Indicate critical path */ buf_pool_resizing = true; - /* Acquire all buf_pool_mutex/hash_lock */ - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - - buf_pool_mutex_enter(buf_pool); - } - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - - hash_lock_x_all(buf_pool->page_hash); - } - + mutex_enter(&buf_pool->mutex); + hash_lock_x_all(buf_pool->page_hash); buf_chunk_map_reg = UT_NEW_NOKEY(buf_pool_chunk_map_t()); /* add/delete chunks */ - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - buf_chunk_t* chunk; - buf_chunk_t* echunk; - buf_resize_status("buffer pool %lu :" - " resizing with chunks %lu to %lu.", - i, buf_pool->n_chunks, buf_pool->n_chunks_new); + buf_resize_status("buffer pool resizing with chunks " + ULINTPF " to " ULINTPF ".", + buf_pool->n_chunks, buf_pool->n_chunks_new); - if (buf_pool->n_chunks_new < buf_pool->n_chunks) { - /* delete chunks */ - chunk = buf_pool->chunks - + buf_pool->n_chunks_new; - echunk = buf_pool->chunks + buf_pool->n_chunks; + if (buf_pool->n_chunks_new < buf_pool->n_chunks) { + /* delete chunks */ + buf_chunk_t* chunk = buf_pool->chunks + buf_pool->n_chunks_new; + const buf_chunk_t* const echunk = buf_pool->chunks + + buf_pool->n_chunks; - ulint sum_freed = 0; + ulint sum_freed = 0; - while (chunk < echunk) { - buf_block_t* block = chunk->blocks; + while (chunk < echunk) { + buf_block_t* block = chunk->blocks; - for (ulint j = chunk->size; - j--; block++) { - buf_block_free_mutexes(block); - } - - buf_pool->allocator.deallocate_large_dodump( - chunk->mem, &chunk->mem_pfx, chunk->mem_size()); - - sum_freed += chunk->size; - - ++chunk; + for (ulint j = chunk->size; j--; block++) { + buf_block_free_mutexes(block); } - /* discard withdraw list */ - UT_LIST_INIT(buf_pool->withdraw, - &buf_page_t::list); - buf_pool->withdraw_target = 0; - - ib::info() << "buffer pool " << i << " : " - << buf_pool->n_chunks - buf_pool->n_chunks_new - << " chunks (" << sum_freed - << " blocks) were freed."; - - buf_pool->n_chunks = buf_pool->n_chunks_new; + buf_pool->allocator.deallocate_large_dodump( + chunk->mem, &chunk->mem_pfx, + chunk->mem_size()); + sum_freed += chunk->size; + ++chunk; } - { - /* reallocate buf_pool->chunks */ - const ulint new_chunks_size - = buf_pool->n_chunks_new * sizeof(*chunk); + /* discard withdraw list */ + UT_LIST_INIT(buf_pool->withdraw, &buf_page_t::list); + buf_pool->withdraw_target = 0; - buf_chunk_t* new_chunks - = reinterpret_cast( - ut_zalloc_nokey_nofatal(new_chunks_size)); + ib::info() << buf_pool->n_chunks - buf_pool->n_chunks_new + << " chunks (" << sum_freed + << " blocks) were freed."; - DBUG_EXECUTE_IF("buf_pool_resize_chunk_null", + buf_pool->n_chunks = buf_pool->n_chunks_new; + } + + { + /* reallocate buf_pool->chunks */ + const ulint new_chunks_size + = buf_pool->n_chunks_new * sizeof(buf_chunk_t); + + buf_chunk_t* new_chunks = reinterpret_cast( + ut_zalloc_nokey_nofatal(new_chunks_size)); + + DBUG_EXECUTE_IF("buf_pool_resize_chunk_null", buf_pool_resize_chunk_make_null(&new_chunks);); - if (new_chunks == NULL) { - ib::error() << "buffer pool " << i - << " : failed to allocate" - " the chunk array."; - buf_pool->n_chunks_new - = buf_pool->n_chunks; + if (!new_chunks) { + ib::error() << "failed to allocate" + " the chunk array."; + buf_pool->n_chunks_new = buf_pool->n_chunks; + warning = true; + buf_pool->chunks_old = NULL; + goto calc_buf_pool_size; + } + + ulint n_chunks_copy = ut_min(buf_pool->n_chunks_new, + buf_pool->n_chunks); + + memcpy(new_chunks, buf_pool->chunks, + n_chunks_copy * sizeof *new_chunks); + + for (ulint j = 0; j < n_chunks_copy; j++) { + buf_pool_register_chunk(&new_chunks[j]); + } + + buf_pool->chunks_old = buf_pool->chunks; + buf_pool->chunks = new_chunks; + } + + if (buf_pool->n_chunks_new > buf_pool->n_chunks) { + /* add chunks */ + buf_chunk_t* chunk = buf_pool->chunks + buf_pool->n_chunks; + const buf_chunk_t* const echunk = buf_pool->chunks + + buf_pool->n_chunks_new; + + ulint sum_added = 0; + ulint n_chunks = buf_pool->n_chunks; + + while (chunk < echunk) { + ulong unit = srv_buf_pool_chunk_unit; + + if (!buf_chunk_init(chunk, unit)) { + ib::error() << "failed to allocate" + " memory for buffer pool chunk"; + warning = true; - buf_pool->chunks_old = NULL; - for (ulint j = 0; j < buf_pool->n_chunks_new; j++) { - buf_pool_register_chunk(&(buf_pool->chunks[j])); - } - goto calc_buf_pool_size; + buf_pool->n_chunks_new = n_chunks; + break; } - ulint n_chunks_copy = ut_min(buf_pool->n_chunks_new, - buf_pool->n_chunks); - - memcpy(new_chunks, buf_pool->chunks, - n_chunks_copy * sizeof(*chunk)); - - for (ulint j = 0; j < n_chunks_copy; j++) { - buf_pool_register_chunk(&new_chunks[j]); - } - - buf_pool->chunks_old = buf_pool->chunks; - buf_pool->chunks = new_chunks; + sum_added += chunk->size; + ++n_chunks; + ++chunk; } + ib::info() << buf_pool->n_chunks_new - buf_pool->n_chunks + << " chunks (" << sum_added + << " blocks) were added."; - if (buf_pool->n_chunks_new > buf_pool->n_chunks) { - /* add chunks */ - chunk = buf_pool->chunks + buf_pool->n_chunks; - echunk = buf_pool->chunks - + buf_pool->n_chunks_new; - - ulint sum_added = 0; - ulint n_chunks = buf_pool->n_chunks; - - while (chunk < echunk) { - ulong unit = srv_buf_pool_chunk_unit; - - if (!buf_chunk_init(buf_pool, chunk, unit)) { - - ib::error() << "buffer pool " << i - << " : failed to allocate" - " new memory."; - - warning = true; - - buf_pool->n_chunks_new - = n_chunks; - - break; - } - - sum_added += chunk->size; - - ++n_chunks; - ++chunk; - } - - ib::info() << "buffer pool " << i << " : " - << buf_pool->n_chunks_new - buf_pool->n_chunks - << " chunks (" << sum_added - << " blocks) were added."; - - buf_pool->n_chunks = n_chunks; - } + buf_pool->n_chunks = n_chunks; + } calc_buf_pool_size: + /* recalc buf_pool->curr_size */ + ulint new_size = 0; - /* recalc buf_pool->curr_size */ - ulint new_size = 0; - - chunk = buf_pool->chunks; + { + buf_chunk_t* chunk = buf_pool->chunks; + const buf_chunk_t* const echunk = chunk + buf_pool->n_chunks; do { new_size += chunk->size; - } while (++chunk < buf_pool->chunks - + buf_pool->n_chunks); + } while (++chunk != echunk); + } - buf_pool->curr_size = new_size; - buf_pool->n_chunks_new = buf_pool->n_chunks; + buf_pool->curr_size = new_size; + buf_pool->n_chunks_new = buf_pool->n_chunks; - if (buf_pool->chunks_old) { - ut_free(buf_pool->chunks_old); - buf_pool->chunks_old = NULL; - } + if (buf_pool->chunks_old) { + ut_free(buf_pool->chunks_old); + buf_pool->chunks_old = NULL; } buf_pool_chunk_map_t* chunk_map_old = buf_chunk_map_ref; buf_chunk_map_ref = buf_chunk_map_reg; - /* set instance sizes */ - { - ulint curr_size = 0; - - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool = buf_pool_from_array(i); - - ut_ad(UT_LIST_GET_LEN(buf_pool->withdraw) == 0); - - buf_pool->read_ahead_area = - ut_min(BUF_READ_AHEAD_PAGES, - ut_2_power_up(buf_pool->curr_size / - BUF_READ_AHEAD_PORTION)); - buf_pool->curr_pool_size - = buf_pool->n_chunks * srv_buf_pool_chunk_unit; - curr_size += buf_pool->curr_pool_size; - buf_pool->old_size = buf_pool->curr_size; - } - srv_buf_pool_curr_size = curr_size; - innodb_set_buf_pool_size(buf_pool_size_align(curr_size)); - } + /* set size */ + ut_ad(UT_LIST_GET_LEN(buf_pool->withdraw) == 0); + buf_pool->read_ahead_area = ut_min( + BUF_READ_AHEAD_PAGES, + ut_2_power_up(buf_pool->curr_size / BUF_READ_AHEAD_PORTION)); + buf_pool->curr_pool_size = buf_pool->n_chunks * srv_buf_pool_chunk_unit; + srv_buf_pool_curr_size = buf_pool->curr_pool_size;/* FIXME: remove*/ + buf_pool->old_size = buf_pool->curr_size; + innodb_set_buf_pool_size(buf_pool_size_align(srv_buf_pool_curr_size)); const bool new_size_too_diff = srv_buf_pool_base_size > srv_buf_pool_size * 2 @@ -3026,30 +2675,17 @@ calc_buf_pool_size: /* Normalize page_hash and zip_hash, if the new size is too different */ if (!warning && new_size_too_diff) { - - buf_resize_status("Resizing hash tables."); - - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - - buf_pool_resize_hash(buf_pool); - - ib::info() << "buffer pool " << i - << " : hash tables were resized."; - } + buf_resize_status("Resizing hash table"); + buf_pool_resize_hash(); + ib::info() << "hash tables were resized"; } - /* Release all buf_pool_mutex/page_hash */ - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); + hash_unlock_x_all(buf_pool->page_hash); + mutex_exit(&buf_pool->mutex); - hash_unlock_x_all(buf_pool->page_hash); - buf_pool_mutex_exit(buf_pool); - - if (buf_pool->page_hash_old != NULL) { - hash_table_free(buf_pool->page_hash_old); - buf_pool->page_hash_old = NULL; - } + if (buf_pool->page_hash_old != NULL) { + hash_table_free(buf_pool->page_hash_old); + buf_pool->page_hash_old = NULL; } UT_DELETE(chunk_map_old); @@ -3111,27 +2747,29 @@ calc_buf_pool_size: } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(buf_validate()); + buf_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ return; } -/* Thread pool task invoked by innodb_buffer_pool_size changes. */ +/** Thread pool task invoked by innodb_buffer_pool_size changes. */ static void buf_resize_callback(void *) { - ut_a(srv_shutdown_state == SRV_SHUTDOWN_NONE); - buf_pool_mutex_enter_all(); - if (srv_buf_pool_old_size == srv_buf_pool_size) { - buf_pool_mutex_exit_all(); - std::ostringstream sout; - sout << "Size did not change (old size = new size = " - << srv_buf_pool_size << ". Nothing to do."; - buf_resize_status(sout.str().c_str()); - return; - } - buf_pool_mutex_exit_all(); - buf_pool_resize(); + ut_a(srv_shutdown_state == SRV_SHUTDOWN_NONE); + mutex_enter(&buf_pool->mutex); + const auto size= srv_buf_pool_size; + const bool work= srv_buf_pool_old_size != size; + mutex_exit(&buf_pool->mutex); + + if (work) + buf_pool_resize(); + else + { + std::ostringstream sout; + sout << "Size did not change: old size = new size = " << size; + buf_resize_status(sout.str().c_str()); + } } /* Ensure that task does not run in parallel, by setting max_concurrency to 1 for the thread group */ @@ -3152,59 +2790,53 @@ void buf_resize_shutdown() #ifdef BTR_CUR_HASH_ADAPT /** Clear the adaptive hash index on all pages in the buffer pool. */ -void -buf_pool_clear_hash_index() +void buf_pool_clear_hash_index() { - ulint p; - ut_ad(btr_search_own_all(RW_LOCK_X)); ut_ad(!buf_pool_resizing); ut_ad(!btr_search_enabled); - for (p = 0; p < srv_buf_pool_instances; p++) { - buf_pool_t* buf_pool = buf_pool_from_array(p); - buf_chunk_t* chunks = buf_pool->chunks; - buf_chunk_t* chunk = chunks + buf_pool->n_chunks; + buf_chunk_t* chunks = buf_pool->chunks; + buf_chunk_t* chunk = chunks + buf_pool->n_chunks; - while (--chunk >= chunks) { - buf_block_t* block = chunk->blocks; - ulint i = chunk->size; + while (--chunk >= chunks) { + buf_block_t* block = chunk->blocks; + ulint i = chunk->size; - for (; i--; block++) { - dict_index_t* index = block->index; - assert_block_ahi_valid(block); + for (; i--; block++) { + dict_index_t* index = block->index; + assert_block_ahi_valid(block); - /* We can set block->index = NULL - and block->n_pointers = 0 - when btr_search_own_all(RW_LOCK_X); - see the comments in buf0buf.h */ + /* We can set block->index = NULL + and block->n_pointers = 0 + when btr_search_own_all(RW_LOCK_X); + see the comments in buf0buf.h */ - if (!index) { + if (!index) { # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - ut_a(!block->n_pointers); + ut_a(!block->n_pointers); # endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - continue; - } - - ut_d(buf_page_state state - = buf_block_get_state(block)); - /* Another thread may have set the - state to BUF_BLOCK_REMOVE_HASH in - buf_LRU_block_remove_hashed(). - - The state change in buf_page_realloc() - is not observable here, because in - that case we would have !block->index. - - In the end, the entire adaptive hash - index will be removed. */ - ut_ad(state == BUF_BLOCK_FILE_PAGE - || state == BUF_BLOCK_REMOVE_HASH); -# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - block->n_pointers = 0; -# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - block->index = NULL; + continue; } + + ut_d(buf_page_state state + = buf_block_get_state(block)); + /* Another thread may have set the + state to BUF_BLOCK_REMOVE_HASH in + buf_LRU_block_remove_hashed(). + + The state change in buf_page_realloc() + is not observable here, because in + that case we would have !block->index. + + In the end, the entire adaptive hash + index will be removed. */ + ut_ad(state == BUF_BLOCK_FILE_PAGE + || state == BUF_BLOCK_REMOVE_HASH); +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + block->n_pointers = 0; +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + block->index = NULL; } } } @@ -3224,19 +2856,17 @@ buf_relocate( buf_page_t* dpage) /*!< in/out: destination control block */ { buf_page_t* b; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(buf_page_hash_lock_held_x(buf_pool, bpage)); + ut_ad(mutex_own(&buf_pool->mutex)); + ut_ad(buf_page_hash_lock_held_x(bpage)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE); ut_a(bpage->buf_fix_count == 0); ut_ad(bpage->in_LRU_list); ut_ad(!bpage->in_zip_hash); ut_ad(bpage->in_page_hash); - ut_ad(bpage == buf_page_hash_get_low(buf_pool, bpage->id)); - - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); + ut_ad(bpage == buf_page_hash_get_low(bpage->id)); + ut_ad(!buf_pool_watch_is_sentinel(bpage)); #ifdef UNIV_DEBUG switch (buf_page_get_state(bpage)) { case BUF_BLOCK_POOL_WATCH: @@ -3256,7 +2886,7 @@ buf_relocate( /* Important that we adjust the hazard pointer before removing bpage from LRU list. */ - buf_LRU_adjust_hp(buf_pool, bpage); + buf_LRU_adjust_hp(bpage); ut_d(bpage->in_LRU_list = FALSE); ut_d(bpage->in_page_hash = FALSE); @@ -3288,7 +2918,7 @@ buf_relocate( #endif /* UNIV_LRU_DEBUG */ } - ut_d(CheckInLRUList::validate(buf_pool)); + ut_d(CheckInLRUList::validate()); /* relocate buf_pool->page_hash */ ulint fold = bpage->id.fold(); @@ -3305,26 +2935,11 @@ void HazardPointer::set(buf_page_t* bpage) { ut_ad(mutex_own(m_mutex)); - ut_ad(!bpage || buf_pool_from_bpage(bpage) == m_buf_pool); ut_ad(!bpage || buf_page_in_file(bpage)); m_hp = bpage; } -/** Checks if a bpage is the hp -@param bpage buffer block to be compared -@return true if it is hp */ - -bool -HazardPointer::is_hp(const buf_page_t* bpage) -{ - ut_ad(mutex_own(m_mutex)); - ut_ad(!m_hp || buf_pool_from_bpage(m_hp) == m_buf_pool); - ut_ad(!bpage || buf_pool_from_bpage(bpage) == m_buf_pool); - - return(bpage == m_hp); -} - /** Adjust the value of hp. This happens when some other thread working on the same list attempts to remove the hp from the list. @param bpage buffer block to be compared */ @@ -3359,33 +2974,13 @@ LRUHp::adjust(const buf_page_t* bpage) ut_ad(!m_hp || m_hp->in_LRU_list); } -/** Selects from where to start a scan. If we have scanned too deep into -the LRU list it resets the value to the tail of the LRU list. -@return buf_page_t from where to start scan. */ - -buf_page_t* -LRUItr::start() -{ - ut_ad(mutex_own(m_mutex)); - - if (!m_hp || m_hp->old) { - m_hp = UT_LIST_GET_LAST(m_buf_pool->LRU); - } - - return(m_hp); -} - /** Determine if a block is a sentinel for a buffer pool watch. -@param[in] buf_pool buffer pool instance @param[in] bpage block -@return TRUE if a sentinel for a buffer pool watch, FALSE if not */ -ibool -buf_pool_watch_is_sentinel( - const buf_pool_t* buf_pool, - const buf_page_t* bpage) +@return whether bpage a sentinel for a buffer pool watch */ +bool buf_pool_watch_is_sentinel(const buf_page_t* bpage) { - /* We must also own the appropriate hash lock. */ - ut_ad(buf_page_hash_lock_held_s_or_x(buf_pool, bpage)); + /* We must own the appropriate hash lock. */ + ut_ad(buf_page_hash_lock_held_s_or_x(bpage)); ut_ad(buf_page_in_file(bpage)); if (bpage < &buf_pool->watch[0] @@ -3394,14 +2989,14 @@ buf_pool_watch_is_sentinel( ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE || bpage->zip.data != NULL); - return(FALSE); + return false; } ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE); ut_ad(!bpage->in_zip_hash); ut_ad(bpage->in_page_hash); ut_ad(bpage->zip.data == NULL); - return(TRUE); + return true; } /** Add watch for the given page to be read in. Caller must have @@ -3418,17 +3013,16 @@ buf_pool_watch_set( { buf_page_t* bpage; ulint i; - buf_pool_t* buf_pool = buf_pool_get(page_id); - ut_ad(*hash_lock == buf_page_hash_lock_get(buf_pool, page_id)); + ut_ad(*hash_lock == buf_page_hash_lock_get(page_id)); ut_ad(rw_lock_own(*hash_lock, RW_LOCK_X)); - bpage = buf_page_hash_get_low(buf_pool, page_id); + bpage = buf_page_hash_get_low(page_id); if (bpage != NULL) { page_found: - if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) { + if (!buf_pool_watch_is_sentinel(bpage)) { /* The page was loaded meanwhile. */ return(bpage); } @@ -3449,28 +3043,27 @@ page_found: /* To obey latching order first release the hash_lock. */ rw_lock_x_unlock(*hash_lock); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); hash_lock_x_all(buf_pool->page_hash); - /* If not own buf_pool_mutex, page_hash can be changed. */ - *hash_lock = buf_page_hash_lock_get(buf_pool, page_id); - /* We have to recheck that the page was not loaded or a watch set by some other purge thread. This is because of the small time window between when we release the - hash_lock to acquire buf_pool mutex above. */ + hash_lock to acquire buf_pool->mutex above. */ - bpage = buf_page_hash_get_low(buf_pool, page_id); + *hash_lock = buf_page_hash_lock_get(page_id); + + bpage = buf_page_hash_get_low(page_id); if (UNIV_LIKELY_NULL(bpage)) { - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); hash_unlock_x_all_but(buf_pool->page_hash, *hash_lock); goto page_found; } /* The maximum number of purge threads should never exceed - BUF_POOL_WATCH_SIZE. So there is no way for purge thread - instance to hold a watch when setting another watch. */ + BUF_POOL_WATCH_SIZE. So there is no way for a purge task + to hold a watch when setting another watch. */ for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) { bpage = &buf_pool->watch[i]; @@ -3497,7 +3090,7 @@ page_found: HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, page_id.fold(), bpage); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* Once the sentinel is in the page_hash we can safely release all locks except just the relevant hash_lock */ @@ -3527,22 +3120,19 @@ page_found: /** Remove the sentinel block for the watch before replacing it with a real block. buf_page_watch_clear() or buf_page_watch_occurred() will notice that the block has been replaced with the real block. -@param[in,out] buf_pool buffer pool instance @param[in,out] watch sentinel for watch @return reference count, to be added to the replacement block */ static void -buf_pool_watch_remove( - buf_pool_t* buf_pool, - buf_page_t* watch) +buf_pool_watch_remove(buf_page_t* watch) { #ifdef UNIV_DEBUG /* We must also own the appropriate hash_bucket mutex. */ - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, watch->id); + rw_lock_t* hash_lock = buf_page_hash_lock_get(watch->id); ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); #endif /* UNIV_DEBUG */ - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, watch->id.fold(), watch); @@ -3557,28 +3147,25 @@ buf_pool_watch_set(same_page_id) must have returned NULL before. void buf_pool_watch_unset(const page_id_t page_id) { buf_page_t* bpage; - buf_pool_t* buf_pool = buf_pool_get(page_id); - - /* We only need to have buf_pool mutex in case where we end + /* We only need to have buf_pool->mutex in case where we end up calling buf_pool_watch_remove but to obey latching order we acquire it here before acquiring hash_lock. This should not cause too much grief as this function is only ever called from the purge thread. */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + rw_lock_t* hash_lock = buf_page_hash_lock_get(page_id); rw_lock_x_lock(hash_lock); /* The page must exist because buf_pool_watch_set() increments buf_fix_count. */ - bpage = buf_page_hash_get_low(buf_pool, page_id); + bpage = buf_page_hash_get_low(page_id); - if (bpage->unfix() == 0 - && buf_pool_watch_is_sentinel(buf_pool, bpage)) { - buf_pool_watch_remove(buf_pool, bpage); + if (bpage->unfix() == 0 && buf_pool_watch_is_sentinel(bpage)) { + buf_pool_watch_remove(bpage); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); rw_lock_x_unlock(hash_lock); } @@ -3591,19 +3178,18 @@ bool buf_pool_watch_occurred(const page_id_t page_id) { bool ret; buf_page_t* bpage; - buf_pool_t* buf_pool = buf_pool_get(page_id); - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + rw_lock_t* hash_lock = buf_page_hash_lock_get(page_id); rw_lock_s_lock(hash_lock); /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = buf_page_hash_lock_s_confirm(hash_lock, buf_pool, page_id); + hash_lock = buf_page_hash_lock_s_confirm(hash_lock, page_id); /* The page must exist because buf_pool_watch_set() increments buf_fix_count. */ - bpage = buf_page_hash_get_low(buf_pool, page_id); + bpage = buf_page_hash_get_low(page_id); - ret = !buf_pool_watch_is_sentinel(buf_pool, bpage); + ret = !buf_pool_watch_is_sentinel(bpage); rw_lock_s_unlock(hash_lock); return(ret); @@ -3612,25 +3198,20 @@ bool buf_pool_watch_occurred(const page_id_t page_id) /********************************************************************//** Moves a page to the start of the buffer pool LRU list. This high-level function can be used to prevent an important page from slipping out of -the buffer pool. */ -void -buf_page_make_young( -/*================*/ - buf_page_t* bpage) /*!< in: buffer block of a file page */ +the buffer pool. +@param[in,out] bpage buffer block of a file page */ +void buf_page_make_young(buf_page_t* bpage) { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); ut_a(buf_page_in_file(bpage)); buf_LRU_make_block_young(bpage); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } #ifdef UNIV_DEBUG - /** Sets file_page_was_freed TRUE if the page is found in the buffer pool. This function should be called when we free a file page and want the debug version to check that it is not accessed any more unless @@ -3640,14 +3221,13 @@ reallocated. buf_page_t* buf_page_set_file_page_was_freed(const page_id_t page_id) { buf_page_t* bpage; - buf_pool_t* buf_pool = buf_pool_get(page_id); rw_lock_t* hash_lock; - bpage = buf_page_hash_get_s_locked(buf_pool, page_id, &hash_lock); + bpage = buf_page_hash_get_s_locked(page_id, &hash_lock); if (bpage) { BPageMutex* block_mutex = buf_page_get_mutex(bpage); - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); + ut_ad(!buf_pool_watch_is_sentinel(bpage)); mutex_enter(block_mutex); rw_lock_s_unlock(hash_lock); /* bpage->file_page_was_freed can already hold @@ -3668,13 +3248,12 @@ reallocated. buf_page_t* buf_page_reset_file_page_was_freed(const page_id_t page_id) { buf_page_t* bpage; - buf_pool_t* buf_pool = buf_pool_get(page_id); rw_lock_t* hash_lock; - bpage = buf_page_hash_get_s_locked(buf_pool, page_id, &hash_lock); + bpage = buf_page_hash_get_s_locked(page_id, &hash_lock); if (bpage) { BPageMutex* block_mutex = buf_page_get_mutex(bpage); - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); + ut_ad(!buf_pool_watch_is_sentinel(bpage)); mutex_enter(block_mutex); rw_lock_s_unlock(hash_lock); bpage->file_page_was_freed = FALSE; @@ -3691,7 +3270,6 @@ The caller should not be holding any mutexes when this function is called. static void buf_block_try_discard_uncompressed(const page_id_t page_id) { buf_page_t* bpage; - buf_pool_t* buf_pool = buf_pool_get(page_id); /* Since we need to acquire buf_pool mutex to discard the uncompressed frame and because page_hash mutex resides @@ -3699,15 +3277,15 @@ static void buf_block_try_discard_uncompressed(const page_id_t page_id) first release the page_hash mutex. This means that the block in question can move out of page_hash. Therefore we need to check again if the block is still in page_hash. */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - bpage = buf_page_hash_get(buf_pool, page_id); + bpage = buf_page_hash_get(page_id); if (bpage) { buf_LRU_free_page(bpage, false); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } /** Get read access to a compressed page (usually of type @@ -3727,7 +3305,6 @@ buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size) rw_lock_t* hash_lock; ibool discard_attempted = FALSE; ibool must_read; - buf_pool_t* buf_pool = buf_pool_get(page_id); ut_ad(zip_size); ut_ad(ut_is_2pow(zip_size)); @@ -3738,10 +3315,9 @@ lookup: /* The following call will also grab the page_hash mutex if the page is found. */ - bpage = buf_page_hash_get_s_locked(buf_pool, page_id, - &hash_lock); + bpage = buf_page_hash_get_s_locked(page_id, &hash_lock); if (bpage) { - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); + ut_ad(!buf_pool_watch_is_sentinel(bpage)); break; } @@ -3758,11 +3334,11 @@ lookup: } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ } - ut_ad(buf_page_hash_lock_held_s(buf_pool, bpage)); + ut_ad(buf_page_hash_lock_held_s(bpage)); if (!bpage->zip.data) { /* There is no compressed page. */ @@ -3771,7 +3347,7 @@ err_exit: return(NULL); } - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); + ut_ad(!buf_pool_watch_is_sentinel(bpage)); switch (buf_page_get_state(bpage)) { case BUF_BLOCK_ZIP_PAGE: @@ -3812,10 +3388,10 @@ got_block: mutex_exit(block_mutex); - buf_page_make_young_if_needed(buf_pool, bpage); + buf_page_make_young_if_needed(bpage); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); ut_a(bpage->buf_fix_count > 0); ut_a(buf_page_in_file(bpage)); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ @@ -4008,17 +3584,11 @@ buf_block_from_ahi(const byte* ptr) } #endif /* BTR_CUR_HASH_ADAPT */ -/********************************************************************//** -Find out if a pointer belongs to a buf_block_t. It can be a pointer to -the buf_block_t itself or a member of it. This functions checks one of -the buffer pool instances. -@return TRUE if ptr belongs to a buf_block_t struct */ -static -ibool -buf_pointer_is_block_field_instance( -/*================================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - const void* ptr) /*!< in: pointer not dereferenced */ +/** Determine if a pointer belongs to a buf_block_t. It can be a pointer to +the buf_block_t itself or a member of it. +@param ptr a pointer that will not be dereferenced +@return whether the ptr belongs to a buf_block_t struct */ +bool buf_pointer_is_block_field(const void* ptr) { const buf_chunk_t* chunk = buf_pool->chunks; const buf_chunk_t* const echunk = chunk + ut_min( @@ -4030,56 +3600,23 @@ buf_pointer_is_block_field_instance( if (ptr >= (void*) chunk->blocks && ptr < (void*) (chunk->blocks + chunk->size)) { - return(TRUE); + return true; } chunk++; } - return(FALSE); + return false; } -/********************************************************************//** -Find out if a pointer belongs to a buf_block_t. It can be a pointer to -the buf_block_t itself or a member of it -@return TRUE if ptr belongs to a buf_block_t struct */ -ibool -buf_pointer_is_block_field( -/*=======================*/ - const void* ptr) /*!< in: pointer not dereferenced */ +/** Determine if a buffer block was created by buf_chunk_init(). +@param[in] block block descriptor (not dereferenced) +@return whether block has been added to buf_pool->free by buf_chunk_init() */ +static bool buf_block_is_uncompressed(const buf_block_t* block) { - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - ibool found; - - found = buf_pointer_is_block_field_instance( - buf_pool_from_array(i), ptr); - if (found) { - return(TRUE); - } - } - - return(FALSE); -} - -/********************************************************************//** -Find out if a buffer block was created by buf_chunk_init(). -@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */ -static -ibool -buf_block_is_uncompressed( -/*======================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - const buf_block_t* block) /*!< in: pointer to block, - not dereferenced */ -{ - if ((((ulint) block) % sizeof *block) != 0) { - /* The pointer should be aligned. */ - return(FALSE); - } - - return(buf_pointer_is_block_field_instance(buf_pool, (void*) block)); + /* The pointer should be aligned. */ + return !(ulint(block) % sizeof *block) && buf_pointer_is_block_field( + reinterpret_cast(block)); } #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG @@ -4171,7 +3708,6 @@ buf_page_get_gen( rw_lock_t* hash_lock; buf_block_t* fix_block; ulint retries = 0; - buf_pool_t* buf_pool = buf_pool_get(page_id); ut_ad((mtr == NULL) == (mode == BUF_EVICT_IF_IN_POOL)); ut_ad(!mtr || mtr->is_active()); @@ -4220,14 +3756,14 @@ buf_page_get_gen( || ibuf_page_low(page_id, zip_size, FALSE, file, line, NULL)); buf_pool->stat.n_page_gets++; - hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + hash_lock = buf_page_hash_lock_get(page_id); loop: block = guess; rw_lock_s_lock(hash_lock); - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = buf_page_hash_lock_s_confirm(hash_lock, buf_pool, page_id); + /* page_hash can be changed. */ + hash_lock = buf_page_hash_lock_s_confirm(hash_lock, page_id); if (block != NULL) { @@ -4235,10 +3771,9 @@ loop: has been allocated by buf_page_alloc_descriptor(), it may have been freed by buf_relocate(). */ - if (!buf_block_is_uncompressed(buf_pool, block) + if (!buf_block_is_uncompressed(block) || page_id != block->page.id || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { - /* Our guess was bogus or things have changed since. */ block = guess = NULL; @@ -4248,10 +3783,10 @@ loop: } if (block == NULL) { - block = (buf_block_t*) buf_page_hash_get_low(buf_pool, page_id); + block = (buf_block_t*) buf_page_hash_get_low(page_id); } - if (!block || buf_pool_watch_is_sentinel(buf_pool, &block->page)) { + if (!block || buf_pool_watch_is_sentinel(&block->page)) { rw_lock_s_unlock(hash_lock); block = NULL; } @@ -4266,7 +3801,7 @@ loop: /* If not own buf_pool_mutex, page_hash can be changed. */ hash_lock = buf_page_hash_lock_x_confirm( - hash_lock, buf_pool, page_id); + hash_lock, page_id); block = (buf_block_t*) buf_pool_watch_set( page_id, &hash_lock); @@ -4390,7 +3925,7 @@ loop: } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ goto loop; } else { @@ -4455,14 +3990,14 @@ got_block: if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) { evict_from_pool: ut_ad(!fix_block->page.oldest_modification); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); fix_block->unfix(); if (!buf_LRU_free_page(&fix_block->page, true)) { ut_ad(0); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(NULL); } break; @@ -4508,17 +4043,16 @@ evict_from_pool: or relocated while we are attempting to allocate an uncompressed page. */ - block = buf_LRU_get_free_block(buf_pool); + block = buf_LRU_get_free_block(); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + hash_lock = buf_page_hash_lock_get(page_id); rw_lock_x_lock(hash_lock); /* Buffer-fixing prevents the page_hash from changing. */ - ut_ad(bpage == buf_page_hash_get_low(buf_pool, page_id)); + ut_ad(bpage == buf_page_hash_get_low(page_id)); fix_block->unfix(); @@ -4538,7 +4072,7 @@ evict_from_pool: if buf_page_get_zip() was invoked. */ buf_LRU_block_free_non_file_page(block); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); rw_lock_x_unlock(hash_lock); buf_page_mutex_exit(block); @@ -4591,7 +4125,7 @@ evict_from_pool: rw_lock_x_unlock(hash_lock); buf_pool->n_pend_unzip++; mutex_exit(&buf_pool->zip_mutex); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); access_time = buf_page_is_accessed(&block->page); @@ -4608,14 +4142,14 @@ evict_from_pool: buf_pool->mutex or block->mutex. */ if (!buf_zip_decompress(block, TRUE)) { - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); buf_page_mutex_enter(fix_block); buf_block_set_io_fix(fix_block, BUF_IO_NONE); buf_page_mutex_exit(fix_block); --buf_pool->n_pend_unzip; + mutex_exit(&buf_pool->mutex); fix_block->unfix(); - buf_pool_mutex_exit(buf_pool); rw_lock_x_unlock(&fix_block->lock); if (err) { @@ -4624,7 +4158,7 @@ evict_from_pool: return NULL; } - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); buf_page_mutex_enter(fix_block); @@ -4634,7 +4168,7 @@ evict_from_pool: --buf_pool->n_pend_unzip; - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); rw_lock_x_unlock(&block->lock); @@ -4657,7 +4191,7 @@ evict_from_pool: /* Try to evict the block from the buffer pool, to use the insert buffer (change buffer) as much as possible. */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); fix_block->unfix(); @@ -4668,18 +4202,16 @@ evict_from_pool: if (buf_LRU_free_page(&fix_block->page, true)) { - buf_pool_mutex_exit(buf_pool); - - /* If not own buf_pool_mutex, - page_hash can be changed. */ - hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + mutex_exit(&buf_pool->mutex); + /* page_hash can be changed. */ + hash_lock = buf_page_hash_lock_get(page_id); rw_lock_x_lock(hash_lock); /* If not own buf_pool_mutex, page_hash can be changed. */ hash_lock = buf_page_hash_lock_x_confirm( - hash_lock, buf_pool, page_id); + hash_lock, page_id); if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { /* Set the watch, as it would have @@ -4689,7 +4221,7 @@ evict_from_pool: page_id, &hash_lock); } else { block = (buf_block_t*) buf_page_hash_get_low( - buf_pool, page_id); + page_id); } rw_lock_x_unlock(hash_lock); @@ -4710,7 +4242,7 @@ evict_from_pool: buf_page_mutex_enter(fix_block); - if (buf_flush_page_try(buf_pool, fix_block)) { + if (buf_flush_page_try(fix_block)) { guess = fix_block; goto loop; @@ -4722,7 +4254,7 @@ evict_from_pool: /* Failed to evict the page; change it directly */ - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ @@ -4765,11 +4297,11 @@ evict_from_pool: } if (mode != BUF_PEEK_IF_IN_POOL) { - buf_page_make_young_if_needed(buf_pool, &fix_block->page); + buf_page_make_young_if_needed(&fix_block->page); } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); ut_a(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ @@ -4890,8 +4422,7 @@ buf_page_optimistic_get( buf_page_mutex_exit(block); - buf_pool_t* buf_pool = buf_pool_from_block(block); - buf_page_make_young_if_needed(buf_pool, &block->page); + buf_page_make_young_if_needed(&block->page); ut_ad(!ibuf_inside(mtr) || ibuf_page(block->page.id, block->zip_size(), NULL)); @@ -4936,7 +4467,7 @@ buf_page_optimistic_get( mtr_memo_push(mtr, block, fix_type); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); ut_a(block->page.buf_fix_count > 0); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ @@ -4974,13 +4505,12 @@ buf_page_try_get_func( { buf_block_t* block; ibool success; - buf_pool_t* buf_pool = buf_pool_get(page_id); rw_lock_t* hash_lock; ut_ad(mtr); ut_ad(mtr->is_active()); - block = buf_block_hash_get_s_locked(buf_pool, page_id, &hash_lock); + block = buf_block_hash_get_s_locked(page_id, &hash_lock); if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { if (block) { @@ -4989,7 +4519,7 @@ buf_page_try_get_func( return(NULL); } - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page)); + ut_ad(!buf_pool_watch_is_sentinel(&block->page)); buf_page_mutex_enter(block); rw_lock_s_unlock(hash_lock); @@ -5023,7 +4553,7 @@ buf_page_try_get_func( mtr_memo_push(mtr, block, fix_type); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); ut_a(block->page.buf_fix_count > 0); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ @@ -5065,28 +4595,18 @@ buf_page_init_low( } /** Inits a page to the buffer buf_pool. -@param[in,out] buf_pool buffer pool @param[in] page_id page id @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] block block to init */ -static -void -buf_page_init( - buf_pool_t* buf_pool, - const page_id_t page_id, - ulint zip_size, - buf_block_t* block) +static void buf_page_init(const page_id_t page_id, ulint zip_size, + buf_block_t *block) { buf_page_t* hash_page; - ut_ad(buf_pool == buf_pool_get(page_id)); - ut_ad(buf_pool_mutex_own(buf_pool)); - + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_page_mutex_own(block)); ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE); - - ut_ad(rw_lock_own(buf_page_hash_lock_get(buf_pool, page_id), - RW_LOCK_X)); + ut_ad(rw_lock_own(buf_page_hash_lock_get(page_id), RW_LOCK_X)); /* Set the state of the block */ buf_block_set_file_page(block, page_id); @@ -5109,11 +4629,11 @@ buf_page_init( /* Insert into the hash table of file pages */ - hash_page = buf_page_hash_get_low(buf_pool, page_id); + hash_page = buf_page_hash_get_low(page_id); if (hash_page == NULL) { /* Block not found in hash table */ - } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) { + } else if (buf_pool_watch_is_sentinel(hash_page)) { /* Preserve the reference count. */ ib_uint32_t buf_fix_count = hash_page->buf_fix_count; @@ -5121,7 +4641,7 @@ buf_page_init( block->page.buf_fix_count += buf_fix_count; - buf_pool_watch_remove(buf_pool, hash_page); + buf_pool_watch_remove(hash_page); } else { ib::error() << "Page " << page_id @@ -5129,7 +4649,7 @@ buf_page_init( << hash_page << ", " << block; ut_d(buf_page_mutex_exit(block)); - ut_d(buf_pool_mutex_exit(buf_pool)); + ut_d(mutex_exit(&buf_pool->mutex)); ut_d(buf_print()); ut_d(buf_LRU_print()); ut_d(buf_validate()); @@ -5180,9 +4700,6 @@ buf_page_init_for_read( mtr_t mtr; bool lru = false; void* data; - buf_pool_t* buf_pool = buf_pool_get(page_id); - - ut_ad(buf_pool); *err = DB_SUCCESS; @@ -5207,18 +4724,17 @@ buf_page_init_for_read( if (zip_size && !unzip && !recv_recovery_is_on()) { block = NULL; } else { - block = buf_LRU_get_free_block(buf_pool); + block = buf_LRU_get_free_block(); ut_ad(block); - ut_ad(buf_pool_from_block(block) == buf_pool); } - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + hash_lock = buf_page_hash_lock_get(page_id); rw_lock_x_lock(hash_lock); - watch_page = buf_page_hash_get_low(buf_pool, page_id); - if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) { + watch_page = buf_page_hash_get_low(page_id); + if (watch_page && !buf_pool_watch_is_sentinel(watch_page)) { /* The page is already in the buffer pool. */ watch_page = NULL; rw_lock_x_unlock(hash_lock); @@ -5237,9 +4753,7 @@ buf_page_init_for_read( buf_page_mutex_enter(block); - ut_ad(buf_pool_from_bpage(bpage) == buf_pool); - - buf_page_init(buf_pool, page_id, zip_size, block); + buf_page_init(page_id, zip_size, block); /* Note: We are using the hash_lock for protection. This is safe because no other thread can lookup the block from the @@ -5273,7 +4787,7 @@ buf_page_init_for_read( been added to buf_pool->LRU and buf_pool->page_hash. */ buf_page_mutex_exit(block); - data = buf_buddy_alloc(buf_pool, zip_size, &lru); + data = buf_buddy_alloc(zip_size, &lru); buf_page_mutex_enter(block); block->page.zip.data = (page_zip_t*) data; @@ -5294,7 +4808,7 @@ buf_page_init_for_read( control block (bpage), in order to avoid the invocation of buf_buddy_relocate_block() on uninitialized data. */ - data = buf_buddy_alloc(buf_pool, zip_size, &lru); + data = buf_buddy_alloc(zip_size, &lru); rw_lock_x_lock(hash_lock); @@ -5302,17 +4816,15 @@ buf_page_init_for_read( it released and reacquired buf_pool->mutex. Thus, we must check the page_hash again, as it may have been modified. */ if (UNIV_UNLIKELY(lru)) { - - watch_page = buf_page_hash_get_low(buf_pool, page_id); + watch_page = buf_page_hash_get_low(page_id); if (UNIV_UNLIKELY(watch_page - && !buf_pool_watch_is_sentinel(buf_pool, - watch_page))) { + && !buf_pool_watch_is_sentinel(watch_page))) { /* The block was added by some other thread. */ rw_lock_x_unlock(hash_lock); watch_page = NULL; - buf_buddy_free(buf_pool, data, zip_size); + buf_buddy_free(data, zip_size); bpage = NULL; goto func_exit; @@ -5321,9 +4833,6 @@ buf_page_init_for_read( bpage = buf_page_alloc_descriptor(); - /* Initialize the buf_pool pointer. */ - bpage->buf_pool_index = buf_pool_index(buf_pool); - page_zip_des_init(&bpage->zip); page_zip_set_size(&bpage->zip, zip_size); bpage->zip.data = (page_zip_t*) data; @@ -5356,8 +4865,8 @@ buf_page_init_for_read( bpage->buf_fix_count += buf_fix_count; - ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page)); - buf_pool_watch_remove(buf_pool, watch_page); + ut_ad(buf_pool_watch_is_sentinel(watch_page)); + buf_pool_watch_remove(watch_page); } HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, @@ -5379,7 +4888,7 @@ buf_page_init_for_read( buf_pool->n_pend_reads++; func_exit: - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if (mode == BUF_READ_IBUF_PAGES_ONLY) { @@ -5410,28 +4919,27 @@ buf_page_create( buf_frame_t* frame; buf_block_t* block; buf_block_t* free_block = NULL; - buf_pool_t* buf_pool = buf_pool_get(page_id); rw_lock_t* hash_lock; ut_ad(mtr->is_active()); ut_ad(page_id.space() != 0 || !zip_size); - free_block = buf_LRU_get_free_block(buf_pool); + free_block = buf_LRU_get_free_block(); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - hash_lock = buf_page_hash_lock_get(buf_pool, page_id); + hash_lock = buf_page_hash_lock_get(page_id); rw_lock_x_lock(hash_lock); - block = (buf_block_t*) buf_page_hash_get_low(buf_pool, page_id); + block = (buf_block_t*) buf_page_hash_get_low(page_id); if (block && buf_page_in_file(&block->page) - && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) { + && !buf_pool_watch_is_sentinel(&block->page)) { ut_d(block->page.file_page_was_freed = FALSE); /* Page can be found in buf_pool */ - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); rw_lock_x_unlock(hash_lock); buf_block_free(free_block); @@ -5456,7 +4964,7 @@ buf_page_create( buf_page_mutex_enter(block); - buf_page_init(buf_pool, page_id, zip_size, block); + buf_page_init(page_id, zip_size, block); rw_lock_x_unlock(hash_lock); @@ -5467,9 +4975,6 @@ buf_page_create( buf_pool->stat.n_pages_created++; if (zip_size) { - void* data; - bool lru; - /* Prevent race conditions during buf_buddy_alloc(), which may release and reacquire buf_pool->mutex, by IO-fixing and X-latching the block. */ @@ -5484,9 +4989,8 @@ buf_page_create( the reacquisition of buf_pool->mutex. We also must defer this operation until after the block descriptor has been added to buf_pool->LRU and buf_pool->page_hash. */ - data = buf_buddy_alloc(buf_pool, zip_size, &lru); + block->page.zip.data = buf_buddy_alloc(zip_size); buf_page_mutex_enter(block); - block->page.zip.data = (page_zip_t*) data; /* To maintain the invariant block->in_unzip_LRU_list @@ -5500,7 +5004,7 @@ buf_page_create( rw_lock_x_unlock(&block->lock); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); @@ -5532,7 +5036,7 @@ buf_page_create( memset_aligned<8>(frame + FIL_PAGE_LSN, 0, 8); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 5771 || buf_validate()); + if (!(++buf_dbg_counter % 5771)) buf_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ return(block); } @@ -5670,13 +5174,12 @@ static void buf_corrupt_page_release(buf_page_t* bpage, const fil_space_t* space) { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); const ibool uncompressed = (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); page_id_t old_page_id = bpage->id; /* First unfix and release lock on the bpage */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); mutex_enter(buf_page_get_mutex(bpage)); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ); ut_ad(bpage->id.space() == space->id); @@ -5706,7 +5209,7 @@ buf_corrupt_page_release(buf_page_t* bpage, const fil_space_t* space) ut_ad(buf_pool->n_pend_reads > 0); buf_pool->n_pend_reads--; - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } /** Check if the encrypted page is corrupted for the full crc32 format. @@ -5816,7 +5319,6 @@ dberr_t buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict) { enum buf_io_fix io_type; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); const bool uncompressed = (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); ut_a(buf_page_in_file(bpage)); @@ -6014,7 +5516,7 @@ release_page: } BPageMutex* block_mutex = buf_page_get_mutex(bpage); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); mutex_enter(block_mutex); /* Because this thread which does the unlocking is not the same that @@ -6074,30 +5576,18 @@ release_page: io_type == BUF_IO_READ ? "read" : "wrote", bpage->id.space(), bpage->id.page_no())); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return DB_SUCCESS; } -/*********************************************************************//** -Asserts that all file pages in the buffer are in a replaceable state. -@return TRUE */ -static -ibool -buf_all_freed_instance( -/*===================*/ - buf_pool_t* buf_pool) /*!< in: buffer pool instancce */ +/** Assert that all buffer pool pages are in a replaceable state */ +void buf_assert_all_freed() { - ulint i; - buf_chunk_t* chunk; + mutex_enter(&buf_pool->mutex); + buf_chunk_t* chunk = buf_pool->chunks; - ut_ad(buf_pool); - - buf_pool_mutex_enter(buf_pool); - - chunk = buf_pool->chunks; - - for (i = buf_pool->n_chunks; i--; chunk++) { + for (ulint i = buf_pool->n_chunks; i--; chunk++) { if (const buf_block_t* block = buf_chunk_not_freed(chunk)) { ib::fatal() << "Page " << block->page.id @@ -6105,64 +5595,49 @@ buf_all_freed_instance( } } - buf_pool_mutex_exit(buf_pool); - - return(TRUE); + mutex_exit(&buf_pool->mutex); } -/** Refreshes the statistics used to print per-second averages. -@param[in,out] buf_pool buffer pool instance */ -static -void -buf_refresh_io_stats( - buf_pool_t* buf_pool) +/** Refresh the statistics used to print per-second averages. */ +void buf_refresh_io_stats() { buf_pool->last_printout_time = time(NULL); buf_pool->old_stat = buf_pool->stat; } -/*********************************************************************//** -Invalidates file pages in one buffer pool instance */ -static -void -buf_pool_invalidate_instance( -/*=========================*/ - buf_pool_t* buf_pool) /*!< in: buffer pool instance */ +/** Invalidate all pages in the buffer pool. +All pages must be in a replaceable state (not modified or latched). */ +void buf_pool_invalidate() { - ulint i; + mutex_enter(&buf_pool->mutex); - buf_pool_mutex_enter(buf_pool); - - for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) { + for (unsigned i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) { /* As this function is called during startup and during redo application phase during recovery, InnoDB is single threaded (apart from IO helper threads) at this stage. No new write batch can be in intialization stage at this point. */ - ut_ad(buf_pool->init_flush[i] == FALSE); + ut_ad(!buf_pool->init_flush[i]); /* However, it is possible that a write batch that has been posted earlier is still not complete. For buffer pool invalidation to proceed we must ensure there is NO write activity happening. */ if (buf_pool->n_flush[i] > 0) { - buf_flush_t type = static_cast(i); + buf_flush_t type = buf_flush_t(i); - buf_pool_mutex_exit(buf_pool); - buf_flush_wait_batch_end(buf_pool, type); - buf_pool_mutex_enter(buf_pool); + mutex_exit(&buf_pool->mutex); + buf_flush_wait_batch_end(type); + mutex_enter(&buf_pool->mutex); } } - buf_pool_mutex_exit(buf_pool); + ut_d(mutex_exit(&buf_pool->mutex)); + ut_d(buf_assert_all_freed()); + ut_d(mutex_enter(&buf_pool->mutex)); - ut_ad(buf_all_freed_instance(buf_pool)); - - buf_pool_mutex_enter(buf_pool); - - while (buf_LRU_scan_and_free_block(buf_pool, true)) { - } + while (buf_LRU_scan_and_free_block(true)); ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0); ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0); @@ -6172,35 +5647,13 @@ buf_pool_invalidate_instance( buf_pool->LRU_old_len = 0; memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat)); - buf_refresh_io_stats(buf_pool); - - buf_pool_mutex_exit(buf_pool); -} - -/*********************************************************************//** -Invalidates the file pages in the buffer pool when an archive recovery is -completed. All the file pages buffered must be in a replaceable state when -this function is called: not latched and not modified. */ -void -buf_pool_invalidate(void) -/*=====================*/ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_invalidate_instance(buf_pool_from_array(i)); - } + buf_refresh_io_stats(); + mutex_exit(&buf_pool->mutex); } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/*********************************************************************//** -Validates data in one buffer pool instance -@return TRUE */ -static -ibool -buf_pool_validate_instance( -/*=======================*/ - buf_pool_t* buf_pool) /*!< in: buffer pool instance */ +/** Validate the buffer pool. */ +void buf_validate() { buf_page_t* b; buf_chunk_t* chunk; @@ -6213,9 +5666,7 @@ buf_pool_validate_instance( ulint n_free = 0; ulint n_zip = 0; - ut_ad(buf_pool); - - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); hash_lock_x_all(buf_pool->page_hash); chunk = buf_pool->chunks; @@ -6241,9 +5692,8 @@ buf_pool_validate_instance( break; case BUF_BLOCK_FILE_PAGE: - ut_a(buf_page_hash_get_low( - buf_pool, block->page.id) - == &block->page); + ut_ad(buf_page_hash_get_low(block->page.id) + == &block->page); switch (buf_page_get_io_fix(&block->page)) { case BUF_IO_NONE: @@ -6271,15 +5721,11 @@ assert_s_latched: default: ut_error; } - break; - case BUF_IO_READ: - - ut_a(rw_lock_is_locked(&block->lock, - RW_LOCK_X)); + ut_ad(rw_lock_is_locked(&block->lock, + RW_LOCK_X)); break; - case BUF_IO_PIN: break; } @@ -6308,7 +5754,7 @@ assert_s_latched: for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b; b = UT_LIST_GET_NEXT(list, b)) { - ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE); + ut_ad(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE); switch (buf_page_get_io_fix(b)) { case BUF_IO_NONE: case BUF_IO_PIN: @@ -6328,19 +5774,19 @@ assert_s_latched: /* It is OK to read oldest_modification here because we have acquired buf_pool->zip_mutex above which acts as the 'block->mutex' for these bpages. */ - ut_a(!b->oldest_modification); - ut_a(buf_page_hash_get_low(buf_pool, b->id) == b); + ut_ad(!b->oldest_modification); + ut_ad(buf_page_hash_get_low(b->id) == b); n_lru++; n_zip++; } /* Check dirty blocks. */ - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b; b = UT_LIST_GET_NEXT(list, b)) { ut_ad(b->in_flush_list); - ut_a(b->oldest_modification); + ut_ad(b->oldest_modification); n_flush++; switch (buf_page_get_state(b)) { @@ -6381,13 +5827,13 @@ assert_s_latched: ut_error; break; } - ut_a(buf_page_hash_get_low(buf_pool, b->id) == b); + ut_ad(buf_page_hash_get_low(b->id) == b); } - ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush); + ut_ad(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush); hash_unlock_x_all(buf_pool->page_hash); - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); mutex_exit(&buf_pool->zip_mutex); @@ -6399,7 +5845,8 @@ assert_s_latched: << " zip " << n_zip << ". Aborting..."; } - ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru); + ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru); + if (buf_pool->curr_size == buf_pool->old_size && UT_LIST_GET_LEN(buf_pool->free) != n_free) { @@ -6408,47 +5855,20 @@ assert_s_latched: << ", free blocks " << n_free << ". Aborting..."; } - ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush); - ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush); - ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_page_flush); + ut_ad(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush); + ut_ad(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush); + ut_ad(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_page_flush); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); - ut_a(buf_LRU_validate()); - ut_a(buf_flush_validate(buf_pool)); - - return(TRUE); + ut_d(buf_LRU_validate()); + ut_d(buf_flush_validate()); } - -/*********************************************************************//** -Validates the buffer buf_pool data structure. -@return TRUE */ -ibool -buf_validate(void) -/*==============*/ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_pool_validate_instance(buf_pool); - } - return(TRUE); -} - #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/*********************************************************************//** -Prints info of the buffer buf_pool data structure for one instance. */ -static -void -buf_print_instance( -/*===============*/ - buf_pool_t* buf_pool) +/** Write information of the buf_pool to the error log. */ +void buf_print() { index_id_t* index_ids; ulint* counts; @@ -6460,8 +5880,6 @@ buf_print_instance( buf_chunk_t* chunk; dict_index_t* index; - ut_ad(buf_pool); - size = buf_pool->curr_size; index_ids = static_cast( @@ -6469,12 +5887,27 @@ buf_print_instance( counts = static_cast(ut_malloc_nokey(sizeof(ulint) * size)); - buf_pool_mutex_enter(buf_pool); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); + mutex_enter(&buf_pool->flush_list_mutex); - ib::info() << *buf_pool; + ib::info() + << "[buffer pool: size=" << buf_pool->curr_size + << ", database pages=" << UT_LIST_GET_LEN(buf_pool->LRU) + << ", free pages=" << UT_LIST_GET_LEN(buf_pool->free) + << ", modified database pages=" + << UT_LIST_GET_LEN(buf_pool->flush_list) + << ", n pending decompressions=" << buf_pool->n_pend_unzip + << ", n pending reads=" << buf_pool->n_pend_reads + << ", n pending flush LRU=" << buf_pool->n_flush[BUF_FLUSH_LRU] + << " list=" << buf_pool->n_flush[BUF_FLUSH_LIST] + << " single page=" << buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] + << ", pages made young=" << buf_pool->stat.n_pages_made_young + << ", not young=" << buf_pool->stat.n_pages_not_made_young + << ", pages read=" << buf_pool->stat.n_pages_read + << ", created=" << buf_pool->stat.n_pages_created + << ", written=" << buf_pool->stat.n_pages_written << "]"; - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); /* Count the number of blocks belonging to each index in the buffer */ @@ -6515,7 +5948,7 @@ buf_print_instance( } } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); for (i = 0; i < n_found; i++) { index = dict_index_get_if_in_cache(index_ids[i]); @@ -6535,42 +5968,20 @@ buf_print_instance( ut_free(index_ids); ut_free(counts); - ut_a(buf_pool_validate_instance(buf_pool)); -} - -/*********************************************************************//** -Prints info of the buffer buf_pool data structure. */ -void -buf_print(void) -/*===========*/ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - buf_print_instance(buf_pool); - } + buf_validate(); } #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ #ifdef UNIV_DEBUG -/*********************************************************************//** -Returns the number of latched pages in the buffer pool. -@return number of latched pages */ -static -ulint -buf_get_latched_pages_number_instance( -/*==================================*/ - buf_pool_t* buf_pool) /*!< in: buffer pool instance */ +/** @return the number of latched pages in the buffer pool */ +ulint buf_get_latched_pages_number() { buf_page_t* b; ulint i; buf_chunk_t* chunk; ulint fixed_pages_number = 0; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); chunk = buf_pool->chunks; @@ -6614,7 +6025,7 @@ buf_get_latched_pages_number_instance( } } - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b; b = UT_LIST_GET_NEXT(list, b)) { ut_ad(b->in_flush_list); @@ -6640,155 +6051,23 @@ buf_get_latched_pages_number_instance( } } - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); mutex_exit(&buf_pool->zip_mutex); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(fixed_pages_number); } - -/*********************************************************************//** -Returns the number of latched pages in all the buffer pools. -@return number of latched pages */ -ulint -buf_get_latched_pages_number(void) -/*==============================*/ -{ - ulint i; - ulint total_latched_pages = 0; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - total_latched_pages += buf_get_latched_pages_number_instance( - buf_pool); - } - - return(total_latched_pages); -} - #endif /* UNIV_DEBUG */ -/*********************************************************************//** -Returns the number of pending buf pool read ios. -@return number of pending read I/O operations */ -ulint -buf_get_n_pending_read_ios(void) -/*============================*/ +/** Collect buffer pool metadata. +@param[out] pool_info buffer pool metadata */ +void buf_stats_get_pool_info(buf_pool_info_t *pool_info) { - ulint pend_ios = 0; - - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - pend_ios += buf_pool_from_array(i)->n_pend_reads; - } - - return(pend_ios); -} - -/*********************************************************************//** -Returns the ratio in percents of modified pages in the buffer pool / -database pages in the buffer pool. -@return modified page percentage ratio */ -double -buf_get_modified_ratio_pct(void) -/*============================*/ -{ - double ratio; - ulint lru_len = 0; - ulint free_len = 0; - ulint flush_list_len = 0; - - buf_get_total_list_len(&lru_len, &free_len, &flush_list_len); - - ratio = static_cast(100 * flush_list_len) - / (1 + lru_len + free_len); - - /* 1 + is there to avoid division by zero */ - - return(ratio); -} - -/*******************************************************************//** -Aggregates a pool stats information with the total buffer pool stats */ -static -void -buf_stats_aggregate_pool_info( -/*==========================*/ - buf_pool_info_t* total_info, /*!< in/out: the buffer pool - info to store aggregated - result */ - const buf_pool_info_t* pool_info) /*!< in: individual buffer pool - stats info */ -{ - ut_a(total_info && pool_info); - - /* Nothing to copy if total_info is the same as pool_info */ - if (total_info == pool_info) { - return; - } - - total_info->pool_size += pool_info->pool_size; - total_info->lru_len += pool_info->lru_len; - total_info->old_lru_len += pool_info->old_lru_len; - total_info->free_list_len += pool_info->free_list_len; - total_info->flush_list_len += pool_info->flush_list_len; - total_info->n_pend_unzip += pool_info->n_pend_unzip; - total_info->n_pend_reads += pool_info->n_pend_reads; - total_info->n_pending_flush_lru += pool_info->n_pending_flush_lru; - total_info->n_pending_flush_list += pool_info->n_pending_flush_list; - total_info->n_pages_made_young += pool_info->n_pages_made_young; - total_info->n_pages_not_made_young += pool_info->n_pages_not_made_young; - total_info->n_pages_read += pool_info->n_pages_read; - total_info->n_pages_created += pool_info->n_pages_created; - total_info->n_pages_written += pool_info->n_pages_written; - total_info->n_page_gets += pool_info->n_page_gets; - total_info->n_ra_pages_read_rnd += pool_info->n_ra_pages_read_rnd; - total_info->n_ra_pages_read += pool_info->n_ra_pages_read; - total_info->n_ra_pages_evicted += pool_info->n_ra_pages_evicted; - total_info->page_made_young_rate += pool_info->page_made_young_rate; - total_info->page_not_made_young_rate += - pool_info->page_not_made_young_rate; - total_info->pages_read_rate += pool_info->pages_read_rate; - total_info->pages_created_rate += pool_info->pages_created_rate; - total_info->pages_written_rate += pool_info->pages_written_rate; - total_info->n_page_get_delta += pool_info->n_page_get_delta; - total_info->page_read_delta += pool_info->page_read_delta; - total_info->young_making_delta += pool_info->young_making_delta; - total_info->not_young_making_delta += pool_info->not_young_making_delta; - total_info->pages_readahead_rnd_rate += pool_info->pages_readahead_rnd_rate; - total_info->pages_readahead_rate += pool_info->pages_readahead_rate; - total_info->pages_evicted_rate += pool_info->pages_evicted_rate; - total_info->unzip_lru_len += pool_info->unzip_lru_len; - total_info->io_sum += pool_info->io_sum; - total_info->io_cur += pool_info->io_cur; - total_info->unzip_sum += pool_info->unzip_sum; - total_info->unzip_cur += pool_info->unzip_cur; -} -/*******************************************************************//** -Collect buffer pool stats information for a buffer pool. Also -record aggregated stats if there are more than one buffer pool -in the server */ -void -buf_stats_get_pool_info( -/*====================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool */ - uint pool_id, /*!< in: buffer pool ID */ - buf_pool_info_t* all_pool_info) /*!< in/out: buffer pool info - to fill */ -{ - buf_pool_info_t* pool_info; time_t current_time; double time_elapsed; - /* Find appropriate pool_info to store stats for this buffer pool */ - pool_info = &all_pool_info[pool_id]; - - buf_pool_mutex_enter(buf_pool); - buf_flush_list_mutex_enter(buf_pool); - - pool_info->pool_unique_id = pool_id; + mutex_enter(&buf_pool->mutex); + mutex_enter(&buf_pool->flush_list_mutex); pool_info->pool_size = buf_pool->curr_size; @@ -6816,7 +6095,7 @@ buf_stats_get_pool_info( (buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] + buf_pool->init_flush[BUF_FLUSH_SINGLE_PAGE]); - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); current_time = time(NULL); time_elapsed = 0.001 + difftime(current_time, @@ -6898,8 +6177,8 @@ buf_stats_get_pool_info( pool_info->unzip_cur = buf_LRU_stat_cur.unzip; - buf_refresh_io_stats(buf_pool); - buf_pool_mutex_exit(buf_pool); + buf_refresh_io_stats(); + mutex_exit(&buf_pool->mutex); } /*********************************************************************//** @@ -7003,94 +6282,10 @@ buf_print_io( /*=========*/ FILE* file) /*!< in/out: buffer where to print */ { - buf_pool_info_t* pool_info; - buf_pool_info_t* pool_info_total; + buf_pool_info_t pool_info; - /* If srv_buf_pool_instances is greater than 1, allocate - one extra buf_pool_info_t, the last one stores - aggregated/total values from all pools */ - if (srv_buf_pool_instances > 1) { - pool_info = (buf_pool_info_t*) ut_zalloc_nokey(( - srv_buf_pool_instances + 1) * sizeof *pool_info); - - pool_info_total = &pool_info[srv_buf_pool_instances]; - } else { - ut_a(srv_buf_pool_instances == 1); - - pool_info_total = pool_info = - static_cast( - ut_zalloc_nokey(sizeof *pool_info)); - } - - for (uint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - /* Fetch individual buffer pool info and calculate - aggregated stats along the way */ - buf_stats_get_pool_info(buf_pool, i, pool_info); - - /* If we have more than one buffer pool, store - the aggregated stats */ - if (srv_buf_pool_instances > 1) { - buf_stats_aggregate_pool_info(pool_info_total, - &pool_info[i]); - } - } - - /* Print the aggreate buffer pool info */ - buf_print_io_instance(pool_info_total, file); - - /* If there are more than one buffer pool, print each individual pool - info */ - if (srv_buf_pool_instances > 1) { - fputs("----------------------\n" - "INDIVIDUAL BUFFER POOL INFO\n" - "----------------------\n", file); - - for (uint i = 0; i < srv_buf_pool_instances; i++) { - fprintf(file, "---BUFFER POOL %u\n", i); - buf_print_io_instance(&pool_info[i], file); - } - } - - ut_free(pool_info); -} - -/**********************************************************************//** -Refreshes the statistics used to print per-second averages. */ -void -buf_refresh_io_stats_all(void) -/*==========================*/ -{ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_refresh_io_stats(buf_pool); - } -} - -/**********************************************************************//** -Check if all pages in all buffer pools are in a replacable state. -@return FALSE if not */ -ibool -buf_all_freed(void) -/*===============*/ -{ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - if (!buf_all_freed_instance(buf_pool)) { - return(FALSE); - } - } - - return(TRUE); + buf_stats_get_pool_info(&pool_info); + buf_print_io_instance(&pool_info, file); } /** Verify that post encryption checksum match with the calculated checksum. @@ -7108,32 +6303,18 @@ bool buf_page_verify_crypt_checksum(const byte* page, ulint fsp_flags) return !buf_page_is_corrupted(true, page, fsp_flags); } -/*********************************************************************//** -Checks that there currently are no pending i/o-operations for the buffer -pool. +/** Checks that there currently are no I/O operations pending. @return number of pending i/o */ -ulint -buf_pool_check_no_pending_io(void) -/*==============================*/ +ulint buf_pool_check_no_pending_io() { - ulint i; - ulint pending_io = 0; - - buf_pool_mutex_enter_all(); - - for (i = 0; i < srv_buf_pool_instances; i++) { - const buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - pending_io += buf_pool->n_pend_reads - + buf_pool->n_flush[BUF_FLUSH_LRU] - + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] - + buf_pool->n_flush[BUF_FLUSH_LIST]; - - } - - buf_pool_mutex_exit_all(); + /* FIXME: use atomics, no mutex */ + ulint pending_io = buf_pool->n_pend_reads; + mutex_enter(&buf_pool->mutex); + pending_io += + + buf_pool->n_flush[BUF_FLUSH_LRU] + + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] + + buf_pool->n_flush[BUF_FLUSH_LIST]; + mutex_exit(&buf_pool->mutex); return(pending_io); } @@ -7149,34 +6330,6 @@ std::ostream& operator<<(std::ostream &out, const page_id_t page_id) return out; } -/** Print the given buf_pool_t object. -@param[in,out] out the output stream -@param[in] buf_pool the buf_pool_t object to be printed -@return the output stream */ -std::ostream& -operator<<( - std::ostream& out, - const buf_pool_t& buf_pool) -{ - out << "[buffer pool instance: " - << "buf_pool size=" << buf_pool.curr_size - << ", database pages=" << UT_LIST_GET_LEN(buf_pool.LRU) - << ", free pages=" << UT_LIST_GET_LEN(buf_pool.free) - << ", modified database pages=" - << UT_LIST_GET_LEN(buf_pool.flush_list) - << ", n pending decompressions=" << buf_pool.n_pend_unzip - << ", n pending reads=" << buf_pool.n_pend_reads - << ", n pending flush LRU=" << buf_pool.n_flush[BUF_FLUSH_LRU] - << " list=" << buf_pool.n_flush[BUF_FLUSH_LIST] - << " single page=" << buf_pool.n_flush[BUF_FLUSH_SINGLE_PAGE] - << ", pages made young=" << buf_pool.stat.n_pages_made_young - << ", not young=" << buf_pool.stat.n_pages_not_made_young - << ", pages read=" << buf_pool.stat.n_pages_read - << ", created=" << buf_pool.stat.n_pages_created - << ", written=" << buf_pool.stat.n_pages_written << "]"; - return(out); -} - /** Should we punch hole to deallocate unused portion of the page. @param[in] bpage Page control block diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index c5f851fd1af..a5383f48233 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -253,7 +253,6 @@ buf_dump( char tmp_filename[OS_FILE_MAX_PATH + sizeof "incomplete"]; char now[32]; FILE* f; - ulint i; int ret; buf_dump_generate_path(full_filename, sizeof(full_filename)); @@ -284,114 +283,99 @@ buf_dump( tmp_filename, strerror(errno)); return; } - /* else */ + const buf_page_t* bpage; + buf_dump_t* dump; + ulint n_pages; + ulint j; - /* walk through each buffer pool */ - for (i = 0; i < srv_buf_pool_instances && !SHOULD_QUIT(); i++) { - buf_pool_t* buf_pool; - const buf_page_t* bpage; - buf_dump_t* dump; - ulint n_pages; - ulint j; + mutex_enter(&buf_pool->mutex); - buf_pool = buf_pool_from_array(i); + n_pages = UT_LIST_GET_LEN(buf_pool->LRU); - /* obtain buf_pool mutex before allocate, since - UT_LIST_GET_LEN(buf_pool->LRU) could change */ - buf_pool_mutex_enter(buf_pool); + /* skip empty buffer pools */ + if (n_pages == 0) { + mutex_exit(&buf_pool->mutex); + goto done; + } - n_pages = UT_LIST_GET_LEN(buf_pool->LRU); + if (srv_buf_pool_dump_pct != 100) { + ulint t_pages; + + /* limit the number of total pages dumped to X% of the + total number of pages */ + t_pages = buf_pool->curr_size * srv_buf_pool_dump_pct / 100; + if (n_pages > t_pages) { + buf_dump_status(STATUS_INFO, + "Restricted to " ULINTPF + " pages due to " + "innodb_buf_pool_dump_pct=%lu", + t_pages, srv_buf_pool_dump_pct); + n_pages = t_pages; + } - /* skip empty buffer pools */ if (n_pages == 0) { - buf_pool_mutex_exit(buf_pool); + n_pages = 1; + } + } + + dump = static_cast(ut_malloc_nokey( + n_pages * sizeof(*dump))); + + if (dump == NULL) { + mutex_exit(&buf_pool->mutex); + fclose(f); + buf_dump_status(STATUS_ERR, + "Cannot allocate " ULINTPF " bytes: %s", + (ulint) (n_pages * sizeof(*dump)), + strerror(errno)); + /* leave tmp_filename to exist */ + return; + } + + for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU), j = 0; + bpage != NULL && j < n_pages; + bpage = UT_LIST_GET_NEXT(LRU, bpage)) { + + ut_a(buf_page_in_file(bpage)); + + if (bpage->id.space() == SRV_TMP_SPACE_ID) { + /* Ignore the innodb_temporary tablespace. */ continue; } - if (srv_buf_pool_dump_pct != 100) { - ulint t_pages; + dump[j++] = BUF_DUMP_CREATE(bpage->id.space(), + bpage->id.page_no()); + } - ut_ad(srv_buf_pool_dump_pct < 100); + mutex_exit(&buf_pool->mutex); - /* limit the number of total pages dumped to X% of the - * total number of pages */ - t_pages = buf_pool->curr_size - * srv_buf_pool_dump_pct / 100; - if (n_pages > t_pages) { - buf_dump_status(STATUS_INFO, - "Instance " ULINTPF - ", restricted to " ULINTPF - " pages due to " - "innodb_buf_pool_dump_pct=%lu", - i, t_pages, - srv_buf_pool_dump_pct); - n_pages = t_pages; - } + ut_a(j <= n_pages); + n_pages = j; - if (n_pages == 0) { - n_pages = 1; - } - } - - dump = static_cast(ut_malloc_nokey( - n_pages * sizeof(*dump))); - - if (dump == NULL) { - buf_pool_mutex_exit(buf_pool); + for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) { + ret = fprintf(f, ULINTPF "," ULINTPF "\n", + BUF_DUMP_SPACE(dump[j]), + BUF_DUMP_PAGE(dump[j])); + if (ret < 0) { + ut_free(dump); fclose(f); buf_dump_status(STATUS_ERR, - "Cannot allocate " ULINTPF " bytes: %s", - (ulint) (n_pages * sizeof(*dump)), - strerror(errno)); + "Cannot write to '%s': %s", + tmp_filename, strerror(errno)); /* leave tmp_filename to exist */ return; } - - for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU), j = 0; - bpage != NULL && j < n_pages; - bpage = UT_LIST_GET_NEXT(LRU, bpage)) { - - ut_a(buf_page_in_file(bpage)); - if (bpage->id.space() == SRV_TMP_SPACE_ID) { - /* Ignore the innodb_temporary tablespace. */ - continue; - } - - dump[j++] = BUF_DUMP_CREATE(bpage->id.space(), - bpage->id.page_no()); + if (SHUTTING_DOWN() && !(j & 1023)) { + service_manager_extend_timeout( + INNODB_EXTEND_TIMEOUT_INTERVAL, + "Dumping buffer pool page " + ULINTPF "/" ULINTPF, j + 1, n_pages); } - - buf_pool_mutex_exit(buf_pool); - - ut_a(j <= n_pages); - n_pages = j; - - for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) { - ret = fprintf(f, ULINTPF "," ULINTPF "\n", - BUF_DUMP_SPACE(dump[j]), - BUF_DUMP_PAGE(dump[j])); - if (ret < 0) { - ut_free(dump); - fclose(f); - buf_dump_status(STATUS_ERR, - "Cannot write to '%s': %s", - tmp_filename, strerror(errno)); - /* leave tmp_filename to exist */ - return; - } - if (SHUTTING_DOWN() && !(j % 1024)) { - service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, - "Dumping buffer pool " - ULINTPF "/%lu, " - "page " ULINTPF "/" ULINTPF, - i + 1, srv_buf_pool_instances, - j + 1, n_pages); - } - } - - ut_free(dump); } + ut_free(dump); + +done: ret = fclose(f); if (ret != 0) { buf_dump_status(STATUS_ERR, @@ -517,7 +501,6 @@ buf_load() FILE* f; buf_dump_t* dump; ulint dump_n; - ulint total_buffer_pools_pages; ulint i; ulint space_id; ulint page_no; @@ -567,13 +550,9 @@ buf_load() /* If dump is larger than the buffer pool(s), then we ignore the extra trailing. This could happen if a dump is made, then buffer pool is shrunk and then load is attempted. */ - total_buffer_pools_pages = buf_pool_get_n_pages() - * srv_buf_pool_instances; - if (dump_n > total_buffer_pools_pages) { - dump_n = total_buffer_pools_pages; - } + dump_n = std::min(dump_n, buf_pool_get_n_pages()); - if(dump_n != 0) { + if (dump_n != 0) { dump = static_cast(ut_malloc_nokey( dump_n * sizeof(*dump))); } else { @@ -805,7 +784,7 @@ static void buf_dump_load_func(void *) while (!SHUTTING_DOWN()) { if (buf_dump_should_start) { buf_dump_should_start = false; - buf_dump(TRUE /* quit on shutdown */); + buf_dump(true); } if (buf_load_should_start) { buf_load_should_start = false; @@ -827,7 +806,7 @@ static void buf_dump_load_func(void *) } else if (get_wsrep_recovery()) { #endif /* WITH_WSREP */ } else { - buf_dump(FALSE/* do complete dump at shutdown */); + buf_dump(false/* do complete dump at shutdown */); } } } diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 7f7391ba9f0..20adfa0079f 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -104,21 +104,17 @@ static tpool::waitable_task pc_flush_slot_task( /** State for page cleaner array slot */ enum page_cleaner_state_t { - /** Not requested any yet. - Moved from FINISHED by the coordinator. */ + /** Not requested any yet. Moved from FINISHED. */ PAGE_CLEANER_STATE_NONE = 0, - /** Requested but not started flushing. - Moved from NONE by the coordinator. */ + /** Requested but not started flushing. Moved from NONE. */ PAGE_CLEANER_STATE_REQUESTED, - /** Flushing is on going. - Moved from REQUESTED by the worker. */ + /** Flushing is on going. Moved from REQUESTED. */ PAGE_CLEANER_STATE_FLUSHING, - /** Flushing was finished. - Moved from FLUSHING by the worker. */ + /** Flushing was finished. Moved from FLUSHING. */ PAGE_CLEANER_STATE_FINISHED }; -/** Page cleaner request state for each buffer pool instance */ +/** Page cleaner request state for buf_pool */ struct page_cleaner_slot_t { page_cleaner_state_t state; /*!< state of the request. protected by page_cleaner_t::mutex @@ -154,20 +150,19 @@ struct page_cleaner_slot_t { flushing */ }; -/** Page cleaner structure common for all threads */ +/** Page cleaner structure */ struct page_cleaner_t { + /* FIXME: do we need mutex? use atomics? */ ib_mutex_t mutex; /*!< mutex to protect whole of page_cleaner_t struct and page_cleaner_slot_t slots. */ os_event_t is_finished; /*!< event to signal that all slots were finished. */ - volatile ulint n_workers; /*!< number of worker threads - in existence */ bool requested; /*!< true if requested pages to flush */ lsn_t lsn_limit; /*!< upper limit of LSN to be flushed */ - ulint n_slots; /*!< total number of slots */ +#if 1 /* FIXME: use bool for these, or remove some of these */ ulint n_slots_requested; /*!< number of slots in the state @@ -180,24 +175,16 @@ struct page_cleaner_t { /*!< number of slots in the state PAGE_CLEANER_STATE_FINISHED */ +#endif ulint flush_time; /*!< elapsed time to flush requests for all slots */ ulint flush_pass; /*!< count to finish to flush requests for all slots */ - page_cleaner_slot_t slots[MAX_BUFFER_POOLS]; + page_cleaner_slot_t slot; bool is_running; /*!< false if attempt to shutdown */ - -#ifdef UNIV_DEBUG - ulint n_disabled_debug; - /*flush_list_mutex)); buf_pool->stat.flush_list_bytes += block->physical_size(); - ut_ad(buf_pool->stat.flush_list_bytes <= buf_pool->curr_pool_size); } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/******************************************************************//** -Validates the flush list. -@return TRUE if ok */ -static -ibool -buf_flush_validate_low( -/*===================*/ - buf_pool_t* buf_pool); /*!< in: Buffer pool instance */ +/** Validate the flush list. */ +static void buf_flush_validate_low(); -/******************************************************************//** -Validates the flush list some of the time. -@return TRUE if ok or the check was skipped */ -static -ibool -buf_flush_validate_skip( -/*====================*/ - buf_pool_t* buf_pool) /*!< in: Buffer pool instance */ +/** Validates the flush list some of the time. */ +static void buf_flush_validate_skip() { /** Try buf_flush_validate_low() every this many times */ # define BUF_FLUSH_VALIDATE_SKIP 23 @@ -259,11 +227,11 @@ buf_flush_validate_skip( reduce the call frequency of the costly buf_flush_validate_low() check in debug builds. */ if (--buf_flush_validate_count > 0) { - return(TRUE); + return; } buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP; - return(buf_flush_validate_low(buf_pool)); + buf_flush_validate_low(); } #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ @@ -281,10 +249,9 @@ buf_flush_insert_in_flush_rbt( const ib_rbt_node_t* c_node; const ib_rbt_node_t* p_node; buf_page_t* prev = NULL; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE); - ut_ad(buf_flush_list_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->flush_list_mutex)); /* Insert this buffer into the rbt. */ c_node = rbt_insert(buf_pool->flush_rbt, &bpage, &bpage); @@ -311,15 +278,10 @@ buf_flush_delete_from_flush_rbt( /*============================*/ buf_page_t* bpage) /*!< in: bpage to be removed. */ { -#ifdef UNIV_DEBUG - ibool ret = FALSE; -#endif /* UNIV_DEBUG */ - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_flush_list_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->flush_list_mutex)); #ifdef UNIV_DEBUG - ret = + ibool ret = #endif /* UNIV_DEBUG */ rbt_delete(buf_pool->flush_rbt, &bpage); @@ -350,11 +312,7 @@ buf_flush_block_cmp( ut_ad(b1 != NULL); ut_ad(b2 != NULL); -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(b1); -#endif /* UNIV_DEBUG */ - - ut_ad(buf_flush_list_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->flush_list_mutex)); ut_ad(b1->in_flush_list); ut_ad(b2->in_flush_list); @@ -380,23 +338,12 @@ void buf_flush_init_flush_rbt(void) /*==========================*/ { - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_flush_list_mutex_enter(buf_pool); - - ut_ad(buf_pool->flush_rbt == NULL); - - /* Create red black tree for speedy insertions in flush list. */ - buf_pool->flush_rbt = rbt_create( - sizeof(buf_page_t*), buf_flush_block_cmp); - - buf_flush_list_mutex_exit(buf_pool); - } + mutex_enter(&buf_pool->flush_list_mutex); + ut_ad(buf_pool->flush_rbt == NULL); + /* Create red black tree for speedy insertions in flush list. */ + buf_pool->flush_rbt = rbt_create( + sizeof(buf_page_t*), buf_flush_block_cmp); + mutex_exit(&buf_pool->flush_list_mutex); } /********************************************************************//** @@ -405,40 +352,26 @@ void buf_flush_free_flush_rbt(void) /*==========================*/ { - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_flush_list_mutex_enter(buf_pool); - + mutex_enter(&buf_pool->flush_list_mutex); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(buf_flush_validate_low(buf_pool)); + buf_flush_validate_low(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - - rbt_free(buf_pool->flush_rbt); - buf_pool->flush_rbt = NULL; - - buf_flush_list_mutex_exit(buf_pool); - } + rbt_free(buf_pool->flush_rbt); + buf_pool->flush_rbt = NULL; + mutex_exit(&buf_pool->flush_list_mutex); } -/********************************************************************//** -Inserts a modified block into the flush list. */ -void -buf_flush_insert_into_flush_list( -/*=============================*/ - buf_pool_t* buf_pool, /*!< buffer pool instance */ - buf_block_t* block, /*!< in/out: block which is modified */ - lsn_t lsn) /*!< in: oldest modification */ +/** Insert a modified block into the flush list. +@param[in,out] block modified block +@param[in] lsn oldest modification */ +void buf_flush_insert_into_flush_list(buf_block_t* block, lsn_t lsn) { - ut_ad(!buf_pool_mutex_own(buf_pool)); + ut_ad(!mutex_own(&buf_pool->mutex)); ut_ad(log_flush_order_mutex_own()); ut_ad(buf_page_mutex_own(block)); + ut_ad(lsn); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); ut_ad(!block->page.in_flush_list); ut_d(block->page.in_flush_list = TRUE); ut_ad(!block->page.oldest_modification); @@ -446,7 +379,7 @@ buf_flush_insert_into_flush_list( UNIV_MEM_ASSERT_RW(block->page.zip.data ? block->page.zip.data : block->frame, block->physical_size()); - incr_flush_list_size_in_bytes(block, buf_pool); + incr_flush_list_size_in_bytes(block); if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) { ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE); @@ -476,10 +409,10 @@ buf_flush_insert_into_flush_list( UT_LIST_ADD_FIRST(buf_pool->flush_list, &block->page); func_exit: #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(buf_flush_validate_skip(buf_pool)); + buf_flush_validate_skip(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); } /********************************************************************//** @@ -492,10 +425,7 @@ buf_flush_ready_for_replace( buf_page_t* bpage) /*!< in: buffer control block, must be buf_page_in_file(bpage) and in the LRU list */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(bpage->in_LRU_list); @@ -522,11 +452,7 @@ buf_flush_ready_for_flush( buf_page_in_file(bpage) */ buf_flush_t flush_type)/*!< in: type of flush */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - + ut_ad(mutex_own(&buf_pool->mutex)); ut_a(buf_page_in_file(bpage)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(flush_type < BUF_FLUSH_N_TYPES); @@ -552,31 +478,24 @@ buf_flush_ready_for_flush( return(false); } -/********************************************************************//** -Remove a block from the flush list of modified blocks. */ -void -buf_flush_remove( -/*=============*/ - buf_page_t* bpage) /*!< in: pointer to the block in question */ +/** Remove a block from the flush list of modified blocks. +@param[in] bpage block to be removed from the flush list */ +void buf_flush_remove(buf_page_t* bpage) { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - #if 0 // FIXME: Rate-limit the output. Move this to the page cleaner? if (UNIV_UNLIKELY(srv_shutdown_state == SRV_SHUTDOWN_FLUSH_PHASE)) { service_manager_extend_timeout( INNODB_EXTEND_TIMEOUT_INTERVAL, "Flush and remove page with tablespace id %u" - ", Poolid " ULINTPF ", flush list length " ULINTPF, - bpage->space, buf_pool->instance_no, - UT_LIST_GET_LEN(buf_pool->flush_list)); + ", flush list length " ULINTPF, + bpage->space, UT_LIST_GET_LEN(buf_pool->flush_list)); } #endif - - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(bpage->in_flush_list); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); /* Important that we adjust the hazard pointer before removing the bpage from flush list. */ @@ -618,10 +537,10 @@ buf_flush_remove( bpage->oldest_modification = 0; #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(buf_flush_validate_skip(buf_pool)); + buf_flush_validate_skip(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); } /*******************************************************************//** @@ -643,15 +562,11 @@ buf_flush_relocate_on_flush_list( { buf_page_t* prev; buf_page_t* prev_b = NULL; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_pool_mutex_own(buf_pool)); - /* Must reside in the same buffer pool. */ - ut_ad(buf_pool == buf_pool_from_bpage(dpage)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); /* FIXME: At this point we have both buf_pool and flush_list mutexes. Theoretically removal of a block from flush list is @@ -693,10 +608,10 @@ buf_flush_relocate_on_flush_list( ut_a(buf_pool->flush_rbt == NULL || prev_b == prev); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(buf_flush_validate_low(buf_pool)); + buf_flush_validate_low(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); } /** Update the flush system data structures when a write is completed. @@ -704,18 +619,15 @@ buf_flush_relocate_on_flush_list( @param[in] dblwr whether the doublewrite buffer was used */ void buf_flush_write_complete(buf_page_t* bpage, bool dblwr) { - buf_flush_t flush_type; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(bpage); buf_flush_remove(bpage); - flush_type = buf_page_get_flush_type(bpage); + const buf_flush_t flush_type = buf_page_get_flush_type(bpage); buf_pool->n_flush[flush_type]--; ut_ad(buf_pool->n_flush[flush_type] != ULINT_MAX); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (buf_pool->n_flush[flush_type] == 0 && buf_pool->init_flush[flush_type] == FALSE) { @@ -1039,7 +951,6 @@ static byte* buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s) FIL_PAGE_LSN + 4 + s, 4); ut_ad(!bpage->zip_size() || !page_compressed); - buf_pool_t *buf_pool= buf_pool_from_bpage(bpage); /* Find free slot from temporary memory array */ buf_tmp_buffer_t *slot= buf_pool->io_buf.reserve(); ut_a(slot); @@ -1136,11 +1047,6 @@ buf_flush_write_block_low( page_t* frame = NULL; const bool full_crc32 = space->full_crc32(); -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(!buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ - DBUG_PRINT("ib_buf", ("flush %s %u page %u:%u", sync ? "sync" : "async", (unsigned) flush_type, bpage->id.space(), bpage->id.page_no())); @@ -1152,8 +1058,8 @@ buf_flush_write_block_low( io_fixed and oldest_modification != 0. Thus, it cannot be relocated in the buffer pool or removed from flush_list or LRU_list. */ - ut_ad(!buf_pool_mutex_own(buf_pool)); - ut_ad(!buf_flush_list_mutex_own(buf_pool)); + ut_ad(!mutex_own(&buf_pool->mutex)); + ut_ad(!mutex_own(&buf_pool->flush_list_mutex)); ut_ad(!buf_page_get_mutex(bpage)->is_owned()); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE); ut_ad(bpage->oldest_modification != 0); @@ -1260,24 +1166,22 @@ buf_flush_write_block_low( buf_LRU_stat_inc_io(); } -/********************************************************************//** -Writes a flushable page asynchronously from the buffer pool to a file. -NOTE: buf_pool->mutex and buf_page_get_mutex(bpage) must be -held upon entering this function, and they will be released by this -function if it returns true. -@return TRUE if the page was flushed */ -ibool -buf_flush_page( -/*===========*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_page_t* bpage, /*!< in: buffer control block */ - buf_flush_t flush_type, /*!< in: type of flush */ - bool sync) /*!< in: true if sync IO request */ +/** Write a flushable page asynchronously from the buffer pool to a file. +NOTE: 1. in simulated aio we must call os_aio_simulated_wake_handler_threads +after we have posted a batch of writes! 2. buf_page_get_mutex(bpage) must be +held upon entering this function. The LRU list mutex must be held if flush_type +== BUF_FLUSH_SINGLE_PAGE. Both mutexes will be released by this function if it +returns true. +@param[in] bpage buffer control block +@param[in] flush_type type of flush +@param[in] sync true if sync IO request +@return whether the page was flushed */ +bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync) { BPageMutex* block_mutex; ut_ad(flush_type < BUF_FLUSH_N_TYPES); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_page_in_file(bpage)); ut_ad(!sync || flush_type == BUF_FLUSH_SINGLE_PAGE); @@ -1334,7 +1238,7 @@ buf_flush_page( mutex_exit(block_mutex); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if (flush_type == BUF_FLUSH_LIST && is_uncompressed @@ -1364,31 +1268,24 @@ buf_flush_page( } # if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG -/********************************************************************//** -Writes a flushable page asynchronously from the buffer pool to a file. -NOTE: buf_pool->mutex and block->mutex must be held upon entering this -function, and they will be released by this function after flushing. -This is loosely based on buf_flush_batch() and buf_flush_page(). -@return TRUE if the page was flushed and the mutexes released */ -ibool -buf_flush_page_try( -/*===============*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ - buf_block_t* block) /*!< in/out: buffer control block */ +/** Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: block and LRU list mutexes must be held upon entering this function, and +they will be released by this function after flushing. This is loosely based on +buf_flush_batch() and buf_flush_page(). +@param[in,out] block buffer control block +@return whether the page was flushed and the mutex released */ +bool buf_flush_page_try(buf_block_t* block) { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_ad(buf_page_mutex_own(block)); if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_SINGLE_PAGE)) { - return(FALSE); + return false; } - /* The following call will release the buffer pool and - block mutex. */ - return(buf_flush_page( - buf_pool, &block->page, - BUF_FLUSH_SINGLE_PAGE, true)); + /* The following call will release the buf_pool and block mutex. */ + return buf_flush_page(&block->page, BUF_FLUSH_SINGLE_PAGE, true); } # endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ @@ -1403,20 +1300,18 @@ buf_flush_check_neighbor( buf_flush_t flush_type) { buf_page_t* bpage; - buf_pool_t* buf_pool = buf_pool_get(page_id); bool ret; ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - /* We only want to flush pages from this buffer pool. */ - bpage = buf_page_hash_get(buf_pool, page_id); + bpage = buf_page_hash_get(page_id); if (!bpage) { - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(false); } @@ -1435,7 +1330,7 @@ buf_flush_check_neighbor( } mutex_exit(block_mutex); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(ret); } @@ -1458,7 +1353,6 @@ buf_flush_try_neighbors( ulint low; ulint high; ulint count = 0; - buf_pool_t* buf_pool = buf_pool_get(page_id); ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); fil_space_t* space = fil_space_acquire_for_io(page_id.space()); @@ -1480,7 +1374,7 @@ buf_flush_try_neighbors( ulint buf_flush_area; buf_flush_area = ut_min( - BUF_READ_AHEAD_AREA(buf_pool), + buf_pool->read_ahead_area, buf_pool->curr_size / 16); low = (page_id.page_no() / buf_flush_area) * buf_flush_area; @@ -1550,16 +1444,12 @@ buf_flush_try_neighbors( const page_id_t cur_page_id(page_id.space(), i); - buf_pool = buf_pool_get(cur_page_id); + mutex_enter(&buf_pool->mutex); - buf_pool_mutex_enter(buf_pool); - - /* We only want to flush pages from this buffer pool. */ - bpage = buf_page_hash_get(buf_pool, cur_page_id); + bpage = buf_page_hash_get(cur_page_id); if (bpage == NULL) { - - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); continue; } @@ -1583,13 +1473,11 @@ buf_flush_try_neighbors( /* We also try to flush those neighbors != offset */ - if (buf_flush_page( - buf_pool, bpage, flush_type, false)) { - + if (buf_flush_page(bpage, flush_type, false)) { ++count; } else { mutex_exit(block_mutex); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } continue; @@ -1597,7 +1485,7 @@ buf_flush_try_neighbors( mutex_exit(block_mutex); } } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } space->release_for_io(); @@ -1632,11 +1520,7 @@ buf_flush_page_and_try_neighbors( ulint n_to_flush, ulint* count) { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(&buf_pool->mutex)); bool flushed; BPageMutex* block_mutex = buf_page_get_mutex(bpage); @@ -1646,29 +1530,23 @@ buf_flush_page_and_try_neighbors( ut_a(buf_page_in_file(bpage)); if (buf_flush_ready_for_flush(bpage, flush_type)) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_bpage(bpage); - const page_id_t page_id = bpage->id; mutex_exit(block_mutex); - - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* Try to flush also all the neighbors */ *count += buf_flush_try_neighbors( page_id, flush_type, *count, n_to_flush); - buf_pool_mutex_enter(buf_pool); - flushed = TRUE; + mutex_enter(&buf_pool->mutex); + flushed = true; } else { mutex_exit(block_mutex); - flushed = false; } - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); return(flushed); } @@ -1681,21 +1559,16 @@ tail of the unzip_LRU and puts those freed frames in the free list. Note that it is a best effort attempt and it is not guaranteed that after a call to this function there will be 'max' blocks in the free list. +@param[in] max desired number of blocks in the free_list @return number of blocks moved to the free list. */ -static -ulint -buf_free_from_unzip_LRU_list_batch( -/*===============================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint max) /*!< in: desired number of - blocks in the free_list */ +static ulint buf_free_from_unzip_LRU_list_batch(ulint max) { ulint scanned = 0; ulint count = 0; ulint free_len = UT_LIST_GET_LEN(buf_pool->free); ulint lru_len = UT_LIST_GET_LEN(buf_pool->unzip_LRU); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); buf_block_t* block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); @@ -1720,7 +1593,7 @@ buf_free_from_unzip_LRU_list_batch( lru_len = UT_LIST_GET_LEN(buf_pool->unzip_LRU); } - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (scanned) { MONITOR_INC_VALUE_CUMULATIVE( @@ -1733,21 +1606,13 @@ buf_free_from_unzip_LRU_list_batch( return(count); } -/*******************************************************************//** -This utility flushes dirty blocks from the end of the LRU list. +/** Flush dirty blocks from the end of the LRU list. The calling thread is not allowed to own any latches on pages! -It attempts to make 'max' blocks available in the free list. Note that -it is a best effort attempt and it is not guaranteed that after a call -to this function there will be 'max' blocks in the free list.*/ -void -buf_flush_LRU_list_batch( -/*=====================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint max, /*!< in: desired number of - blocks in the free_list */ - flush_counters_t* n) /*!< out: flushed/evicted page - counts */ +@param[in] max desired number of blocks to make available + in the free list (best effort; not guaranteed) +@param[out] n counts of flushed and evicted pages */ +static void buf_flush_LRU_list_batch(ulint max, flush_counters_t* n) { buf_page_t* bpage; ulint scanned = 0; @@ -1758,11 +1623,11 @@ buf_flush_LRU_list_batch( n->flushed = 0; n->evicted = 0; n->unzip_LRU_evicted = 0; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (buf_pool->curr_size < buf_pool->old_size && buf_pool->withdraw_target > 0) { withdraw_depth = buf_pool->withdraw_target - - UT_LIST_GET_LEN(buf_pool->withdraw); + - UT_LIST_GET_LEN(buf_pool->withdraw); } for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); @@ -1801,7 +1666,7 @@ buf_flush_LRU_list_batch( } ut_ad(!mutex_own(block_mutex)); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); free_len = UT_LIST_GET_LEN(buf_pool->free); lru_len = UT_LIST_GET_LEN(buf_pool->LRU); @@ -1814,7 +1679,7 @@ buf_flush_LRU_list_batch( should be flushed, we factor in this value. */ buf_lru_flush_page_count += n->flushed; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (n->evicted) { MONITOR_INC_VALUE_CUMULATIVE( @@ -1833,28 +1698,18 @@ buf_flush_LRU_list_batch( } } -/*******************************************************************//** -Flush and move pages from LRU or unzip_LRU list to the free list. -Whether LRU or unzip_LRU is used depends on the state of the system.*/ - -static -void -buf_do_LRU_batch( -/*=============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint max, /*!< in: desired number of - blocks in the free_list */ - flush_counters_t* n) /*!< out: flushed/evicted page - counts */ +/** Flush and move pages from LRU or unzip_LRU list to the free list. +Whether LRU or unzip_LRU is used depends on the state of the system. +@param[in] max desired number of blocks to make available + in the free list (best effort; not guaranteed) +@param[out] n counts of flushed and evicted pages */ +static void buf_do_LRU_batch(ulint max, flush_counters_t* n) { - if (buf_LRU_evict_from_unzip_LRU(buf_pool)) { - n->unzip_LRU_evicted = buf_free_from_unzip_LRU_list_batch(buf_pool, max); - } else { - n->unzip_LRU_evicted = 0; - } + n->unzip_LRU_evicted = buf_LRU_evict_from_unzip_LRU() + ? buf_free_from_unzip_LRU_list_batch(max) : 0; if (max > n->unzip_LRU_evicted) { - buf_flush_LRU_list_batch(buf_pool, max - n->unzip_LRU_evicted, n); + buf_flush_LRU_list_batch(max - n->unzip_LRU_evicted, n); } else { n->evicted = 0; n->flushed = 0; @@ -1867,7 +1722,6 @@ buf_do_LRU_batch( /** This utility flushes dirty blocks from the end of the flush_list. The calling thread is not allowed to own any latches on pages! -@param[in] buf_pool buffer pool instance @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @param[in] lsn_limit all blocks whose oldest_modification is smaller @@ -1875,21 +1729,16 @@ than this should be flushed (if their number does not exceed min_n) @return number of blocks for which the write request was queued; ULINT_UNDEFINED if there was a flush of the same type already running */ -static -ulint -buf_do_flush_list_batch( - buf_pool_t* buf_pool, - ulint min_n, - lsn_t lsn_limit) +static ulint buf_do_flush_list_batch(ulint min_n, lsn_t lsn_limit) { ulint count = 0; ulint scanned = 0; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); /* Start from the end of the list looking for a suitable block to be flushed. */ - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); ulint len = UT_LIST_GET_LEN(buf_pool->flush_list); /* In order not to degenerate this scan to O(n*n) we attempt @@ -1910,7 +1759,7 @@ buf_do_flush_list_batch( prev = UT_LIST_GET_PREV(list, bpage); buf_pool->flush_hp.set(prev); - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); #ifdef UNIV_DEBUG bool flushed = @@ -1918,7 +1767,7 @@ buf_do_flush_list_batch( buf_flush_page_and_try_neighbors( bpage, BUF_FLUSH_LIST, min_n, &count); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); ut_ad(flushed || buf_pool->flush_hp.is_hp(prev)); @@ -1926,7 +1775,7 @@ buf_do_flush_list_batch( } buf_pool->flush_hp.set(NULL); - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); if (scanned) { MONITOR_INC_VALUE_CUMULATIVE( @@ -1944,7 +1793,7 @@ buf_do_flush_list_batch( count); } - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); return(count); } @@ -1955,45 +1804,43 @@ NOTE 1: in the case of an LRU flush the calling thread may own latches to pages: to avoid deadlocks, this function must be written so that it cannot end up waiting for these latches! NOTE 2: in the case of a flush list flush, the calling thread is not allowed to own any latches on pages! -@param[in] buf_pool buffer pool instance @param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST; if BUF_FLUSH_LIST, then the caller must not own any latches on pages @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @param[in] lsn_limit in the case of BUF_FLUSH_LIST all blocks whose +@param[out] n counts of flushed and evicted pages oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored */ static void buf_flush_batch( - buf_pool_t* buf_pool, buf_flush_t flush_type, ulint min_n, lsn_t lsn_limit, - flush_counters_t* n) /*!< out: flushed/evicted page - counts */ + flush_counters_t* n) { ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); ut_ad(flush_type == BUF_FLUSH_LRU || !sync_check_iterate(dict_sync_check())); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); /* Note: The buffer pool mutex is released and reacquired within the flush functions. */ switch (flush_type) { case BUF_FLUSH_LRU: - buf_do_LRU_batch(buf_pool, min_n, n); + buf_do_LRU_batch(min_n, n); break; case BUF_FLUSH_LIST: - n->flushed = buf_do_flush_list_batch(buf_pool, min_n, lsn_limit); + n->flushed = buf_do_flush_list_batch(min_n, lsn_limit); n->evicted = 0; break; default: ut_error; } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); DBUG_LOG("ib_buf", "flush " << flush_type << " completed"); } @@ -2018,50 +1865,39 @@ buf_flush_stats( srv_stats.buf_pool_flushed.add(page_count_flush + page_count_LRU); } -/******************************************************************//** -Start a buffer flush batch for LRU or flush list */ -static -ibool -buf_flush_start( -/*============*/ - buf_pool_t* buf_pool, /*!< buffer pool instance */ - buf_flush_t flush_type) /*!< in: BUF_FLUSH_LRU - or BUF_FLUSH_LIST */ +/** Start a buffer flush batch for LRU or flush list +@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST +@return whether the flush batch was started (was not already running) */ +bool buf_flush_start(buf_flush_t flush_type) { ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); if (buf_pool->n_flush[flush_type] > 0 || buf_pool->init_flush[flush_type] == TRUE) { /* There is already a flush batch of the same type running */ - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); - return(FALSE); + return(false); } buf_pool->init_flush[flush_type] = TRUE; os_event_reset(buf_pool->no_flush[flush_type]); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); - return(TRUE); + return(true); } -/******************************************************************//** -End a buffer flush batch for LRU or flush list */ -static -void -buf_flush_end( -/*==========*/ - buf_pool_t* buf_pool, /*!< buffer pool instance */ - buf_flush_t flush_type) /*!< in: BUF_FLUSH_LRU - or BUF_FLUSH_LIST */ +/** End a buffer flush batch. +@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ +void buf_flush_end(buf_flush_t flush_type) { - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); buf_pool->init_flush[flush_type] = FALSE; @@ -2074,46 +1910,25 @@ buf_flush_end( os_event_set(buf_pool->no_flush[flush_type]); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if (!srv_read_only_mode) { buf_dblwr_flush_buffered_writes(); } } -/******************************************************************//** -Waits until a flush batch of the given type ends */ -void -buf_flush_wait_batch_end( -/*=====================*/ - buf_pool_t* buf_pool, /*!< buffer pool instance */ - buf_flush_t type) /*!< in: BUF_FLUSH_LRU - or BUF_FLUSH_LIST */ +/** Wait until a flush batch ends. +@param[in] type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ +void buf_flush_wait_batch_end(buf_flush_t type) { ut_ad(type == BUF_FLUSH_LRU || type == BUF_FLUSH_LIST); - - if (buf_pool == NULL) { - ulint i; - - for (i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - thd_wait_begin(NULL, THD_WAIT_DISKIO); - os_event_wait(buf_pool->no_flush[type]); - thd_wait_end(NULL); - } - } else { - thd_wait_begin(NULL, THD_WAIT_DISKIO); - os_event_wait(buf_pool->no_flush[type]); - thd_wait_end(NULL); - } + thd_wait_begin(NULL, THD_WAIT_DISKIO); + os_event_wait(buf_pool->no_flush[type]); + thd_wait_end(NULL); } /** Do flushing batch of a given type. NOTE: The calling thread is not allowed to own any latches on pages! -@param[in,out] buf_pool buffer pool instance @param[in] type flush type @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @@ -2126,7 +1941,6 @@ passed back to caller. Ignored if NULL @retval false if another batch of same type was already running. */ bool buf_flush_do_batch( - buf_pool_t* buf_pool, buf_flush_t type, ulint min_n, lsn_t lsn_limit, @@ -2138,70 +1952,54 @@ buf_flush_do_batch( n->flushed = 0; } - if (!buf_flush_start(buf_pool, type)) { + if (!buf_flush_start(type)) { return(false); } - buf_flush_batch(buf_pool, type, min_n, lsn_limit, n); - - buf_flush_end(buf_pool, type); + buf_flush_batch(type, min_n, lsn_limit, n); + buf_flush_end(type); return(true); } -/** -Waits until a flush batch of the given lsn ends +/** Wait until a flush batch of the given lsn ends @param[in] new_oldest target oldest_modified_lsn to wait for */ - -void -buf_flush_wait_flushed( - lsn_t new_oldest) +void buf_flush_wait_flushed(lsn_t new_oldest) { - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool; - lsn_t oldest; + for (;;) { + /* We don't need to wait for fsync of the flushed + blocks, because anyway we need fsync to make chekpoint. + So, we don't need to wait for the batch end here. */ - buf_pool = buf_pool_from_array(i); + mutex_enter(&buf_pool->flush_list_mutex); - for (;;) { - /* We don't need to wait for fsync of the flushed - blocks, because anyway we need fsync to make chekpoint. - So, we don't need to wait for the batch end here. */ + buf_page_t* bpage; - buf_flush_list_mutex_enter(buf_pool); - - buf_page_t* bpage; - - /* We don't need to wait for system temporary pages */ - for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); - bpage != NULL - && fsp_is_system_temporary(bpage->id.space()); - bpage = UT_LIST_GET_PREV(list, bpage)) { - /* Do nothing. */ - } - - if (bpage != NULL) { - ut_ad(bpage->in_flush_list); - oldest = bpage->oldest_modification; - } else { - oldest = 0; - } - - buf_flush_list_mutex_exit(buf_pool); - - if (oldest == 0 || oldest >= new_oldest) { - break; - } - - /* sleep and retry */ - os_thread_sleep(buf_flush_wait_flushed_sleep_time); - - MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); + /* FIXME: Keep temporary tablespace pages in a separate flush + list. We would only need to write out temporary pages if the + page is about to be evicted from the buffer pool, and the page + contents is still needed (the page has not been freed). */ + for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); + bpage && fsp_is_system_temporary(bpage->id.space()); + bpage = UT_LIST_GET_PREV(list, bpage)) { + ut_ad(bpage->in_flush_list); } + + lsn_t oldest = bpage ? bpage->oldest_modification : 0; + + mutex_exit(&buf_pool->flush_list_mutex); + + if (oldest == 0 || oldest >= new_oldest) { + break; + } + + /* sleep and retry */ + os_thread_sleep(buf_flush_wait_flushed_sleep_time); + + MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); } } -/** This utility flushes dirty blocks from the end of the flush list of all -buffer pool instances. +/** This utility flushes dirty blocks from the end of the flush list. NOTE: The calling thread is not allowed to own any latches on pages! @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @@ -2210,70 +2008,24 @@ oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored @param[out] n_processed the number of pages which were processed is passed back to caller. Ignored if NULL. -@return true if a batch was queued successfully for each buffer pool -instance. false if another batch of same type was already running in -at least one of the buffer pool instance */ -bool -buf_flush_lists( - ulint min_n, - lsn_t lsn_limit, - ulint* n_processed) +@retval true if a batch was queued successfully +@retval false if another batch of same type was already running */ +bool buf_flush_lists(ulint min_n, lsn_t lsn_limit, ulint *n_processed) { - ulint i; - ulint n_flushed = 0; - bool success = true; + flush_counters_t n; + + bool success = buf_flush_do_batch( + BUF_FLUSH_LIST, min_n, lsn_limit, &n); + + if (n.flushed) { + buf_flush_stats(n.flushed, 0); + } if (n_processed) { - *n_processed = 0; + *n_processed = n.flushed; } - if (min_n != ULINT_MAX) { - /* Ensure that flushing is spread evenly amongst the - buffer pool instances. When min_n is ULINT_MAX - we need to flush everything up to the lsn limit - so no limit here. */ - min_n = (min_n + srv_buf_pool_instances - 1) - / srv_buf_pool_instances; - } - - /* Flush to lsn_limit in all buffer pool instances */ - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - flush_counters_t n; - - memset(&n, 0, sizeof(flush_counters_t)); - buf_pool = buf_pool_from_array(i); - - if (!buf_flush_do_batch(buf_pool, - BUF_FLUSH_LIST, - min_n, - lsn_limit, - &n)) { - /* We have two choices here. If lsn_limit was - specified then skipping an instance of buffer - pool means we cannot guarantee that all pages - up to lsn_limit has been flushed. We can - return right now with failure or we can try - to flush remaining buffer pools up to the - lsn_limit. We attempt to flush other buffer - pools based on the assumption that it will - help in the retry which will follow the - failure. */ - success = false; - - } - - n_flushed += n.flushed; - } - - if (n_flushed) { - buf_flush_stats(n_flushed, 0); - if (n_processed) { - *n_processed = n_flushed; - } - } - - return(success); + return success; } /******************************************************************//** @@ -2284,23 +2036,20 @@ they are unable to find a replaceable page at the tail of the LRU list i.e.: when the background LRU flushing in the page_cleaner thread is not fast enough to keep pace with the workload. @return true if success. */ -bool -buf_flush_single_page_from_LRU( -/*===========================*/ - buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */ +bool buf_flush_single_page_from_LRU() { ulint scanned; buf_page_t* bpage; ibool freed; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); for (bpage = buf_pool->single_scan_itr.start(), scanned = 0, freed = false; bpage != NULL; ++scanned, bpage = buf_pool->single_scan_itr.get()) { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); buf_pool->single_scan_itr.set(prev); @@ -2316,7 +2065,7 @@ buf_flush_single_page_from_LRU( mutex_exit(block_mutex); if (buf_LRU_free_page(bpage, true)) { - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); freed = true; break; } @@ -2332,8 +2081,8 @@ buf_flush_single_page_from_LRU( Note: There is no guarantee that this page has actually been freed, only that it has been flushed to disk */ - freed = buf_flush_page( - buf_pool, bpage, BUF_FLUSH_SINGLE_PAGE, true); + freed = buf_flush_page(bpage, BUF_FLUSH_SINGLE_PAGE, + true); if (freed) { break; @@ -2348,7 +2097,7 @@ buf_flush_single_page_from_LRU( if (!freed) { /* Can't find a single flushable page. */ ut_ad(!bpage); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } if (scanned) { @@ -2359,41 +2108,36 @@ buf_flush_single_page_from_LRU( scanned); } - ut_ad(!buf_pool_mutex_own(buf_pool)); + ut_ad(!mutex_own(&buf_pool->mutex)); return(freed); } /** -Clears up tail of the LRU list of a given buffer pool instance: -* Put replaceable pages at the tail of LRU to the free list -* Flush dirty pages at the tail of LRU to the disk +Clear up the tail of the LRU list. +Put replaceable pages at the tail of LRU to the free list. +Flush dirty pages at the tail of LRU to the disk. The depth to which we scan each buffer pool is controlled by dynamic config parameter innodb_LRU_scan_depth. -@param buf_pool buffer pool instance @return total pages flushed */ -static -ulint -buf_flush_LRU_list( - buf_pool_t* buf_pool) +static ulint buf_flush_LRU_list() { ulint scan_depth, withdraw_depth; flush_counters_t n; memset(&n, 0, sizeof(flush_counters_t)); - ut_ad(buf_pool); /* srv_LRU_scan_depth can be arbitrarily large value. We cap it with current LRU size. */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); scan_depth = UT_LIST_GET_LEN(buf_pool->LRU); if (buf_pool->curr_size < buf_pool->old_size && buf_pool->withdraw_target > 0) { withdraw_depth = buf_pool->withdraw_target - - UT_LIST_GET_LEN(buf_pool->withdraw); + - UT_LIST_GET_LEN(buf_pool->withdraw); } else { withdraw_depth = 0; } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if (withdraw_depth > srv_LRU_scan_depth) { scan_depth = ut_min(withdraw_depth, scan_depth); } else { @@ -2404,33 +2148,20 @@ buf_flush_LRU_list( that can trigger an LRU flush at the same time. So, it is not possible that a batch triggered during last iteration is still running, */ - buf_flush_do_batch(buf_pool, BUF_FLUSH_LRU, scan_depth, - 0, &n); + buf_flush_do_batch(BUF_FLUSH_LRU, scan_depth, 0, &n); return(n.flushed); } -/*********************************************************************//** -Wait for any possible LRU flushes that are in progress to end. */ -void -buf_flush_wait_LRU_batch_end(void) -/*==============================*/ +/** Wait for any possible LRU flushes to complete. */ +void buf_flush_wait_LRU_batch_end() { - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_pool_mutex_enter(buf_pool); - - if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0 - || buf_pool->init_flush[BUF_FLUSH_LRU]) { - - buf_pool_mutex_exit(buf_pool); - buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU); - } else { - buf_pool_mutex_exit(buf_pool); - } + mutex_enter(&buf_pool->mutex); + bool wait = buf_pool->n_flush[BUF_FLUSH_LRU] + || buf_pool->init_flush[BUF_FLUSH_LRU]; + mutex_exit(&buf_pool->mutex); + if (wait) { + buf_flush_wait_batch_end(BUF_FLUSH_LRU); } } @@ -2441,15 +2172,20 @@ the buffer pool. static ulint af_get_pct_for_dirty() -/*==================*/ { - double dirty_pct = buf_get_modified_ratio_pct(); - - if (dirty_pct == 0.0) { + const ulint dirty = UT_LIST_GET_LEN(buf_pool->flush_list); + if (!dirty) { /* No pages modified */ - return(0); + return 0; } + /* 1 + is there to avoid division by zero (in case the buffer + pool (including the flush_list) was emptied while we are + looking at it) */ + double dirty_pct = double(100 * dirty) + / (1 + UT_LIST_GET_LEN(buf_pool->LRU) + + UT_LIST_GET_LEN(buf_pool->free)); + ut_a(srv_max_dirty_pages_pct_lwm <= srv_max_buf_pool_modified_pct); @@ -2516,15 +2252,11 @@ This function is called approximately once every second by the page_cleaner thread. Based on various factors it decides if there is a need to do flushing. @return number of pages recommended to be flushed -@param lsn_limit pointer to return LSN up to which flushing must happen @param last_pages_in the number of pages flushed by the last flush_list flushing. */ static ulint -page_cleaner_flush_pages_recommendation( -/*====================================*/ - lsn_t* lsn_limit, - ulint last_pages_in) +page_cleaner_flush_pages_recommendation(ulint last_pages_in) { static lsn_t prev_lsn = 0; static ulint sum_pages = 0; @@ -2595,27 +2327,14 @@ page_cleaner_flush_pages_recommendation( page_cleaner.flush_time = 0; page_cleaner.flush_pass = 0; - ulint lru_tm = 0; - ulint list_tm = 0; - ulint lru_pass = 0; - ulint list_pass = 0; - - for (ulint i = 0; i < page_cleaner.n_slots; i++) { - page_cleaner_slot_t* slot; - - slot = &page_cleaner.slots[i]; - - lru_tm += slot->flush_lru_time; - lru_pass += slot->flush_lru_pass; - list_tm += slot->flush_list_time; - list_pass += slot->flush_list_pass; - - slot->flush_lru_time = 0; - slot->flush_lru_pass = 0; - slot->flush_list_time = 0; - slot->flush_list_pass = 0; - } - + ulint lru_tm = page_cleaner.slot.flush_lru_time; + ulint list_tm = page_cleaner.slot.flush_list_time; + ulint lru_pass = page_cleaner.slot.flush_lru_pass; + ulint list_pass = page_cleaner.slot.flush_list_pass; + page_cleaner.slot.flush_lru_time = 0; + page_cleaner.slot.flush_lru_pass = 0; + page_cleaner.slot.flush_list_time = 0; + page_cleaner.slot.flush_list_pass = 0; mutex_exit(&page_cleaner.mutex); /* minimum values are 1, to avoid dividing by zero. */ @@ -2645,9 +2364,9 @@ page_cleaner_flush_pages_recommendation( lru_tm / lru_pass); MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_TIME_THREAD, - list_tm / (srv_n_page_cleaners * flush_pass)); + list_tm / flush_pass); MONITOR_SET(MONITOR_LRU_BATCH_FLUSH_AVG_TIME_THREAD, - lru_tm / (srv_n_page_cleaners * flush_pass)); + lru_tm / flush_pass); MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_TIME_EST, flush_tm * list_tm / flush_pass / (list_tm + lru_tm)); @@ -2656,10 +2375,8 @@ page_cleaner_flush_pages_recommendation( / (list_tm + lru_tm)); MONITOR_SET(MONITOR_FLUSH_AVG_TIME, flush_tm / flush_pass); - MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_PASS, - list_pass / page_cleaner.n_slots); - MONITOR_SET(MONITOR_LRU_BATCH_FLUSH_AVG_PASS, - lru_pass / page_cleaner.n_slots); + MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_PASS, list_pass); + MONITOR_SET(MONITOR_LRU_BATCH_FLUSH_AVG_PASS, lru_pass); MONITOR_SET(MONITOR_FLUSH_AVG_PASS, flush_pass); prev_lsn = cur_lsn; @@ -2682,44 +2399,36 @@ page_cleaner_flush_pages_recommendation( pct_total = ut_max(pct_for_dirty, pct_for_lsn); /* Estimate pages to be flushed for the lsn progress */ - ulint sum_pages_for_lsn = 0; lsn_t target_lsn = oldest_lsn - + lsn_avg_rate * buf_flush_lsn_scan_factor; + + lsn_avg_rate * buf_flush_lsn_scan_factor; + ulint pages_for_lsn = 0; - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - ulint pages_for_lsn = 0; - - buf_flush_list_mutex_enter(buf_pool); - for (buf_page_t* b = UT_LIST_GET_LAST(buf_pool->flush_list); - b != NULL; - b = UT_LIST_GET_PREV(list, b)) { - if (b->oldest_modification > target_lsn) { - break; - } - ++pages_for_lsn; + mutex_enter(&buf_pool->flush_list_mutex); + for (buf_page_t* b = UT_LIST_GET_LAST(buf_pool->flush_list); + b != NULL; + b = UT_LIST_GET_PREV(list, b)) { + if (b->oldest_modification > target_lsn) { + break; } - buf_flush_list_mutex_exit(buf_pool); - - sum_pages_for_lsn += pages_for_lsn; - - mutex_enter(&page_cleaner.mutex); - ut_ad(page_cleaner.slots[i].state - == PAGE_CLEANER_STATE_NONE); - page_cleaner.slots[i].n_pages_requested - = pages_for_lsn / buf_flush_lsn_scan_factor + 1; - mutex_exit(&page_cleaner.mutex); + ++pages_for_lsn; } + mutex_exit(&buf_pool->flush_list_mutex); - sum_pages_for_lsn /= buf_flush_lsn_scan_factor; - if(sum_pages_for_lsn < 1) { - sum_pages_for_lsn = 1; + mutex_enter(&page_cleaner.mutex); + ut_ad(page_cleaner.slot.state == PAGE_CLEANER_STATE_NONE); + page_cleaner.slot.n_pages_requested + = pages_for_lsn / buf_flush_lsn_scan_factor + 1; + mutex_exit(&page_cleaner.mutex); + + pages_for_lsn /= buf_flush_lsn_scan_factor; + if (pages_for_lsn < 1) { + pages_for_lsn = 1; } /* Cap the maximum IO capacity that we are going to use by max_io_capacity. Limit the value to avoid too quick increase */ - ulint pages_for_lsn = - std::min(sum_pages_for_lsn, srv_max_io_capacity * 2); + pages_for_lsn = std::min( + pages_for_lsn, srv_max_io_capacity * 2); n_pages = (PCT_IO(pct_total) + avg_page_rate + pages_for_lsn) / 3; @@ -2727,33 +2436,30 @@ page_cleaner_flush_pages_recommendation( n_pages = srv_max_io_capacity; } - /* Normalize request for each instance */ mutex_enter(&page_cleaner.mutex); ut_ad(page_cleaner.n_slots_requested == 0); ut_ad(page_cleaner.n_slots_flushing == 0); ut_ad(page_cleaner.n_slots_finished == 0); - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - /* if REDO has enough of free space, - don't care about age distribution of pages */ - page_cleaner.slots[i].n_pages_requested = pct_for_lsn > 30 ? - page_cleaner.slots[i].n_pages_requested - * n_pages / sum_pages_for_lsn + 1 - : n_pages / srv_buf_pool_instances; + /* if REDO has enough of free space, + don't care about age distribution of pages */ + if (pct_for_lsn > 30) { + page_cleaner.slot.n_pages_requested *= n_pages + / pages_for_lsn + 1; + } else { + page_cleaner.slot.n_pages_requested = n_pages; } mutex_exit(&page_cleaner.mutex); MONITOR_SET(MONITOR_FLUSH_N_TO_FLUSH_REQUESTED, n_pages); - MONITOR_SET(MONITOR_FLUSH_N_TO_FLUSH_BY_AGE, sum_pages_for_lsn); + MONITOR_SET(MONITOR_FLUSH_N_TO_FLUSH_BY_AGE, pages_for_lsn); MONITOR_SET(MONITOR_FLUSH_AVG_PAGE_RATE, avg_page_rate); MONITOR_SET(MONITOR_FLUSH_LSN_AVG_RATE, lsn_avg_rate); MONITOR_SET(MONITOR_FLUSH_PCT_FOR_DIRTY, pct_for_dirty); MONITOR_SET(MONITOR_FLUSH_PCT_FOR_LSN, pct_for_lsn); - *lsn_limit = LSN_MAX; - return(n_pages); } @@ -2794,47 +2500,16 @@ pc_sleep_if_needed( return(OS_SYNC_TIME_EXCEEDED); } -/******************************************************************//** -Initialize page_cleaner. */ -void -buf_flush_page_cleaner_init(void) -/*=============================*/ -{ - ut_ad(!page_cleaner.is_running); - - mutex_create(LATCH_ID_PAGE_CLEANER, &page_cleaner.mutex); - - page_cleaner.is_finished = os_event_create("pc_is_finished"); - page_cleaner.n_slots = static_cast(srv_buf_pool_instances); - - ut_d(page_cleaner.n_disabled_debug = 0); - - page_cleaner.is_running = true; -} - /** -Requests for all slots to flush all buffer pool instances. +Requests for all slots to flush. @param min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big) @param lsn_limit in the case BUF_FLUSH_LIST all blocks whose oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored */ -static -void -pc_request( - ulint min_n, - lsn_t lsn_limit) +static void pc_request(ulint min_n, lsn_t lsn_limit) { - if (min_n != ULINT_MAX) { - /* Ensure that flushing is spread evenly amongst the - buffer pool instances. When min_n is ULINT_MAX - we need to flush everything up to the lsn limit - so no limit here. */ - min_n = (min_n + srv_buf_pool_instances - 1) - / srv_buf_pool_instances; - } - mutex_enter(&page_cleaner.mutex); ut_ad(page_cleaner.n_slots_requested == 0); @@ -2844,40 +2519,28 @@ pc_request( page_cleaner.requested = (min_n > 0); page_cleaner.lsn_limit = lsn_limit; - for (ulint i = 0; i < page_cleaner.n_slots; i++) { - page_cleaner_slot_t* slot = &page_cleaner.slots[i]; + ut_ad(page_cleaner.slot.state == PAGE_CLEANER_STATE_NONE); - ut_ad(slot->state == PAGE_CLEANER_STATE_NONE); - - if (min_n == ULINT_MAX) { - slot->n_pages_requested = ULINT_MAX; - } else if (min_n == 0) { - slot->n_pages_requested = 0; - } - - /* slot->n_pages_requested was already set by - page_cleaner_flush_pages_recommendation() */ - - slot->state = PAGE_CLEANER_STATE_REQUESTED; + if (min_n == 0 || min_n == ULINT_MAX) { + page_cleaner.slot.n_pages_requested = min_n; } - page_cleaner.n_slots_requested = page_cleaner.n_slots; + /* page_cleaner.slot.n_pages_requested was already set by + page_cleaner_flush_pages_recommendation() */ + + page_cleaner.slot.state = PAGE_CLEANER_STATE_REQUESTED; + + page_cleaner.n_slots_requested = 1; page_cleaner.n_slots_flushing = 0; page_cleaner.n_slots_finished = 0; - /* Submit slots-1 tasks, coordinator also does the work itself */ - for (ulint i = pc_flush_slot_task.get_ref_count(); i < page_cleaner.n_slots - 1; i++) { - pc_submit_task(); - } mutex_exit(&page_cleaner.mutex); } /** Do flush for one slot. @return the number of the slots which has not been treated yet. */ -static -ulint -pc_flush_slot(void) +static ulint pc_flush_slot() { ulint lru_tm = 0; ulint list_tm = 0; @@ -2887,30 +2550,14 @@ pc_flush_slot(void) mutex_enter(&page_cleaner.mutex); if (page_cleaner.n_slots_requested) { - page_cleaner_slot_t* slot = NULL; - ulint i; - - for (i = 0; i < page_cleaner.n_slots; i++) { - slot = &page_cleaner.slots[i]; - - if (slot->state == PAGE_CLEANER_STATE_REQUESTED) { - break; - } - } - - /* slot should be found because - page_cleaner.n_slots_requested > 0 */ - ut_a(i < page_cleaner.n_slots); - - buf_pool_t* buf_pool = buf_pool_from_array(i); - + ut_ad(page_cleaner.slot.state == PAGE_CLEANER_STATE_REQUESTED); page_cleaner.n_slots_requested--; page_cleaner.n_slots_flushing++; - slot->state = PAGE_CLEANER_STATE_FLUSHING; + page_cleaner.slot.state = PAGE_CLEANER_STATE_FLUSHING; if (UNIV_UNLIKELY(!page_cleaner.is_running)) { - slot->n_flushed_lru = 0; - slot->n_flushed_list = 0; + page_cleaner.slot.n_flushed_lru = 0; + page_cleaner.slot.n_flushed_list = 0; goto finish_mutex; } @@ -2919,13 +2566,13 @@ pc_flush_slot(void) lru_tm = ut_time_ms(); /* Flush pages from end of LRU if required */ - slot->n_flushed_lru = buf_flush_LRU_list(buf_pool); + page_cleaner.slot.n_flushed_lru = buf_flush_LRU_list(); lru_tm = ut_time_ms() - lru_tm; lru_pass++; if (UNIV_UNLIKELY(!page_cleaner.is_running)) { - slot->n_flushed_list = 0; + page_cleaner.slot.n_flushed_list = 0; goto finish; } @@ -2935,31 +2582,31 @@ pc_flush_slot(void) memset(&n, 0, sizeof(flush_counters_t)); list_tm = ut_time_ms(); - slot->succeeded_list = buf_flush_do_batch( - buf_pool, BUF_FLUSH_LIST, - slot->n_pages_requested, + page_cleaner.slot.succeeded_list = buf_flush_do_batch( + BUF_FLUSH_LIST, + page_cleaner.slot.n_pages_requested, page_cleaner.lsn_limit, &n); - slot->n_flushed_list = n.flushed; + page_cleaner.slot.n_flushed_list = n.flushed; list_tm = ut_time_ms() - list_tm; list_pass++; } else { - slot->n_flushed_list = 0; - slot->succeeded_list = true; + page_cleaner.slot.n_flushed_list = 0; + page_cleaner.slot.succeeded_list = true; } finish: mutex_enter(&page_cleaner.mutex); finish_mutex: page_cleaner.n_slots_flushing--; page_cleaner.n_slots_finished++; - slot->state = PAGE_CLEANER_STATE_FINISHED; + page_cleaner.slot.state = PAGE_CLEANER_STATE_FINISHED; - slot->flush_lru_time += lru_tm; - slot->flush_list_time += list_tm; - slot->flush_lru_pass += lru_pass; - slot->flush_list_pass += list_pass; + page_cleaner.slot.flush_lru_time += lru_tm; + page_cleaner.slot.flush_list_time += list_tm; + page_cleaner.slot.flush_lru_pass += lru_pass; + page_cleaner.slot.flush_list_pass += list_pass; if (page_cleaner.n_slots_requested == 0 && page_cleaner.n_slots_flushing == 0) { @@ -2997,21 +2644,14 @@ pc_wait_finished( ut_ad(page_cleaner.n_slots_requested == 0); ut_ad(page_cleaner.n_slots_flushing == 0); - ut_ad(page_cleaner.n_slots_finished == page_cleaner.n_slots); + ut_ad(page_cleaner.n_slots_finished == 1); - for (ulint i = 0; i < page_cleaner.n_slots; i++) { - page_cleaner_slot_t* slot = &page_cleaner.slots[i]; - - ut_ad(slot->state == PAGE_CLEANER_STATE_FINISHED); - - *n_flushed_lru += slot->n_flushed_lru; - *n_flushed_list += slot->n_flushed_list; - all_succeeded &= slot->succeeded_list; - - slot->state = PAGE_CLEANER_STATE_NONE; - - slot->n_pages_requested = 0; - } + ut_ad(page_cleaner.slot.state == PAGE_CLEANER_STATE_FINISHED); + page_cleaner.slot.state = PAGE_CLEANER_STATE_NONE; + *n_flushed_lru = page_cleaner.slot.n_flushed_lru; + *n_flushed_list = page_cleaner.slot.n_flushed_list; + all_succeeded = page_cleaner.slot.succeeded_list; + page_cleaner.slot.n_pages_requested = 0; page_cleaner.n_slots_finished = 0; @@ -3040,70 +2680,14 @@ buf_flush_page_cleaner_set_priority( #endif /* UNIV_LINUX */ #ifdef UNIV_DEBUG -/** Loop used to disable page cleaner threads. */ -static -void -buf_flush_page_cleaner_disabled_loop(void) +/** Loop used to disable the page cleaner thread. */ +static void buf_flush_page_cleaner_disabled_loop() { - if (!innodb_page_cleaner_disabled_debug) { - /* We return to avoid entering and exiting mutex. */ - return; - } - - mutex_enter(&page_cleaner.mutex); - page_cleaner.n_disabled_debug++; - mutex_exit(&page_cleaner.mutex); - while (innodb_page_cleaner_disabled_debug && srv_shutdown_state == SRV_SHUTDOWN_NONE && page_cleaner.is_running) { - - os_thread_sleep(100000); /* [A] */ + os_thread_sleep(100000); } - - /* We need to wait for threads exiting here, otherwise we would - encounter problem when we quickly perform following steps: - 1) SET GLOBAL innodb_page_cleaner_disabled_debug = 1; - 2) SET GLOBAL innodb_page_cleaner_disabled_debug = 0; - 3) SET GLOBAL innodb_page_cleaner_disabled_debug = 1; - That's because after step 1 this thread could still be sleeping - inside the loop above at [A] and steps 2, 3 could happen before - this thread wakes up from [A]. In such case this thread would - not re-increment n_disabled_debug and we would be waiting for - him forever in buf_flush_page_cleaner_disabled_debug_update(...). - - Therefore we are waiting in step 2 for this thread exiting here. */ - - mutex_enter(&page_cleaner.mutex); - page_cleaner.n_disabled_debug--; - mutex_exit(&page_cleaner.mutex); -} - -/** Disables page cleaner threads (coordinator and workers). -@param[in] save immediate result from check function */ -void buf_flush_page_cleaner_disabled_debug_update(THD*, - st_mysql_sys_var*, void*, - const void* save) -{ - if (!page_cleaner.is_running) { - return; - } - - if (!*static_cast(save)) { - if (!innodb_page_cleaner_disabled_debug) { - return; - } - - innodb_page_cleaner_disabled_debug = false; - return; - } - - if (innodb_page_cleaner_disabled_debug) { - return; - } - - innodb_page_cleaner_disabled_debug = true; - pc_wait_all_tasks(); } #endif /* UNIV_DEBUG */ @@ -3111,9 +2695,7 @@ void buf_flush_page_cleaner_disabled_debug_update(THD*, page_cleaner thread tasked with flushing dirty pages from the buffer pools. As of now we'll have only one coordinator. @return a dummy parameter */ -extern "C" -os_thread_ret_t -DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) +static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) { my_thread_init(); #ifdef UNIV_PFS_THREAD @@ -3197,9 +2779,8 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) /* The page_cleaner skips sleep if the server is idle and there are no pending IOs in the buffer pool and there is work to do. */ - if (srv_check_activity(last_activity) - || buf_get_n_pending_read_ios() - || n_flushed == 0) { + if (!n_flushed || !buf_pool->n_pend_reads + || srv_check_activity(last_activity)) { ret_sleep = pc_sleep_if_needed( next_loop_time, sig_count, curr_time); @@ -3291,16 +2872,18 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) } else if (srv_check_activity(last_activity)) { ulint n_to_flush; - lsn_t lsn_limit = 0; + lsn_t lsn_limit; /* Estimate pages from flush_list to be flushed */ if (ret_sleep == OS_SYNC_TIME_EXCEEDED) { last_activity = srv_get_activity_count(); n_to_flush = page_cleaner_flush_pages_recommendation( - &lsn_limit, last_pages); + last_pages); + lsn_limit = LSN_MAX; } else { n_to_flush = 0; + lsn_limit = 0; } /* Request flushing for threads */ @@ -3426,7 +3009,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) considering end of that batch as a finish of our final sweep and we'll come out of the loop leaving behind dirty pages in the flush_list */ - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + buf_flush_wait_batch_end(BUF_FLUSH_LIST); buf_flush_wait_LRU_batch_end(); bool success; @@ -3442,7 +3025,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) n_flushed = n_flushed_lru + n_flushed_list; - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + buf_flush_wait_batch_end(BUF_FLUSH_LIST); buf_flush_wait_LRU_batch_end(); } while (!success || n_flushed > 0); @@ -3450,18 +3033,12 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) /* Some sanity checks */ ut_ad(!srv_any_background_activity()); ut_ad(srv_shutdown_state == SRV_SHUTDOWN_FLUSH_PHASE); - - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == 0); - } + ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == 0); /* We have lived our life. Time to die. */ thread_exit: - /* Wait for worker tasks to finish */ page_cleaner.is_running = false; - pc_wait_all_tasks(); mutex_destroy(&page_cleaner.mutex); os_event_destroy(page_cleaner.is_finished); @@ -3482,57 +3059,35 @@ static void pc_flush_slot_func(void*) } -/** Adjust thread count for page cleaner workers. -@param[in] new_cnt Number of threads to be used */ -void -buf_flush_set_page_cleaner_thread_cnt(ulong new_cnt) +/** Initialize page_cleaner. */ +void buf_flush_page_cleaner_init() { - mutex_enter(&page_cleaner.mutex); - page_cleaner_task_group.set_max_tasks((uint)new_cnt); - srv_n_page_cleaners = new_cnt; + ut_ad(!page_cleaner.is_running); - mutex_exit(&page_cleaner.mutex); + mutex_create(LATCH_ID_PAGE_CLEANER, &page_cleaner.mutex); + page_cleaner.is_finished = os_event_create("pc_is_finished"); + page_cleaner.is_running = true; + + buf_page_cleaner_is_active = true; + os_thread_create(buf_flush_page_cleaner, NULL, NULL); } - -void pc_submit_task() -{ -#ifdef UNIV_DEBUG - if (innodb_page_cleaner_disabled_debug) - return; -#endif - srv_thread_pool->submit_task(&pc_flush_slot_task); -} - -void pc_wait_all_tasks() -{ - pc_flush_slot_task.wait(); -} - -/*******************************************************************//** -Synchronously flush dirty blocks from the end of the flush list of all buffer -pool instances. -NOTE: The calling thread is not allowed to own any latches on pages! */ -void -buf_flush_sync_all_buf_pools(void) -/*==============================*/ +/** Synchronously flush dirty blocks. +NOTE: The calling thread is not allowed to hold any buffer page latches! */ +void buf_flush_sync() { bool success; do { success = buf_flush_lists(ULINT_MAX, LSN_MAX, NULL); - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + buf_flush_wait_batch_end(BUF_FLUSH_LIST); } while (!success); - - ut_a(success); } /** Request IO burst and wake page_cleaner up. @param[in] lsn_limit upper limit of LSN to be flushed */ -void -buf_flush_request_force( - lsn_t lsn_limit) +void buf_flush_request_force(lsn_t lsn_limit) { /* adjust based on lsn_avg_rate not to get old */ lsn_t lsn_target = lsn_limit + lsn_avg_rate * 3; @@ -3555,19 +3110,13 @@ struct Check { } }; -/******************************************************************//** -Validates the flush list. -@return TRUE if ok */ -static -ibool -buf_flush_validate_low( -/*===================*/ - buf_pool_t* buf_pool) /*!< in: Buffer pool instance */ +/** Validate the flush list. */ +static void buf_flush_validate_low() { buf_page_t* bpage; const ib_rbt_node_t* rnode = NULL; - ut_ad(buf_flush_list_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->flush_list_mutex)); ut_list_validate(buf_pool->flush_list, Check()); @@ -3582,9 +3131,6 @@ buf_flush_validate_low( while (bpage != NULL) { const lsn_t om = bpage->oldest_modification; - - ut_ad(buf_pool_from_bpage(bpage) == buf_pool); - ut_ad(bpage->in_flush_list); /* A page in buf_pool->flush_list can be in @@ -3616,45 +3162,27 @@ buf_flush_validate_low( /* By this time we must have exhausted the traversal of flush_rbt (if active) as well. */ ut_a(rnode == NULL); - - return(TRUE); } -/******************************************************************//** -Validates the flush list. -@return TRUE if ok */ -ibool -buf_flush_validate( -/*===============*/ - buf_pool_t* buf_pool) /*!< buffer pool instance */ +/** Validate the flush list. */ +void buf_flush_validate() { - ibool ret; - - buf_flush_list_mutex_enter(buf_pool); - - ret = buf_flush_validate_low(buf_pool); - - buf_flush_list_mutex_exit(buf_pool); - - return(ret); + mutex_enter(&buf_pool->flush_list_mutex); + buf_flush_validate_low(); + mutex_exit(&buf_pool->flush_list_mutex); } #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -/******************************************************************//** -Check if there are any dirty pages that belong to a space id in the flush -list in a particular buffer pool. -@return number of dirty pages present in a single buffer pool */ -ulint -buf_pool_get_dirty_pages_count( -/*===========================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool */ - ulint id) /*!< in: space id to check */ +/** Determine the number of dirty pages in a tablespace. +@param[in] id tablespace identifier +@return number of dirty pages */ +ulint buf_pool_get_dirty_pages_count(ulint id) { ulint count = 0; - buf_pool_mutex_enter(buf_pool); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); + mutex_enter(&buf_pool->flush_list_mutex); buf_page_t* bpage; @@ -3671,8 +3199,8 @@ buf_pool_get_dirty_pages_count( } } - buf_flush_list_mutex_exit(buf_pool); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); + mutex_exit(&buf_pool->mutex); return(count); } diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 65678f2ef65..e28eb66d13c 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -157,36 +157,27 @@ buf_LRU_block_free_hashed_page( buf_block_t* block); /*!< in: block, must contain a file page and be in a state where it can be freed */ -/******************************************************************//** -Increases LRU size in bytes with page size inline function */ -static inline -void -incr_LRU_size_in_bytes( -/*===================*/ - buf_page_t* bpage, /*!< in: control block */ - buf_pool_t* buf_pool) /*!< in: buffer pool instance */ +/** Increase LRU size in bytes by the page size. +@param[in] bpage control block */ +static inline void incr_LRU_size_in_bytes(const buf_page_t* bpage) { - ut_ad(buf_pool_mutex_own(buf_pool)); + /* FIXME: use atomics, not mutex */ + ut_ad(mutex_own(&buf_pool->mutex)); buf_pool->stat.LRU_bytes += bpage->physical_size(); ut_ad(buf_pool->stat.LRU_bytes <= buf_pool->curr_pool_size); } -/******************************************************************//** -Determines if the unzip_LRU list should be used for evicting a victim -instead of the general LRU list. -@return TRUE if should use unzip_LRU */ -ibool -buf_LRU_evict_from_unzip_LRU( -/*=========================*/ - buf_pool_t* buf_pool) +/** @return whether the unzip_LRU list should be used for evicting a victim +instead of the general LRU list */ +bool buf_LRU_evict_from_unzip_LRU() { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); /* If the unzip_LRU list is empty, we can only use the LRU. */ if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) { - return(FALSE); + return false; } /* If unzip_LRU is at most 10% of the size of the LRU list, @@ -194,13 +185,13 @@ buf_LRU_evict_from_unzip_LRU( decompressed pages in the buffer pool. */ if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) { - return(FALSE); + return false; } /* If eviction hasn't started yet, we assume by default that a workload is disk bound. */ if (buf_pool->freed_page_clock == 0) { - return(TRUE); + return true; } /* Calculate the average over past intervals, and add the values @@ -244,20 +235,18 @@ buf_LRU_drop_page_hash_batch(ulint space_id, const ulint* arr, ulint count) When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page hash index entries belonging to that table. This function tries to do that in batch. Note that this is a 'best effort' attempt and does -not guarantee that ALL hash entries will be removed. */ +not guarantee that ALL hash entries will be removed. +@param[in] id space id */ static void -buf_LRU_drop_page_hash_for_tablespace( -/*==================================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint id) /*!< in: space id */ +buf_LRU_drop_page_hash_for_tablespace(ulint id) { ulint* page_arr = static_cast(ut_malloc_nokey( sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE)); ulint num_entries = 0; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); scan_again: for (buf_page_t* bpage = UT_LIST_GET_LAST(buf_pool->LRU); @@ -316,13 +305,13 @@ next_page: /* Array full. We release the buf_pool->mutex to obey the latching order. */ - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); num_entries = 0; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); /* Note that we released the buf_pool mutex above after reading the prev_bpage during processing of a @@ -347,7 +336,7 @@ next_page: } } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* Drop any remaining batch of search hashed pages. */ buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); @@ -364,37 +353,25 @@ bool buf_LRU_drop_page_hash_for_tablespace(dict_table_t* table) index = dict_table_get_next_index(index)) { if (btr_search_info_get_ref_count(btr_search_get_info(index), index)) { - goto drop_ahi; + buf_LRU_drop_page_hash_for_tablespace(table->space_id); + return true; } } return false; -drop_ahi: - ulint id = table->space_id; - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_LRU_drop_page_hash_for_tablespace(buf_pool_from_array(i), - id); - } - - return true; } -/******************************************************************//** +/** While flushing (or removing dirty) pages from a tablespace we don't want to hog the CPU and resources. Release the buffer pool and block mutex and try to force a context switch. Then reacquire the same mutexes. The current page is "fixed" before the release of the mutexes and then -"unfixed" again once we have reacquired the mutexes. */ -static -void -buf_flush_yield( -/*============*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ - buf_page_t* bpage) /*!< in/out: current page */ +"unfixed" again once we have reacquired the mutexes. +@param[in,out] bpage current page */ +static void buf_flush_yield(buf_page_t* bpage) { BPageMutex* block_mutex; - ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(buf_page_in_file(bpage)); block_mutex = buf_page_get_mutex(bpage); @@ -407,14 +384,13 @@ buf_flush_yield( buf_page_set_sticky(bpage); /* Now it is safe to release the buf_pool->mutex. */ - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); mutex_exit(block_mutex); /* Try and force a context switch. */ os_thread_yield(); - buf_pool_mutex_enter(buf_pool); - + mutex_enter(&buf_pool->mutex); mutex_enter(block_mutex); /* "Unfix" the block now that we have both the @@ -432,7 +408,6 @@ static MY_ATTRIBUTE((warn_unused_result)) bool buf_flush_try_yield( /*================*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ buf_page_t* bpage, /*!< in/out: bpage to remove */ ulint processed) /*!< in: number of pages processed */ { @@ -446,14 +421,14 @@ buf_flush_try_yield( && processed >= BUF_LRU_DROP_SEARCH_SIZE && buf_page_get_io_fix(bpage) == BUF_IO_NONE) { - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); /* Release the buffer pool and block mutex to give the other threads a go. */ - buf_flush_yield(buf_pool, bpage); + buf_flush_yield(bpage); - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); /* Should not have been removed from the flush list during the yield. However, this check is @@ -469,15 +444,13 @@ buf_flush_try_yield( #endif /* BTR_CUR_HASH_ADAPT */ /** Remove a single page from flush_list. -@param[in,out] buf_pool buffer pool @param[in,out] bpage buffer page to remove @param[in] flush whether to flush the page before removing @return true if page was removed. */ -static bool buf_flush_or_remove_page(buf_pool_t* buf_pool, buf_page_t* bpage, - bool flush) +static bool buf_flush_or_remove_page(buf_page_t *bpage, bool flush) { - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(buf_flush_list_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); + ut_ad(mutex_own(&buf_pool->flush_list_mutex)); /* bpage->space and bpage->io_fix are protected by buf_pool->mutex and block_mutex. It is safe to check @@ -503,7 +476,7 @@ static bool buf_flush_or_remove_page(buf_pool_t* buf_pool, buf_page_t* bpage, buf_flush_remove() and buf_flush_relocate_on_flush_list() need buf_pool->mutex as well. */ - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); mutex_enter(block_mutex); @@ -522,10 +495,10 @@ static bool buf_flush_or_remove_page(buf_pool_t* buf_pool, buf_page_t* bpage, /* The following call will release the buffer pool and block mutex. */ processed = buf_flush_page( - buf_pool, bpage, BUF_FLUSH_SINGLE_PAGE, false); + bpage, BUF_FLUSH_SINGLE_PAGE, false); if (processed) { - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); } else { mutex_exit(block_mutex); } @@ -533,32 +506,29 @@ static bool buf_flush_or_remove_page(buf_pool_t* buf_pool, buf_page_t* bpage, mutex_exit(block_mutex); } - buf_flush_list_mutex_enter(buf_pool); + mutex_enter(&buf_pool->flush_list_mutex); ut_ad(!mutex_own(block_mutex)); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); return(processed); } -/** Remove all dirty pages belonging to a given tablespace inside a specific -buffer pool instance when we are deleting the data file(s) of that -tablespace. The pages still remain a part of LRU and are evicted from +/** Remove all dirty pages belonging to a given tablespace when we are +deleting the data file of that tablespace. +The pages still remain a part of LRU and are evicted from the list as they age towards the tail of the LRU. -@param[in,out] buf_pool buffer pool @param[in] id tablespace identifier @param[in] flush whether to flush the pages before removing @param[in] first first page to be flushed or evicted @return whether all matching dirty pages were removed */ -static bool buf_flush_or_remove_pages(buf_pool_t* buf_pool, ulint id, - bool flush, ulint first) +static bool buf_flush_or_remove_pages(ulint id, bool flush, ulint first) { buf_page_t* prev; buf_page_t* bpage; ulint processed = 0; - buf_flush_list_mutex_enter(buf_pool); - + mutex_enter(&buf_pool->flush_list_mutex); rescan: bool all_freed = true; @@ -578,7 +548,7 @@ rescan: different tablespace. */ } else if (bpage->id.page_no() < first) { /* Skip this block, because it is below the limit. */ - } else if (!buf_flush_or_remove_page(buf_pool, bpage, flush)) { + } else if (!buf_flush_or_remove_page(bpage, flush)) { /* Remove was unsuccessful, we have to try again by scanning the entire list from the end. @@ -614,51 +584,42 @@ rescan: ++processed; /* Yield if we have hogged the CPU and mutexes for too long. */ - if (buf_flush_try_yield(buf_pool, prev, processed)) { - + if (buf_flush_try_yield(prev, processed)) { /* Reset the batch size counter if we had to yield. */ - processed = 0; } #endif /* BTR_CUR_HASH_ADAPT */ } - buf_flush_list_mutex_exit(buf_pool); + mutex_exit(&buf_pool->flush_list_mutex); return(all_freed); } -/** Remove or flush all the dirty pages that belong to a given tablespace -inside a specific buffer pool instance. The pages will remain in the LRU -list and will be evicted from the LRU list as they age and move towards -the tail of the LRU list. -@param[in,out] buf_pool buffer pool +/** Remove or flush all the dirty pages that belong to a given tablespace. +The pages will remain in the LRU list and will be evicted from the LRU list +as they age and move towards the tail of the LRU list. @param[in] id tablespace identifier @param[in] flush whether to flush the pages before removing @param[in] first first page to be flushed or evicted */ -static void buf_flush_dirty_pages(buf_pool_t* buf_pool, ulint id, bool flush, - ulint first) +static void buf_flush_dirty_pages(ulint id, bool flush, ulint first) { for (;;) { - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); + bool freed = buf_flush_or_remove_pages(id, flush, first); + mutex_exit(&buf_pool->mutex); - bool freed = buf_flush_or_remove_pages(buf_pool, id, flush, - first); - - buf_pool_mutex_exit(buf_pool); - - ut_ad(buf_flush_validate(buf_pool)); + ut_d(buf_flush_validate()); if (freed) { break; } os_thread_sleep(2000); - ut_ad(buf_flush_validate(buf_pool)); + ut_d(buf_flush_validate()); } - ut_ad(first - || buf_pool_get_dirty_pages_count(buf_pool, id) == 0); + ut_ad(first || buf_pool_get_dirty_pages_count(id) == 0); } /** Empty the flush list for all pages belonging to a tablespace. @@ -670,10 +631,7 @@ void buf_LRU_flush_or_remove_pages(ulint id, bool flush, ulint first) /* Pages in the system tablespace must never be discarded. */ ut_ad(id || flush); - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_flush_dirty_pages(buf_pool_from_array(i), id, flush, - first); - } + buf_flush_dirty_pages(id, flush, first); if (flush) { /* Ensure that all asynchronous IO is completed. */ @@ -690,9 +648,7 @@ buf_LRU_insert_zip_clean( /*=====================*/ buf_page_t* bpage) /*!< in: pointer to the block in question */ { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE); /* Find the first successor of bpage in the LRU list @@ -716,22 +672,16 @@ buf_LRU_insert_zip_clean( } #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -/******************************************************************//** -Try to free an uncompressed page of a compressed block from the unzip +/** Try to free an uncompressed page of a compressed block from the unzip LRU list. The compressed page is preserved, and it need not be clean. +@param[in] scan_all true=scan the whole list; + false=scan srv_LRU_scan_depth / 2 blocks @return true if freed */ -static -bool -buf_LRU_free_from_unzip_LRU_list( -/*=============================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - bool scan_all) /*!< in: scan whole LRU list - if true, otherwise scan only - srv_LRU_scan_depth / 2 blocks. */ +static bool buf_LRU_free_from_unzip_LRU_list(bool scan_all) { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); - if (!buf_LRU_evict_from_unzip_LRU(buf_pool)) { + if (!buf_LRU_evict_from_unzip_LRU()) { return(false); } @@ -768,19 +718,13 @@ buf_LRU_free_from_unzip_LRU_list( return(freed); } -/******************************************************************//** -Try to free a clean page from the common LRU list. -@return true if freed */ -static -bool -buf_LRU_free_from_common_LRU_list( -/*==============================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - bool scan_all) /*!< in: scan whole LRU list - if true, otherwise scan only - up to BUF_LRU_SEARCH_SCAN_THRESHOLD */ +/** Try to free a clean page from the common LRU list. +@param[in] scan_all true=scan the whole LRU list + false=use BUF_LRU_SEARCH_SCAN_THRESHOLD +@return whether a page was freed */ +static bool buf_LRU_free_from_common_LRU_list(bool scan_all) { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ulint scanned = 0; bool freed = false; @@ -817,7 +761,7 @@ buf_LRU_free_from_common_LRU_list( ++buf_pool->stat.n_ra_pages_evicted; } - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(!mutex_own(mutex)); } @@ -832,69 +776,34 @@ buf_LRU_free_from_common_LRU_list( return(freed); } -/******************************************************************//** -Try to free a replaceable block. +/** Try to free a replaceable block. +@param[in] scan_all true=scan the whole LRU list, + false=use BUF_LRU_SEARCH_SCAN_THRESHOLD @return true if found and freed */ -bool -buf_LRU_scan_and_free_block( -/*========================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - bool scan_all) /*!< in: scan whole LRU list - if true, otherwise scan only - BUF_LRU_SEARCH_SCAN_THRESHOLD - blocks. */ +bool buf_LRU_scan_and_free_block(bool scan_all) { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); - return(buf_LRU_free_from_unzip_LRU_list(buf_pool, scan_all) - || buf_LRU_free_from_common_LRU_list(buf_pool, scan_all)); + return(buf_LRU_free_from_unzip_LRU_list(scan_all) + || buf_LRU_free_from_common_LRU_list(scan_all)); } -/******************************************************************//** -Returns TRUE if less than 25 % of the buffer pool in any instance is -available. This can be used in heuristics to prevent huge transactions -eating up the whole buffer pool for their locks. -@return TRUE if less than 25 % of buffer pool left */ -ibool -buf_LRU_buf_pool_running_out(void) -/*==============================*/ +/** @return whether less than 1/4 of the buffer pool is available */ +bool buf_LRU_buf_pool_running_out() { - ibool ret = FALSE; - - for (ulint i = 0; i < srv_buf_pool_instances && !ret; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_pool_mutex_enter(buf_pool); - - if (!recv_recovery_is_on() - && UT_LIST_GET_LEN(buf_pool->free) - + UT_LIST_GET_LEN(buf_pool->LRU) - < ut_min(buf_pool->curr_size, - buf_pool->old_size) / 4) { - - ret = TRUE; - } - - buf_pool_mutex_exit(buf_pool); - } - - return(ret); + return !recv_recovery_is_on() + && UT_LIST_GET_LEN(buf_pool->free) + + UT_LIST_GET_LEN(buf_pool->LRU) + < ut_min(buf_pool->curr_size, buf_pool->old_size) / 4; } -/******************************************************************//** -Returns a free block from the buf_pool. The block is taken off the -free list. If it is empty, returns NULL. -@return a free control block, or NULL if the buf_block->free list is empty */ -buf_block_t* -buf_LRU_get_free_only( -/*==================*/ - buf_pool_t* buf_pool) +/** @return a buffer block from the buf_pool->free list +@retval NULL if the free list is empty */ +buf_block_t* buf_LRU_get_free_only() { buf_block_t* block; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); block = reinterpret_cast( UT_LIST_GET_FIRST(buf_pool->free)); @@ -911,7 +820,7 @@ buf_LRU_get_free_only( if (buf_pool->curr_size >= buf_pool->old_size || UT_LIST_GET_LEN(buf_pool->withdraw) >= buf_pool->withdraw_target - || !buf_block_will_withdrawn(buf_pool, block)) { + || !buf_block_will_be_withdrawn(block)) { /* found valid free block */ buf_page_mutex_enter(block); /* No adaptive hash index entries may point to @@ -921,8 +830,6 @@ buf_LRU_get_free_only( buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE); UNIV_MEM_ALLOC(block->frame, srv_page_size); - ut_ad(buf_pool_from_block(block) == buf_pool); - buf_page_mutex_exit(block); break; } @@ -945,13 +852,9 @@ Checks how much of buf_pool is occupied by non-data objects like AHI, lock heaps etc. Depending on the size of non-data objects this function will either assert or issue a warning and switch on the status monitor. */ -static -void -buf_LRU_check_size_of_non_data_objects( -/*===================================*/ - const buf_pool_t* buf_pool) /*!< in: buffer pool instance */ +static void buf_LRU_check_size_of_non_data_objects() { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (!recv_recovery_is_on() && buf_pool->curr_size == buf_pool->old_size @@ -1010,8 +913,7 @@ buf_LRU_check_size_of_non_data_objects( } } -/******************************************************************//** -Returns a free block from the buf_pool. The block is taken off the +/** Get a free block from the buf_pool. The block is taken off the free list. If free list is empty, blocks are moved from the end of the LRU list to the free list. This function is called from a user thread when it needs a clean @@ -1034,10 +936,7 @@ we put it to free list to be used. * iteration > 1: * same as iteration 1 but sleep 10ms @return the free control block, in state BUF_BLOCK_READY_FOR_USE */ -buf_block_t* -buf_LRU_get_free_block( -/*===================*/ - buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */ +buf_block_t* buf_LRU_get_free_block() { buf_block_t* block = NULL; bool freed = false; @@ -1046,9 +945,9 @@ buf_LRU_get_free_block( MONITOR_INC(MONITOR_LRU_GET_FREE_SEARCH); loop: - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); - buf_LRU_check_size_of_non_data_objects(buf_pool); + buf_LRU_check_size_of_non_data_objects(); DBUG_EXECUTE_IF("ib_lru_force_no_free_page", if (!buf_lru_free_blocks_error_printed) { @@ -1056,14 +955,11 @@ loop: goto not_found;}); /* If there is a block in the free list, take it */ - block = buf_LRU_get_free_only(buf_pool); + block = buf_LRU_get_free_only(); if (block != NULL) { - - buf_pool_mutex_exit(buf_pool); - ut_ad(buf_pool_from_block(block) == buf_pool); + mutex_exit(&buf_pool->mutex); memset(&block->page.zip, 0, sizeof block->page.zip); - block->skip_flush_check = false; return(block); } @@ -1076,8 +972,7 @@ loop: If we are doing for the first time we'll scan only tail of the LRU list otherwise we scan the whole LRU list. */ - freed = buf_LRU_scan_and_free_block( - buf_pool, n_iterations > 0); + freed = buf_LRU_scan_and_free_block(n_iterations > 0); if (!freed && n_iterations == 0) { /* Tell other threads that there is no point @@ -1096,7 +991,7 @@ loop: not_found: #endif - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if (freed) { goto loop; @@ -1147,7 +1042,7 @@ not_found: involved (particularly in case of compressed pages). We can do that in a separate patch sometime in future. */ - if (!buf_flush_single_page_from_LRU(buf_pool)) { + if (!buf_flush_single_page_from_LRU()) { MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT); ++flush_failures; } @@ -1159,20 +1054,15 @@ not_found: goto loop; } -/*******************************************************************//** -Moves the LRU_old pointer so that the length of the old blocks list +/** Move the LRU_old pointer so that the length of the old blocks list is inside the allowed limits. */ -UNIV_INLINE -void -buf_LRU_old_adjust_len( -/*===================*/ - buf_pool_t* buf_pool) /*!< in: buffer pool instance */ +static void buf_LRU_old_adjust_len() { ulint old_len; ulint new_len; ut_a(buf_pool->LRU_old); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_pool->LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN); ut_ad(buf_pool->LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX); compile_time_assert(BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN @@ -1229,16 +1119,11 @@ buf_LRU_old_adjust_len( } } -/*******************************************************************//** -Initializes the old blocks pointer in the LRU list. This function should be +/** Initialize the old blocks pointer in the LRU list. This function should be called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */ -static -void -buf_LRU_old_init( -/*=============*/ - buf_pool_t* buf_pool) +static void buf_LRU_old_init() { - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN); /* We first initialize all blocks in the LRU list as old and then use @@ -1260,21 +1145,15 @@ buf_LRU_old_init( buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU); buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU); - buf_LRU_old_adjust_len(buf_pool); + buf_LRU_old_adjust_len(); } -/******************************************************************//** -Remove a block from the unzip_LRU list if it belonged to the list. */ -static -void -buf_unzip_LRU_remove_block_if_needed( -/*=================================*/ - buf_page_t* bpage) /*!< in/out: control block */ +/** Remove a block from the unzip_LRU list if it belonged to the list. +@param[in] bpage control block */ +static void buf_unzip_LRU_remove_block_if_needed(buf_page_t* bpage) { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_page_in_file(bpage)); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (buf_page_belongs_to_unzip_LRU(bpage)) { buf_block_t* block = reinterpret_cast(bpage); @@ -1286,30 +1165,20 @@ buf_unzip_LRU_remove_block_if_needed( } } -/******************************************************************//** -Adjust LRU hazard pointers if needed. */ -void -buf_LRU_adjust_hp( -/*==============*/ - buf_pool_t* buf_pool,/*!< in: buffer pool instance */ - const buf_page_t* bpage) /*!< in: control block */ +/** Adjust LRU hazard pointers if needed. +@param[in] bpage buffer page descriptor */ +void buf_LRU_adjust_hp(const buf_page_t* bpage) { buf_pool->lru_hp.adjust(bpage); buf_pool->lru_scan_itr.adjust(bpage); buf_pool->single_scan_itr.adjust(bpage); } -/******************************************************************//** -Removes a block from the LRU list. */ -UNIV_INLINE -void -buf_LRU_remove_block( -/*=================*/ - buf_page_t* bpage) /*!< in: control block */ +/** Removes a block from the LRU list. +@param[in] bpage control block */ +static inline void buf_LRU_remove_block(buf_page_t* bpage) { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_a(buf_page_in_file(bpage)); @@ -1317,7 +1186,7 @@ buf_LRU_remove_block( /* Important that we adjust the hazard pointers before removing bpage from the LRU list. */ - buf_LRU_adjust_hp(buf_pool, bpage); + buf_LRU_adjust_hp(bpage); /* If the LRU_old pointer is defined and points to just this block, move it backward one step */ @@ -1377,7 +1246,7 @@ buf_LRU_remove_block( } /* Adjust the length of the old block list if necessary */ - buf_LRU_old_adjust_len(buf_pool); + buf_LRU_old_adjust_len(); } /******************************************************************//** @@ -1389,12 +1258,8 @@ buf_unzip_LRU_add_block( ibool old) /*!< in: TRUE if should be put to the end of the list, else put to the start */ { - buf_pool_t* buf_pool = buf_pool_from_block(block); - - ut_ad(buf_pool_mutex_own(buf_pool)); - + ut_ad(mutex_own(&buf_pool->mutex)); ut_a(buf_page_belongs_to_unzip_LRU(&block->page)); - ut_ad(!block->in_unzip_LRU_list); ut_d(block->in_unzip_LRU_list = TRUE); @@ -1419,10 +1284,7 @@ buf_LRU_add_block_low( LRU list is very short, the block is added to the start, regardless of this parameter */ { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_pool_mutex_own(buf_pool)); - + ut_ad(mutex_own(&buf_pool->mutex)); ut_a(buf_page_in_file(bpage)); ut_ad(!bpage->in_LRU_list); @@ -1449,7 +1311,7 @@ buf_LRU_add_block_low( ut_d(bpage->in_LRU_list = TRUE); - incr_LRU_size_in_bytes(bpage, buf_pool); + incr_LRU_size_in_bytes(bpage); if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { @@ -1458,14 +1320,14 @@ buf_LRU_add_block_low( /* Adjust the length of the old block list if necessary */ buf_page_set_old(bpage, old); - buf_LRU_old_adjust_len(buf_pool); + buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) { /* The LRU list is now long enough for LRU_old to become defined: init it */ - buf_LRU_old_init(buf_pool); + buf_LRU_old_init(); } else { buf_page_set_old(bpage, buf_pool->LRU_old != NULL); } @@ -1501,9 +1363,7 @@ buf_LRU_make_block_young( /*=====================*/ buf_page_t* bpage) /*!< in: control block */ { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); if (bpage->old) { buf_pool->stat.n_pages_made_young++; @@ -1532,13 +1392,10 @@ buf_LRU_free_page( compressed page of an uncompressed page */ { buf_page_t* b = NULL; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, bpage->id); - + rw_lock_t* hash_lock = buf_page_hash_lock_get(bpage->id); BPageMutex* block_mutex = buf_page_get_mutex(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); @@ -1574,7 +1431,7 @@ func_exit: new (b) buf_page_t(*bpage); } - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); ut_ad(!bpage->in_flush_list == !bpage->oldest_modification); @@ -1607,7 +1464,7 @@ func_exit: mutex_enter(block_mutex); - ut_a(!buf_page_hash_get_low(buf_pool, b->id)); + ut_a(!buf_page_hash_get_low(b->id)); b->state = b->oldest_modification ? BUF_BLOCK_ZIP_DIRTY @@ -1647,7 +1504,7 @@ func_exit: UT_LIST_INSERT_AFTER(buf_pool->LRU, prev_b, b); - incr_LRU_size_in_bytes(b, buf_pool); + incr_LRU_size_in_bytes(b); if (buf_page_is_old(b)) { buf_pool->LRU_old_len++; @@ -1664,12 +1521,12 @@ func_exit: ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ - buf_LRU_old_adjust_len(buf_pool); + buf_LRU_old_adjust_len(); } else if (lru_len == BUF_LRU_OLD_MIN_LEN) { /* The LRU list is now long enough for LRU_old to become defined: init it */ - buf_LRU_old_init(buf_pool); + buf_LRU_old_init(); } #ifdef UNIV_LRU_DEBUG /* Check that the "old" flag is consistent @@ -1710,7 +1567,7 @@ func_exit: rw_lock_x_unlock(hash_lock); } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* Remove possible adaptive hash index on the page. The page was declared uninitialized by @@ -1745,7 +1602,7 @@ func_exit: checksum); } - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); if (b != NULL) { mutex_enter(block_mutex); @@ -1768,9 +1625,8 @@ buf_LRU_block_free_non_file_page( buf_block_t* block) /*!< in: block, must not contain a file page */ { void* data; - buf_pool_t* buf_pool = buf_pool_from_block(block); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(buf_page_mutex_own(block)); switch (buf_block_get_state(block)) { @@ -1806,13 +1662,13 @@ buf_LRU_block_free_non_file_page( if (data != NULL) { block->page.zip.data = NULL; buf_page_mutex_exit(block); - buf_pool_mutex_exit_forbid(buf_pool); + buf_pool_mutex_exit_forbid(); ut_ad(block->zip_size()); - buf_buddy_free(buf_pool, data, block->zip_size()); + buf_buddy_free(data, block->zip_size()); - buf_pool_mutex_exit_allow(buf_pool); + buf_pool_mutex_exit_allow(); buf_page_mutex_enter(block); page_zip_set_size(&block->page.zip, 0); @@ -1820,7 +1676,7 @@ buf_LRU_block_free_non_file_page( if (buf_pool->curr_size < buf_pool->old_size && UT_LIST_GET_LEN(buf_pool->withdraw) < buf_pool->withdraw_target - && buf_block_will_withdrawn(buf_pool, block)) { + && buf_block_will_be_withdrawn(block)) { /* This should be withdrawn */ UT_LIST_ADD_LAST( buf_pool->withdraw, @@ -1859,13 +1715,12 @@ buf_LRU_block_remove_hashed( compressed page of an uncompressed page */ { const buf_page_t* hashed_bpage; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); rw_lock_t* hash_lock; - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); - hash_lock = buf_page_hash_lock_get(buf_pool, bpage->id); + hash_lock = buf_page_hash_lock_get(bpage->id); ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); @@ -1946,7 +1801,7 @@ buf_LRU_block_remove_hashed( break; } - hashed_bpage = buf_page_hash_get_low(buf_pool, bpage->id); + hashed_bpage = buf_page_hash_get_low(bpage->id); if (bpage != hashed_bpage) { ib::error() << "Page " << bpage->id << " not found in the hash table"; @@ -1962,22 +1817,19 @@ buf_LRU_block_remove_hashed( << " page_state:" << buf_page_get_state(bpage); if (hashed_bpage) { - ib::error() << "In hash table we find block " << hashed_bpage << " of " << hashed_bpage->id << " which is not " << bpage; } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - mutex_exit(buf_page_get_mutex(bpage)); - rw_lock_x_unlock(hash_lock); - buf_pool_mutex_exit(buf_pool); - buf_print(); - buf_LRU_print(); - buf_validate(); - buf_LRU_validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - ut_error; + ut_d(mutex_exit(buf_page_get_mutex(bpage))); + ut_d(rw_lock_x_unlock(hash_lock)); + ut_d(mutex_exit(&buf_pool->mutex)); + ut_d(buf_print()); + ut_d(buf_LRU_print()); + ut_d(buf_validate()); + ut_d(buf_LRU_validate()); + ut_ad(0); } ut_ad(!bpage->in_zip_hash); @@ -1998,14 +1850,13 @@ buf_LRU_block_remove_hashed( #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG UT_LIST_REMOVE(buf_pool->zip_clean, bpage); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - mutex_exit(&buf_pool->zip_mutex); rw_lock_x_unlock(hash_lock); - buf_pool_mutex_exit_forbid(buf_pool); + buf_pool_mutex_exit_forbid(); - buf_buddy_free(buf_pool, bpage->zip.data, bpage->zip_size()); + buf_buddy_free(bpage->zip.data, bpage->zip_size()); - buf_pool_mutex_exit_allow(buf_pool); + buf_pool_mutex_exit_allow(); buf_page_free_descriptor(bpage); return(false); @@ -2052,11 +1903,11 @@ buf_LRU_block_remove_hashed( ut_ad(!bpage->in_free_list); ut_ad(!bpage->in_flush_list); ut_ad(!bpage->in_LRU_list); - buf_pool_mutex_exit_forbid(buf_pool); + buf_pool_mutex_exit_forbid(); - buf_buddy_free(buf_pool, data, bpage->zip_size()); + buf_buddy_free(data, bpage->zip_size()); - buf_pool_mutex_exit_allow(buf_pool); + buf_pool_mutex_exit_allow(); page_zip_set_size(&bpage->zip, 0); } @@ -2085,8 +1936,7 @@ buf_LRU_block_free_hashed_page( buf_block_t* block) /*!< in: block, must contain a file page and be in a state where it can be freed */ { - buf_pool_t* buf_pool = buf_pool_from_block(block); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); buf_page_mutex_enter(block); @@ -2108,12 +1958,10 @@ buf_LRU_block_free_hashed_page( @param[in] old_page_id page number before bpage->id was invalidated */ void buf_LRU_free_one_page(buf_page_t* bpage, page_id_t old_page_id) { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, - old_page_id); + rw_lock_t* hash_lock = buf_page_hash_lock_get(old_page_id); BPageMutex* block_mutex = buf_page_get_mutex(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); rw_lock_x_lock(hash_lock); @@ -2136,23 +1984,16 @@ void buf_LRU_free_one_page(buf_page_t* bpage, page_id_t old_page_id) ut_ad(!mutex_own(block_mutex)); } -/**********************************************************************//** -Updates buf_pool->LRU_old_ratio for one buffer pool instance. -@return updated old_pct */ -static -uint -buf_LRU_old_ratio_update_instance( -/*==============================*/ - buf_pool_t* buf_pool,/*!< in: buffer pool instance */ - uint old_pct,/*!< in: Reserve this percentage of - the buffer pool for "old" blocks. */ - bool adjust) /*!< in: true=adjust the LRU list; +/** Update buf_pool->LRU_old_ratio. +@param[in] old_pct Reserve this percentage of + the buffer pool for "old" blocks +@param[in] adjust true=adjust the LRU list; false=just assign buf_pool->LRU_old_ratio - during the initialization of InnoDB */ + during the initialization of InnoDB +@return updated old_pct */ +uint buf_LRU_old_ratio_update(uint old_pct, bool adjust) { - uint ratio; - - ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100; + uint ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100; if (ratio < BUF_LRU_OLD_RATIO_MIN) { ratio = BUF_LRU_OLD_RATIO_MIN; } else if (ratio > BUF_LRU_OLD_RATIO_MAX) { @@ -2160,19 +2001,18 @@ buf_LRU_old_ratio_update_instance( } if (adjust) { - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); if (ratio != buf_pool->LRU_old_ratio) { buf_pool->LRU_old_ratio = ratio; if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) { - - buf_LRU_old_adjust_len(buf_pool); + buf_LRU_old_adjust_len(); } } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } else { buf_pool->LRU_old_ratio = ratio; } @@ -2181,56 +2021,16 @@ buf_LRU_old_ratio_update_instance( return((uint) (ratio * 100 / (double) BUF_LRU_OLD_RATIO_DIV + 0.5)); } -/**********************************************************************//** -Updates buf_pool->LRU_old_ratio. -@return updated old_pct */ -uint -buf_LRU_old_ratio_update( -/*=====================*/ - uint old_pct,/*!< in: Reserve this percentage of - the buffer pool for "old" blocks. */ - bool adjust) /*!< in: true=adjust the LRU list; - false=just assign buf_pool->LRU_old_ratio - during the initialization of InnoDB */ -{ - uint new_ratio = 0; - - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - new_ratio = buf_LRU_old_ratio_update_instance( - buf_pool, old_pct, adjust); - } - - return(new_ratio); -} - /********************************************************************//** Update the historical stats that we are collecting for LRU eviction policy at the end of each interval. */ void -buf_LRU_stat_update(void) -/*=====================*/ +buf_LRU_stat_update() { buf_LRU_stat_t* item; - buf_pool_t* buf_pool; - bool evict_started = FALSE; buf_LRU_stat_t cur_stat; - /* If we haven't started eviction yet then don't update stats. */ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - - buf_pool = buf_pool_from_array(i); - - if (buf_pool->freed_page_clock != 0) { - evict_started = true; - break; - } - } - - if (!evict_started) { + if (!buf_pool->freed_page_clock) { goto func_exit; } @@ -2259,18 +2059,13 @@ func_exit: } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/**********************************************************************//** -Validates the LRU list for one buffer pool instance. */ -static -void -buf_LRU_validate_instance( -/*======================*/ - buf_pool_t* buf_pool) +/** Validate the LRU list. */ +void buf_LRU_validate() { - ulint old_len; - ulint new_len; + ulint old_len; + ulint new_len; - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) { @@ -2288,7 +2083,7 @@ buf_LRU_validate_instance( ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE); } - CheckInLRUList::validate(buf_pool); + CheckInLRUList::validate(); old_len = 0; @@ -2330,7 +2125,7 @@ buf_LRU_validate_instance( ut_a(buf_pool->LRU_old_len == old_len); - CheckInFreeList::validate(buf_pool); + CheckInFreeList::validate(); for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool->free); bpage != NULL; @@ -2339,7 +2134,7 @@ buf_LRU_validate_instance( ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED); } - CheckUnzipLRUAndLRUList::validate(buf_pool); + CheckUnzipLRUAndLRUList::validate(); for (buf_block_t* block = UT_LIST_GET_FIRST(buf_pool->unzip_LRU); block != NULL; @@ -2350,37 +2145,15 @@ buf_LRU_validate_instance( ut_a(buf_page_belongs_to_unzip_LRU(&block->page)); } - buf_pool_mutex_exit(buf_pool); -} - -/**********************************************************************//** -Validates the LRU list. -@return TRUE */ -ibool -buf_LRU_validate(void) -/*==================*/ -{ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - buf_LRU_validate_instance(buf_pool); - } - - return(TRUE); + mutex_exit(&buf_pool->mutex); } #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/**********************************************************************//** -Prints the LRU list for one buffer pool instance. */ -static -void -buf_LRU_print_instance( -/*===================*/ - buf_pool_t* buf_pool) +/** Dump the LRU list to stderr. */ +void buf_LRU_print() { - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); for (const buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool->LRU); bpage != NULL; @@ -2435,20 +2208,6 @@ buf_LRU_print_instance( mutex_exit(buf_page_get_mutex(bpage)); } - buf_pool_mutex_exit(buf_pool); -} - -/**********************************************************************//** -Prints the LRU list. */ -void -buf_LRU_print(void) -/*===============*/ -{ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - buf_LRU_print_instance(buf_pool); - } + mutex_exit(&buf_pool->mutex); } #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index e8190595ec0..232c7e0e8b2 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -41,11 +41,6 @@ Created 11/5/1995 Heikki Tuuri #include "srv0start.h" #include "srv0srv.h" -/** There must be at least this many pages in buf_pool in the area to start -a random read-ahead */ -#define BUF_READ_AHEAD_RANDOM_THRESHOLD(b) \ - (5 + BUF_READ_AHEAD_AREA(b) / 8) - /** If there are buf_pool->curr_size per the number below pending reads, then read-ahead is not done: this is to prevent flooding the buffer pool with i/o-fixed buffer blocks */ @@ -60,13 +55,12 @@ buf_read_page_handle_error( /*=======================*/ buf_page_t* bpage) /*!< in: pointer to the block */ { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); const bool uncompressed = (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); const page_id_t old_page_id = bpage->id; /* First unfix and release lock on the bpage */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); mutex_enter(buf_page_get_mutex(bpage)); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ); @@ -88,7 +82,7 @@ buf_read_page_handle_error( ut_ad(buf_pool->n_pend_reads > 0); buf_pool->n_pend_reads--; - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } /** Low-level function which reads a page asynchronously from a file to the @@ -224,15 +218,12 @@ get read even if we return a positive value! */ ulint buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) { - buf_pool_t* buf_pool = buf_pool_get(page_id); ulint recent_blocks = 0; ulint ibuf_mode; ulint count; ulint low, high; dberr_t err = DB_SUCCESS; ulint i; - const ulint buf_read_ahead_random_area - = BUF_READ_AHEAD_AREA(buf_pool); if (!srv_random_read_ahead) { /* Disabled by user */ @@ -253,6 +244,8 @@ buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) return(0); } + const ulint buf_read_ahead_random_area + = buf_pool->read_ahead_area; low = (page_id.page_no() / buf_read_ahead_random_area) * buf_read_ahead_random_area; @@ -289,11 +282,11 @@ buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) return(0); } - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); if (buf_pool->n_pend_reads > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(0); } @@ -302,25 +295,19 @@ buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) that is, reside near the start of the LRU list. */ for (i = low; i < high; i++) { - const buf_page_t* bpage = buf_page_hash_get( - buf_pool, page_id_t(page_id.space(), i)); - - if (bpage != NULL - && buf_page_is_accessed(bpage) - && buf_page_peek_if_young(buf_pool, bpage)) { - - recent_blocks++; - - if (recent_blocks - >= BUF_READ_AHEAD_RANDOM_THRESHOLD(buf_pool)) { - - buf_pool_mutex_exit(buf_pool); + if (const buf_page_t* bpage = buf_page_hash_get( + page_id_t(page_id.space(), i))) { + if (buf_page_is_accessed(bpage) + && buf_page_peek_if_young(bpage) + && ++recent_blocks + >= 5 + buf_pool->read_ahead_area / 8) { + mutex_exit(&buf_pool->mutex); goto read_ahead; } } } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* Do nothing */ return(0); @@ -490,7 +477,6 @@ which could result in a deadlock if the OS does not support asynchronous io. ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) { - buf_pool_t* buf_pool = buf_pool_get(page_id); buf_page_t* bpage; buf_frame_t* frame; buf_page_t* pred_bpage = NULL; @@ -502,8 +488,6 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) ulint low, high; dberr_t err = DB_SUCCESS; ulint i; - const ulint buf_read_ahead_linear_area - = BUF_READ_AHEAD_AREA(buf_pool); ulint threshold; /* check if readahead is disabled */ @@ -516,6 +500,8 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) return(0); } + const ulint buf_read_ahead_linear_area + = buf_pool->read_ahead_area; low = (page_id.page_no() / buf_read_ahead_linear_area) * buf_read_ahead_linear_area; high = (page_id.page_no() / buf_read_ahead_linear_area + 1) @@ -553,11 +539,11 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) return(0); } - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); if (buf_pool->n_pend_reads > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(0); } @@ -575,13 +561,12 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) /* How many out of order accessed pages can we ignore when working out the access pattern for linear readahead */ threshold = ut_min(static_cast(64 - srv_read_ahead_threshold), - BUF_READ_AHEAD_AREA(buf_pool)); + buf_pool->read_ahead_area); fail_count = 0; for (i = low; i < high; i++) { - bpage = buf_page_hash_get(buf_pool, - page_id_t(page_id.space(), i)); + bpage = buf_page_hash_get(page_id_t(page_id.space(), i)); if (bpage == NULL || !buf_page_is_accessed(bpage)) { /* Not accessed */ @@ -607,7 +592,7 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) if (fail_count > threshold) { /* Too many failures: return */ - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(0); } @@ -619,10 +604,10 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) /* If we got this far, we know that enough pages in the area have been accessed in the right order: linear read-ahead can be sensible */ - bpage = buf_page_hash_get(buf_pool, page_id); + bpage = buf_page_hash_get(page_id); if (bpage == NULL) { - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); return(0); } @@ -648,7 +633,7 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) pred_offset = fil_page_get_prev(frame); succ_offset = fil_page_get_next(frame); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if ((page_id.page_no() == low) && (succ_offset == page_id.page_no() + 1)) { @@ -760,19 +745,14 @@ buf_read_recv_pages( const ulint zip_size = space->zip_size(); for (ulint i = 0; i < n_stored; i++) { - buf_pool_t* buf_pool; const page_id_t cur_page_id(space_id, page_nos[i]); - ulint count = 0; - - buf_pool = buf_pool_get(cur_page_id); - while (buf_pool->n_pend_reads >= recv_sys.max_blocks() / 2) { + for (ulint count = 0, limit = recv_sys.max_blocks() / 2; + buf_pool->n_pend_reads >= limit; ) { os_thread_sleep(10000); - count++; - - if (!(count % 1000)) { + if (!(++count % 1000)) { ib::error() << "Waited for " << count / 100 diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 89c900e10bc..1b7862ae358 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1200,7 +1200,7 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space) do { ulint n_pages = 0; success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages); - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + buf_flush_wait_batch_end(BUF_FLUSH_LIST); sum_pages += n_pages; } while (!success); @@ -2137,7 +2137,7 @@ fil_crypt_flush_space( do { success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages); - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + buf_flush_wait_batch_end(BUF_FLUSH_LIST); sum_pages += n_pages; } while (!success && !space->is_stopping()); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index eee52923b11..dc12aef7ff8 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3407,58 +3407,10 @@ static ulonglong innodb_prepare_commit_versioned(THD* thd, ulonglong *trx_id) /** Initialize and normalize innodb_buffer_pool_size. */ static void innodb_buffer_pool_size_init() { - if (srv_buf_pool_size >= BUF_POOL_SIZE_THRESHOLD) { - - if (srv_buf_pool_instances == srv_buf_pool_instances_default) { -#if defined(_WIN32) && !defined(_WIN64) - /* Do not allocate too large of a buffer pool on - Windows 32-bit systems, which can have trouble - allocating larger single contiguous memory blocks. */ - srv_buf_pool_size = ulint( - ut_uint64_align_up(srv_buf_pool_size, - srv_buf_pool_chunk_unit)); - srv_buf_pool_instances = std::min( - MAX_BUFFER_POOLS, - ulong(srv_buf_pool_size - / srv_buf_pool_chunk_unit)); -#else /* defined(_WIN32) && !defined(_WIN64) */ - /* Default to 8 instances when size > 1GB. */ - srv_buf_pool_instances = 8; -#endif /* defined(_WIN32) && !defined(_WIN64) */ - } - } else { - /* If buffer pool is less than 1 GiB, assume fewer - threads. Also use only one buffer pool instance. */ - if (srv_buf_pool_instances != srv_buf_pool_instances_default - && srv_buf_pool_instances != 1) { - /* We can't distinguish whether the user has explicitly - started mysqld with --innodb-buffer-pool-instances=0, - (srv_buf_pool_instances_default is 0) or has not - specified that option at all. Thus we have the - limitation that if the user started with =0, we - will not emit a warning here, but we should actually - do so. */ - ib::info() - << "Adjusting innodb_buffer_pool_instances" - " from " << srv_buf_pool_instances << " to 1" - " since innodb_buffer_pool_size is less than " - << BUF_POOL_SIZE_THRESHOLD / (1024 * 1024) - << " MiB"; - } - - srv_buf_pool_instances = 1; - } - - if (srv_buf_pool_chunk_unit * srv_buf_pool_instances - > srv_buf_pool_size) { + if (srv_buf_pool_chunk_unit > srv_buf_pool_size) { /* Size unit of buffer pool is larger than srv_buf_pool_size. adjust srv_buf_pool_chunk_unit for srv_buf_pool_size. */ - srv_buf_pool_chunk_unit - = static_cast(srv_buf_pool_size) - / srv_buf_pool_instances; - if (srv_buf_pool_size % srv_buf_pool_instances != 0) { - ++srv_buf_pool_chunk_unit; - } + srv_buf_pool_chunk_unit = ulong(srv_buf_pool_size); } srv_buf_pool_size = buf_pool_size_align(srv_buf_pool_size); @@ -3480,6 +3432,12 @@ static ulong innodb_undo_logs; /** Deprecation message for innodb_undo_logs */ static const char* innodb_undo_logs_deprecated = "The parameter innodb_undo_logs is deprecated and has no effect."; +/** Deprecated parameter with no effect */ +static ulong innodb_buffer_pool_instances; +/** Deprecated parameter with no effect */ +static ulong innodb_page_cleaners; +static const char* innodb_page_cleaners_deprecated += "The parameter innodb_page_cleaners is deprecated and has no effect."; /** Initialize, validate and normalize the InnoDB startup parameters. @return failure code @@ -3789,6 +3747,19 @@ static int innodb_init_params() innodb_log_optimize_ddl = FALSE; } + if (UNIV_UNLIKELY(innodb_buffer_pool_instances)) { + sql_print_warning("The parameter innodb_buffer_pool_instances" + " is deprecated and has no effect."); + } + + if (UNIV_UNLIKELY(innodb_page_cleaners)) { + sql_print_warning(innodb_page_cleaners_deprecated); + } + + innodb_buffer_pool_instances = 1; + + innodb_page_cleaners = 1; + if (UNIV_UNLIKELY(innodb_undo_logs != TRX_SYS_N_RSEGS)) { sql_print_warning(innodb_undo_logs_deprecated); innodb_undo_logs = TRX_SYS_N_RSEGS; @@ -3894,12 +3865,6 @@ static int innodb_init_params() innodb_buffer_pool_size_init(); - if (srv_n_page_cleaners > srv_buf_pool_instances) { - /* limit of page_cleaner parallelizability - is number of buffer pool instances. */ - srv_n_page_cleaners = srv_buf_pool_instances; - } - srv_lock_table_size = 5 * (srv_buf_pool_size >> srv_page_size_shift); DBUG_RETURN(0); } @@ -4045,8 +4010,8 @@ static int innodb_init(void* p) srv_was_started = true; innodb_params_adjust(); - innobase_old_blocks_pct = static_cast( - buf_LRU_old_ratio_update(innobase_old_blocks_pct, TRUE)); + innobase_old_blocks_pct = buf_LRU_old_ratio_update( + innobase_old_blocks_pct, true); ibuf_max_size_update(srv_change_buffer_max_size); @@ -18293,36 +18258,28 @@ Keep the compressed pages in the buffer pool. @return whether all uncompressed pages were evicted */ static MY_ATTRIBUTE((warn_unused_result)) bool -innodb_buffer_pool_evict_uncompressed(void) -/*=======================================*/ +innodb_buffer_pool_evict_uncompressed() { bool all_evicted = true; - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool = &buf_pool_ptr[i]; + mutex_enter(&buf_pool->mutex); - buf_pool_mutex_enter(buf_pool); + for (buf_block_t* block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); + block != NULL; ) { + buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block); + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->in_unzip_LRU_list); + ut_ad(block->page.in_LRU_list); + mutex_enter(&block->mutex); - for (buf_block_t* block = UT_LIST_GET_LAST( - buf_pool->unzip_LRU); - block != NULL; ) { - buf_block_t* prev_block = UT_LIST_GET_PREV( - unzip_LRU, block); - ut_ad(buf_block_get_state(block) - == BUF_BLOCK_FILE_PAGE); - ut_ad(block->in_unzip_LRU_list); - ut_ad(block->page.in_LRU_list); - - if (!buf_LRU_free_page(&block->page, false)) { - all_evicted = false; - } - - block = prev_block; + if (!buf_LRU_free_page(&block->page, false)) { + mutex_exit(&block->mutex); + all_evicted = false; } - - buf_pool_mutex_exit(buf_pool); + block = prev_block; } + mutex_exit(&buf_pool->mutex); return(all_evicted); } @@ -18644,7 +18601,7 @@ buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save) { if (*(my_bool*) save) { mysql_mutex_unlock(&LOCK_global_system_variables); - buf_flush_sync_all_buf_pools(); + buf_flush_sync(); mysql_mutex_lock(&LOCK_global_system_variables); } } @@ -18906,6 +18863,16 @@ innodb_log_optimize_ddl_warn(THD* thd, st_mysql_sys_var*, void*, const void*) innodb_log_optimize_ddl_deprecated); } +/** Issue a deprecation warning for SET GLOBAL innodb_page_cleaners. +@param[in,out] thd client connection */ +static void +innodb_page_cleaners_warn(THD* thd, st_mysql_sys_var*, void*, const void*) +{ + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + HA_ERR_UNSUPPORTED, + innodb_page_cleaners_deprecated); +} + /** Issue a deprecation warning for SET GLOBAL innodb_undo_logs. @param[in,out] thd client connection */ static void @@ -19274,20 +19241,9 @@ static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "Path to InnoDB log files.", NULL, NULL, NULL); -/** Update innodb_page_cleaners. -@param[in] save the new value of innodb_page_cleaners */ -static -void -innodb_page_cleaners_threads_update(THD*, struct st_mysql_sys_var*, void*, const void *save) -{ - buf_flush_set_page_cleaner_thread_cnt(*static_cast(save)); -} - -static MYSQL_SYSVAR_ULONG(page_cleaners, srv_n_page_cleaners, +static MYSQL_SYSVAR_ULONG(page_cleaners, innodb_page_cleaners, PLUGIN_VAR_RQCMDARG, - "Page cleaner threads can be from 1 to 64. Default is 4.", - NULL, - innodb_page_cleaners_threads_update, 4, 1, 64, 0); + innodb_deprecated_ignored, NULL, innodb_page_cleaners_warn, 0, 0, 64, 0); static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, PLUGIN_VAR_RQCMDARG, @@ -19451,11 +19407,6 @@ innodb_buffer_pool_size_validate( void* save, struct st_mysql_value* value); -/* If the default value of innodb_buffer_pool_size is increased to be more than -BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default -can be removed and 8 used instead. The problem with the current setup is that -with 128MiB default buffer pool size and 8 instances by default we would emit -a warning when no options are specified. */ static MYSQL_SYSVAR_ULONGLONG(buffer_pool_size, innobase_buffer_pool_size, PLUGIN_VAR_RQCMDARG, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", @@ -19467,7 +19418,7 @@ static MYSQL_SYSVAR_ULONGLONG(buffer_pool_size, innobase_buffer_pool_size, static MYSQL_SYSVAR_ULONG(buffer_pool_chunk_size, srv_buf_pool_chunk_unit, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Size of a single memory chunk within each buffer pool instance" + "Size of a single memory chunk" " for resizing buffer pool. Online buffer pool resizing happens" " at this granularity. 0 means disable resizing buffer pool.", NULL, NULL, @@ -19497,10 +19448,9 @@ static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm NULL, NULL, INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS, &innodb_lock_schedule_algorithm_typelib); -static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances, +static MYSQL_SYSVAR_ULONG(buffer_pool_instances, innodb_buffer_pool_instances, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Number of buffer pool instances, set to higher value on high-end machines to increase scalability", - NULL, NULL, srv_buf_pool_instances_default, 0, MAX_BUFFER_POOLS, 0); + innodb_deprecated_ignored, NULL, NULL, 0, 0, 64, 0); static MYSQL_SYSVAR_STR(buffer_pool_filename, srv_buf_dump_filename, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, @@ -20080,10 +20030,9 @@ static MYSQL_SYSVAR_BOOL(disable_resize_buffer_pool_debug, NULL, NULL, TRUE); static MYSQL_SYSVAR_BOOL(page_cleaner_disabled_debug, - innodb_page_cleaner_disabled_debug, - PLUGIN_VAR_OPCMDARG, + innodb_page_cleaner_disabled_debug, PLUGIN_VAR_OPCMDARG, "Disable page cleaner", - NULL, buf_flush_page_cleaner_disabled_debug_update, FALSE); + NULL, NULL, FALSE); static MYSQL_SYSVAR_BOOL(sync_debug, srv_sync_debug, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, @@ -21447,38 +21396,27 @@ innodb_buffer_pool_size_validate( #endif /* UNIV_DEBUG */ - buf_pool_mutex_enter_all(); + mutex_enter(&buf_pool->mutex); if (srv_buf_pool_old_size != srv_buf_pool_size) { - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); my_printf_error(ER_WRONG_ARGUMENTS, "Another buffer pool resize is already in progress.", MYF(0)); return(1); } - if (srv_buf_pool_instances > 1 && intbuf < BUF_POOL_SIZE_THRESHOLD) { - buf_pool_mutex_exit_all(); - - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WRONG_ARGUMENTS, - "Cannot update innodb_buffer_pool_size" - " to less than 1GB if" - " innodb_buffer_pool_instances > 1."); - return(1); - } - ulint requested_buf_pool_size = buf_pool_size_align(ulint(intbuf)); *static_cast(save) = requested_buf_pool_size; if (srv_buf_pool_size == ulint(intbuf)) { - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); /* nothing to do */ return(0); } if (srv_buf_pool_size == requested_buf_pool_size) { - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, "innodb_buffer_pool_size must be at least" @@ -21489,7 +21427,7 @@ innodb_buffer_pool_size_validate( } srv_buf_pool_size = requested_buf_pool_size; - buf_pool_mutex_exit_all(); + mutex_exit(&buf_pool->mutex); if (intbuf != static_cast(requested_buf_pool_size)) { char buf[64]; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 71fece7aa6f..6084f897e59 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -117,9 +117,6 @@ struct buf_page_info_t{ unsigned space_id:32; /*!< Tablespace ID */ unsigned page_num:32; /*!< Page number/offset */ unsigned access_time:32; /*!< Time of first access */ - unsigned pool_id:MAX_BUFFER_POOLS_BITS; - /*!< Buffer Pool ID. Must be less than - MAX_BUFFER_POOLS */ unsigned flush_type:2; /*!< Flush type */ unsigned io_fix:2; /*!< type of pending I/O operation */ unsigned fix_count:19; /*!< Count of how manyfold this block @@ -1601,7 +1598,6 @@ namespace Show { static ST_FIELD_INFO i_s_cmpmem_fields_info[] = { Column("page_size", SLong(5), NOT_NULL, "Buddy Block Size"), - Column("buffer_pool_instance", SLong(), NOT_NULL, "Buffer Pool Id"), Column("pages_used", SLong(), NOT_NULL, "Currently in Use"), Column("pages_free", SLong(), NOT_NULL, "Currently Available"), Column("relocation_ops", SLonglong(), NOT_NULL, "Total Number of Relocations"), @@ -1624,7 +1620,6 @@ i_s_cmpmem_fill_low( Item* , /*!< in: condition (ignored) */ ibool reset) /*!< in: TRUE=reset cumulated counts */ { - int status = 0; TABLE* table = (TABLE*) tables->table; DBUG_ENTER("i_s_cmpmem_fill_low"); @@ -1637,57 +1632,45 @@ i_s_cmpmem_fill_low( RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - ulint zip_free_len_local[BUF_BUDDY_SIZES_MAX + 1]; - buf_buddy_stat_t buddy_stat_local[BUF_BUDDY_SIZES_MAX + 1]; + ulint zip_free_len_local[BUF_BUDDY_SIZES_MAX + 1]; + buf_buddy_stat_t buddy_stat_local[BUF_BUDDY_SIZES_MAX + 1]; - status = 0; + /* Save buddy stats for buffer pool in local variables. */ + mutex_enter(&buf_pool->mutex); - buf_pool = buf_pool_from_array(i); + for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) { + zip_free_len_local[x] = (x < BUF_BUDDY_SIZES) ? + UT_LIST_GET_LEN(buf_pool->zip_free[x]) : 0; - /* Save buddy stats for buffer pool in local variables. */ - buf_pool_mutex_enter(buf_pool); - for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) { + buddy_stat_local[x] = buf_pool->buddy_stat[x]; - zip_free_len_local[x] = (x < BUF_BUDDY_SIZES) ? - UT_LIST_GET_LEN(buf_pool->zip_free[x]) : 0; - - buddy_stat_local[x] = buf_pool->buddy_stat[x]; - - if (reset) { - /* This is protected by buf_pool->mutex. */ - buf_pool->buddy_stat[x].relocated = 0; - buf_pool->buddy_stat[x].relocated_usec = 0; - } - } - buf_pool_mutex_exit(buf_pool); - - for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) { - buf_buddy_stat_t* buddy_stat; - - buddy_stat = &buddy_stat_local[x]; - - table->field[0]->store(BUF_BUDDY_LOW << x); - table->field[1]->store(i, true); - table->field[2]->store(buddy_stat->used, true); - table->field[3]->store(zip_free_len_local[x], true); - table->field[4]->store(buddy_stat->relocated, true); - table->field[5]->store( - buddy_stat->relocated_usec / 1000000, true); - - if (schema_table_store_record(thd, table)) { - status = 1; - break; - } - } - - if (status) { - break; + if (reset) { + /* This is protected by buf_pool->mutex. */ + buf_pool->buddy_stat[x].relocated = 0; + buf_pool->buddy_stat[x].relocated_usec = 0; } } - DBUG_RETURN(status); + mutex_exit(&buf_pool->mutex); + + for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) { + buf_buddy_stat_t* buddy_stat; + + buddy_stat = &buddy_stat_local[x]; + + table->field[0]->store(BUF_BUDDY_LOW << x); + table->field[1]->store(buddy_stat->used, true); + table->field[2]->store(zip_free_len_local[x], true); + table->field[3]->store(buddy_stat->relocated, true); + table->field[4]->store( + buddy_stat->relocated_usec / 1000000, true); + + if (schema_table_store_record(thd, table)) { + DBUG_RETURN(1); + } + } + + DBUG_RETURN(0); } /*******************************************************************//** @@ -3559,257 +3542,117 @@ namespace Show { /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] = { -#define IDX_BUF_STATS_POOL_ID 0 - Column("POOL_ID", ULong(), NOT_NULL), - -#define IDX_BUF_STATS_POOL_SIZE 1 +#define IDX_BUF_STATS_POOL_SIZE 0 Column("POOL_SIZE", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_FREE_BUFFERS 2 +#define IDX_BUF_STATS_FREE_BUFFERS 1 Column("FREE_BUFFERS", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_LRU_LEN 3 +#define IDX_BUF_STATS_LRU_LEN 2 Column("DATABASE_PAGES", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_OLD_LRU_LEN 4 +#define IDX_BUF_STATS_OLD_LRU_LEN 3 Column("OLD_DATABASE_PAGES", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_FLUSH_LIST_LEN 5 +#define IDX_BUF_STATS_FLUSH_LIST_LEN 4 Column("MODIFIED_DATABASE_PAGES", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PENDING_ZIP 6 +#define IDX_BUF_STATS_PENDING_ZIP 5 Column("PENDING_DECOMPRESS", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PENDING_READ 7 +#define IDX_BUF_STATS_PENDING_READ 6 Column("PENDING_READS",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_FLUSH_LRU 8 +#define IDX_BUF_STATS_FLUSH_LRU 7 Column("PENDING_FLUSH_LRU",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_FLUSH_LIST 9 +#define IDX_BUF_STATS_FLUSH_LIST 8 Column("PENDING_FLUSH_LIST", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PAGE_YOUNG 10 +#define IDX_BUF_STATS_PAGE_YOUNG 9 Column("PAGES_MADE_YOUNG",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PAGE_NOT_YOUNG 11 +#define IDX_BUF_STATS_PAGE_NOT_YOUNG 10 Column("PAGES_NOT_MADE_YOUNG",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PAGE_YOUNG_RATE 12 +#define IDX_BUF_STATS_PAGE_YOUNG_RATE 11 Column("PAGES_MADE_YOUNG_RATE", Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13 +#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 12 Column("PAGES_MADE_NOT_YOUNG_RATE", Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_PAGE_READ 14 +#define IDX_BUF_STATS_PAGE_READ 13 Column("NUMBER_PAGES_READ",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PAGE_CREATED 15 +#define IDX_BUF_STATS_PAGE_CREATED 14 Column("NUMBER_PAGES_CREATED",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PAGE_WRITTEN 16 +#define IDX_BUF_STATS_PAGE_WRITTEN 15 Column("NUMBER_PAGES_WRITTEN",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_PAGE_READ_RATE 17 +#define IDX_BUF_STATS_PAGE_READ_RATE 16 Column("PAGES_READ_RATE", Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_PAGE_CREATE_RATE 18 +#define IDX_BUF_STATS_PAGE_CREATE_RATE 17 Column("PAGES_CREATE_RATE", Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19 +#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 18 Column("PAGES_WRITTEN_RATE",Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_GET 20 +#define IDX_BUF_STATS_GET 19 Column("NUMBER_PAGES_GET", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_HIT_RATE 21 +#define IDX_BUF_STATS_HIT_RATE 20 Column("HIT_RATE", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_MADE_YOUNG_PCT 22 +#define IDX_BUF_STATS_MADE_YOUNG_PCT 21 Column("YOUNG_MAKE_PER_THOUSAND_GETS", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23 +#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 22 Column("NOT_YOUNG_MAKE_PER_THOUSAND_GETS", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_READ_AHREAD 24 +#define IDX_BUF_STATS_READ_AHREAD 23 Column("NUMBER_PAGES_READ_AHEAD", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_READ_AHEAD_EVICTED 25 +#define IDX_BUF_STATS_READ_AHEAD_EVICTED 24 Column("NUMBER_READ_AHEAD_EVICTED", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_READ_AHEAD_RATE 26 +#define IDX_BUF_STATS_READ_AHEAD_RATE 25 Column("READ_AHEAD_RATE", Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27 +#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 26 Column("READ_AHEAD_EVICTED_RATE",Float(MAX_FLOAT_STR_LENGTH), NOT_NULL), -#define IDX_BUF_STATS_LRU_IO_SUM 28 +#define IDX_BUF_STATS_LRU_IO_SUM 27 Column("LRU_IO_TOTAL", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_LRU_IO_CUR 29 +#define IDX_BUF_STATS_LRU_IO_CUR 28 Column("LRU_IO_CURRENT", ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_UNZIP_SUM 30 +#define IDX_BUF_STATS_UNZIP_SUM 29 Column("UNCOMPRESS_TOTAL",ULonglong(), NOT_NULL), -#define IDX_BUF_STATS_UNZIP_CUR 31 +#define IDX_BUF_STATS_UNZIP_CUR 30 Column("UNCOMPRESS_CURRENT", ULonglong(), NOT_NULL), CEnd() }; } // namespace Show -/*******************************************************************//** -Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular -buffer pool +/** Fill INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS +@param[in,out] thd connection +@param[in,out] tables tables to fill @return 0 on success, 1 on failure */ static int -i_s_innodb_stats_fill( -/*==================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - const buf_pool_info_t* info) /*!< in: buffer pool - information */ +i_s_innodb_stats_fill(THD* thd, TABLE_LIST* tables, Item*) { - TABLE* table; - Field** fields; + TABLE* table; + Field** fields; + buf_pool_info_t info; DBUG_ENTER("i_s_innodb_stats_fill"); - table = tables->table; - - fields = table->field; - - OK(fields[IDX_BUF_STATS_POOL_ID]->store( - info->pool_unique_id, true)); - - OK(fields[IDX_BUF_STATS_POOL_SIZE]->store( - info->pool_size, true)); - - OK(fields[IDX_BUF_STATS_LRU_LEN]->store( - info->lru_len, true)); - - OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store( - info->old_lru_len, true)); - - OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store( - info->free_list_len, true)); - - OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store( - info->flush_list_len, true)); - - OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store( - info->n_pend_unzip, true)); - - OK(fields[IDX_BUF_STATS_PENDING_READ]->store( - info->n_pend_reads, true)); - - OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store( - info->n_pending_flush_lru, true)); - - OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store( - info->n_pending_flush_list, true)); - - OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store( - info->n_pages_made_young, true)); - - OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store( - info->n_pages_not_made_young, true)); - - OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store( - info->page_made_young_rate)); - - OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store( - info->page_not_made_young_rate)); - - OK(fields[IDX_BUF_STATS_PAGE_READ]->store( - info->n_pages_read, true)); - - OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store( - info->n_pages_created, true)); - - OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store( - info->n_pages_written, true)); - - OK(fields[IDX_BUF_STATS_GET]->store( - info->n_page_gets, true)); - - OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store( - info->pages_read_rate)); - - OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store( - info->pages_created_rate)); - - OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store( - info->pages_written_rate)); - - if (info->n_page_get_delta) { - if (info->page_read_delta <= info->n_page_get_delta) { - OK(fields[IDX_BUF_STATS_HIT_RATE]->store( - static_cast( - 1000 - (1000 * info->page_read_delta - / info->n_page_get_delta)))); - } else { - OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0)); - } - - OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store( - 1000 * info->young_making_delta - / info->n_page_get_delta, true)); - - OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store( - 1000 * info->not_young_making_delta - / info->n_page_get_delta, true)); - } else { - OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0, true)); - OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0, true)); - OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0, true)); - } - - OK(fields[IDX_BUF_STATS_READ_AHREAD]->store( - info->n_ra_pages_read, true)); - - OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store( - info->n_ra_pages_evicted, true)); - - OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store( - info->pages_readahead_rate)); - - OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store( - info->pages_evicted_rate)); - - OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store( - info->io_sum, true)); - - OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store( - info->io_cur, true)); - - OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store( - info->unzip_sum, true)); - - OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( - info->unzip_cur, true)); - - DBUG_RETURN(schema_table_store_record(thd, table)); -} - -/*******************************************************************//** -This is the function that loops through each buffer pool and fetch buffer -pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS -@return 0 on success, 1 on failure */ -static -int -i_s_innodb_buffer_stats_fill_table( -/*===============================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (ignored) */ -{ - int status = 0; - buf_pool_info_t* pool_info; - - DBUG_ENTER("i_s_innodb_buffer_fill_general"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); /* Only allow the PROCESS privilege holder to access the stats */ @@ -3817,29 +3660,109 @@ i_s_innodb_buffer_stats_fill_table( DBUG_RETURN(0); } - pool_info = (buf_pool_info_t*) ut_zalloc_nokey( - srv_buf_pool_instances * sizeof *pool_info); + buf_stats_get_pool_info(&info); - /* Walk through each buffer pool */ - for (uint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; + table = tables->table; - buf_pool = buf_pool_from_array(i); + fields = table->field; - /* Fetch individual buffer pool info */ - buf_stats_get_pool_info(buf_pool, i, pool_info); + OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info.pool_size, true)); - status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]); + OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info.lru_len, true)); - /* If something goes wrong, break and return */ - if (status) { - break; + OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info.old_lru_len, true)); + + OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store( + info.free_list_len, true)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store( + info.flush_list_len, true)); + + OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info.n_pend_unzip, true)); + + OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info.n_pend_reads, true)); + + OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store( + info.n_pending_flush_lru, true)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store( + info.n_pending_flush_list, true)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store( + info.n_pages_made_young, true)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store( + info.n_pages_not_made_young, true)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store( + info.page_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store( + info.page_not_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info.n_pages_read, true)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store( + info.n_pages_created, true)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store( + info.n_pages_written, true)); + + OK(fields[IDX_BUF_STATS_GET]->store(info.n_page_gets, true)); + + OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store( + info.pages_read_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store( + info.pages_created_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store( + info.pages_written_rate)); + + if (info.n_page_get_delta) { + if (info.page_read_delta <= info.n_page_get_delta) { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store( + static_cast( + 1000 - (1000 * info.page_read_delta + / info.n_page_get_delta)))); + } else { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0)); } + + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store( + 1000 * info.young_making_delta + / info.n_page_get_delta, true)); + + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store( + 1000 * info.not_young_making_delta + / info.n_page_get_delta, true)); + } else { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0, true)); + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0, true)); + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0, true)); } - ut_free(pool_info); + OK(fields[IDX_BUF_STATS_READ_AHREAD]->store( + info.n_ra_pages_read, true)); - DBUG_RETURN(status); + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store( + info.n_ra_pages_evicted, true)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store( + info.pages_readahead_rate)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store( + info.pages_evicted_rate)); + + OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info.io_sum, true)); + + OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info.io_cur, true)); + + OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info.unzip_sum, true)); + + OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store(info.unzip_cur, true)); + + DBUG_RETURN(schema_table_store_record(thd, table)); } /*******************************************************************//** @@ -3858,7 +3781,7 @@ i_s_innodb_buffer_pool_stats_init( schema = reinterpret_cast(p); schema->fields_info = Show::i_s_innodb_buffer_stats_fields_info; - schema->fill_table = i_s_innodb_buffer_stats_fill_table; + schema->fill_table = i_s_innodb_stats_fill; DBUG_RETURN(0); } @@ -3939,66 +3862,63 @@ namespace Show { /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = { -#define IDX_BUFFER_POOL_ID 0 - Column("POOL_ID", ULong(), NOT_NULL), - -#define IDX_BUFFER_BLOCK_ID 1 +#define IDX_BUFFER_BLOCK_ID 0 Column("BLOCK_ID", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_SPACE 2 +#define IDX_BUFFER_PAGE_SPACE 1 Column("SPACE", ULong(), NOT_NULL), -#define IDX_BUFFER_PAGE_NUM 3 +#define IDX_BUFFER_PAGE_NUM 2 Column("PAGE_NUMBER", ULong(), NOT_NULL), -#define IDX_BUFFER_PAGE_TYPE 4 +#define IDX_BUFFER_PAGE_TYPE 3 Column("PAGE_TYPE", Varchar(64), NULLABLE), -#define IDX_BUFFER_PAGE_FLUSH_TYPE 5 +#define IDX_BUFFER_PAGE_FLUSH_TYPE 4 Column("FLUSH_TYPE", ULong(), NOT_NULL), -#define IDX_BUFFER_PAGE_FIX_COUNT 6 +#define IDX_BUFFER_PAGE_FIX_COUNT 5 Column("FIX_COUNT", ULong(), NOT_NULL), #ifdef BTR_CUR_HASH_ADAPT -#define IDX_BUFFER_PAGE_HASHED 7 +#define IDX_BUFFER_PAGE_HASHED 6 Column("IS_HASHED", SLong(1), NOT_NULL), #endif /* BTR_CUR_HASH_ADAPT */ -#define IDX_BUFFER_PAGE_NEWEST_MOD 7 + I_S_AHI +#define IDX_BUFFER_PAGE_NEWEST_MOD 6 + I_S_AHI Column("NEWEST_MODIFICATION", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_OLDEST_MOD 8 + I_S_AHI +#define IDX_BUFFER_PAGE_OLDEST_MOD 7 + I_S_AHI Column("OLDEST_MODIFICATION", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_ACCESS_TIME 9 + I_S_AHI +#define IDX_BUFFER_PAGE_ACCESS_TIME 8 + I_S_AHI Column("ACCESS_TIME", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_TABLE_NAME 10 + I_S_AHI +#define IDX_BUFFER_PAGE_TABLE_NAME 9 + I_S_AHI Column("TABLE_NAME", Varchar(1024), NULLABLE), -#define IDX_BUFFER_PAGE_INDEX_NAME 11 + I_S_AHI +#define IDX_BUFFER_PAGE_INDEX_NAME 10 + I_S_AHI Column("INDEX_NAME", Varchar(NAME_CHAR_LEN), NULLABLE), -#define IDX_BUFFER_PAGE_NUM_RECS 12 + I_S_AHI +#define IDX_BUFFER_PAGE_NUM_RECS 11 + I_S_AHI Column("NUMBER_RECORDS", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_DATA_SIZE 13 + I_S_AHI +#define IDX_BUFFER_PAGE_DATA_SIZE 12 + I_S_AHI Column("DATA_SIZE", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_ZIP_SIZE 14 + I_S_AHI +#define IDX_BUFFER_PAGE_ZIP_SIZE 13 + I_S_AHI Column("COMPRESSED_SIZE", ULonglong(), NOT_NULL), -#define IDX_BUFFER_PAGE_STATE 15 + I_S_AHI +#define IDX_BUFFER_PAGE_STATE 14 + I_S_AHI Column("PAGE_STATE", Enum(&page_state_values_typelib), NOT_NULL, DEFAULT_NONE), -#define IDX_BUFFER_PAGE_IO_FIX 16 + I_S_AHI +#define IDX_BUFFER_PAGE_IO_FIX 15 + I_S_AHI Column("IO_FIX", Enum(&io_values_typelib), NOT_NULL, DEFAULT_NONE), -#define IDX_BUFFER_PAGE_IS_OLD 17 + I_S_AHI +#define IDX_BUFFER_PAGE_IS_OLD 16 + I_S_AHI Column("IS_OLD", SLong(1), NOT_NULL), -#define IDX_BUFFER_PAGE_FREE_CLOCK 18 + I_S_AHI +#define IDX_BUFFER_PAGE_FREE_CLOCK 17 + I_S_AHI Column("FREE_PAGE_CLOCK", ULonglong(), NOT_NULL), CEnd() @@ -4039,9 +3959,6 @@ i_s_innodb_buffer_page_fill( page_info = info_array + i; - OK(fields[IDX_BUFFER_POOL_ID]->store( - page_info->pool_id, true)); - OK(fields[IDX_BUFFER_BLOCK_ID]->store( page_info->block_id, true)); @@ -4226,17 +4143,12 @@ void i_s_innodb_buffer_page_get_info( /*============================*/ const buf_page_t*bpage, /*!< in: buffer pool page to scan */ - ulint pool_id, /*!< in: buffer pool id */ ulint pos, /*!< in: buffer block position in buffer pool or in the LRU list */ buf_page_info_t*page_info) /*!< in: zero filled info structure; out: structure filled with scanned info */ { - ut_ad(pool_id < MAX_BUFFER_POOLS); - - page_info->pool_id = pool_id; - page_info->block_id = pos; page_info->page_state = buf_page_get_state(bpage); @@ -4305,25 +4217,25 @@ i_s_innodb_buffer_page_get_info( /*******************************************************************//** This is the function that goes through each block of the buffer pool and fetch information to information schema tables: INNODB_BUFFER_PAGE. +@param[in,out] thd connection +@param[in,out] tables tables to fill @return 0 on success, 1 on failure */ -static -int -i_s_innodb_fill_buffer_pool( -/*========================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - buf_pool_t* buf_pool, /*!< in: buffer pool to scan */ - const ulint pool_id) /*!< in: buffer pool id */ +static int i_s_innodb_buffer_page_fill(THD *thd, TABLE_LIST *tables, Item *) { int status = 0; mem_heap_t* heap; - DBUG_ENTER("i_s_innodb_fill_buffer_pool"); + DBUG_ENTER("i_s_innodb_buffer_page_fill"); + + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); + + /* deny access to user without PROCESS privilege */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } heap = mem_heap_create(10000); - /* Go through each chunk of buffer pool. Currently, we only - have one single chunk for each buffer pool */ for (ulint n = 0; n < ut_min(buf_pool->n_chunks, buf_pool->n_chunks_new); n++) { const buf_block_t* block; @@ -4336,7 +4248,8 @@ i_s_innodb_fill_buffer_pool( ulint block_id = 0; /* Get buffer block of the nth chunk */ - block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size); + block = buf_pool->chunks[n].blocks; + chunk_size = buf_pool->chunks[n].size; num_page = 0; while (chunk_size > 0) { @@ -4357,18 +4270,18 @@ i_s_innodb_fill_buffer_pool( buffer pool info printout, we are not required to preserve the overall consistency, so we can release mutex periodically */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); /* GO through each block in the chunk */ for (n_blocks = num_to_process; n_blocks--; block++) { i_s_innodb_buffer_page_get_info( - &block->page, pool_id, block_id, + &block->page, block_id, info_buffer + num_page); block_id++; num_page++; } - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); /* Fill in information schema table with information just collected from the buffer chunk scan */ @@ -4392,48 +4305,6 @@ i_s_innodb_fill_buffer_pool( DBUG_RETURN(status); } -/*******************************************************************//** -Fill page information for pages in InnoDB buffer pool to the -dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -@return 0 on success, 1 on failure */ -static -int -i_s_innodb_buffer_page_fill_table( -/*==============================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (ignored) */ -{ - int status = 0; - - DBUG_ENTER("i_s_innodb_buffer_page_fill_table"); - - RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); - - /* deny access to user without PROCESS privilege */ - if (check_global_access(thd, PROCESS_ACL)) { - DBUG_RETURN(0); - } - - /* Walk through each buffer pool */ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - /* Fetch information from pages in this buffer pool, - and fill the corresponding I_S table */ - status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i); - - /* If something wrong, break and return */ - if (status) { - break; - } - } - - DBUG_RETURN(status); -} - /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE. @return 0 on success, 1 on failure */ @@ -4450,7 +4321,7 @@ i_s_innodb_buffer_page_init( schema = reinterpret_cast(p); schema->fields_info = Show::i_s_innodb_buffer_page_fields_info; - schema->fill_table = i_s_innodb_buffer_page_fill_table; + schema->fill_table = i_s_innodb_buffer_page_fill; DBUG_RETURN(0); } @@ -4507,66 +4378,63 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page = namespace Show { static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = { -#define IDX_BUF_LRU_POOL_ID 0 - Column("POOL_ID", ULong(), NOT_NULL), - -#define IDX_BUF_LRU_POS 1 +#define IDX_BUF_LRU_POS 0 Column("LRU_POSITION", ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_SPACE 2 +#define IDX_BUF_LRU_PAGE_SPACE 1 Column("SPACE", ULong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_NUM 3 +#define IDX_BUF_LRU_PAGE_NUM 2 Column("PAGE_NUMBER", ULong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_TYPE 4 +#define IDX_BUF_LRU_PAGE_TYPE 3 Column("PAGE_TYPE", Varchar(64), NULLABLE), -#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5 +#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 4 Column("FLUSH_TYPE", ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_FIX_COUNT 6 +#define IDX_BUF_LRU_PAGE_FIX_COUNT 5 Column("FIX_COUNT", ULong(), NOT_NULL), #ifdef BTR_CUR_HASH_ADAPT -#define IDX_BUF_LRU_PAGE_HASHED 7 +#define IDX_BUF_LRU_PAGE_HASHED 6 Column("IS_HASHED", SLong(1), NOT_NULL), #endif /* BTR_CUR_HASH_ADAPT */ -#define IDX_BUF_LRU_PAGE_NEWEST_MOD 7 + I_S_AHI +#define IDX_BUF_LRU_PAGE_NEWEST_MOD 6 + I_S_AHI Column("NEWEST_MODIFICATION",ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_OLDEST_MOD 8 + I_S_AHI +#define IDX_BUF_LRU_PAGE_OLDEST_MOD 7 + I_S_AHI Column("OLDEST_MODIFICATION",ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_ACCESS_TIME 9 + I_S_AHI +#define IDX_BUF_LRU_PAGE_ACCESS_TIME 8 + I_S_AHI Column("ACCESS_TIME",ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_TABLE_NAME 10 + I_S_AHI +#define IDX_BUF_LRU_PAGE_TABLE_NAME 9 + I_S_AHI Column("TABLE_NAME", Varchar(1024), NULLABLE), -#define IDX_BUF_LRU_PAGE_INDEX_NAME 11 + I_S_AHI +#define IDX_BUF_LRU_PAGE_INDEX_NAME 10 + I_S_AHI Column("INDEX_NAME", Varchar(NAME_CHAR_LEN), NULLABLE), -#define IDX_BUF_LRU_PAGE_NUM_RECS 12 + I_S_AHI +#define IDX_BUF_LRU_PAGE_NUM_RECS 11 + I_S_AHI Column("NUMBER_RECORDS", ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_DATA_SIZE 13 + I_S_AHI +#define IDX_BUF_LRU_PAGE_DATA_SIZE 12 + I_S_AHI Column("DATA_SIZE", ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_ZIP_SIZE 14 + I_S_AHI +#define IDX_BUF_LRU_PAGE_ZIP_SIZE 13 + I_S_AHI Column("COMPRESSED_SIZE",ULonglong(), NOT_NULL), -#define IDX_BUF_LRU_PAGE_STATE 15 + I_S_AHI +#define IDX_BUF_LRU_PAGE_STATE 14 + I_S_AHI Column("COMPRESSED", SLong(1), NOT_NULL), -#define IDX_BUF_LRU_PAGE_IO_FIX 16 + I_S_AHI +#define IDX_BUF_LRU_PAGE_IO_FIX 15 + I_S_AHI Column("IO_FIX", Enum(&io_values_typelib), NOT_NULL, DEFAULT_NONE), -#define IDX_BUF_LRU_PAGE_IS_OLD 17 + I_S_AHI +#define IDX_BUF_LRU_PAGE_IS_OLD 16 + I_S_AHI Column("IS_OLD", SLong(1), NULLABLE), -#define IDX_BUF_LRU_PAGE_FREE_CLOCK 18 + I_S_AHI +#define IDX_BUF_LRU_PAGE_FREE_CLOCK 17 + I_S_AHI Column("FREE_PAGE_CLOCK", ULonglong(), NOT_NULL), CEnd() @@ -4601,9 +4469,6 @@ i_s_innodb_buf_page_lru_fill( page_info = info_array + i; - OK(fields[IDX_BUF_LRU_POOL_ID]->store( - page_info->pool_id, true)); - OK(fields[IDX_BUF_LRU_POS]->store( page_info->block_id, true)); @@ -4713,18 +4578,13 @@ i_s_innodb_buf_page_lru_fill( DBUG_RETURN(0); } -/*******************************************************************//** -This is the function that goes through buffer pool's LRU list -and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +/** Fill the table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@param[in] thd thread +@param[in,out] tables tables to fill @return 0 on success, 1 on failure */ static int -i_s_innodb_fill_buffer_lru( -/*=======================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - buf_pool_t* buf_pool, /*!< in: buffer pool to scan */ - const ulint pool_id) /*!< in: buffer pool id */ +i_s_innodb_fill_buffer_lru(THD *thd, TABLE_LIST *tables, Item*) { int status = 0; buf_page_info_t* info_buffer; @@ -4734,9 +4594,16 @@ i_s_innodb_fill_buffer_lru( DBUG_ENTER("i_s_innodb_fill_buffer_lru"); - /* Obtain buf_pool mutex before allocate info_buffer, since + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); + + /* deny access to any users that do not hold PROCESS_ACL */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Aquire the mutex before allocating info_buffer, since UT_LIST_GET_LEN(buf_pool->LRU) could change */ - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); lru_len = UT_LIST_GET_LEN(buf_pool->LRU); @@ -4762,7 +4629,7 @@ i_s_innodb_fill_buffer_lru( while (bpage != NULL) { /* Use the same function that collect buffer info for INNODB_BUFFER_PAGE to get buffer page info */ - i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos, + i_s_innodb_buffer_page_get_info(bpage, lru_pos, (info_buffer + lru_pos)); bpage = UT_LIST_GET_PREV(LRU, bpage); @@ -4774,7 +4641,7 @@ i_s_innodb_fill_buffer_lru( ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU)); exit: - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); if (info_buffer) { status = i_s_innodb_buf_page_lru_fill( @@ -4786,48 +4653,6 @@ exit: DBUG_RETURN(status); } -/*******************************************************************//** -Fill page information for pages in InnoDB buffer pool to the -dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU -@return 0 on success, 1 on failure */ -static -int -i_s_innodb_buf_page_lru_fill_table( -/*===============================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (ignored) */ -{ - int status = 0; - - DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table"); - - RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); - - /* deny access to any users that do not hold PROCESS_ACL */ - if (check_global_access(thd, PROCESS_ACL)) { - DBUG_RETURN(0); - } - - /* Walk through each buffer pool */ - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - - /* Fetch information from pages in this buffer pool's LRU list, - and fill the corresponding I_S table */ - status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i); - - /* If something wrong, break and return */ - if (status) { - break; - } - } - - DBUG_RETURN(status); -} - /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. @return 0 on success, 1 on failure */ @@ -4844,7 +4669,7 @@ i_s_innodb_buffer_page_lru_init( schema = reinterpret_cast(p); schema->fields_info = Show::i_s_innodb_buf_page_lru_fields_info; - schema->fill_table = i_s_innodb_buf_page_lru_fill_table; + schema->fill_table = i_s_innodb_fill_buffer_lru; DBUG_RETURN(0); } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 7ad543297c8..69835746add 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -3367,7 +3367,7 @@ fail_exit: /* We check if the index page is suitable for buffered entries */ - if (buf_page_peek(page_id) + if (buf_page_hash_get(page_id) || lock_rec_expl_exist_on_page(page_id.space(), page_id.page_no())) { @@ -3610,20 +3610,14 @@ check_watch: that the issuer of IBUF_OP_DELETE has called buf_pool_watch_set(space, page_no). */ - { - buf_pool_t* buf_pool = buf_pool_get(page_id); - buf_page_t* bpage - = buf_page_get_also_watch(buf_pool, page_id); - - if (bpage != NULL) { - /* A buffer pool watch has been set or the - page has been read into the buffer pool. - Do not buffer the request. If a purge operation - is being buffered, have this request executed - directly on the page in the buffer pool after the - buffered entries for this page have been merged. */ - DBUG_RETURN(false); - } + if (buf_page_get_also_watch(page_id)) { + /* A buffer pool watch has been set or the + page has been read into the buffer pool. + Do not buffer the request. If a purge operation + is being buffered, have this request executed + directly on the page in the buffer pool after the + buffered entries for this page have been merged. */ + DBUG_RETURN(false); } skip_watch: diff --git a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h index 5119a1c58c4..117e1cb8736 100644 --- a/storage/innobase/include/buf0buddy.h +++ b/storage/innobase/include/buf0buddy.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -28,60 +29,66 @@ Created December 2006 by Marko Makela #include "buf0types.h" -/**********************************************************************//** -Allocate a block. The thread calling this function must hold -buf_pool->mutex and must not hold buf_pool->zip_mutex or any -block->mutex. The buf_pool->mutex may be released and reacquired. -This function should only be used for allocating compressed page frames. +/** +@param[in] block size in bytes +@return index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ +inline +ulint +buf_buddy_get_slot(ulint size) +{ + ulint i; + ulint s; + + ut_ad(ut_is_2pow(size)); + ut_ad(size >= UNIV_ZIP_SIZE_MIN); + ut_ad(size <= srv_page_size); + + for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) { + } + ut_ad(i <= BUF_BUDDY_SIZES); + return i; +} + +/** Allocate a ROW_FORMAT=COMPRESSED block. +@param[in] i index of buf_pool->zip_free[] or BUF_BUDDY_SIZES +@param[out] lru whether buf_pool->mutex was temporarily released @return allocated block, never NULL */ -UNIV_INLINE -byte* -buf_buddy_alloc( -/*============*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool in which - the page resides */ - ulint size, /*!< in: compressed page size - (between UNIV_ZIP_SIZE_MIN and - srv_page_size) */ - bool* lru) /*!< in: pointer to a variable - that will be assigned true if - storage was allocated from the - LRU list and buf_pool->mutex was - temporarily released */ - MY_ATTRIBUTE((malloc, nonnull)); +byte *buf_buddy_alloc_low(ulint i, bool *lru) MY_ATTRIBUTE((malloc)); -/**********************************************************************//** -Deallocate a block. */ -UNIV_INLINE -void -buf_buddy_free( -/*===========*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool in which - the block resides */ - void* buf, /*!< in: block to be freed, must not - be pointed to by the buffer pool */ - ulint size) /*!< in: block size, - up to srv_page_size */ - MY_ATTRIBUTE((nonnull)); +/** Allocate a ROW_FORMAT=COMPRESSED block. +The caller must not hold buf_pool->mutex nor buf_pool->zip_mutex nor any +block->mutex. +@param[in] size compressed page size +@param[out] lru whether buf_pool->mutex was temporarily released +@return allocated block, never NULL */ +inline byte *buf_buddy_alloc(ulint size, bool *lru= nullptr) +{ + return buf_buddy_alloc_low(buf_buddy_get_slot(size), lru); +} -/** Reallocate a block. -@param[in] buf_pool buffer pool instance +/** Deallocate a block. +@param[in] buf block to be freed, must not be pointed to + by the buffer pool +@param[in] i index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ +void buf_buddy_free_low(void* buf, ulint i); + +/** Deallocate a block. +@param[in] buf block to be freed, must not be pointed to + by the buffer pool +@param[in] size block size in bytes */ +inline void buf_buddy_free(void* buf, ulint size) +{ + buf_buddy_free_low(buf, buf_buddy_get_slot(size)); +} + +/** Try to reallocate a block. @param[in] buf block to be reallocated, must be pointed to by the buffer pool @param[in] size block size, up to srv_page_size @retval false if failed because of no free blocks. */ -bool -buf_buddy_realloc( - buf_pool_t* buf_pool, - void* buf, - ulint size); +bool buf_buddy_realloc(void* buf, ulint size); -/** Combine all pairs of free buddies. -@param[in] buf_pool buffer pool instance */ -void -buf_buddy_condense_free( - buf_pool_t* buf_pool); - -#include "buf0buddy.ic" +/** Combine all pairs of free buddies. */ +void buf_buddy_condense_free(); #endif /* buf0buddy_h */ diff --git a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf0buddy.ic deleted file mode 100644 index 39ab46d80dd..00000000000 --- a/storage/innobase/include/buf0buddy.ic +++ /dev/null @@ -1,129 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/buf0buddy.ic -Binary buddy allocator for compressed pages - -Created December 2006 by Marko Makela -*******************************************************/ - -#include "buf0buf.h" -#include "buf0buddy.h" - -/**********************************************************************//** -Allocate a block. The thread calling this function must hold -buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex. -The buf_pool_mutex may be released and reacquired. -@return allocated block, never NULL */ -void* -buf_buddy_alloc_low( -/*================*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ - ulint i, /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ - bool* lru) /*!< in: pointer to a variable that - will be assigned true if storage was - allocated from the LRU list and - buf_pool->mutex was temporarily - released */ - MY_ATTRIBUTE((malloc, nonnull)); - -/**********************************************************************//** -Deallocate a block. */ -void -buf_buddy_free_low( -/*===============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* buf, /*!< in: block to be freed, must not be - pointed to by the buffer pool */ - ulint i) /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ - MY_ATTRIBUTE((nonnull)); - -/**********************************************************************//** -Get the index of buf_pool->zip_free[] for a given block size. -@return index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ -UNIV_INLINE -ulint -buf_buddy_get_slot( -/*===============*/ - ulint size) /*!< in: block size */ -{ - ulint i; - ulint s; - - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - - for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) { - } - - ut_ad(i <= BUF_BUDDY_SIZES); - return(i); -} - -/**********************************************************************//** -Allocate a block. The thread calling this function must hold -buf_pool->mutex and must not hold buf_pool->zip_mutex or any -block->mutex. The buf_pool->mutex may be released and reacquired. -This function should only be used for allocating compressed page frames. -@return allocated block, never NULL */ -UNIV_INLINE -byte* -buf_buddy_alloc( -/*============*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool in which - the page resides */ - ulint size, /*!< in: compressed page size - (between UNIV_ZIP_SIZE_MIN and - srv_page_size) */ - bool* lru) /*!< in: pointer to a variable - that will be assigned true if - storage was allocated from the - LRU list and buf_pool->mutex was - temporarily released */ -{ - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(ut_is_2pow(size)); - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - ut_ad(size <= srv_page_size); - - return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), - lru)); -} - -/**********************************************************************//** -Deallocate a block. */ -UNIV_INLINE -void -buf_buddy_free( -/*===========*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool in which - the block resides */ - void* buf, /*!< in: block to be freed, must not - be pointed to by the buffer pool */ - ulint size) /*!< in: block size, - up to srv_page_size */ -{ - ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(ut_is_2pow(size)); - ut_ad(size >= UNIV_ZIP_SIZE_MIN); - ut_ad(size <= srv_page_size); - - buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size)); -} diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index e5ea24a166f..3432ef12df9 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -68,20 +68,13 @@ struct fil_addr_t; #define BUF_EVICT_IF_IN_POOL 20 /*!< evict a clean block if found */ /* @} */ -#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing - a buffer pool ID */ - -#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS) - /*!< The maximum number of buffer - pools that can be defined */ - #define BUF_POOL_WATCH_SIZE (srv_n_purge_threads + 1) /*!< Maximum number of concurrent buffer pool watches */ #define MAX_PAGE_HASH_LOCKS 1024 /*!< The maximum number of page_hash locks */ -extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools +extern buf_pool_t* buf_pool; /*!< The buffer pools of the database */ extern volatile bool buf_pool_withdrawing; /*!< true when withdrawing buffer @@ -124,9 +117,9 @@ enum buf_page_state { /** This structure defines information we will fetch from each buffer pool. It will be used to print table IO stats */ -struct buf_pool_info_t{ +struct buf_pool_info_t +{ /* General buffer pool info */ - uint pool_unique_id; /*!< Buffer Pool ID */ ulint pool_size; /*!< Buffer Pool size in pages */ ulint lru_len; /*!< Length of buf_pool->LRU */ ulint old_lru_len; /*!< buf_pool->LRU_old_len */ @@ -194,13 +187,6 @@ struct buf_pool_info_t{ pages decompressed in current interval */ }; - -/** The occupied bytes of lists in all buffer pools */ -struct buf_pools_list_size_t { - ulint LRU_bytes; /*!< LRU size in bytes */ - ulint unzip_LRU_bytes; /*!< unzip_LRU size in bytes */ - ulint flush_list_bytes; /*!< flush_list size in bytes */ -}; #endif /* !UNIV_INNOCHECKSUM */ /** Print the given page_id_t object. @@ -213,58 +199,26 @@ operator<<( const page_id_t page_id); #ifndef UNIV_INNOCHECKSUM -/********************************************************************//** -Acquire mutex on all buffer pool instances */ -UNIV_INLINE -void -buf_pool_mutex_enter_all(void); -/*===========================*/ - -/********************************************************************//** -Release mutex on all buffer pool instances */ -UNIV_INLINE -void -buf_pool_mutex_exit_all(void); -/*==========================*/ - -/********************************************************************//** -Creates the buffer pool. -@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */ -dberr_t -buf_pool_init( -/*=========*/ - ulint size, /*!< in: Size of the total pool in bytes */ - ulint n_instances); /*!< in: Number of instances */ -/********************************************************************//** -Frees the buffer pool at shutdown. This must not be invoked before -freeing all mutexes. */ -void -buf_pool_free( -/*==========*/ - ulint n_instances); /*!< in: numbere of instances to free */ +/** Create the buffer pool. +@return whether the creation failed */ +bool buf_pool_init(); +/** Free the buffer pool at shutdown. +This must not be invoked before freeing all mutexes. */ +void buf_pool_free(); /** Determines if a block is intended to be withdrawn. -@param[in] buf_pool buffer pool instance @param[in] block pointer to control block @retval true if will be withdrawn */ -bool -buf_block_will_withdrawn( - buf_pool_t* buf_pool, - const buf_block_t* block); +bool buf_block_will_be_withdrawn(const buf_block_t* block); /** Determines if a frame is intended to be withdrawn. -@param[in] buf_pool buffer pool instance @param[in] ptr pointer to a frame @retval true if will be withdrawn */ -bool -buf_frame_will_withdrawn( - buf_pool_t* buf_pool, - const byte* ptr); +bool buf_frame_will_be_withdrawn(const byte* ptr); #ifdef BTR_CUR_HASH_ADAPT /** Clear the adaptive hash index on all pages in the buffer pool. */ -void -buf_pool_clear_hash_index(); +void buf_pool_clear_hash_index(); #endif /* BTR_CUR_HASH_ADAPT */ /*********************************************************************//** @@ -281,13 +235,11 @@ UNIV_INLINE ulint buf_pool_get_n_pages(void); /*=======================*/ -/********************************************************************//** -Gets the smallest oldest_modification lsn for any page in the pool. Returns -zero if all modified pages have been flushed to disk. -@return oldest modification in pool, zero if none */ +/** +@return the smallest oldest_modification lsn for any page. +@retval 0 if all modified persistent pages have been flushed */ lsn_t -buf_pool_get_oldest_modification(void); -/*==================================*/ +buf_pool_get_oldest_modification(); /********************************************************************//** Allocates a buf_page_t descriptor. This function must succeed. In case @@ -306,15 +258,10 @@ buf_page_free_descriptor( buf_page_t* bpage) /*!< in: bpage descriptor to free. */ MY_ATTRIBUTE((nonnull)); -/********************************************************************//** -Allocates a buffer block. +/** Allocate a buffer block. @return own: the allocated block, in state BUF_BLOCK_MEMORY */ buf_block_t* -buf_block_alloc( -/*============*/ - buf_pool_t* buf_pool); /*!< in: buffer pool instance, - or NULL for round-robin selection - of the buffer pool */ +buf_block_alloc(); /********************************************************************//** Frees a buffer block which does not contain a file page. */ UNIV_INLINE @@ -455,15 +402,7 @@ buf_page_make_young( /*================*/ buf_page_t* bpage); /*!< in: buffer block of a file page */ -/** Returns TRUE if the page can be found in the buffer pool hash table. -NOTE that it is possible that the page is not yet read from disk, -though. -@param[in] page_id page id -@return TRUE if found in the page hash table */ -inline bool buf_page_peek(const page_id_t page_id); - #ifdef UNIV_DEBUG - /** Sets file_page_was_freed TRUE if the page is found in the buffer pool. This function should be called when we free a file page and want the debug version to check that it is not accessed any more unless @@ -505,27 +444,21 @@ meaning that it is not in danger of getting evicted and also implying that it has been accessed recently. Note that this is for heuristics only and does not reserve buffer pool mutex. -@param[in] buf_pool buffer pool @param[in] bpage buffer pool page @return whether bpage is close to MRU end of LRU */ -inline bool buf_page_peek_if_young(const buf_pool_t* buf_pool, - const buf_page_t* bpage); +inline bool buf_page_peek_if_young(const buf_page_t *bpage); /** Determine if a block should be moved to the start of the LRU list if there is danger of dropping from the buffer pool. -@param[in,out] buf_pool buffer pool @param[in] bpage buffer pool page @return true if bpage should be made younger */ -inline bool buf_page_peek_if_too_old(buf_pool_t* buf_pool, - const buf_page_t* bpage); +inline bool buf_page_peek_if_too_old(const buf_page_t *bpage); /** Move a page to the start of the buffer pool LRU list if it is too old. -@param[in,out] buf_pool buffer pool @param[in,out] bpage buffer pool page */ -inline void buf_page_make_young_if_needed(buf_pool_t* buf_pool, - buf_page_t* bpage) +inline void buf_page_make_young_if_needed(buf_page_t *bpage) { - if (UNIV_UNLIKELY(buf_page_peek_if_too_old(buf_pool, bpage))) { + if (UNIV_UNLIKELY(buf_page_peek_if_too_old(bpage))) { buf_page_make_young(bpage); } } @@ -720,15 +653,11 @@ buf_block_get_lock_hash_val( const buf_block_t* block) /*!< in: block */ MY_ATTRIBUTE((warn_unused_result)); #ifdef UNIV_DEBUG -/*********************************************************************//** -Finds a block in the buffer pool that points to a -given compressed page. -@return buffer block pointing to the compressed page, or NULL */ -buf_block_t* -buf_pool_contains_zip( -/*==================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - const void* data); /*!< in: pointer to compressed page */ +/** Find a block in the buffer pool that points to a given compressed page. +@param[in] data pointer to compressed page +@return buffer block pointing to the compressed page +@retval NULL if not found */ +buf_block_t* buf_pool_contains_zip(const void* data); #endif /* UNIV_DEBUG */ /*********************************************************************** @@ -742,19 +671,12 @@ buf_frame_align( #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/*********************************************************************//** -Validates the buffer pool data structure. -@return TRUE */ -ibool -buf_validate(void); -/*==============*/ +/** Validate the buffer pool. */ +void buf_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/*********************************************************************//** -Prints info of the buffer pool data structure. */ -void -buf_print(void); -/*============*/ +/** Write information of the buf_pool to the error log. */ +void buf_print(); #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ /** Dump a page to stderr. @@ -772,62 +694,32 @@ buf_zip_decompress( ibool check); /*!< in: TRUE=verify the page checksum */ #ifdef UNIV_DEBUG -/*********************************************************************//** -Returns the number of latched pages in the buffer pool. -@return number of latched pages */ -ulint -buf_get_latched_pages_number(void); -/*==============================*/ +/** @return the number of latched pages in the buffer pool */ +ulint buf_get_latched_pages_number(); #endif /* UNIV_DEBUG */ /*********************************************************************//** -Returns the number of pending buf pool read ios. -@return number of pending read I/O operations */ -ulint -buf_get_n_pending_read_ios(void); -/*============================*/ -/*********************************************************************//** Prints info of the buffer i/o. */ void buf_print_io( /*=========*/ FILE* file); /*!< in: file where to print */ -/*******************************************************************//** -Collect buffer pool stats information for a buffer pool. Also -record aggregated stats if there are more than one buffer pool -in the server */ -void -buf_stats_get_pool_info( -/*====================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool */ - uint pool_id, /*!< in: buffer pool ID */ - buf_pool_info_t* all_pool_info); /*!< in/out: buffer pool info - to fill */ -/** Return the ratio in percents of modified pages in the buffer pool / -database pages in the buffer pool. -@return modified page percentage ratio */ -double -buf_get_modified_ratio_pct(void); +/** Collect buffer pool metadata. +@param[out] pool_info buffer pool metadata */ +void buf_stats_get_pool_info(buf_pool_info_t *pool_info); + /** Refresh the statistics used to print per-second averages. */ -void -buf_refresh_io_stats_all(void); -/** Assert that all file pages in the buffer are in a replaceable state. -@return TRUE */ -ibool -buf_all_freed(void); -/*********************************************************************//** -Checks that there currently are no pending i/o-operations for the buffer -pool. -@return number of pending i/o operations */ -ulint -buf_pool_check_no_pending_io(void); -/*==============================*/ -/*********************************************************************//** -Invalidates the file pages in the buffer pool when an archive recovery is -completed. All the file pages buffered must be in a replaceable state when -this function is called: not latched and not modified. */ -void -buf_pool_invalidate(void); -/*=====================*/ +void buf_refresh_io_stats(); + +/** Assert that all buffer pool pages are in a replaceable state */ +void buf_assert_all_freed(); + +/** Check that there currently are no I/O operations pending. +@return number of pending i/o */ +ulint buf_pool_check_no_pending_io(); + +/** Invalidate all pages in the buffer pool. +All pages must be in a replaceable state (not modified or latched). */ +void buf_pool_invalidate(); /*======================================================================== --------------------------- LOWER LEVEL ROUTINES ------------------------- @@ -858,15 +750,6 @@ buf_page_get_state( const buf_page_t* bpage); /*!< in: pointer to the control block */ /*********************************************************************//** -Gets the state name for state of a block -@return name or "CORRUPTED" */ -UNIV_INLINE -const char* -buf_get_state_name( -/*===============*/ - const buf_block_t* block); /*!< in: pointer to the control - block */ -/*********************************************************************//** Gets the state of a block. @return state */ UNIV_INLINE @@ -1090,15 +973,11 @@ buf_block_t* buf_block_from_ahi(const byte* ptr); #endif /* BTR_CUR_HASH_ADAPT */ -/********************************************************************//** -Find out if a pointer belongs to a buf_block_t. It can be a pointer to -the buf_block_t itself or a member of it -@return TRUE if ptr belongs to a buf_block_t struct */ -ibool -buf_pointer_is_block_field( -/*=======================*/ - const void* ptr); /*!< in: pointer not - dereferenced */ +/** Determine if a pointer belongs to a buf_block_t. It can be a pointer to +the buf_block_t itself or a member of it. +@param ptr a pointer that will not be dereferenced +@return whether the ptr belongs to a buf_block_t struct */ +bool buf_pointer_is_block_field(const void* ptr); /** Find out if a pointer corresponds to a buf_block_t::mutex. @param m in: mutex candidate @return TRUE if m is a buf_block_t::mutex */ @@ -1152,56 +1031,10 @@ buf_page_io_complete( bool evict = false) MY_ATTRIBUTE((nonnull)); -/********************************************************************//** -Calculates the index of a buffer pool to the buf_pool[] array. -@return the position of the buffer pool in buf_pool[] */ -UNIV_INLINE -unsigned -buf_pool_index( -/*===========*/ - const buf_pool_t* buf_pool) /*!< in: buffer pool */ - MY_ATTRIBUTE((warn_unused_result)); -/******************************************************************//** -Returns the buffer pool instance given a page instance -@return buf_pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_bpage( -/*================*/ - const buf_page_t* bpage); /*!< in: buffer pool page */ -/******************************************************************//** -Returns the buffer pool instance given a block instance -@return buf_pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_block( -/*================*/ - const buf_block_t* block); /*!< in: block */ - -/** Returns the buffer pool instance given a page id. -@param[in] page_id page id -@return buffer pool */ -inline buf_pool_t* buf_pool_get(const page_id_t page_id); - -/******************************************************************//** -Returns the buffer pool instance given its array index -@return buffer pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_array( -/*================*/ - ulint index); /*!< in: array index to get - buffer pool instance from */ - /** Returns the control block of a file page, NULL if not found. -@param[in] buf_pool buffer pool instance @param[in] page_id page id @return block, NULL if not found */ -UNIV_INLINE -buf_page_t* -buf_page_hash_get_low( - buf_pool_t* buf_pool, - const page_id_t page_id); +inline buf_page_t *buf_page_hash_get_low(const page_id_t page_id); /** Returns the control block of a file page, NULL if not found. If the block is found and lock is not NULL then the appropriate @@ -1209,7 +1042,6 @@ page_hash lock is acquired in the specified lock mode. Otherwise, mode value is ignored. It is up to the caller to release the lock. If the block is found and the lock is NULL then the page_hash lock is released by this function. -@param[in] buf_pool buffer pool instance @param[in] page_id page id @param[in,out] lock lock of the page hash acquired if bpage is found, NULL otherwise. If NULL is passed then the hash_lock is released by @@ -1222,7 +1054,6 @@ a watch sentinel. */ UNIV_INLINE buf_page_t* buf_page_hash_get_locked( - buf_pool_t* buf_pool, const page_id_t page_id, rw_lock_t** lock, ulint lock_mode, @@ -1234,7 +1065,6 @@ page_hash lock is acquired in the specified lock mode. Otherwise, mode value is ignored. It is up to the caller to release the lock. If the block is found and the lock is NULL then the page_hash lock is released by this function. -@param[in] buf_pool buffer pool instance @param[in] page_id page id @param[in,out] lock lock of the page hash acquired if bpage is found, NULL otherwise. If NULL is passed then the hash_lock is released by @@ -1245,7 +1075,6 @@ lock == NULL UNIV_INLINE buf_block_t* buf_block_hash_get_locked( - buf_pool_t* buf_pool, const page_id_t page_id, rw_lock_t** lock, ulint lock_mode); @@ -1257,30 +1086,26 @@ buf_page_hash_get_low() function. 2) Caller wants to hold page hash lock in x-mode 3) Caller wants to hold page hash lock in s-mode 4) Caller doesn't want to hold page hash lock */ -#define buf_page_hash_get_s_locked(b, page_id, l) \ - buf_page_hash_get_locked(b, page_id, l, RW_LOCK_S) -#define buf_page_hash_get_x_locked(b, page_id, l) \ - buf_page_hash_get_locked(b, page_id, l, RW_LOCK_X) -#define buf_page_hash_get(b, page_id) \ - buf_page_hash_get_locked(b, page_id, NULL, 0) -#define buf_page_get_also_watch(b, page_id) \ - buf_page_hash_get_locked(b, page_id, NULL, 0, true) +#define buf_page_hash_get_s_locked(page_id, l) \ + buf_page_hash_get_locked(page_id, l, RW_LOCK_S) +#define buf_page_hash_get_x_locked(page_id, l) \ + buf_page_hash_get_locked(page_id, l, RW_LOCK_X) +#define buf_page_hash_get(page_id) \ + buf_page_hash_get_locked(page_id, NULL, 0) +#define buf_page_get_also_watch(page_id) \ + buf_page_hash_get_locked(page_id, NULL, 0, true) -#define buf_block_hash_get_s_locked(b, page_id, l) \ - buf_block_hash_get_locked(b, page_id, l, RW_LOCK_S) -#define buf_block_hash_get_x_locked(b, page_id, l) \ - buf_block_hash_get_locked(b, page_id, l, RW_LOCK_X) -#define buf_block_hash_get(b, page_id) \ - buf_block_hash_get_locked(b, page_id, NULL, 0) +#define buf_block_hash_get_s_locked(page_id, l) \ + buf_block_hash_get_locked(page_id, l, RW_LOCK_S) +#define buf_block_hash_get_x_locked(page_id, l) \ + buf_block_hash_get_locked(page_id, l, RW_LOCK_X) +#define buf_block_hash_get(page_id) \ + buf_block_hash_get_locked(page_id, NULL, 0) -/********************************************************************//** -Determine if a block is a sentinel for a buffer pool watch. -@return TRUE if a sentinel for a buffer pool watch, FALSE if not */ -ibool -buf_pool_watch_is_sentinel( -/*=======================*/ - const buf_pool_t* buf_pool, /*!< buffer pool instance */ - const buf_page_t* bpage) /*!< in: block */ +/** Determine if a block is a sentinel for a buffer pool watch. +@param[in] bpage block +@return whether bpage a sentinel for a buffer pool watch */ +bool buf_pool_watch_is_sentinel(const buf_page_t* bpage) MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Stop watching if the page has been read in. @@ -1296,38 +1121,6 @@ has returned NULL and before invoking buf_pool_watch_unset(space,offset). bool buf_pool_watch_occurred(const page_id_t page_id) MY_ATTRIBUTE((warn_unused_result)); -/********************************************************************//** -Get total buffer pool statistics. */ -void -buf_get_total_list_len( -/*===================*/ - ulint* LRU_len, /*!< out: length of all LRU lists */ - ulint* free_len, /*!< out: length of all free lists */ - ulint* flush_list_len);/*!< out: length of all flush lists */ -/********************************************************************//** -Get total list size in bytes from all buffer pools. */ -void -buf_get_total_list_size_in_bytes( -/*=============================*/ - buf_pools_list_size_t* buf_pools_list_size); /*!< out: list sizes - in all buffer pools */ -/********************************************************************//** -Get total buffer pool statistics. */ -void -buf_get_total_stat( -/*===============*/ - buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */ -/*********************************************************************//** -Get the nth chunk's buffer block in the specified buffer pool. -@return the nth chunk's buffer block. */ -UNIV_INLINE -buf_block_t* -buf_get_nth_chunk_block( -/*====================*/ - const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint n, /*!< in: nth chunk in the buffer pool */ - ulint* chunk_size); /*!< in: chunk size */ - /** Verify the possibility that a stored page is not in buffer pool. @param[in] withdraw_clock withdraw clock when stored the page @retval true if the page might be relocated */ @@ -1438,11 +1231,6 @@ public: flushed to disk, this tells the flush_type. @see buf_flush_t */ - unsigned buf_pool_index:6;/*!< index number of the buffer pool - that this block belongs to */ -# if MAX_BUFFER_POOLS > 64 -# error "MAX_BUFFER_POOLS > 64; redefine buf_pool_index:6" -# endif /* @} */ page_zip_des_t zip; /*!< compressed page; zip.data (but not the data it points to) is @@ -1803,19 +1591,16 @@ Compute the hash fold value for blocks in buf_pool->zip_hash. */ inside the buffer pool. A hazard pointer is a buf_page_t pointer which we intend to iterate over next and we want it remain valid even after we release the buffer pool mutex. */ -class HazardPointer { - +class HazardPointer +{ public: /** Constructor - @param buf_pool buffer pool instance @param mutex mutex that is protecting the hp. */ - HazardPointer(const buf_pool_t* buf_pool, const ib_mutex_t* mutex) - : - m_buf_pool(buf_pool) + HazardPointer(const ib_mutex_t* ut_d(mutex)) : #ifdef UNIV_DEBUG - , m_mutex(mutex) -#endif /* UNIV_DEBUG */ - , m_hp() {} + m_mutex(mutex), +#endif + m_hp() {} /** Destructor */ virtual ~HazardPointer() {} @@ -1834,7 +1619,11 @@ public: /** Checks if a bpage is the hp @param bpage buffer block to be compared @return true if it is hp */ - bool is_hp(const buf_page_t* bpage); + bool is_hp(const buf_page_t* bpage) const + { + ut_ad(mutex_own(m_mutex)); + return bpage == m_hp; + } /** Adjust the value of hp. This happens when some other thread working on the same list attempts to @@ -1848,9 +1637,6 @@ protected: HazardPointer(const HazardPointer&); HazardPointer& operator=(const HazardPointer&); - /** Buffer pool instance */ - const buf_pool_t* m_buf_pool; - #ifdef UNIV_DEBUG /** mutex that protects access to the m_hp. */ const ib_mutex_t* m_mutex; @@ -1865,11 +1651,8 @@ class FlushHp: public HazardPointer { public: /** Constructor - @param buf_pool buffer pool instance @param mutex mutex that is protecting the hp. */ - FlushHp(const buf_pool_t* buf_pool, const ib_mutex_t* mutex) - : - HazardPointer(buf_pool, mutex) {} + FlushHp(const ib_mutex_t* mutex) : HazardPointer(mutex) {} /** Destructor */ ~FlushHp() override {} @@ -1886,11 +1669,8 @@ class LRUHp: public HazardPointer { public: /** Constructor - @param buf_pool buffer pool instance @param mutex mutex that is protecting the hp. */ - LRUHp(const buf_pool_t* buf_pool, const ib_mutex_t* mutex) - : - HazardPointer(buf_pool, mutex) {} + LRUHp(const ib_mutex_t* mutex) : HazardPointer(mutex) {} /** Destructor */ ~LRUHp() override {} @@ -1907,23 +1687,19 @@ The idea is that when one thread finishes the scan it leaves the itr in that position and the other thread can start scan from there */ class LRUItr: public LRUHp { - public: /** Constructor - @param buf_pool buffer pool instance @param mutex mutex that is protecting the hp. */ - LRUItr(const buf_pool_t* buf_pool, const ib_mutex_t* mutex) - : - LRUHp(buf_pool, mutex) {} + LRUItr(const ib_mutex_t* mutex) : LRUHp(mutex) {} /** Destructor */ ~LRUItr() override {} - /** Selects from where to start a scan. If we have scanned + /** Select from where to start a scan. If we have scanned too deep into the LRU list it resets the value to the tail of the LRU list. @return buf_page_t from where to start scan. */ - buf_page_t* start(); + inline buf_page_t* start(); }; /** Struct that is embedded in the free zip blocks */ @@ -1985,23 +1761,15 @@ struct buf_buddy_stat_t { ib_uint64_t relocated_usec; }; -/** @brief The buffer pool structure. - -NOTE! The definition appears here only for other modules of this -directory (buf) to see it. Do not use from outside! */ - -struct buf_pool_t{ - +/** The buffer pool */ +struct buf_pool_t +{ /** @name General fields */ /* @{ */ - BufPoolMutex mutex; /*!< Buffer pool mutex of this - instance */ - BufPoolZipMutex zip_mutex; /*!< Zip mutex of this buffer - pool instance, protects compressed + BufPoolMutex mutex; /*!< Buffer pool mutex */ + BufPoolZipMutex zip_mutex; /*!< Zip mutex, protects compressed only pages (of type buf_page_t, not buf_block_t */ - ulint instance_no; /*!< Array index of this buffer - pool instance */ ulint curr_pool_size; /*!< Current pool size in bytes */ ulint LRU_old_ratio; /*!< Reserve this much of the buffer pool for "old" blocks */ @@ -2237,40 +2005,10 @@ struct buf_pool_t{ } io_buf; }; -/** Print the given buf_pool_t object. -@param[in,out] out the output stream -@param[in] buf_pool the buf_pool_t object to be printed -@return the output stream */ -std::ostream& -operator<<( - std::ostream& out, - const buf_pool_t& buf_pool); - -/** @name Accessors for buf_pool->mutex. -Use these instead of accessing buf_pool->mutex directly. */ +/** @name Accessors for buffer pool mutexes +Use these instead of accessing buffer pool mutexes directly. */ /* @{ */ -/** Test if a buffer pool mutex is owned. */ -#define buf_pool_mutex_own(b) mutex_own(&b->mutex) -/** Acquire a buffer pool mutex. */ -#define buf_pool_mutex_enter(b) do { \ - ut_ad(!(b)->zip_mutex.is_owned()); \ - mutex_enter(&(b)->mutex); \ -} while (0) - -/** Test if flush list mutex is owned. */ -#define buf_flush_list_mutex_own(b) mutex_own(&(b)->flush_list_mutex) - -/** Acquire the flush list mutex. */ -#define buf_flush_list_mutex_enter(b) do { \ - mutex_enter(&(b)->flush_list_mutex); \ -} while (0) -/** Release the flush list mutex. */ -# define buf_flush_list_mutex_exit(b) do { \ - mutex_exit(&(b)->flush_list_mutex); \ -} while (0) - - /** Test if block->mutex is owned. */ #define buf_page_mutex_own(b) (b)->mutex.is_owned() @@ -2288,73 +2026,65 @@ Use these instead of accessing buf_pool->mutex directly. */ /** Get appropriate page_hash_lock. */ UNIV_INLINE rw_lock_t* -buf_page_hash_lock_get(const buf_pool_t* buf_pool, const page_id_t& page_id) +buf_page_hash_lock_get(const page_id_t& page_id) { return hash_get_lock(buf_pool->page_hash, page_id.fold()); } /** If not appropriate page_hash_lock, relock until appropriate. */ -# define buf_page_hash_lock_s_confirm(hash_lock, buf_pool, page_id)\ - hash_lock_s_confirm(hash_lock, (buf_pool)->page_hash, (page_id).fold()) +# define buf_page_hash_lock_s_confirm(hash_lock, page_id)\ + hash_lock_s_confirm(hash_lock, buf_pool->page_hash, (page_id).fold()) -# define buf_page_hash_lock_x_confirm(hash_lock, buf_pool, page_id)\ - hash_lock_x_confirm(hash_lock, (buf_pool)->page_hash, (page_id).fold()) +# define buf_page_hash_lock_x_confirm(hash_lock, page_id)\ + hash_lock_x_confirm(hash_lock, buf_pool->page_hash, (page_id).fold()) #ifdef UNIV_DEBUG /** Test if page_hash lock is held in s-mode. */ -# define buf_page_hash_lock_held_s(buf_pool, bpage) \ - rw_lock_own(buf_page_hash_lock_get((buf_pool), (bpage)->id), RW_LOCK_S) +# define buf_page_hash_lock_held_s(bpage) \ + rw_lock_own(buf_page_hash_lock_get((bpage)->id), RW_LOCK_S) /** Test if page_hash lock is held in x-mode. */ -# define buf_page_hash_lock_held_x(buf_pool, bpage) \ - rw_lock_own(buf_page_hash_lock_get((buf_pool), (bpage)->id), RW_LOCK_X) +# define buf_page_hash_lock_held_x(bpage) \ + rw_lock_own(buf_page_hash_lock_get((bpage)->id), RW_LOCK_X) /** Test if page_hash lock is held in x or s-mode. */ -# define buf_page_hash_lock_held_s_or_x(buf_pool, bpage)\ - (buf_page_hash_lock_held_s((buf_pool), (bpage)) \ - || buf_page_hash_lock_held_x((buf_pool), (bpage))) +# define buf_page_hash_lock_held_s_or_x(bpage)\ + (buf_page_hash_lock_held_s(bpage) \ + || buf_page_hash_lock_held_x(bpage)) -# define buf_block_hash_lock_held_s(buf_pool, block) \ - buf_page_hash_lock_held_s((buf_pool), &(block)->page) +# define buf_block_hash_lock_held_s(block) \ + buf_page_hash_lock_held_s(&(block)->page) -# define buf_block_hash_lock_held_x(buf_pool, block) \ - buf_page_hash_lock_held_x((buf_pool), &(block)->page) +# define buf_block_hash_lock_held_x(block) \ + buf_page_hash_lock_held_x(&(block)->page) -# define buf_block_hash_lock_held_s_or_x(buf_pool, block) \ - buf_page_hash_lock_held_s_or_x((buf_pool), &(block)->page) +# define buf_block_hash_lock_held_s_or_x(block) \ + buf_page_hash_lock_held_s_or_x(&(block)->page) #else /* UNIV_DEBUG */ -# define buf_page_hash_lock_held_s(b, p) (TRUE) -# define buf_page_hash_lock_held_x(b, p) (TRUE) -# define buf_page_hash_lock_held_s_or_x(b, p) (TRUE) -# define buf_block_hash_lock_held_s(b, p) (TRUE) -# define buf_block_hash_lock_held_x(b, p) (TRUE) -# define buf_block_hash_lock_held_s_or_x(b, p) (TRUE) +# define buf_page_hash_lock_held_s(p) (TRUE) +# define buf_page_hash_lock_held_x(p) (TRUE) +# define buf_page_hash_lock_held_s_or_x(p) (TRUE) +# define buf_block_hash_lock_held_s(p) (TRUE) +# define buf_block_hash_lock_held_x(p) (TRUE) +# define buf_block_hash_lock_held_s_or_x(p) (TRUE) #endif /* UNIV_DEBUG */ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /** Forbid the release of the buffer pool mutex. */ -# define buf_pool_mutex_exit_forbid(b) do { \ - ut_ad(buf_pool_mutex_own(b)); \ - b->mutex_exit_forbidden++; \ +# define buf_pool_mutex_exit_forbid() do { \ + ut_ad(mutex_own(&buf_pool->mutex)); \ + buf_pool->mutex_exit_forbidden++; \ } while (0) /** Allow the release of the buffer pool mutex. */ -# define buf_pool_mutex_exit_allow(b) do { \ - ut_ad(buf_pool_mutex_own(b)); \ - ut_a(b->mutex_exit_forbidden); \ - b->mutex_exit_forbidden--; \ -} while (0) -/** Release the buffer pool mutex. */ -# define buf_pool_mutex_exit(b) do { \ - ut_a(!b->mutex_exit_forbidden); \ - mutex_exit(&b->mutex); \ +# define buf_pool_mutex_exit_allow() do { \ + ut_ad(mutex_own(&buf_pool->mutex)); \ + ut_ad(buf_pool->mutex_exit_forbidden--); \ } while (0) #else /** Forbid the release of the buffer pool mutex. */ -# define buf_pool_mutex_exit_forbid(b) ((void) 0) +# define buf_pool_mutex_exit_forbid() ((void) 0) /** Allow the release of the buffer pool mutex. */ -# define buf_pool_mutex_exit_allow(b) ((void) 0) -/** Release the buffer pool mutex. */ -# define buf_pool_mutex_exit(b) mutex_exit(&b->mutex) +# define buf_pool_mutex_exit_allow() ((void) 0) #endif /* @} */ @@ -2402,6 +2132,21 @@ FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if (3) io_fix == 0. */ +/** Select from where to start a scan. If we have scanned +too deep into the LRU list it resets the value to the tail +of the LRU list. +@return buf_page_t from where to start scan. */ +inline buf_page_t* LRUItr::start() +{ + ut_ad(mutex_own(m_mutex)); + + if (!m_hp || m_hp->old) { + m_hp = UT_LIST_GET_LAST(buf_pool->LRU); + } + + return(m_hp); +} + #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /** Functor to validate the LRU list. */ struct CheckInLRUList { @@ -2410,7 +2155,7 @@ struct CheckInLRUList { ut_a(elem->in_LRU_list); } - static void validate(const buf_pool_t* buf_pool) + static void validate() { ut_list_validate(buf_pool->LRU, CheckInLRUList()); } @@ -2423,7 +2168,7 @@ struct CheckInFreeList { ut_a(elem->in_free_list); } - static void validate(const buf_pool_t* buf_pool) + static void validate() { ut_list_validate(buf_pool->free, CheckInFreeList()); } @@ -2436,7 +2181,7 @@ struct CheckUnzipLRUAndLRUList { ut_a(elem->in_unzip_LRU_list); } - static void validate(const buf_pool_t* buf_pool) + static void validate() { ut_list_validate(buf_pool->unzip_LRU, CheckUnzipLRUAndLRUList()); diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 501f0ff6e96..cc25ab2c2ca 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -65,64 +65,17 @@ buf_pool_get_curr_size(void) return(srv_buf_pool_curr_size); } -/********************************************************************//** -Calculates the index of a buffer pool to the buf_pool[] array. -@return the position of the buffer pool in buf_pool[] */ -UNIV_INLINE -unsigned -buf_pool_index( -/*===========*/ - const buf_pool_t* buf_pool) /*!< in: buffer pool */ -{ - unsigned i = unsigned(buf_pool - buf_pool_ptr); - ut_ad(i < MAX_BUFFER_POOLS); - ut_ad(i < srv_buf_pool_instances); - return(i); -} - -/******************************************************************//** -Returns the buffer pool instance given a page instance -@return buf_pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_bpage( -/*================*/ - const buf_page_t* bpage) /*!< in: buffer pool page */ -{ - ut_ad(bpage->buf_pool_index < srv_buf_pool_instances); - return(&buf_pool_ptr[bpage->buf_pool_index]); -} - -/******************************************************************//** -Returns the buffer pool instance given a block instance -@return buf_pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_block( -/*================*/ - const buf_block_t* block) /*!< in: block */ -{ - return(buf_pool_from_bpage(&block->page)); -} - /*********************************************************************//** Gets the current size of buffer buf_pool in pages. @return size in pages*/ -UNIV_INLINE -ulint -buf_pool_get_n_pages(void) -/*======================*/ +inline ulint buf_pool_get_n_pages() { - if (!buf_pool_ptr) - return buf_pool_get_curr_size() >> srv_page_size_shift; + if (!buf_pool) + return srv_buf_pool_curr_size >> srv_page_size_shift; ulint chunk_size= 0; - for (uint i= 0; i < srv_buf_pool_instances; i++) - { - buf_pool_t* buf_pool = buf_pool_from_array(i); - for (uint j= 0; j < buf_pool->n_chunks; j++) - chunk_size+= buf_pool->chunks[j].size; - } + for (uint j= 0; j < buf_pool->n_chunks; j++) + chunk_size+= buf_pool->chunks[j].size; return chunk_size; } @@ -154,13 +107,10 @@ buf_block_get_freed_page_clock( /** Determine if a block is still close enough to the MRU end of the LRU list meaning that it is not in danger of getting evicted and also implying that it has been accessed recently. -Note that this is for heuristics only and does not reserve buffer pool -mutex. -@param[in] buf_pool buffer pool +The page must be either buffer-fixed, or its page hash must be locked. @param[in] bpage buffer pool page @return whether bpage is close to MRU end of LRU */ -inline bool buf_page_peek_if_young(const buf_pool_t* buf_pool, - const buf_page_t* bpage) +inline bool buf_page_peek_if_young(const buf_page_t *bpage) { /* FIXME: bpage->freed_page_clock is 31 bits */ return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) @@ -172,15 +122,10 @@ inline bool buf_page_peek_if_young(const buf_pool_t* buf_pool, /** Determine if a block should be moved to the start of the LRU list if there is danger of dropping from the buffer pool. -@param[in,out] buf_pool buffer pool @param[in] bpage buffer pool page @return true if bpage should be made younger */ -inline bool buf_page_peek_if_too_old(buf_pool_t* buf_pool, - const buf_page_t* bpage) +inline bool buf_page_peek_if_too_old(const buf_page_t *bpage) { - ut_ad(!buf_pool_mutex_own(buf_pool)); - ut_ad(buf_page_in_file(bpage)); - if (buf_pool->freed_page_clock == 0) { /* If eviction has not started yet, do not update the statistics or move blocks in the LRU list. This is @@ -204,7 +149,7 @@ inline bool buf_page_peek_if_too_old(buf_pool_t* buf_pool, buf_pool->stat.n_pages_not_made_young++; return false; } else { - return !buf_page_peek_if_young(buf_pool, bpage); + return !buf_page_peek_if_young(bpage); } } @@ -249,40 +194,6 @@ buf_block_get_state( return(buf_page_get_state(&block->page)); } -/*********************************************************************//** -Gets the state name for state of a block -@return name or "CORRUPTED" */ -UNIV_INLINE -const char* -buf_get_state_name( -/*===============*/ - const buf_block_t* block) /*!< in: pointer to the control - block */ -{ - enum buf_page_state state = buf_page_get_state(&block->page); - - switch (state) { - case BUF_BLOCK_POOL_WATCH: - return (const char *) "BUF_BLOCK_POOL_WATCH"; - case BUF_BLOCK_ZIP_PAGE: - return (const char *) "BUF_BLOCK_ZIP_PAGE"; - case BUF_BLOCK_ZIP_DIRTY: - return (const char *) "BUF_BLOCK_ZIP_DIRTY"; - case BUF_BLOCK_NOT_USED: - return (const char *) "BUF_BLOCK_NOT_USED"; - case BUF_BLOCK_READY_FOR_USE: - return (const char *) "BUF_BLOCK_NOT_USED"; - case BUF_BLOCK_FILE_PAGE: - return (const char *) "BUF_BLOCK_FILE_PAGE"; - case BUF_BLOCK_MEMORY: - return (const char *) "BUF_BLOCK_MEMORY"; - case BUF_BLOCK_REMOVE_HASH: - return (const char *) "BUF_BLOCK_REMOVE_HASH"; - default: - return (const char *) "CORRUPTED"; - } -} - /*********************************************************************//** Sets the state of a block. */ UNIV_INLINE @@ -300,44 +211,35 @@ buf_page_set_state( ut_error; break; case BUF_BLOCK_ZIP_PAGE: - ut_a(state == BUF_BLOCK_ZIP_DIRTY); + ut_ad(state == BUF_BLOCK_ZIP_DIRTY); break; case BUF_BLOCK_ZIP_DIRTY: - ut_a(state == BUF_BLOCK_ZIP_PAGE); + ut_ad(state == BUF_BLOCK_ZIP_PAGE); break; case BUF_BLOCK_NOT_USED: - ut_a(state == BUF_BLOCK_READY_FOR_USE); + ut_ad(state == BUF_BLOCK_READY_FOR_USE); break; case BUF_BLOCK_READY_FOR_USE: - ut_a(state == BUF_BLOCK_MEMORY - || state == BUF_BLOCK_FILE_PAGE - || state == BUF_BLOCK_NOT_USED); + ut_ad(state == BUF_BLOCK_MEMORY + || state == BUF_BLOCK_FILE_PAGE + || state == BUF_BLOCK_NOT_USED); break; case BUF_BLOCK_MEMORY: - ut_a(state == BUF_BLOCK_NOT_USED); + ut_ad(state == BUF_BLOCK_NOT_USED); break; case BUF_BLOCK_FILE_PAGE: - if (!(state == BUF_BLOCK_NOT_USED + ut_ad(state == BUF_BLOCK_NOT_USED || state == BUF_BLOCK_REMOVE_HASH - || state == BUF_BLOCK_FILE_PAGE)) { - const char *old_state_name = buf_get_state_name((buf_block_t*)bpage); - bpage->state = state; - - fprintf(stderr, - "InnoDB: Error: block old state %d (%s) " - " new state %d (%s) not correct\n", - old_state, - old_state_name, - state, - buf_get_state_name((buf_block_t*)bpage)); - ut_a(state == BUF_BLOCK_NOT_USED - || state == BUF_BLOCK_REMOVE_HASH - || state == BUF_BLOCK_FILE_PAGE); + || state == BUF_BLOCK_FILE_PAGE); + if (state == BUF_BLOCK_REMOVE_HASH) { + ut_ad(!bpage->in_page_hash); + ut_ad(!bpage->in_zip_hash); + ut_ad(!bpage->in_LRU_list); + ut_ad(!bpage->in_free_list); } - break; case BUF_BLOCK_REMOVE_HASH: - ut_a(state == BUF_BLOCK_MEMORY); + ut_ad(state == BUF_BLOCK_MEMORY); break; } #endif /* UNIV_DEBUG */ @@ -407,8 +309,6 @@ buf_page_get_mutex( /*===============*/ const buf_page_t* bpage) /*!< in: pointer to control block */ { - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - switch (buf_page_get_state(bpage)) { case BUF_BLOCK_POOL_WATCH: ut_error; @@ -518,10 +418,7 @@ buf_page_set_io_fix( buf_page_t* bpage, /*!< in/out: control block */ enum buf_io_fix io_fix) /*!< in: io_fix state */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); bpage->io_fix = io_fix; @@ -555,10 +452,7 @@ buf_page_set_sticky( /*================*/ buf_page_t* bpage) /*!< in/out: control block */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE); @@ -573,10 +467,7 @@ buf_page_unset_sticky( /*==================*/ buf_page_t* bpage) /*!< in/out: control block */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN); @@ -592,10 +483,7 @@ buf_page_can_relocate( /*==================*/ const buf_page_t* bpage) /*!< control block being relocated */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); @@ -613,10 +501,11 @@ buf_page_is_old( /*============*/ const buf_page_t* bpage) /*!< in: control block */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(buf_pool_mutex_own(buf_pool)); -#endif /* UNIV_DEBUG */ + /* Buffer page mutex is not strictly required here for heuristic + purposes even if LRU mutex is not being held. Keep the assertion + for not since all the callers hold it. */ + ut_ad(mutex_own(buf_page_get_mutex(bpage)) + || mutex_own(&buf_pool->mutex)); ut_ad(buf_page_in_file(bpage)); return(bpage->old); @@ -631,11 +520,8 @@ buf_page_set_old( buf_page_t* bpage, /*!< in/out: control block */ bool old) /*!< in: old */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); -#endif /* UNIV_DEBUG */ ut_a(buf_page_in_file(bpage)); - ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->mutex)); ut_ad(bpage->in_LRU_list); #ifdef UNIV_LRU_DEBUG @@ -680,12 +566,8 @@ buf_page_set_accessed( /*==================*/ buf_page_t* bpage) /*!< in/out: control block */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - ut_ad(!buf_pool_mutex_own(buf_pool)); + ut_ad(!mutex_own(&buf_pool->mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); -#endif /* UNIV_DEBUG */ - ut_a(buf_page_in_file(bpage)); if (bpage->access_time == 0) { @@ -705,6 +587,8 @@ buf_page_get_block( buf_page_t* bpage) /*!< in: control block, or NULL */ { if (bpage != NULL) { + ut_ad(buf_page_hash_lock_held_s_or_x(bpage) + || mutex_own(&buf_pool->mutex)); ut_ad(buf_page_in_file(bpage)); if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { @@ -823,9 +707,7 @@ buf_block_free( /*===========*/ buf_block_t* block) /*!< in, own: block to be freed */ { - buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); - - buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->mutex); buf_page_mutex_enter(block); @@ -835,7 +717,7 @@ buf_block_free( buf_page_mutex_exit(block); - buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->mutex); } /********************************************************************//** @@ -848,17 +730,12 @@ buf_block_modify_clock_inc( /*=======================*/ buf_block_t* block) /*!< in: block */ { -#ifdef UNIV_DEBUG - buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*) block); - /* No latch is acquired for the shared temporary tablespace. */ - if (!fsp_is_system_temporary(block->page.id.space())) { - ut_ad((buf_pool_mutex_own(buf_pool) - && (block->page.buf_fix_count == 0)) - || rw_lock_own_flagged(&block->lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); - } -#endif /* UNIV_DEBUG */ + ut_ad(fsp_is_system_temporary(block->page.id.space()) + || (mutex_own(&buf_pool->mutex) + && block->page.buf_fix_count == 0) + || rw_lock_own_flagged(&block->lock, + RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); assert_block_ahi_valid(block); block->modify_clock++; @@ -932,45 +809,10 @@ buf_block_buf_fix_dec( #endif /* UNIV_DEBUG */ } -/** Returns the buffer pool instance given a page id. -@param[in] page_id page id -@return buffer pool */ -inline buf_pool_t* buf_pool_get(const page_id_t page_id) -{ - /* 2log of BUF_READ_AHEAD_AREA (64) */ - ulint ignored_page_no = page_id.page_no() >> 6; - - page_id_t id(page_id.space(), ignored_page_no); - - ulint i = id.fold() % srv_buf_pool_instances; - - return(&buf_pool_ptr[i]); -} - -/******************************************************************//** -Returns the buffer pool instance given its array index -@return buffer pool */ -UNIV_INLINE -buf_pool_t* -buf_pool_from_array( -/*================*/ - ulint index) /*!< in: array index to get - buffer pool instance from */ -{ - ut_ad(index < MAX_BUFFER_POOLS); - ut_ad(index < srv_buf_pool_instances); - return(&buf_pool_ptr[index]); -} - /** Returns the control block of a file page, NULL if not found. -@param[in] buf_pool buffer pool instance @param[in] page_id page id @return block, NULL if not found */ -UNIV_INLINE -buf_page_t* -buf_page_hash_get_low( - buf_pool_t* buf_pool, - const page_id_t page_id) +inline buf_page_t *buf_page_hash_get_low(page_id_t page_id) { buf_page_t* bpage; @@ -993,7 +835,6 @@ buf_page_hash_get_low( ut_a(buf_page_in_file(bpage)); ut_ad(bpage->in_page_hash); ut_ad(!bpage->in_zip_hash); - ut_ad(buf_pool_from_bpage(bpage) == buf_pool); } return(bpage); @@ -1005,7 +846,6 @@ page_hash lock is acquired in the specified lock mode. Otherwise, mode value is ignored. It is up to the caller to release the lock. If the block is found and the lock is NULL then the page_hash lock is released by this function. -@param[in] buf_pool buffer pool instance @param[in] page_id page id @param[in,out] lock lock of the page hash acquired if bpage is found, NULL otherwise. If NULL is passed then the hash_lock is released by @@ -1018,7 +858,6 @@ a watch sentinel. */ UNIV_INLINE buf_page_t* buf_page_hash_get_locked( - buf_pool_t* buf_pool, const page_id_t page_id, rw_lock_t** lock, ulint lock_mode, @@ -1053,9 +892,9 @@ buf_page_hash_get_locked( hash_lock, buf_pool->page_hash, page_id.fold()); } - bpage = buf_page_hash_get_low(buf_pool, page_id); + bpage = buf_page_hash_get_low(page_id); - if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) { + if (!bpage || buf_pool_watch_is_sentinel(bpage)) { if (!watch) { bpage = NULL; } @@ -1090,7 +929,6 @@ page_hash lock is acquired in the specified lock mode. Otherwise, mode value is ignored. It is up to the caller to release the lock. If the block is found and the lock is NULL then the page_hash lock is released by this function. -@param[in] buf_pool buffer pool instance @param[in] page_id page id @param[in,out] lock lock of the page hash acquired if bpage is found, NULL otherwise. If NULL is passed then the hash_lock is released by @@ -1101,14 +939,11 @@ lock == NULL UNIV_INLINE buf_block_t* buf_block_hash_get_locked( - buf_pool_t* buf_pool, const page_id_t page_id, rw_lock_t** lock, ulint lock_mode) { - buf_page_t* bpage = buf_page_hash_get_locked(buf_pool, - page_id, - lock, + buf_page_t* bpage = buf_page_hash_get_locked(page_id, lock, lock_mode); buf_block_t* block = buf_page_get_block(bpage); @@ -1138,18 +973,6 @@ buf_block_hash_get_locked( return(NULL); } -/** Returns TRUE if the page can be found in the buffer pool hash table. -NOTE that it is possible that the page is not yet read from disk, -though. -@param[in] page_id page id -@return true if found in the page hash table */ -inline bool buf_page_peek(const page_id_t page_id) -{ - buf_pool_t* buf_pool = buf_pool_get(page_id); - - return(buf_page_hash_get(buf_pool, page_id) != NULL); -} - /********************************************************************//** Releases a compressed-only page acquired with buf_page_get_zip(). */ UNIV_INLINE @@ -1234,55 +1057,7 @@ buf_block_dbg_add_level( { sync_check_lock(&block->lock, level); } - #endif /* UNIV_DEBUG */ -/********************************************************************//** -Acquire mutex on all buffer pool instances. */ -UNIV_INLINE -void -buf_pool_mutex_enter_all(void) -/*==========================*/ -{ - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - - buf_pool_mutex_enter(buf_pool); - } -} - -/********************************************************************//** -Release mutex on all buffer pool instances. */ -UNIV_INLINE -void -buf_pool_mutex_exit_all(void) -/*=========================*/ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - - buf_pool = buf_pool_from_array(i); - buf_pool_mutex_exit(buf_pool); - } -} -/*********************************************************************//** -Get the nth chunk's buffer block in the specified buffer pool. -@return the nth chunk's buffer block. */ -UNIV_INLINE -buf_block_t* -buf_get_nth_chunk_block( -/*====================*/ - const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint n, /*!< in: nth chunk in the buffer pool */ - ulint* chunk_size) /*!< in: chunk size */ -{ - const buf_chunk_t* chunk; - - chunk = buf_pool->chunks + n; - *chunk_size = chunk->size; - return(chunk->blocks); -} /********************************************************************//** Get buf frame. */ @@ -1324,7 +1099,7 @@ ulint buf_pool_size_align( ulint size) { - const ib_uint64_t m = ((ib_uint64_t)srv_buf_pool_instances) * srv_buf_pool_chunk_unit; + const ulong m = srv_buf_pool_chunk_unit; size = ut_max(size, srv_buf_pool_min_size); if (size % m == 0) { diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index fa884725d02..2b7315fdf30 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -57,12 +57,10 @@ struct flush_counters_t { evicted */ }; -/********************************************************************//** -Remove a block from the flush list of modified blocks. */ -void -buf_flush_remove( -/*=============*/ - buf_page_t* bpage); /*!< in: pointer to the block in question */ +/** Remove a block from the flush list of modified blocks. +@param[in] bpage block to be removed from the flush list */ +void buf_flush_remove(buf_page_t* bpage); + /*******************************************************************//** Relocates a buffer control block on the flush_list. Note that it is assumed that the contents of bpage has already been @@ -94,22 +92,17 @@ buf_flush_init_for_writing( bool use_full_checksum); # if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG -/********************************************************************//** -Writes a flushable page asynchronously from the buffer pool to a file. -NOTE: buf_pool->mutex and block->mutex must be held upon entering this -function, and they will be released by this function after flushing. -This is loosely based on buf_flush_batch() and buf_flush_page(). -@return TRUE if the page was flushed and the mutexes released */ -ibool -buf_flush_page_try( -/*===============*/ - buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ - buf_block_t* block) /*!< in/out: buffer control block */ +/** Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: block and LRU list mutexes must be held upon entering this function, and +they will be released by this function after flushing. This is loosely based on +buf_flush_batch() and buf_flush_page(). +@param[in,out] block buffer control block +@return whether the page was flushed and the mutex released */ +bool buf_flush_page_try(buf_block_t* block) MY_ATTRIBUTE((warn_unused_result)); # endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ /** Do flushing batch of a given type. NOTE: The calling thread is not allowed to own any latches on pages! -@param[in,out] buf_pool buffer pool instance @param[in] type flush type @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @@ -122,14 +115,12 @@ passed back to caller. Ignored if NULL @retval false if another batch of same type was already running. */ bool buf_flush_do_batch( - buf_pool_t* buf_pool, buf_flush_t type, ulint min_n, lsn_t lsn_limit, flush_counters_t* n); -/** This utility flushes dirty blocks from the end of the flush list of all -buffer pool instances. +/** This utility flushes dirty blocks from the end of the flush list. NOTE: The calling thread is not allowed to own any latches on pages! @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @@ -138,14 +129,9 @@ oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored @param[out] n_processed the number of pages which were processed is passed back to caller. Ignored if NULL. -@return true if a batch was queued successfully for each buffer pool -instance. false if another batch of same type was already running in -at least one of the buffer pool instance */ -bool -buf_flush_lists( - ulint min_n, - lsn_t lsn_limit, - ulint* n_processed); +@retval true if a batch was queued successfully +@retval false if another batch of same type was already running */ +bool buf_flush_lists(ulint min_n, lsn_t lsn_limit, ulint *n_processed); /******************************************************************//** This function picks up a single page from the tail of the LRU @@ -155,26 +141,14 @@ they are unable to find a replaceable page at the tail of the LRU list i.e.: when the background LRU flushing in the page_cleaner thread is not fast enough to keep pace with the workload. @return true if success. */ -bool -buf_flush_single_page_from_LRU( -/*===========================*/ - buf_pool_t* buf_pool); /*!< in/out: buffer pool instance */ -/******************************************************************//** -Waits until a flush batch of the given type ends */ -void -buf_flush_wait_batch_end( -/*=====================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_flush_t type); /*!< in: BUF_FLUSH_LRU - or BUF_FLUSH_LIST */ -/** -Waits until a flush batch of the given lsn ends +bool buf_flush_single_page_from_LRU(); + +/** Wait until a flush batch ends. +@param[in] type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ +void buf_flush_wait_batch_end(buf_flush_t type); +/** Wait until a flush batch of the given lsn ends @param[in] new_oldest target oldest_modified_lsn to wait for */ - -void -buf_flush_wait_flushed( - lsn_t new_oldest); - +void buf_flush_wait_flushed(lsn_t new_oldest); /********************************************************************//** This function should be called at a mini-transaction commit, if a page was modified in it. Puts the block to the list of modified blocks, if it not @@ -198,56 +172,15 @@ buf_flush_ready_for_replace( buf_page_t* bpage); /*!< in: buffer control block, must be buf_page_in_file(bpage) and in the LRU list */ -#ifdef UNIV_DEBUG -/** Disables page cleaner threads (coordinator and workers). -It's used by: SET GLOBAL innodb_page_cleaner_disabled_debug = 1 (0). -@param[in] save immediate result from check function */ -void buf_flush_page_cleaner_disabled_debug_update(THD*, - st_mysql_sys_var*, void*, - const void* save); -#endif /* UNIV_DEBUG */ - -/******************************************************************//** -page_cleaner thread tasked with flushing dirty pages from the buffer -pools. As of now we'll have only one coordinator of this thread. -@return a dummy parameter */ -extern "C" -os_thread_ret_t -DECLARE_THREAD(buf_flush_page_cleaner_coordinator)( -/*===============================================*/ - void* arg); /*!< in: a dummy parameter required by - os_thread_create */ - -/** Adjust thread count for page cleaner workers. -@param[in] new_cnt Number of threads to be used */ -void -buf_flush_set_page_cleaner_thread_cnt(ulong new_cnt); - -/******************************************************************//** -Worker thread of page_cleaner. -@return a dummy parameter */ -extern "C" -os_thread_ret_t -DECLARE_THREAD(buf_flush_page_cleaner_worker)( -/*==========================================*/ - void* arg); /*!< in: a dummy parameter required by - os_thread_create */ /** Initialize page_cleaner. */ -void -buf_flush_page_cleaner_init(void); +void buf_flush_page_cleaner_init(); -/** Wait for any possible LRU flushes that are in progress to end. */ -void -buf_flush_wait_LRU_batch_end(void); +/** Wait for any possible LRU flushes to complete. */ +void buf_flush_wait_LRU_batch_end(); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/******************************************************************//** -Validates the flush list. -@return TRUE if ok */ -ibool -buf_flush_validate( -/*===============*/ - buf_pool_t* buf_pool); +/** Validate the flush list. */ +void buf_flush_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ /********************************************************************//** @@ -264,21 +197,21 @@ void buf_flush_free_flush_rbt(void); /*==========================*/ -/********************************************************************//** -Writes a flushable page asynchronously from the buffer pool to a file. -NOTE: buf_pool->mutex and buf_page_get_mutex(bpage) must be -held upon entering this function, and they will be released by this -function. -@return TRUE if page was flushed */ -ibool -buf_flush_page( -/*===========*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_page_t* bpage, /*!< in: buffer control block */ - buf_flush_t flush_type, /*!< in: type of flush */ - bool sync); /*!< in: true if sync IO request */ -/********************************************************************//** -Returns true if the block is modified and ready for flushing. +/** Write a flushable page asynchronously from the buffer pool to a file. +NOTE: 1. in simulated aio we must call os_aio_simulated_wake_handler_threads +after we have posted a batch of writes! 2. buf_page_get_mutex(bpage) must be +held upon entering this function. The LRU list mutex must be held if flush_type +== BUF_FLUSH_SINGLE_PAGE. Both mutexes will be released by this function if it +returns true. +@param[in] bpage buffer control block +@param[in] flush_type type of flush +@param[in] sync true if sync IO request +@return whether the page was flushed */ +bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync); + +/** Check if the block is modified and ready for flushing. +@param[in] bpage buffer control block, must be buf_page_in_file() +@param[in] flush_type type of flush @return true if can flush immediately */ bool buf_flush_ready_for_flush( @@ -288,29 +221,26 @@ buf_flush_ready_for_flush( buf_flush_t flush_type)/*!< in: type of flush */ MY_ATTRIBUTE((warn_unused_result)); -/******************************************************************//** -Check if there are any dirty pages that belong to a space id in the flush -list in a particular buffer pool. -@return number of dirty pages present in a single buffer pool */ -ulint -buf_pool_get_dirty_pages_count( -/*===========================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool */ - ulint id); /*!< in: space id to check */ +/** Determine the number of dirty pages in a tablespace. +@param[in] id tablespace identifier +@return number of dirty pages */ +ulint buf_pool_get_dirty_pages_count(ulint id); -/*******************************************************************//** -Synchronously flush dirty blocks from the end of the flush list of all buffer -pool instances. -NOTE: The calling thread is not allowed to own any latches on pages! */ -void -buf_flush_sync_all_buf_pools(void); -/*==============================*/ +/** Synchronously flush dirty blocks. +NOTE: The calling thread is not allowed to hold any buffer page latches! */ +void buf_flush_sync(); /** Request IO burst and wake page_cleaner up. @param[in] lsn_limit upper limit of LSN to be flushed */ -void -buf_flush_request_force( - lsn_t lsn_limit); +void buf_flush_request_force(lsn_t lsn_limit); + +/** Start a buffer flush batch for LRU or flush list +@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST +@return whether the flush batch was started (was not already running) */ +bool buf_flush_start(buf_flush_t flush_type); +/** End a buffer flush batch. +@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ +void buf_flush_end(buf_flush_t flush_type); #include "buf0flu.ic" diff --git a/storage/innobase/include/buf0flu.ic b/storage/innobase/include/buf0flu.ic index 7a28c94150b..6f57bcb6fc8 100644 --- a/storage/innobase/include/buf0flu.ic +++ b/storage/innobase/include/buf0flu.ic @@ -34,7 +34,6 @@ Inserts a modified block into the flush list. */ void buf_flush_insert_into_flush_list( /*=============================*/ - buf_pool_t* buf_pool, /*!< buffer pool instance */ buf_block_t* block, /*!< in/out: block which is modified */ lsn_t lsn); /*!< in: oldest modification */ @@ -65,9 +64,7 @@ buf_flush_note_modification( } if (block->page.oldest_modification == 0) { - buf_pool_t* buf_pool = buf_pool_from_block(block); - - buf_flush_insert_into_flush_list(buf_pool, block, start_lsn); + buf_flush_insert_into_flush_list(block, start_lsn); } else { ut_ad(block->page.oldest_modification <= start_lsn); } diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index 2eb483381b4..3a41e0dd664 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -34,14 +34,9 @@ Created 11/5/1995 Heikki Tuuri struct trx_t; struct fil_space_t; -/******************************************************************//** -Returns TRUE if less than 25 % of the buffer pool is available. This can be -used in heuristics to prevent huge transactions eating up the whole buffer -pool for their locks. -@return TRUE if less than 25 % of buffer pool left */ -ibool -buf_LRU_buf_pool_running_out(void); -/*==============================*/ +/** @return whether less than 1/4 of the buffer pool is available */ +bool +buf_LRU_buf_pool_running_out(); /*####################################################################### These are low-level functions @@ -94,27 +89,18 @@ buf_LRU_free_page( bool zip) /*!< in: true if should remove also the compressed page of an uncompressed page */ MY_ATTRIBUTE((nonnull)); -/******************************************************************//** -Try to free a replaceable block. + +/** Try to free a replaceable block. +@param[in] scan_all true=scan the whole LRU list, + false=use BUF_LRU_SEARCH_SCAN_THRESHOLD @return true if found and freed */ -bool -buf_LRU_scan_and_free_block( -/*========================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - bool scan_all) /*!< in: scan whole LRU list - if true, otherwise scan only - 'old' blocks. */ - MY_ATTRIBUTE((nonnull,warn_unused_result)); -/******************************************************************//** -Returns a free block from the buf_pool. The block is taken off the -free list. If it is empty, returns NULL. -@return a free control block, or NULL if the buf_block->free list is empty */ -buf_block_t* -buf_LRU_get_free_only( -/*==================*/ - buf_pool_t* buf_pool); /*!< buffer pool instance */ -/******************************************************************//** -Returns a free block from the buf_pool. The block is taken off the +bool buf_LRU_scan_and_free_block(bool scan_all); + +/** @return a buffer block from the buf_pool->free list +@retval NULL if the free list is empty */ +buf_block_t* buf_LRU_get_free_only(); + +/** Get a free block from the buf_pool. The block is taken off the free list. If free list is empty, blocks are moved from the end of the LRU list to the free list. This function is called from a user thread when it needs a clean @@ -137,25 +123,17 @@ we put it to free list to be used. * iteration > 1: * same as iteration 1 but sleep 10ms @return the free control block, in state BUF_BLOCK_READY_FOR_USE */ -buf_block_t* -buf_LRU_get_free_block( -/*===================*/ - buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */ - MY_ATTRIBUTE((nonnull,warn_unused_result)); -/******************************************************************//** -Determines if the unzip_LRU list should be used for evicting a victim -instead of the general LRU list. -@return TRUE if should use unzip_LRU */ -ibool -buf_LRU_evict_from_unzip_LRU( -/*=========================*/ - buf_pool_t* buf_pool); -/******************************************************************//** -Puts a block back to the free list. */ +buf_block_t* buf_LRU_get_free_block() + MY_ATTRIBUTE((malloc,warn_unused_result)); + +/** @return whether the unzip_LRU list should be used for evicting a victim +instead of the general LRU list */ +bool buf_LRU_evict_from_unzip_LRU(); + +/** Puts a block back to the free list. +@param[in] block block; not containing a file page */ void -buf_LRU_block_free_non_file_page( -/*=============================*/ - buf_block_t* block); /*!< in: block, must not contain a file page */ +buf_LRU_block_free_non_file_page(buf_block_t* block); /******************************************************************//** Adds a block to the LRU list. Please make sure that the page_size is already set when invoking the function, so that we can get correct @@ -179,26 +157,21 @@ buf_unzip_LRU_add_block( /******************************************************************//** Moves a block to the start of the LRU list. */ void -buf_LRU_make_block_young( -/*=====================*/ - buf_page_t* bpage); /*!< in: control block */ -/**********************************************************************//** -Updates buf_pool->LRU_old_ratio. +buf_LRU_make_block_young(buf_page_t* bpage); + +/** Update buf_pool->LRU_old_ratio. +@param[in] old_pct Reserve this percentage of + the buffer pool for "old" blocks +@param[in] adjust true=adjust the LRU list; + false=just assign buf_pool->LRU_old_ratio + during the initialization of InnoDB @return updated old_pct */ -uint -buf_LRU_old_ratio_update( -/*=====================*/ - uint old_pct,/*!< in: Reserve this percentage of - the buffer pool for "old" blocks. */ - bool adjust);/*!< in: true=adjust the LRU list; - false=just assign buf_pool->LRU_old_ratio - during the initialization of InnoDB */ +uint buf_LRU_old_ratio_update(uint old_pct, bool adjust); /********************************************************************//** Update the historical stats that we are collecting for LRU eviction policy at the end of each interval. */ void -buf_LRU_stat_update(void); -/*=====================*/ +buf_LRU_stat_update(); /** Remove one page from LRU list and put it to free list. @param[in,out] bpage block, must contain a file page and be in @@ -208,28 +181,17 @@ buf_LRU_stat_update(void); void buf_LRU_free_one_page(buf_page_t* bpage, page_id_t old_page_id) MY_ATTRIBUTE((nonnull)); -/******************************************************************//** -Adjust LRU hazard pointers if needed. */ -void -buf_LRU_adjust_hp( -/*==============*/ - buf_pool_t* buf_pool,/*!< in: buffer pool instance */ - const buf_page_t* bpage); /*!< in: control block */ +/** Adjust LRU hazard pointers if needed. +@param[in] bpage buffer page descriptor */ +void buf_LRU_adjust_hp(const buf_page_t* bpage); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/**********************************************************************//** -Validates the LRU list. -@return TRUE */ -ibool -buf_LRU_validate(void); -/*==================*/ +/** Validate the LRU list. */ +void buf_LRU_validate(); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG -/**********************************************************************//** -Prints the LRU list. */ -void -buf_LRU_print(void); -/*===============*/ +/** Dump the LRU list to stderr. */ +void buf_LRU_print(); #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ /** @name Heuristics for detecting index scan @{ */ diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h index 7653bdbe55f..f4d1560862a 100644 --- a/storage/innobase/include/buf0rea.h +++ b/storage/innobase/include/buf0rea.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -115,10 +115,6 @@ buf_read_recv_pages( const ulint* page_nos, ulint n_stored); -/** The size in pages of the area which the read-ahead algorithms read if -invoked */ -#define BUF_READ_AHEAD_AREA(b) ((b)->read_ahead_area) - /** @name Modes used in read-ahead @{ */ /** read only pages belonging to the insert buffer tree */ #define BUF_READ_IBUF_PAGES_ONLY 131 diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index daca5e3b3fa..9096aa92a82 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -354,13 +354,8 @@ extern ulint srv_buf_pool_size; extern const ulint srv_buf_pool_min_size; /** Default pool size in bytes */ extern const ulint srv_buf_pool_def_size; -/** Requested buffer pool chunk size. Each buffer pool instance consists -of one or more chunks. */ +/** Requested buffer pool chunk size */ extern ulong srv_buf_pool_chunk_unit; -/** Requested number of buffer pool instances */ -extern ulong srv_buf_pool_instances; -/** Default number of buffer pool instances */ -extern const ulong srv_buf_pool_instances_default; /** Number of locks to protect buf_pool->page_hash */ extern ulong srv_n_page_hash_locks; /** Scan depth for LRU flush batch i.e.: number of blocks scanned*/ @@ -422,8 +417,6 @@ extern ulong srv_innodb_stats_method; extern ulint srv_max_n_open_files; -extern ulong srv_n_page_cleaners; - extern double srv_max_dirty_pages_pct; extern double srv_max_dirty_pages_pct_lwm; diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index 8b2b94b3394..10b9a710ac1 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,10 +33,6 @@ Created 10/10/1995 Heikki Tuuri // Forward declaration struct dict_table_t; -/** If buffer pool is less than the size, -only one buffer pool instance is used. */ -#define BUF_POOL_SIZE_THRESHOLD (1024 * 1024 * 1024) - /** Open the configured number of dedicated undo tablespaces. @param[in] create_new_db whether the database is being initialized @return DB_SUCCESS or error code */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 01093becb13..a2de83c0739 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -516,30 +516,18 @@ void lock_sys_t::resize(ulint n_cells) hash_table_free(old_hash); /* need to update block->lock_hash_val */ - for (ulint i = 0; i < srv_buf_pool_instances; ++i) { - buf_pool_t* buf_pool = buf_pool_from_array(i); + mutex_enter(&buf_pool->mutex); + for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool->LRU); + bpage; bpage = UT_LIST_GET_NEXT(LRU, bpage)) { + if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { + buf_block_t* block = reinterpret_cast( + bpage); - buf_pool_mutex_enter(buf_pool); - buf_page_t* bpage; - bpage = UT_LIST_GET_FIRST(buf_pool->LRU); - - while (bpage != NULL) { - if (buf_page_get_state(bpage) - == BUF_BLOCK_FILE_PAGE) { - buf_block_t* block; - block = reinterpret_cast( - bpage); - - block->lock_hash_val - = lock_rec_hash( - bpage->id.space(), - bpage->id.page_no()); - } - bpage = UT_LIST_GET_NEXT(LRU, bpage); + block->lock_hash_val = lock_rec_hash( + bpage->id.space(), bpage->id.page_no()); } - buf_pool_mutex_exit(buf_pool); } - + mutex_exit(&buf_pool->mutex); mutex_exit(&mutex); } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 8e7e06f1115..bf8d7c958e0 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1231,7 +1231,7 @@ static bool log_preflush_pool_modified_pages(lsn_t new_oldest) success = buf_flush_lists(ULINT_MAX, new_oldest, &n_pages); - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + buf_flush_wait_batch_end(BUF_FLUSH_LIST); if (!success) { MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); @@ -1631,7 +1631,7 @@ loop: if (!srv_read_only_mode) { if (recv_sys.flush_start) { /* This is in case recv_writer_thread was never - started, or buf_flush_page_cleaner_coordinator + started, or buf_flush_page_cleaner failed to notice its termination. */ os_event_set(recv_sys.flush_start); } @@ -1745,7 +1745,7 @@ wait_suspend_loop: ut_ad(!log_scrub_thread_active); - if (!buf_pool_ptr) { + if (!buf_pool) { ut_ad(!srv_was_started); } else if (ulint pending_io = buf_pool_check_no_pending_io()) { if (srv_print_verbose_log && count > 600) { @@ -1817,7 +1817,7 @@ wait_suspend_loop: service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "Free innodb buffer pool"); - buf_all_freed(); + ut_d(buf_assert_all_freed()); ut_a(lsn == log_sys.lsn || srv_force_recovery == SRV_FORCE_NO_LOG_REDO); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 44271e1da71..e26d25a34a9 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -891,7 +891,7 @@ inline byte* recv_sys_t::alloc(size_t len, bool store_recv) if (UNIV_UNLIKELY(!block)) { create_block: - block= buf_block_alloc(nullptr); + block= buf_block_alloc(); block->page.access_time= 1U << 16 | ut_calc_align(static_cast(len), ALIGNMENT); static_assert(ut_is_2pow(ALIGNMENT), "ALIGNMENT must be a power of 2"); @@ -941,31 +941,27 @@ inline void recv_sys_t::free(const void *data) ut_ad(!buf_pool_withdrawing); #endif - for (auto i= srv_buf_pool_instances; i--; ) + buf_chunk_t *chunk= buf_pool->chunks; + for (auto i= buf_pool->n_chunks; i--; chunk++) { - buf_pool_t *buf_pool= buf_pool_from_array(i); - buf_chunk_t *chunk= buf_pool->chunks; - for (auto i= buf_pool->n_chunks; i--; chunk++) + if (data < chunk->blocks->frame) + continue; + const size_t offs= (reinterpret_cast(data) - + chunk->blocks->frame) >> srv_page_size_shift; + if (offs >= chunk->size) + continue; + buf_block_t *block= &chunk->blocks[offs]; + ut_ad(block->frame == data); + ut_ad(buf_block_get_state(block) == BUF_BLOCK_MEMORY); + ut_ad(static_cast(block->page.access_time - 1) < + srv_page_size); + ut_ad(block->page.access_time >= 1U << 16); + if (!((block->page.access_time -= 1U << 16) >> 16)) { - if (data < chunk->blocks->frame) - continue; - const size_t offs= (reinterpret_cast(data) - - chunk->blocks->frame) >> srv_page_size_shift; - if (offs >= chunk->size) - continue; - buf_block_t *block= &chunk->blocks[offs]; - ut_ad(block->frame == data); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_MEMORY); - ut_ad(static_cast(block->page.access_time - 1) < - srv_page_size); - ut_ad(block->page.access_time >= 1U << 16); - if (!((block->page.access_time -= 1U << 16) >> 16)) - { - UT_LIST_REMOVE(blocks, block); - buf_block_free(block); - } - return; + UT_LIST_REMOVE(blocks, block); + buf_block_free(block); } + return; } ut_ad(0); } @@ -2182,7 +2178,7 @@ static void recv_read_in_area(page_id_t page_id) && i->first.space() == page_id.space() && i->first.page_no() < up_limit; i++) { if (i->second.state == page_recv_t::RECV_NOT_PROCESSED - && !buf_page_peek(i->first)) { + && !buf_page_hash_get(i->first)) { i->second.state = page_recv_t::RECV_BEING_READ; *p++ = i->first.page_no(); } @@ -3506,15 +3502,10 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ut_ad(srv_operation == SRV_OPERATION_NORMAL || srv_operation == SRV_OPERATION_RESTORE || srv_operation == SRV_OPERATION_RESTORE_EXPORT); -#ifdef UNIV_DEBUG - for (ulint i= 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool = buf_pool_from_array(i); - buf_flush_list_mutex_enter(buf_pool); - ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0); - ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0); - buf_flush_list_mutex_exit(buf_pool); - } -#endif + ut_d(mutex_enter(&buf_pool->flush_list_mutex)); + ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0); + ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0); + ut_d(mutex_exit(&buf_pool->flush_list_mutex)); /* Initialize red-black tree for fast insertions into the flush_list during recovery process. */ diff --git a/storage/innobase/mem/mem0mem.cc b/storage/innobase/mem/mem0mem.cc index 15dee37cc1f..261d8062bd6 100644 --- a/storage/innobase/mem/mem0mem.cc +++ b/storage/innobase/mem/mem0mem.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -291,7 +291,7 @@ mem_heap_create_block_func( return(NULL); } } else { - buf_block = buf_block_alloc(NULL); + buf_block = buf_block_alloc(); } block = (mem_block_t*) buf_block->frame; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 6730d1a9a77..4bb722bd1b0 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -4698,7 +4698,6 @@ page_zip_reorganize( dict_index_t* index, /*!< in: index of the B-tree node */ mtr_t* mtr) /*!< in: mini-transaction */ { - buf_pool_t* buf_pool = buf_pool_from_block(block); page_t* page = buf_block_get_frame(block); buf_block_t* temp_block; page_t* temp_page; @@ -4715,7 +4714,7 @@ page_zip_reorganize( /* Disable logging */ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); - temp_block = buf_block_alloc(buf_pool); + temp_block = buf_block_alloc(); btr_search_drop_page_hash_index(block); temp_page = temp_block->frame; diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 6eb7098574e..8397d3a8ea3 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -2,7 +2,7 @@ Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1613,11 +1613,6 @@ srv_mon_process_existing_counter( mon_type_t value; monitor_info_t* monitor_info; ibool update_min = FALSE; - buf_pool_stat_t stat; - buf_pools_list_size_t buf_pools_list_size; - ulint LRU_len; - ulint free_len; - ulint flush_list_len; monitor_info = srv_mon_get_info(monitor_id); @@ -1635,8 +1630,7 @@ srv_mon_process_existing_counter( /* innodb_buffer_pool_read_requests, the number of logical read requests */ case MONITOR_OVLD_BUF_POOL_READ_REQUESTS: - buf_get_total_stat(&stat); - value = stat.n_page_gets; + value = buf_pool->stat.n_page_gets; break; /* innodb_buffer_pool_write_requests, the number of @@ -1652,14 +1646,12 @@ srv_mon_process_existing_counter( /* innodb_buffer_pool_read_ahead */ case MONITOR_OVLD_BUF_POOL_READ_AHEAD: - buf_get_total_stat(&stat); - value = stat.n_ra_pages_read; + value = buf_pool->stat.n_ra_pages_read; break; /* innodb_buffer_pool_read_ahead_evicted */ case MONITOR_OVLD_BUF_POOL_READ_AHEAD_EVICTED: - buf_get_total_stat(&stat); - value = stat.n_ra_pages_evicted; + value = buf_pool->stat.n_ra_pages_evicted; break; /* innodb_buffer_pool_pages_total */ @@ -1669,51 +1661,46 @@ srv_mon_process_existing_counter( /* innodb_buffer_pool_pages_misc */ case MONITOR_OVLD_BUF_POOL_PAGE_MISC: - buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len); - value = buf_pool_get_n_pages() - LRU_len - free_len; + value = buf_pool_get_n_pages() + - UT_LIST_GET_LEN(buf_pool->LRU) + - UT_LIST_GET_LEN(buf_pool->free); break; /* innodb_buffer_pool_pages_data */ case MONITOR_OVLD_BUF_POOL_PAGES_DATA: - buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len); - value = LRU_len; + value = UT_LIST_GET_LEN(buf_pool->LRU); break; /* innodb_buffer_pool_bytes_data */ case MONITOR_OVLD_BUF_POOL_BYTES_DATA: - buf_get_total_list_size_in_bytes(&buf_pools_list_size); - value = buf_pools_list_size.LRU_bytes - + buf_pools_list_size.unzip_LRU_bytes; + value = buf_pool->stat.LRU_bytes + + (UT_LIST_GET_LEN(buf_pool->unzip_LRU) + << srv_page_size_shift); break; /* innodb_buffer_pool_pages_dirty */ case MONITOR_OVLD_BUF_POOL_PAGES_DIRTY: - buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len); - value = flush_list_len; + value = UT_LIST_GET_LEN(buf_pool->flush_list); break; /* innodb_buffer_pool_bytes_dirty */ case MONITOR_OVLD_BUF_POOL_BYTES_DIRTY: - buf_get_total_list_size_in_bytes(&buf_pools_list_size); - value = buf_pools_list_size.flush_list_bytes; + value = buf_pool->stat.flush_list_bytes; break; /* innodb_buffer_pool_pages_free */ case MONITOR_OVLD_BUF_POOL_PAGES_FREE: - buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len); - value = free_len; + value = UT_LIST_GET_LEN(buf_pool->free); break; /* innodb_pages_created, the number of pages created */ case MONITOR_OVLD_PAGE_CREATED: - buf_get_total_stat(&stat); - value = stat.n_pages_created; + value = buf_pool->stat.n_pages_created; break; /* innodb_pages_written, the number of page written */ case MONITOR_OVLD_PAGES_WRITTEN: - buf_get_total_stat(&stat); - value = stat.n_pages_written; + value = buf_pool->stat.n_pages_written; break; /* innodb_index_pages_written, the number of index pages written */ @@ -1728,8 +1715,7 @@ srv_mon_process_existing_counter( /* innodb_pages_read */ case MONITOR_OVLD_PAGES_READ: - buf_get_total_stat(&stat); - value = stat.n_pages_read; + value = buf_pool->stat.n_pages_read; break; /* Number of times secondary index lookup triggered cluster lookup */ diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index ff69c77e795..1e3e223e94e 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -208,13 +208,8 @@ ulint srv_buf_pool_size; const ulint srv_buf_pool_min_size = 5 * 1024 * 1024; /** Default pool size in bytes */ const ulint srv_buf_pool_def_size = 128 * 1024 * 1024; -/** Requested buffer pool chunk size. Each buffer pool instance consists -of one or more chunks. */ +/** Requested buffer pool chunk size */ ulong srv_buf_pool_chunk_unit; -/** innodb_buffer_pool_instances (0 is interpreted as 1) */ -ulong srv_buf_pool_instances; -/** Default value of innodb_buffer_pool_instances */ -const ulong srv_buf_pool_instances_default = 0; /** innodb_page_hash_locks (a debug-only parameter); number of locks to protect buf_pool->page_hash */ ulong srv_n_page_hash_locks = 16; @@ -267,9 +262,6 @@ ulong srv_io_capacity; /** innodb_io_capacity_max */ ulong srv_max_io_capacity; -/** innodb_page_cleaners; the number of page cleaner threads */ -ulong srv_n_page_cleaners; - /* The InnoDB main thread tries to keep the ratio of modified pages in the buffer pool to all database pages in the buffer pool smaller than the following number. But it is not guaranteed that the value stays below @@ -858,7 +850,7 @@ srv_refresh_innodb_monitor_stats(void) log_refresh_stats(); - buf_refresh_io_stats_all(); + buf_refresh_io_stats(); srv_n_rows_inserted_old = srv_stats.n_rows_inserted; srv_n_rows_updated_old = srv_stats.n_rows_updated; @@ -1129,17 +1121,9 @@ void srv_export_innodb_status(void) /*==========================*/ { - buf_pool_stat_t stat; - buf_pools_list_size_t buf_pools_list_size; - ulint LRU_len; - ulint free_len; - ulint flush_list_len; fil_crypt_stat_t crypt_stat; btr_scrub_stat_t scrub_stat; - buf_get_total_stat(&stat); - buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len); - buf_get_total_list_size_in_bytes(&buf_pools_list_size); if (!srv_read_only_mode) { fil_crypt_total_stat(&crypt_stat); btr_scrub_total_stat(&scrub_stat); @@ -1190,7 +1174,8 @@ srv_export_innodb_status(void) export_vars.innodb_data_written = srv_stats.data_written; - export_vars.innodb_buffer_pool_read_requests = stat.n_page_gets; + export_vars.innodb_buffer_pool_read_requests + = buf_pool->stat.n_page_gets; export_vars.innodb_buffer_pool_write_requests = srv_stats.buf_pool_write_requests; @@ -1204,38 +1189,37 @@ srv_export_innodb_status(void) export_vars.innodb_buffer_pool_reads = srv_stats.buf_pool_reads; export_vars.innodb_buffer_pool_read_ahead_rnd = - stat.n_ra_pages_read_rnd; + buf_pool->stat.n_ra_pages_read_rnd; export_vars.innodb_buffer_pool_read_ahead = - stat.n_ra_pages_read; + buf_pool->stat.n_ra_pages_read; export_vars.innodb_buffer_pool_read_ahead_evicted = - stat.n_ra_pages_evicted; + buf_pool->stat.n_ra_pages_evicted; - export_vars.innodb_buffer_pool_pages_data = LRU_len; + export_vars.innodb_buffer_pool_pages_data = + UT_LIST_GET_LEN(buf_pool->LRU); export_vars.innodb_buffer_pool_bytes_data = - buf_pools_list_size.LRU_bytes - + buf_pools_list_size.unzip_LRU_bytes; + buf_pool->stat.LRU_bytes + + (UT_LIST_GET_LEN(buf_pool->unzip_LRU) + << srv_page_size_shift); - export_vars.innodb_buffer_pool_pages_dirty = flush_list_len; + export_vars.innodb_buffer_pool_pages_dirty = + UT_LIST_GET_LEN(buf_pool->flush_list); export_vars.innodb_buffer_pool_pages_made_young - = stat.n_pages_made_young; + = buf_pool->stat.n_pages_made_young; export_vars.innodb_buffer_pool_pages_made_not_young - = stat.n_pages_not_made_young; + = buf_pool->stat.n_pages_not_made_young; - export_vars.innodb_buffer_pool_pages_old = 0; - - for (ulong i = 0; i < srv_buf_pool_instances; i++) { - export_vars.innodb_buffer_pool_pages_old += - buf_pool_from_array(i)->LRU_old_len; - } + export_vars.innodb_buffer_pool_pages_old = buf_pool->LRU_old_len; export_vars.innodb_buffer_pool_bytes_dirty = - buf_pools_list_size.flush_list_bytes; + buf_pool->stat.flush_list_bytes; - export_vars.innodb_buffer_pool_pages_free = free_len; + export_vars.innodb_buffer_pool_pages_free = + UT_LIST_GET_LEN(buf_pool->free); #ifdef UNIV_DEBUG export_vars.innodb_buffer_pool_pages_latched = @@ -1244,7 +1228,9 @@ srv_export_innodb_status(void) export_vars.innodb_buffer_pool_pages_total = buf_pool_get_n_pages(); export_vars.innodb_buffer_pool_pages_misc = - buf_pool_get_n_pages() - LRU_len - free_len; + buf_pool_get_n_pages() + - UT_LIST_GET_LEN(buf_pool->LRU) + - UT_LIST_GET_LEN(buf_pool->free); export_vars.innodb_max_trx_id = trx_sys.get_max_trx_id(); export_vars.innodb_history_list_length = trx_sys.rseg_history_len; @@ -1270,11 +1256,11 @@ srv_export_innodb_status(void) export_vars.innodb_dblwr_writes = srv_stats.dblwr_writes; - export_vars.innodb_pages_created = stat.n_pages_created; + export_vars.innodb_pages_created = buf_pool->stat.n_pages_created; - export_vars.innodb_pages_read = stat.n_pages_read; + export_vars.innodb_pages_read = buf_pool->stat.n_pages_read; - export_vars.innodb_pages_written = stat.n_pages_written; + export_vars.innodb_pages_written = buf_pool->stat.n_pages_written; export_vars.innodb_row_lock_waits = srv_stats.n_lock_wait_count; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 91f8e83e50a..adc7c74c3c9 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1067,7 +1067,7 @@ srv_prepare_to_delete_redo_log_files( do { /* Clean the buffer pool. */ - buf_flush_sync_all_buf_pools(); + buf_flush_sync(); DBUG_EXECUTE_IF("innodb_log_abort_1", DBUG_RETURN(0);); DBUG_PRINT("ib_log", ("After innodb_log_abort_1")); @@ -1233,11 +1233,11 @@ dberr_t srv_start(bool create_new_db) + 1 /* trx_rollback_all_recovered */ + 128 /* added as margin, for use of InnoDB Memcached etc. */ + + 1/* buf_flush_page_cleaner */ + max_connections + srv_n_read_io_threads + srv_n_write_io_threads + srv_n_purge_threads - + srv_n_page_cleaners /* FTS Parallel Sort */ + fts_sort_pll_degree * FTS_NUM_AUX_INDEX * max_connections; @@ -1324,35 +1324,11 @@ dberr_t srv_start(bool create_new_db) fil_system.create(srv_file_per_table ? 50000 : 5000); - double size; - char unit; - - if (srv_buf_pool_size >= 1024 * 1024 * 1024) { - size = ((double) srv_buf_pool_size) / (1024 * 1024 * 1024); - unit = 'G'; - } else { - size = ((double) srv_buf_pool_size) / (1024 * 1024); - unit = 'M'; - } - - double chunk_size; - char chunk_unit; - - if (srv_buf_pool_chunk_unit >= 1024 * 1024 * 1024) { - chunk_size = srv_buf_pool_chunk_unit / 1024.0 / 1024 / 1024; - chunk_unit = 'G'; - } else { - chunk_size = srv_buf_pool_chunk_unit / 1024.0 / 1024; - chunk_unit = 'M'; - } - ib::info() << "Initializing buffer pool, total size = " - << size << unit << ", instances = " << srv_buf_pool_instances - << ", chunk size = " << chunk_size << chunk_unit; + << srv_buf_pool_size + << ", chunk size = " << srv_buf_pool_chunk_unit; - err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances); - - if (err != DB_SUCCESS) { + if (buf_pool_init()) { ib::error() << "Cannot allocate memory for the buffer pool"; return(srv_init_abort(DB_ERROR)); @@ -1381,16 +1357,6 @@ dberr_t srv_start(bool create_new_db) if (!srv_read_only_mode) { buf_flush_page_cleaner_init(); - buf_page_cleaner_is_active = true; - os_thread_create(buf_flush_page_cleaner_coordinator, - NULL, NULL); - - /* Create page cleaner workers if needed. For example - mariabackup could set srv_n_page_cleaners = 0. */ - if (srv_n_page_cleaners > 1) { - buf_flush_set_page_cleaner_thread_cnt(srv_n_page_cleaners); - } - #ifdef UNIV_LINUX /* Wait for the setpriority() call to finish. */ os_event_wait(recv_sys.flush_end); @@ -1455,7 +1421,7 @@ dberr_t srv_start(bool create_new_db) std::string logfile0; if (create_new_db) { - buf_flush_sync_all_buf_pools(); + buf_flush_sync(); flushed_lsn = log_get_lsn(); @@ -1661,7 +1627,7 @@ files_checked: return(srv_init_abort(err)); } - buf_flush_sync_all_buf_pools(); + buf_flush_sync(); flushed_lsn = log_get_lsn(); @@ -1829,7 +1795,7 @@ files_checked: ut_ad(!srv_force_recovery); ut_ad(srv_n_log_files_found <= 1); ut_ad(recv_no_log_write); - buf_flush_sync_all_buf_pools(); + buf_flush_sync(); err = fil_write_flushed_lsn(log_get_lsn()); ut_ad(!buf_pool_check_no_pending_io()); log_sys.log.close_files(); @@ -2332,9 +2298,9 @@ void innodb_shutdown() pars_lexer_close(); recv_sys.close(); - ut_ad(buf_pool_ptr || !srv_was_started); - if (buf_pool_ptr) { - buf_pool_free(srv_buf_pool_instances); + ut_ad(buf_pool || !srv_was_started); + if (buf_pool) { + buf_pool_free(); } sync_check_close(); diff --git a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result index 6fef17d7a16..abfb70f30af 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result @@ -13,9 +13,9 @@ database_name table_name index_name compress_ops compress_ops_ok compress_time u SELECT * FROM INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX_RESET; database_name table_name index_name compress_ops compress_ops_ok compress_time uncompress_ops uncompress_time SELECT * FROM INFORMATION_SCHEMA.INNODB_CMPMEM; -page_size buffer_pool_instance pages_used pages_free relocation_ops relocation_time +page_size pages_used pages_free relocation_ops relocation_time SELECT * FROM INFORMATION_SCHEMA.INNODB_CMPMEM_RESET; -page_size buffer_pool_instance pages_used pages_free relocation_ops relocation_time +page_size pages_used pages_free relocation_ops relocation_time SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS; NAME SUBSYSTEM COUNT MAX_COUNT MIN_COUNT AVG_COUNT COUNT_RESET MAX_COUNT_RESET MIN_COUNT_RESET AVG_COUNT_RESET TIME_ENABLED TIME_DISABLED TIME_ELAPSED TIME_RESET ENABLED TYPE COMMENT metadata_table_handles_opened metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of table handles opened @@ -316,11 +316,11 @@ WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; KEY VALUE SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; -POOL_ID POOL_SIZE FREE_BUFFERS DATABASE_PAGES OLD_DATABASE_PAGES MODIFIED_DATABASE_PAGES PENDING_DECOMPRESS PENDING_READS PENDING_FLUSH_LRU PENDING_FLUSH_LIST PAGES_MADE_YOUNG PAGES_NOT_MADE_YOUNG PAGES_MADE_YOUNG_RATE PAGES_MADE_NOT_YOUNG_RATE NUMBER_PAGES_READ NUMBER_PAGES_CREATED NUMBER_PAGES_WRITTEN PAGES_READ_RATE PAGES_CREATE_RATE PAGES_WRITTEN_RATE NUMBER_PAGES_GET HIT_RATE YOUNG_MAKE_PER_THOUSAND_GETS NOT_YOUNG_MAKE_PER_THOUSAND_GETS NUMBER_PAGES_READ_AHEAD NUMBER_READ_AHEAD_EVICTED READ_AHEAD_RATE READ_AHEAD_EVICTED_RATE LRU_IO_TOTAL LRU_IO_CURRENT UNCOMPRESS_TOTAL UNCOMPRESS_CURRENT +POOL_SIZE FREE_BUFFERS DATABASE_PAGES OLD_DATABASE_PAGES MODIFIED_DATABASE_PAGES PENDING_DECOMPRESS PENDING_READS PENDING_FLUSH_LRU PENDING_FLUSH_LIST PAGES_MADE_YOUNG PAGES_NOT_MADE_YOUNG PAGES_MADE_YOUNG_RATE PAGES_MADE_NOT_YOUNG_RATE NUMBER_PAGES_READ NUMBER_PAGES_CREATED NUMBER_PAGES_WRITTEN PAGES_READ_RATE PAGES_CREATE_RATE PAGES_WRITTEN_RATE NUMBER_PAGES_GET HIT_RATE YOUNG_MAKE_PER_THOUSAND_GETS NOT_YOUNG_MAKE_PER_THOUSAND_GETS NUMBER_PAGES_READ_AHEAD NUMBER_READ_AHEAD_EVICTED READ_AHEAD_RATE READ_AHEAD_EVICTED_RATE LRU_IO_TOTAL LRU_IO_CURRENT UNCOMPRESS_TOTAL UNCOMPRESS_CURRENT SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; -POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK +BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU; -POOL_ID LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK +LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES; TABLE_ID NAME FLAG N_COLS SPACE ROW_FORMAT ZIP_PAGE_SIZE SPACE_TYPE SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS;