WL#5614: Information schema table for InnoDB buffer pool information
Status: Complete
This is a feature request being mentioned a few times by other developers. One of them is being documented in BUG#12810. There is a recent request, documented in BUG#58059 In summary, this is an implementation to display buffer pool page information for those pages being brought into buffer pool. So user/DBA/developer (with super user privilege) can query to find out detail information in the buffer pool.
Three tables are created for this feature: 1) INFORMATION_SCHEMA.INNODB_BUFFER_PAGE (describes what kind of pages in the buffer pool) 2) INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS (describes general buffer pool information/statistics) 3)INFORMATION_SCHEMA.INNODB_BUFFER_LRU (describes what kind of pages in the buffer pool's LRU list) For INNODB_BUFFER_POOL_STATS, user requires to hold PROCESS privilege (to be compatible with show engine innodb status) to access the table. For INNODB_BUFFER_PAGE and INNODB_BUFFER_LRU, user require to hold SUPER user privilege to access the table. 1) For INFORMATION_SCHEMA.INNODB_BUFFER_PAGE, there are total 19 columns in the table, describing following information: POOL_ID /*!< Buffer Pool ID */ BLOCK_ID /*!< Buffer Pool Block ID */ SPACE /*!< Tablespace ID */ PAGE_NUMBER /*!< Page number */ PAGE_TYPE /*!< Page type string */ FLUSH_TYPE /*!< Flush type */ FIX_COUNT /*!< Count of how manyfold this block is bufferfixed */ IS_HASHED /*!< Whether hash index has been built on this page */ NEWEST_MODIFICATION /*!< log sequence number of the youngest modification */ OLDEST_MODIFICATION /*!< log sequence number of the oldest modification */ ACCESS_TIME /*!< Time of first access */ TABLE_NAME /*!< Name of the table the page belongs to */ INDEX_NAME /*!< Name of the index the page belongs to */ NUMBER_RECORDS /*!< Number of records on Page */ DATA_SIZE /*!< Sum of the sizes of the records */ COMPRESSED_SIZE /*!< Compress Page size */ PAGE_STATE /*!< Page state */ IO_FIX /*!< io_fix */ IS_OLD /*!< bpage->old */ FREE_PAGE_CLOCK/*!< bpage->freed_page_clock */ Pool ID is special for 5.5 as we have multiple Buffer Pool now. For Page types, we have following type strings with each page type: {"allocated", FIL_PAGE_TYPE_ALLOCATED}, /*!< Freshly allocated page */ {"index", FIL_PAGE_INDEX}, /*!< B-tree node */ {"undo_log", FIL_PAGE_UNDO_LOG}, /*!< Undo log page */ {"inode", FIL_PAGE_INODE}, /*!< Index node */ {"ibuf_free_list", FIL_PAGE_IBUF_FREE_LIST}, /*!< Insert buffer free list */ {"ibuf_bitmap", FIL_PAGE_IBUF_BITMAP}, /*!< Insert buffer bitmap */ {"system", FIL_PAGE_TYPE_SYS}, /*!< System page */ {"trx_system", FIL_PAGE_TYPE_TRX_SYS}, /*!< Transaction system data */ {"file_space_header", FIL_PAGE_TYPE_FSP_HDR}, /*!< File space header */ {"extent_descriptor", FIL_PAGE_TYPE_XDES}, /*!< Extent descriptor page */ {"blob", FIL_PAGE_TYPE_BLOB}, /*!< Uncompressed BLOB page */ {"compressed_blob", FIL_PAGE_TYPE_ZBLOB}, /*!< First compressed BLOB page */ {"compressed_blob2", FIL_PAGE_TYPE_ZBLOB2}, /*!< Subsequent comp BLOB page */ {"unknown", I_S_PAGE_TYPE_UNKNOWN} A page with valid data should have one of the following states: * FILE_PAGE (BUF_BLOCK_FILE_PAGE) * MEMORY (BUF_BLOCK_MEMORY) * COMPRESSED (BUF_BLOCK_ZIP_PAGE or BUF_BLOCK_ZIP_DIRTY) Other possible states: * READY_FOR_USE * NOT_USED * REMOVE_HASH A sample row look like following: mysql> select * from INNODB_BUFFER_PAGE LIMIT 1 \G *************************** 1. row *************************** POOL_ID: 0 BLOCK_ID: 0 SPACE: 0 PAGE_NUMBER: 7 PAGE_TYPE: SYSTEM FLUSH_TYPE: 1 FIX_COUNT: 0 IS_HASHED: NO NEWEST_MODIFICATION: 1615278 OLDEST_MODIFICATION: 0 ACCESS_TIME: 1670350787 TABLE_NAME: INDEX_NAME: NUMBER_RECORDS: 0 DATA_SIZE: 0 COMPRESSED_SIZE: 0 PAGE_STATE: FILE_PAGE IO_FIX: IO_NONE IS_OLD: NO FREE_PAGE_CLOCK: 0 1 row in set (3.34 sec) The column for TABLE_NAME, INDEX_NAME and DATA_SIZE are limited to index page only. 2) For INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS, there are 33 columns. Column names are pretty much self explanatory. The result is fully compatible with "show engine innodb status" output for the buffer pool information 1 POOL_ID 2 POOL_SIZE 3 FREE_BUFFERS 4 DATABASE_PAGES 5 OLD_DATABASE_PAGES 6 MODIFIED_DATABASE_PAGES 7 PENDING_DECOMPRESS 8 PENDING_READS 9 PENDING_FLUSH_LRU 10 PENDING_FLUSH_LIST 11 PAGES_MADE_YOUNG 12 PAGES_NOT_MADE_YOUNG 13 PAGES_MADE_YOUNG_RATE 14 PAGES_MADE_NOT_YOUNG_RATE 15 NUMBER_PAGE_READ 16 NUMBER_PAGE_CREATED 17 NUMBER_PAGE_WRITTEN 18 PAGES_READ_RATE 19 PAGES_CREATE_RATE 20 PAGES_WRITTEN_RATE 21 NUMBER_PAGE_GET 22 HIT_RATE 23 YOUNG_MAKE_PER_THOUSAND_GETS 24 NOT_YOUNG_MAKE_PER_THOUSAND_GETS 25 NUMBER_PAGE_READ_AHEAD 26 NUMBER_READ_AHEAD_EVICTED 28 READ_AHEAD_RATE 29 REAT_AHEAD_EVICTED_RATE 30 LRU_IO_TOTAL 31 LRU_IO_CURRENT 32 UNCOMPRESS_TOTAL 33 UNCOMPRESS_CURRENT A sample output is shown here, there is only one buffer pool in this server: mysql> select * from INNODB_BUFFER_POOL_STATS \G *************************** 1. row *************************** POOL_ID: 0 POOL_SIZE: 512 FREE_BUFFERS: 85 DATABASE_PAGES: 426 OLD_DATABASE_PAGES: 0 MODIFIED_DATABASE_PAGES: 0 PENDING_DECOMPRESS: 0 PENDING_READS: 0 PENDING_FLUSH_LRU: 0 PENDING_FLUSH_LIST: 0 PAGES_MADE_YOUNG: 0 PAGES_NOT_MADE_YOUNG: 0 PAGES_MADE_YOUNG_RATE: 0 PAGES_MADE_NOT_YOUNG_RATE: 0 NUMBER_PAGES_READ: 426 NUMBER_PAGES_CREATED: 0 NUMBER_PAGES_WRITTEN: 13 PAGES_READ_RATE: 0.999967742976033 PAGES_CREATE_RATE: 0 PAGES_WRITTEN_RATE: 0 NUMBER_PAGES_GET: 0 HIT_RATE: 1000 YOUNG_MAKE_PER_THOUSAND_GETS: 0 NOT_YOUNG_MAKE_PER_THOUSAND_GETS: 0 NUMBER_PAGES_READ_AHEAD: 0 NUMBER_READ_AHEAD_EVICTED: 0 READ_AHEAD_RATE: 0 READ_AHEAD_EVICTED_RATE: 0 LRU_IO_TOTAL: 0 LRU_IO_CURRENT: 0 UNCOMPRESS_TOTAL: 0 UNCOMPRESS_CURRENT: 0 1 row in set (0.00 sec) There are one row for each buffer pool. And it represents the latest buffer pool activity as shown. 3) INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU, the column and content is almost identical to INNODB_BUFFER_PAGE, except the BLOCK_ID is changed to LRU_POS: mysql> select * from INNODB_BUFFER_PAGE_LRU LIMIT 10 \G .... *************************** 6. row *************************** POOL_ID: 0 LRU_POSITION: 5 SPACE: 0 PAGE_NUMBER: 11 PAGE_TYPE: INDEX FLUSH_TYPE: 0 FIX_COUNT: 0 IS_HASHED: no NEWEST_MODIFICATION: 0 OLDEST_MODIFICATION: 0 ACCESS_TIME: 2533499412 TABLE_NAME: SYS_INDEXES INDEX_NAME: CLUST_IND NUMBER_RECORDS: 70 DATA_SIZE: 4749 COMPRESS_SIZE: 0 COMPRESSED: NO IO_FIX: IO_NONE IS_OLD: NO FREE_PAGE_CLOCK: 0
To start, there is a buffer_page_info_t structure that holds information for each page as we go through each buffer page in a chunk of buffer in a buffer pool. The fill of IS table will be done after scanning of such a buffer chunk with information collected in this buffer_page_info_t array, so we will not need to hold buffer mutex while filling the IS table: /** This structure defines information we will fetch from pages currently cached in the buffer pool. It will be used to poplulate table INFORMATION_SCHEMA.INNODB_BUFFER_PAGES */ struct buffer_page_info_struct{ ulint pool_id; /*!< Buffer Pool ID */ ulint space_id; /*!< Tablespace ID */ ulint page_num; /*!< Page number */ char* page_type; /*!< Page type string */ ulint flush_type; /*!< Flush type */ ulint fix_count; /*!< Count of how manyfold this block is bufferfixed */ ulint hashed; /*!< Whether hash index has been built on this page */ ib_uint64_t newest_mod; /*!< log sequence number of the youngest modification */ ib_uint64_t oldest_mod; /*!< log sequence number of the oldest modification */ ulint access_time; /*!< time of first access */ char* table_name; /*!< Name of the table the page belongs to */ char* index_name; /*!< Name of the index the page belongs to */ ulint num_recs; /*!< Number of records on Page */ ulint data_size; /*!< sum of the sizes of the records */ }; The scan of buffer pool will be done in following four functions in their calling sequence: /*******************************************************************//** 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() /*========================*/ /*******************************************************************//** This is the function that loops through each buffer pool and fetch page information to information schema table: I_S_INNODB_BUFFER_PAGE @return 0 on success, 1 on failure */ static int i_s_innodb_buffer_fill_general() /*******************************************************************//** This is the function that goes through each block of the buffer pool and fetch information to three information schema buffer pool page related tables: I_S_INNODB_BUFFER_POOL_ALL_PAGES, I_S_INNODB_BUFFER_POOL_INDEX_PAGES, I_S_INNODB_BUFFER_POOL_BLOB_PAGES. @return 0 on success, 1 on failure */ static int i_s_innodb_fill_buffer_pool( /*========================*/ /*******************************************************************//** Scans pages in the buffer cache, and cache their general information to the buffer_page_info_t array. */ static void i_s_innodb_fill_general_page_array() /*===============================*/ The buffer pool mutex is held only in the duration when we go through a chunk of buffer pool. So buffer content in other chunks could still change as we go through the buffer pool. After scanning a buffer chunk,i_s_innodb_fill_block_general() is called to fill the IS table: /*******************************************************************//** Fill Information Schema table INNODB_BUFFER_POOL_ALL_PAGES with information cached in the buffer_page_info_t array @return 0 on success, 1 on failure */ static int i_s_innodb_fill_block_general() /*==========================*/ Implementation: * INFORMATION_SCHEMA.INNODB_BUFFER_PAGE and INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS are implemented in rb://465 * INFORMATION_SCHEMA.INNODB_BUFFER_LRU is implemented in rb://527
Copyright (c) 2000, 2024, Oracle Corporation and/or its affiliates. All rights reserved.