35 #ifndef UNIV_HOTBACKUP
58 #define BUF_FLUSH_STAT_N_INTERVAL 20
65 static ulint buf_flush_stat_arr_ind;
76 static ulint buf_lru_flush_page_count = 0;
80 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
86 buf_flush_validate_low(
95 buf_flush_validate_skip(
100 # define BUF_FLUSH_VALIDATE_SKIP 23
104 static int buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
110 if (--buf_flush_validate_count > 0) {
114 buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
115 return(buf_flush_validate_low(buf_pool));
126 buf_flush_insert_in_flush_rbt(
139 ut_a(c_node != NULL);
144 if (p_node != NULL) {
158 buf_flush_delete_from_flush_rbt(
205 ut_ad(b1->in_flush_list);
206 ut_ad(b2->in_flush_list);
263 #ifdef UNIV_DEBUG_VALGRIND
267 if (UNIV_UNLIKELY(zip_size)) {
268 UNIV_MEM_ASSERT_RW(block->page.zip.data, zip_size);
270 UNIV_MEM_ASSERT_RW(block->frame, UNIV_PAGE_SIZE);
274 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
275 ut_a(buf_flush_validate_low(buf_pool));
289 buf_flush_insert_into_flush_list(
307 if (UNIV_LIKELY_NULL(buf_pool->
flush_rbt)) {
309 buf_flush_insert_sorted_into_flush_list(buf_pool, block, lsn);
316 ut_d(block->
page.in_flush_list = TRUE);
320 #ifdef UNIV_DEBUG_VALGRIND
324 if (UNIV_UNLIKELY(zip_size)) {
325 UNIV_MEM_ASSERT_RW(block->
page.
zip.
data, zip_size);
327 UNIV_MEM_ASSERT_RW(block->
frame, UNIV_PAGE_SIZE);
331 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
332 ut_a(buf_flush_validate_skip(buf_pool));
344 buf_flush_insert_sorted_into_flush_list(
377 ut_d(block->
page.in_flush_list = TRUE);
380 #ifdef UNIV_DEBUG_VALGRIND
384 if (UNIV_UNLIKELY(zip_size)) {
385 UNIV_MEM_ASSERT_RW(block->
page.
zip.
data, zip_size);
387 UNIV_MEM_ASSERT_RW(block->
frame, UNIV_PAGE_SIZE);
392 #ifdef UNIV_DEBUG_VALGRIND
396 if (UNIV_UNLIKELY(zip_size)) {
397 UNIV_MEM_ASSERT_RW(block->
page.
zip.
data, zip_size);
399 UNIV_MEM_ASSERT_RW(block->
frame, UNIV_PAGE_SIZE);
414 prev_b = buf_flush_insert_in_flush_rbt(&block->
page);
422 ut_ad(b->in_flush_list);
428 if (prev_b == NULL) {
432 prev_b, &block->
page);
435 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
436 ut_a(buf_flush_validate_low(buf_pool));
458 ut_ad(bpage->in_LRU_list);
469 " InnoDB: Error: buffer block state %lu"
470 " in the LRU list!\n",
483 buf_flush_ready_for_flush(
499 ut_ad(bpage->in_flush_list);
530 ut_ad(bpage->in_flush_list);
555 if (UNIV_LIKELY_NULL(buf_pool->
flush_rbt)) {
556 buf_flush_delete_from_flush_rbt(bpage);
561 ut_d(bpage->in_flush_list = FALSE);
565 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
566 ut_a(buf_flush_validate_skip(buf_pool));
609 ut_ad(bpage->in_flush_list);
610 ut_ad(dpage->in_flush_list);
614 if (UNIV_LIKELY_NULL(buf_pool->
flush_rbt)) {
615 buf_flush_delete_from_flush_rbt(bpage);
616 prev_b = buf_flush_insert_in_flush_rbt(dpage);
621 ut_d(bpage->in_flush_list = FALSE);
627 ut_ad(prev->in_flush_list);
630 buf_pool->flush_list,
635 buf_pool->flush_list,
643 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
644 ut_a(buf_flush_validate_low(buf_pool));
666 buf_pool->
n_flush[flush_type]--;
680 if (buf_pool->
n_flush[flush_type] == 0
681 && buf_pool->
init_flush[flush_type] == FALSE) {
694 buf_flush_sync_datafiles(
void)
719 buf_flush_buffered_writes(
void)
729 buf_flush_sync_datafiles();
760 block->
frame + (UNIV_PAGE_SIZE
765 " InnoDB: ERROR: The page to be written"
767 "InnoDB: The lsn fields do not match!"
768 " Noticed in the buffer pool\n"
769 "InnoDB: before posting to the"
770 " doublewrite buffer.\n");
782 " InnoDB: Apparent corruption of an"
783 " index page n:o %lu in space %lu\n"
784 "InnoDB: to be written to data file."
785 " We intentionally crash server\n"
786 "InnoDB: to prevent corrupt data"
787 " from ending up in data\n"
794 }
else if (UNIV_UNLIKELY
811 fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
813 (
void*) write_buf, NULL);
815 for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len;
816 len2 += UNIV_PAGE_SIZE, i++) {
830 " InnoDB: ERROR: The page to be written"
832 "InnoDB: The lsn fields do not match!"
833 " Noticed in the doublewrite block1.\n");
848 fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
850 (
void*) write_buf, NULL);
852 for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len;
853 len2 += UNIV_PAGE_SIZE, i++) {
867 " InnoDB: ERROR: The page to be"
868 " written seems corrupt!\n"
869 "InnoDB: The lsn fields do not match!"
871 " the doublewrite block2.\n");
914 " InnoDB: ERROR: The page to be written"
916 "InnoDB: The lsn fields do not match!"
917 " Noticed in the buffer pool\n"
918 "InnoDB: after posting and flushing"
919 " the doublewrite buffer.\n"
920 "InnoDB: Page buf fix count %lu,"
921 " io fix %lu, state %lu\n",
930 (
void*)block->
frame, (
void*)block);
938 buf_flush_sync_datafiles();
952 buf_flush_post_to_doublewrite_buf(
966 buf_flush_buffered_writes();
973 if (UNIV_UNLIKELY(zip_size)) {
974 UNIV_MEM_ASSERT_RW(bpage->
zip.
data, zip_size);
981 + zip_size, 0, UNIV_PAGE_SIZE - zip_size);
1000 buf_flush_buffered_writes();
1017 ib_uint64_t newest_lsn)
1027 ut_ad(zip_size <= UNIV_PAGE_SIZE);
1036 memcpy(page_zip->
data, page, zip_size);
1048 page_zip->
data, zip_size)
1054 fputs(
" InnoDB: ERROR: The compressed page to be written"
1055 " seems corrupt:", stderr);
1057 fputs(
"\nInnoDB: Possibly older version of the page:", stderr);
1084 : BUF_NO_CHECKSUM_MAGIC);
1087 #ifndef UNIV_HOTBACKUP
1094 buf_flush_write_block_low(
1106 #ifdef UNIV_LOG_DEBUG
1107 static ibool univ_log_debug_warned;
1123 #ifdef UNIV_IBUF_COUNT_DEBUG
1128 #ifdef UNIV_LOG_DEBUG
1129 if (!univ_log_debug_warned) {
1130 univ_log_debug_warned = TRUE;
1131 fputs(
"Warning: cannot force log to disk if"
1132 " UNIV_LOG_DEBUG is defined!\n"
1133 "Crash recovery will not work!\n",
1151 if (UNIV_LIKELY(srv_use_checksums)) {
1167 ? &bpage->
zip : NULL,
1176 zip_size ? zip_size : UNIV_PAGE_SIZE,
1179 buf_flush_post_to_doublewrite_buf(bpage);
1183 # if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
1235 mutex_exit(&block->
mutex);
1243 buf_flush_write_block_low(&block->
page);
1254 buf_flush_buffered_writes();
1277 ibool is_uncompressed;
1284 ut_ad(mutex_own(block_mutex));
1286 ut_ad(buf_flush_ready_for_flush(bpage, flush_type));
1292 if (buf_pool->
n_flush[flush_type] == 0) {
1297 buf_pool->
n_flush[flush_type]++;
1302 switch (flush_type) {
1310 if (is_s_latched && is_uncompressed) {
1315 mutex_exit(block_mutex);
1324 if (!is_s_latched) {
1325 buf_flush_buffered_writes();
1327 if (is_uncompressed) {
1343 if (is_uncompressed) {
1352 mutex_exit(block_mutex);
1366 if (buf_debug_prints) {
1368 "Flushing %u space %u page %u\n",
1372 buf_flush_write_block_low(bpage);
1380 buf_flush_try_neighbors(
1400 || !srv_flush_neighbor_pages) {
1411 ulint buf_flush_area;
1417 low = (offset / buf_flush_area) * buf_flush_area;
1418 high = (offset / buf_flush_area + 1) * buf_flush_area;
1427 for (i = low; i < high; i++) {
1431 if ((count + n_flushed) >= n_to_flush) {
1469 mutex_enter(block_mutex);
1471 if (buf_flush_ready_for_flush(bpage, flush_type)
1482 buf_flush_page(buf_pool, bpage, flush_type);
1483 ut_ad(!mutex_own(block_mutex));
1488 mutex_exit(block_mutex);
1506 buf_flush_page_and_try_neighbors(
1519 ibool flushed = FALSE;
1527 mutex_enter(block_mutex);
1531 if (buf_flush_ready_for_flush(bpage, flush_type)) {
1545 mutex_exit(block_mutex);
1548 *count += buf_flush_try_neighbors(space,
1557 mutex_exit(block_mutex);
1573 buf_flush_LRU_list_batch(
1590 while (bpage != NULL
1591 && !buf_flush_page_and_try_neighbors(
1596 }
while (bpage != NULL && count < max);
1601 buf_lru_flush_page_count += count;
1616 buf_flush_flush_list_batch(
1623 ib_uint64_t lsn_limit)
1663 ut_ad(bpage->in_flush_list);
1670 while (bpage != NULL
1672 && !buf_flush_page_and_try_neighbors(
1695 ut_ad(!bpage || bpage->in_flush_list);
1702 }
while (count < min_n && bpage != NULL && len > 0);
1729 ib_uint64_t lsn_limit)
1738 #ifdef UNIV_SYNC_DEBUG
1740 || sync_thread_levels_empty_gen(TRUE));
1747 switch(flush_type) {
1749 count = buf_flush_LRU_list_batch(buf_pool, min_n);
1752 count = buf_flush_flush_list_batch(buf_pool, min_n, lsn_limit);
1760 buf_flush_buffered_writes();
1763 if (buf_debug_prints && count > 0) {
1765 ?
"Flushed %lu pages in LRU flush\n"
1766 :
"Flushed %lu pages in flush list flush\n",
1771 srv_buf_pool_flushed += count;
1785 buf_flush_buffered_writes();
1790 if (buf_debug_prints && page_count > 0) {
1792 ?
"Flushed %lu pages in LRU flush\n"
1793 :
"Flushed %lu pages in flush list flush\n",
1794 (ulong) page_count);
1798 srv_buf_pool_flushed += page_count;
1804 buf_lru_flush_page_count += page_count;
1820 if (buf_pool->
n_flush[flush_type] > 0
1821 || buf_pool->
init_flush[flush_type] == TRUE) {
1851 if (buf_pool->
n_flush[flush_type] == 0) {
1873 if (buf_pool == NULL) {
1879 os_event_wait(i_buf_pool->
no_flush[type]);
1882 os_event_wait(buf_pool->
no_flush[type]);
1905 return(ULINT_UNDEFINED);
1908 page_count = buf_flush_batch(buf_pool,
BUF_FLUSH_LRU, min_n, 0);
1930 ib_uint64_t lsn_limit)
1937 ulint total_page_count = 0;
1938 ibool skipped = FALSE;
1940 if (min_n != ULINT_MAX) {
1952 ulint page_count = 0;
1972 page_count = buf_flush_batch(
1979 total_page_count += page_count;
1982 return(lsn_limit != IB_ULONGLONG_MAX && skipped
1983 ? ULINT_UNDEFINED : total_page_count);
1994 buf_flush_LRU_recommendation(
1999 ulint n_replaceable;
2008 while ((bpage != NULL)
2015 mutex_enter(block_mutex);
2021 mutex_exit(block_mutex);
2054 n_to_flush = buf_flush_LRU_recommendation(buf_pool);
2056 if (n_to_flush > 0) {
2061 if (n_flushed == ULINT_UNDEFINED) {
2095 buf_flush_stat_update(
void)
2099 ib_uint64_t lsn_diff;
2104 if (buf_flush_stat_cur.
redo == 0) {
2107 buf_flush_stat_cur.
redo = lsn;
2111 item = &buf_flush_stat_arr[buf_flush_stat_arr_ind];
2114 lsn_diff = lsn - buf_flush_stat_cur.
redo;
2115 n_flushed = buf_lru_flush_page_count
2119 buf_flush_stat_sum.
redo += lsn_diff - item->
redo;
2123 item->
redo = lsn_diff;
2127 buf_flush_stat_arr_ind++;
2128 buf_flush_stat_arr_ind %= BUF_FLUSH_STAT_N_INTERVAL;
2131 buf_flush_stat_cur.
redo = lsn;
2132 buf_flush_stat_cur.
n_flushed = buf_lru_flush_page_count;
2145 buf_flush_get_desired_flush_rate(
void)
2153 ulint lru_flush_avg;
2155 ulint log_capacity = log_get_capacity();
2159 ut_ad(log_capacity != 0);
2178 redo_avg = (ulint) (buf_flush_stat_sum.
redo
2179 / BUF_FLUSH_STAT_N_INTERVAL
2180 + (lsn - buf_flush_stat_cur.
redo));
2190 lru_flush_avg = buf_flush_stat_sum.
n_flushed
2191 / BUF_FLUSH_STAT_N_INTERVAL
2192 + (buf_lru_flush_page_count
2195 n_flush_req = (n_dirty * redo_avg) / log_capacity;
2201 rate = n_flush_req - lru_flush_avg;
2202 return(rate > 0 ? (ulint) rate : 0);
2205 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2211 buf_flush_validate_low(
2221 ut_ad(ut_list_node_313->in_flush_list));
2228 if (UNIV_LIKELY_NULL(buf_pool->
flush_rbt)) {
2232 while (bpage != NULL) {
2237 ut_ad(bpage->in_flush_list);
2249 if (UNIV_LIKELY_NULL(buf_pool->
flush_rbt)) {
2256 ut_a(*prpage == bpage);
2267 ut_a(rnode == NULL);
2285 ret = buf_flush_validate_low(buf_pool);
#define UT_LIST_GET_LEN(BASE)
trx_doublewrite_t * trx_doublewrite
#define buf_pool_mutex_enter(b)
UNIV_INLINE ulint page_is_comp(const page_t *page)
UNIV_INTERN ibool page_simple_validate_old(const page_t *page)
#define UT_LIST_GET_NEXT(NAME, N)
#define BUF_LRU_FREE_SEARCH_LEN(b)
UNIV_INTERN ulint buf_calc_page_old_checksum(const byte *page)
UNIV_INTERN ulint fil_io(ulint type, ibool sync, ulint space_id, ulint zip_size, ulint block_offset, ulint byte_offset, ulint len, void *buf, void *message)
UNIV_INTERN void buf_flush_remove(buf_page_t *bpage)
UNIV_INTERN const ib_rbt_node_t * rbt_prev(const ib_rbt_t *tree, const ib_rbt_node_t *current)
UNIV_INTERN void buf_flush_init_flush_rbt(void)
ib_uint64_t newest_modification
UNIV_INLINE void mach_write_to_4(byte *b, ulint n)
UNIV_INTERN void buf_flush_free_flush_rbt(void)
#define UT_LIST_VALIDATE(NAME, TYPE, BASE, ASSERTION)
UNIV_INLINE ulint buf_page_get_page_no(const buf_page_t *bpage) __attribute__((pure))
#define FIL_PAGE_TYPE_ALLOCATED
UNIV_INLINE ulint buf_block_get_zip_size(const buf_block_t *block) __attribute__((pure))
#define BUF_READ_AHEAD_AREA(b)
UNIV_INTERN void buf_page_print(const byte *read_buf, ulint zip_size)
#define FIL_PAGE_SPACE_OR_CHKSUM
#define FIL_PAGE_TYPE_ZBLOB2
UNIV_INTERN ibool buf_flush_ready_for_replace(buf_page_t *bpage)
UNIV_INLINE enum buf_flush buf_page_get_flush_type(const buf_page_t *bpage) __attribute__((pure))
UNIV_INTERN void ut_print_buf(FILE *file, const void *buf, ulint len)
UNIV_INTERN ibool page_simple_validate_new(const page_t *page)
UNIV_INLINE void mach_write_to_8(byte *b, ib_uint64_t n)
UNIV_INLINE ibool buf_page_in_file(const buf_page_t *bpage) __attribute__((pure))
UNIV_INTERN void fil_flush(ulint space_id)
#define log_flush_order_mutex_own()
UNIV_INTERN void buf_flush_write_complete(buf_page_t *bpage)
#define buf_flush_list_mutex_own(b)
#define FIL_PAGE_TYPE_XDES
#define FIL_PAGE_FILE_FLUSH_LSN
#define buf_LRU_stat_inc_io()
UNIV_INTERN void buf_flush_free_margin(buf_pool_t *buf_pool)
UNIV_INTERN void log_write_up_to(ib_uint64_t lsn, ulint wait, ibool flush_to_disk)
ibool check_index_page_at_flush
UNIV_INTERN void buf_flush_init_for_writing(byte *page, void *page_zip_, ib_uint64_t newest_lsn)
#define buf_flush_list_mutex_enter(b)
UNIV_INLINE ib_uint64_t log_get_lsn(void)
#define BUF_NO_CHECKSUM_MAGIC
The buffer pool structure.
UNIV_INLINE ulint ut_min(ulint n1, ulint n2)
ulint n_flush[BUF_FLUSH_N_TYPES]
UNIV_INLINE ulint buf_block_get_page_no(const buf_block_t *block) __attribute__((pure))
#define UT_LIST_REMOVE(NAME, BASE, N)
UNIV_INLINE void buf_page_set_state(buf_page_t *bpage, enum buf_page_state state)
UNIV_INLINE ulint buf_page_get_zip_size(const buf_page_t *bpage) __attribute__((pure))
UNIV_INLINE enum buf_page_state buf_block_get_state(const buf_block_t *block) __attribute__((pure))
UNIV_INLINE buf_pool_t * buf_pool_from_array(ulint index)
UNIV_INTERN void buf_LRU_make_block_old(buf_page_t *bpage)
UNIV_INTERN void os_event_set(os_event_t event)
#define FIL_PAGE_TYPE_ZBLOB
UNIV_INTERN void buf_flush_free_margins(void)
#define BUF_FLUSH_EXTRA_MARGIN(b)
UNIV_INLINE enum buf_page_state buf_page_get_state(const buf_page_t *bpage)
UNIV_INTERN ib_int64_t os_event_reset(os_event_t event)
UNIV_INLINE enum buf_io_fix buf_page_get_io_fix(const buf_page_t *bpage) __attribute__((pure))
UNIV_INTERN void os_aio_wait_until_no_pending_writes(void)
#define UT_LIST_GET_PREV(NAME, N)
#define UT_LIST_INSERT_AFTER(NAME, BASE, NODE1, NODE2)
#define BUF_FLUSH_FREE_BLOCK_MARGIN(b)
UNIV_INTERN ulint fil_space_get_size(ulint id)
UNIV_INTERN ibool rbt_delete(ib_rbt_t *tree, const void *key)
UNIV_INLINE buf_page_t * buf_page_hash_get(buf_pool_t *buf_pool, ulint space, ulint offset)
UNIV_INTERN ulint fil_page_get_type(const byte *page)
UNIV_INLINE ibool buf_page_is_old(const buf_page_t *bpage) __attribute__((pure))
UNIV_INTERN ulint buf_flush_list(ulint min_n, ib_uint64_t lsn_limit)
#define UT_LIST_GET_FIRST(BASE)
UNIV_INTERN ib_rbt_t * rbt_create(size_t sizeof_value, ib_rbt_compare compare)
UNIV_INLINE ulint buf_page_get_space(const buf_page_t *bpage) __attribute__((pure))
UNIV_INTERN const ib_rbt_node_t * rbt_insert(ib_rbt_t *tree, const void *key, const void *value)
ibool init_flush[BUF_FLUSH_N_TYPES]
UNIV_INLINE buf_pool_t * buf_pool_from_bpage(const buf_page_t *bpage)
UNIV_INTERN ulint buf_calc_page_new_checksum(const byte *page)
UNIV_INLINE void buf_page_set_io_fix(buf_page_t *bpage, enum buf_io_fix io_fix)
#define buf_flush_list_mutex_exit(b)
UNIV_INTERN byte UNIV_INTERN ulint page_zip_calc_checksum(const void *data, ulint size) __attribute__((nonnull))
UNIV_INTERN const ib_rbt_node_t * rbt_first(const ib_rbt_t *tree)
UNIV_INLINE ulint buf_block_get_space(const buf_block_t *block) __attribute__((pure))
buf_page_t ** buf_block_arr
os_event_t no_flush[BUF_FLUSH_N_TYPES]
UNIV_INTERN void buf_flush_wait_batch_end(buf_pool_t *buf_pool, enum buf_flush type)
#define UT_LIST_ADD_FIRST(NAME, BASE, N)
UNIV_INLINE void buf_page_set_flush_type(buf_page_t *bpage, enum buf_flush flush_type)
UNIV_INLINE ulint mach_read_from_4(const byte *b) __attribute__((nonnull
UNIV_INTERN void fil_flush_file_spaces(ulint purpose)
UNIV_INTERN void ut_print_timestamp(FILE *file)
Statistics for selecting flush rate based on redo log generation speed.
UNIV_INTERN void os_aio_simulated_wake_handler_threads(void)
ib_uint64_t oldest_modification
UNIV_INTERN const ib_rbt_node_t * rbt_next(const ib_rbt_t *tree, const ib_rbt_node_t *current)
UNIV_INLINE mutex_t * buf_page_get_mutex(const buf_page_t *bpage) __attribute__((pure))
#define FIL_PAGE_END_LSN_OLD_CHKSUM
UNIV_INLINE buf_pool_t * buf_pool_get(ulint space, ulint offset)
UNIV_INTERN ulint buf_flush_LRU(buf_pool_t *buf_pool, ulint min_n)
#define buf_pool_mutex_own(b)
UNIV_INTERN void rbt_free(ib_rbt_t *tree)
#define OS_AIO_SIMULATED_WAKE_LATER
#define FIL_PAGE_IBUF_BITMAP
#define TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
ulint srv_buf_pool_instances
UNIV_INLINE enum buf_io_fix buf_block_get_io_fix(const buf_block_t *block) __attribute__((pure))
#define FIL_PAGE_TYPE_FSP_HDR
#define buf_pool_mutex_exit(b)
#define UT_LIST_GET_LAST(BASE)
UNIV_INTERN void buf_LRU_insert_zip_clean(buf_page_t *bpage)
#define BUF_LRU_OLD_MIN_LEN
UNIV_INLINE ulint page_zip_get_size(const page_zip_des_t *page_zip) __attribute__((nonnull
UNIV_INTERN void buf_flush_relocate_on_flush_list(buf_page_t *bpage, buf_page_t *dpage)