28 #ifndef UNIV_HOTBACKUP
65 #define BUF_LRU_OLD_TOLERANCE 20
70 #define BUF_LRU_NON_OLD_MIN_LEN 5
71 #if BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN
72 # error "BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN"
82 #define BUF_LRU_DROP_SEARCH_SIZE 1024
86 static ibool buf_lru_switched_on_innodb_mon = FALSE;
102 #define BUF_LRU_STAT_N_INTERVAL 50
106 #define BUF_LRU_IO_TO_UNZIP_FACTOR 50
113 static ulint buf_LRU_stat_arr_ind;
145 static __attribute__((nonnull, warn_unused_result))
147 buf_LRU_block_remove_hashed(
158 buf_LRU_block_free_hashed_page(
168 incr_LRU_size_in_bytes(
175 buf_pool->stat.LRU_bytes += zip_size ? zip_size : UNIV_PAGE_SIZE;
176 ut_ad(buf_pool->stat.LRU_bytes <= buf_pool->curr_pool_size);
232 buf_LRU_drop_page_hash_batch(
245 for (i = 0; i < count; ++
i) {
258 buf_LRU_drop_page_hash_for_tablespace(
270 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
276 page_arr =
static_cast<ulint*
>(
ut_malloc(
285 while (bpage != NULL) {
294 || bpage->
space !=
id
315 page_arr[num_entries] = bpage->
offset;
327 buf_LRU_drop_page_hash_batch(
328 id, zip_size, page_arr, num_entries);
359 buf_LRU_drop_page_hash_batch(
id, zip_size, page_arr, num_entries);
369 static __attribute__((nonnull))
383 mutex_enter(block_mutex);
392 mutex_exit(block_mutex);
398 mutex_enter(block_mutex);
402 mutex_exit(block_mutex);
410 static __attribute__((nonnull(1), warn_unused_result))
433 buf_flush_yield(buf_pool, bpage);
441 ut_ad(bpage->in_flush_list);
453 static __attribute__((nonnull, warn_unused_result))
455 buf_flush_or_remove_page(
480 bool processed =
false;
490 mutex_enter(block_mutex);
492 ut_ad(bpage->oldest_modification != 0);
498 mutex_exit(block_mutex);
508 ut_ad(!mutex_own(block_mutex));
521 ut_ad(bpage->buf_fix_count > 0);
522 mutex_exit(block_mutex);
527 ut_ad(!mutex_own(block_mutex));
541 static __attribute__((nonnull(1), warn_unused_result))
543 buf_flush_or_remove_pages(
561 bool all_freed =
true;
579 }
else if (!buf_flush_or_remove_page(buf_pool, bpage, flush)) {
614 if (buf_flush_try_yield(buf_pool, prev, processed)) {
623 DBUG_EXECUTE_IF(
"ib_export_flush_crash",
624 static ulint n_pages;
625 if (++n_pages == 4) {DBUG_SUICIDE();});
633 return(DB_INTERRUPTED);
639 return(all_freed ? DB_SUCCESS : DB_FAIL);
647 static __attribute__((nonnull(1)))
649 buf_flush_dirty_pages(
663 err = buf_flush_or_remove_pages(buf_pool,
id, flush, trx);
667 ut_ad(buf_flush_validate(buf_pool));
669 if (err == DB_FAIL) {
676 ut_ad(buf_flush_validate(buf_pool));
678 }
while (err == DB_FAIL);
680 ut_ad(err == DB_INTERRUPTED
681 || buf_pool_get_dirty_pages_count(buf_pool,
id) == 0);
687 static __attribute__((nonnull))
689 buf_LRU_remove_all_pages(
711 ut_ad(bpage->in_LRU_list);
736 rw_lock_x_lock(hash_lock);
739 mutex_enter(block_mutex);
743 mutex_exit(block_mutex);
745 rw_lock_x_unlock(hash_lock);
758 ut_ad(mutex_own(block_mutex));
761 if (buf_debug_prints) {
763 "Dropping space %lu page %lu\n",
780 rw_lock_x_unlock(hash_lock);
782 mutex_exit(block_mutex);
788 id, zip_size, page_no);
798 ut_ad(!bpage->in_flush_list);
802 if (buf_LRU_block_remove_hashed(bpage,
true)) {
803 buf_LRU_block_free_hashed_page((
buf_block_t*) bpage);
805 ut_ad(block_mutex == &buf_pool->zip_mutex);
808 ut_ad(!mutex_own(block_mutex));
810 #ifdef UNIV_SYNC_DEBUG
812 ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
813 ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
835 static __attribute__((nonnull(1)))
837 buf_LRU_remove_pages(
845 switch (buf_remove) {
847 buf_LRU_remove_all_pages(buf_pool,
id);
852 buf_flush_dirty_pages(buf_pool,
id,
false, NULL);
857 buf_flush_dirty_pages(buf_pool,
id,
true, trx);
887 for (i = 0; i < srv_buf_pool_instances; i++) {
892 switch (buf_remove) {
894 buf_LRU_drop_page_hash_for_tablespace(buf_pool,
id);
908 buf_LRU_remove_pages(buf_pool,
id, buf_remove, trx);
912 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
917 buf_LRU_insert_zip_clean(
953 buf_LRU_free_from_unzip_LRU_list(
971 scanned = 1, freed = FALSE;
972 block != NULL && !freed
980 ut_ad(block->in_unzip_LRU_list);
989 MONITOR_LRU_UNZIP_SEARCH_SCANNED,
990 MONITOR_LRU_UNZIP_SEARCH_SCANNED_NUM_CALL,
991 MONITOR_LRU_UNZIP_SEARCH_SCANNED_PER_CALL,
1001 buf_LRU_free_from_common_LRU_list(
1015 scanned = 1, freed = FALSE;
1016 bpage != NULL && !freed
1025 ut_ad(bpage->in_LRU_list);
1029 if (freed && !accessed) {
1040 MONITOR_LRU_SEARCH_SCANNED,
1041 MONITOR_LRU_SEARCH_SCANNED_NUM_CALL,
1042 MONITOR_LRU_SEARCH_SCANNED_PER_CALL,
1062 return(buf_LRU_free_from_unzip_LRU_list(buf_pool, scan_all)
1063 || buf_LRU_free_from_common_LRU_list(
1064 buf_pool, scan_all));
1080 for (i = 0; i < srv_buf_pool_instances && !
ret; i++) {
1120 ut_d(block->
page.in_free_list = FALSE);
1126 mutex_enter(&block->
mutex);
1129 UNIV_MEM_ALLOC(block->
frame, UNIV_PAGE_SIZE);
1133 mutex_exit(&block->
mutex);
1146 buf_LRU_check_size_of_non_data_objects(
1157 " InnoDB: ERROR: over 95 percent of the buffer pool"
1159 "InnoDB: lock heaps or the adaptive hash index!"
1160 " Check that your\n"
1161 "InnoDB: transactions do not set too many row locks.\n"
1162 "InnoDB: Your buffer pool size is %lu MB."
1163 " Maybe you should make\n"
1164 "InnoDB: the buffer pool bigger?\n"
1165 "InnoDB: We intentionally generate a seg fault"
1166 " to print a stack trace\n"
1167 "InnoDB: on Linux!\n",
1169 / (1024 * 1024 / UNIV_PAGE_SIZE)));
1178 if (!buf_lru_switched_on_innodb_mon) {
1186 " InnoDB: WARNING: over 67 percent of"
1187 " the buffer pool is occupied by\n"
1188 "InnoDB: lock heaps or the adaptive"
1189 " hash index! Check that your\n"
1190 "InnoDB: transactions do not set too many"
1192 "InnoDB: Your buffer pool size is %lu MB."
1193 " Maybe you should make\n"
1194 "InnoDB: the buffer pool bigger?\n"
1195 "InnoDB: Starting the InnoDB Monitor to print"
1196 " diagnostics, including\n"
1197 "InnoDB: lock heap and hash index sizes.\n",
1199 / (1024 * 1024 / UNIV_PAGE_SIZE)));
1201 buf_lru_switched_on_innodb_mon = TRUE;
1202 srv_print_innodb_monitor = TRUE;
1205 }
else if (buf_lru_switched_on_innodb_mon) {
1212 buf_lru_switched_on_innodb_mon = FALSE;
1213 srv_print_innodb_monitor = FALSE;
1250 ibool freed = FALSE;
1251 ulint n_iterations = 0;
1252 ulint flush_failures = 0;
1253 ibool mon_value_was = FALSE;
1254 ibool started_monitor = FALSE;
1260 buf_LRU_check_size_of_non_data_objects(buf_pool);
1271 if (started_monitor) {
1272 srv_print_innodb_monitor = mon_value_was;
1279 && srv_use_doublewrite_buf
1302 if (!freed && n_iterations == 0) {
1318 if (n_iterations > 20) {
1321 " InnoDB: Warning: difficult to find free blocks in\n"
1322 "InnoDB: the buffer pool (%lu search iterations)!\n"
1323 "InnoDB: %lu failed attempts to flush a page!"
1325 "InnoDB: increasing the buffer pool size.\n"
1326 "InnoDB: It is also possible that"
1327 " in your Unix version\n"
1328 "InnoDB: fsync is very slow, or"
1329 " completely frozen inside\n"
1330 "InnoDB: the OS kernel. Then upgrading to"
1331 " a newer version\n"
1332 "InnoDB: of your operating system may help."
1334 "InnoDB: number of fsyncs in diagnostic info below.\n"
1335 "InnoDB: Pending flushes (fsync) log: %lu;"
1336 " buffer pool: %lu\n"
1337 "InnoDB: %lu OS file reads, %lu OS file writes,"
1339 "InnoDB: Starting InnoDB Monitor to print further\n"
1340 "InnoDB: diagnostics to the standard output.\n",
1341 (ulong) n_iterations,
1342 (ulong) flush_failures,
1345 (ulong) os_n_file_reads, (ulong) os_n_file_writes,
1346 (ulong) os_n_fsyncs);
1348 mon_value_was = srv_print_innodb_monitor;
1349 started_monitor = TRUE;
1350 srv_print_innodb_monitor = TRUE;
1359 if (n_iterations > 1) {
1374 MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT);
1390 buf_LRU_old_adjust_len(
1401 #if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
1402 # error "BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)"
1404 #ifdef UNIV_LRU_DEBUG
1425 ut_ad(LRU_old->in_LRU_list);
1426 #ifdef UNIV_LRU_DEBUG
1436 #ifdef UNIV_LRU_DEBUG
1473 ut_ad(bpage->in_LRU_list);
1483 buf_LRU_old_adjust_len(buf_pool);
1490 buf_unzip_LRU_remove_block_if_needed(
1504 ut_ad(block->in_unzip_LRU_list);
1505 ut_d(block->in_unzip_LRU_list = FALSE);
1515 buf_LRU_remove_block(
1528 ut_ad(bpage->in_LRU_list);
1533 if (UNIV_UNLIKELY(bpage == buf_pool->
LRU_old)) {
1543 #ifdef UNIV_LRU_DEBUG
1546 buf_pool->
LRU_old = prev_bpage;
1554 ut_d(bpage->in_LRU_list = FALSE);
1557 buf_pool->
stat.
LRU_bytes -= zip_size ? zip_size : UNIV_PAGE_SIZE;
1559 buf_unzip_LRU_remove_block_if_needed(bpage);
1587 buf_LRU_old_adjust_len(buf_pool);
1608 ut_ad(!block->in_unzip_LRU_list);
1609 ut_d(block->in_unzip_LRU_list = TRUE);
1625 buf_LRU_add_block_to_end_low(
1637 ut_ad(!bpage->in_LRU_list);
1639 ut_d(bpage->in_LRU_list = TRUE);
1641 incr_LRU_size_in_bytes(bpage, buf_pool);
1651 buf_LRU_old_adjust_len(buf_pool);
1658 buf_LRU_old_init(buf_pool);
1677 buf_LRU_add_block_low(
1692 ut_ad(!bpage->in_LRU_list);
1700 #ifdef UNIV_LRU_DEBUG
1714 ut_d(bpage->in_LRU_list = TRUE);
1716 incr_LRU_size_in_bytes(bpage, buf_pool);
1725 buf_LRU_old_adjust_len(buf_pool);
1732 buf_LRU_old_init(buf_pool);
1760 buf_LRU_add_block_low(bpage, old);
1779 buf_LRU_remove_block(bpage);
1780 buf_LRU_add_block_low(bpage, FALSE);
1791 buf_LRU_remove_block(bpage);
1792 buf_LRU_add_block_to_end_low(bpage);
1824 ut_ad(bpage->in_LRU_list);
1826 rw_lock_x_lock(hash_lock);
1827 mutex_enter(block_mutex);
1829 #if UNIV_WORD_SIZE == 4
1833 UNIV_MEM_ASSERT_RW(bpage,
sizeof *bpage);
1842 #ifdef UNIV_IBUF_COUNT_DEBUG
1846 if (zip || !bpage->
zip.
data) {
1861 rw_lock_x_unlock(hash_lock);
1862 mutex_exit(block_mutex);
1868 memcpy(b, bpage,
sizeof *b);
1873 ut_ad(bpage->in_LRU_list);
1875 #if UNIV_WORD_SIZE == 4
1879 UNIV_MEM_ASSERT_RW(bpage,
sizeof *bpage);
1883 if (buf_debug_prints) {
1884 fprintf(stderr,
"Putting space %lu page %lu to free list\n",
1890 #ifdef UNIV_SYNC_DEBUG
1891 ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX));
1895 if (!buf_LRU_block_remove_hashed(bpage, zip)) {
1899 #ifdef UNIV_SYNC_DEBUG
1901 ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX)
1902 && !rw_lock_own(hash_lock, RW_LOCK_SHARED));
1915 rw_lock_x_lock(hash_lock);
1916 mutex_enter(block_mutex);
1934 ut_ad(!bpage->in_page_hash);
1935 ut_ad(!bpage->in_LRU_list);
1942 ut_ad(!b->in_zip_hash);
1943 ut_ad(b->in_page_hash);
1944 ut_ad(b->in_LRU_list);
1950 if (UNIV_LIKELY(prev_b != NULL)) {
1953 ut_ad(prev_b->in_LRU_list);
1955 #if UNIV_WORD_SIZE == 4
1960 UNIV_MEM_ASSERT_RW(prev_b,
sizeof *prev_b);
1965 incr_LRU_size_in_bytes(b, buf_pool);
1983 buf_LRU_old_adjust_len(buf_pool);
1988 buf_LRU_old_init(buf_pool);
1990 #ifdef UNIV_LRU_DEBUG
1996 ut_d(b->in_LRU_list = FALSE);
2001 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2002 buf_LRU_insert_zip_clean(b);
2011 mutex_exit(block_mutex);
2017 mutex_enter(block_mutex);
2019 mutex_exit(block_mutex);
2021 rw_lock_x_unlock(hash_lock);
2034 mutex_enter(block_mutex);
2036 mutex_exit(block_mutex);
2054 ib_uint32_t checksum;
2065 static_cast<srv_checksum_algorithm_t>(
2074 mutex_enter(block_mutex);
2076 mutex_exit(block_mutex);
2078 buf_LRU_block_free_hashed_page((
buf_block_t*) bpage);
2105 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
2106 ut_a(block->n_pointers == 0);
2114 UNIV_MEM_ALLOC(block->
frame, UNIV_PAGE_SIZE);
2117 memset(block->
frame,
'\0', UNIV_PAGE_SIZE);
2127 mutex_exit(&block->
mutex);
2134 mutex_enter(&block->
mutex);
2139 ut_d(block->
page.in_free_list = TRUE);
2141 UNIV_MEM_ASSERT_AND_FREE(block->
frame, UNIV_PAGE_SIZE);
2160 buf_LRU_block_remove_hashed(
2179 #ifdef UNIV_SYNC_DEBUG
2180 ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX));
2186 #if UNIV_WORD_SIZE == 4
2190 UNIV_MEM_ASSERT_RW(bpage,
sizeof *bpage);
2193 buf_LRU_remove_block(bpage);
2205 const ulint zip_size
2231 #ifdef UNIV_ZIP_DEBUG
2232 ut_a(page_zip_validate(
2239 fputs(
" InnoDB: ERROR: The compressed page"
2240 " to be evicted seems corrupt:", stderr);
2242 fputs(
"\nInnoDB: Possibly older version"
2243 " of the page:", stderr);
2255 UNIV_MEM_ASSERT_W(bpage->
zip.
data,
2271 if (UNIV_UNLIKELY(bpage != hashed_bpage)) {
2273 "InnoDB: Error: page %lu %lu not found"
2274 " in the hash table\n",
2275 (ulong) bpage->
space,
2279 "InnoDB: In hash table we find block"
2280 " %p of %lu %lu which is not %p\n",
2281 (
const void*) hashed_bpage,
2282 (ulong) hashed_bpage->
space,
2283 (ulong) hashed_bpage->
offset,
2284 (
const void*) bpage);
2287 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2289 rw_lock_x_unlock(hash_lock);
2299 ut_ad(!bpage->in_zip_hash);
2300 ut_ad(bpage->in_page_hash);
2301 ut_d(bpage->in_page_hash = FALSE);
2305 ut_ad(!bpage->in_free_list);
2306 ut_ad(!bpage->in_flush_list);
2307 ut_ad(!bpage->in_LRU_list);
2311 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2316 rw_lock_x_unlock(hash_lock);
2355 rw_lock_x_unlock(hash_lock);
2363 ut_ad(!bpage->in_free_list);
2364 ut_ad(!bpage->in_flush_list);
2365 ut_ad(!bpage->in_LRU_list);
2395 buf_LRU_block_free_hashed_page(
2405 mutex_enter(&block->
mutex);
2409 mutex_exit(&block->
mutex);
2430 rw_lock_x_lock(hash_lock);
2431 mutex_enter(block_mutex);
2433 if (buf_LRU_block_remove_hashed(bpage,
true)) {
2434 buf_LRU_block_free_hashed_page((
buf_block_t*) bpage);
2438 #ifdef UNIV_SYNC_DEBUG
2439 ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX)
2440 && !rw_lock_own(hash_lock, RW_LOCK_SHARED));
2442 ut_ad(!mutex_own(block_mutex));
2450 buf_LRU_old_ratio_update_instance(
2477 buf_LRU_old_adjust_len(buf_pool);
2504 ulint new_ratio = 0;
2506 for (i = 0; i < srv_buf_pool_instances; i++) {
2511 new_ratio = buf_LRU_old_ratio_update_instance(
2512 buf_pool, old_pct, adjust);
2529 ibool evict_started = FALSE;
2533 for (i = 0; i < srv_buf_pool_instances; i++) {
2538 evict_started = TRUE;
2543 if (!evict_started) {
2548 item = &buf_LRU_stat_arr[buf_LRU_stat_arr_ind];
2549 buf_LRU_stat_arr_ind++;
2564 memcpy(item, &cur_stat,
sizeof *item);
2571 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2576 buf_LRU_validate_instance(
2655 CheckUnzipLRUAndLRUList());
2661 ut_ad(block->in_unzip_LRU_list);
2674 buf_LRU_validate(
void)
2679 for (i = 0; i < srv_buf_pool_instances; i++) {
2683 buf_LRU_validate_instance(buf_pool);
2690 #if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2695 buf_LRU_print_instance(
2706 while (bpage != NULL) {
2709 fprintf(stderr,
"BLOCK space %lu page %lu ",
2714 fputs(
"old ", stderr);
2718 fprintf(stderr,
"buffix count %lu ",
2723 fprintf(stderr,
"io_fix %lu ",
2728 fputs(
"modif. ", stderr);
2734 frame = buf_block_get_frame((
buf_block_t*) bpage);
2735 fprintf(stderr,
"\ntype %lu"
2742 fprintf(stderr,
"\ntype %lu size %lu"
2750 fprintf(stderr,
"\n!state %lu!\n",
2772 for (i = 0; i < srv_buf_pool_instances; i++) {
2774 buf_LRU_print_instance(buf_pool);