243
242
#ifndef UNIV_HOTBACKUP
244
243
/** Value in microseconds */
245
244
static const int WAIT_FOR_READ = 5000;
246
/** Number of attemtps made to read in a page in the buffer pool */
247
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
249
/** The buffer pools of the database */
250
UNIV_INTERN buf_pool_t* buf_pool_ptr;
246
/** The buffer buf_pool of the database */
247
UNIV_INTERN buf_pool_t* buf_pool = NULL;
249
/** mutex protecting the buffer pool struct and control blocks, except the
250
read-write lock in them */
251
UNIV_INTERN mutex_t buf_pool_mutex;
252
/** mutex protecting the control blocks of compressed-only pages
253
(of type buf_page_t, not buf_block_t) */
254
UNIV_INTERN mutex_t buf_pool_zip_mutex;
252
256
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
253
257
static ulint buf_dbg_counter = 0; /*!< This is used to insert validation
254
operations in execution in the
258
operations in excution in the
260
/** Flag to forbid the release of the buffer pool mutex.
261
Protected by buf_pool_mutex. */
262
UNIV_INTERN ulint buf_pool_mutex_exit_forbidden = 0;
256
263
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
257
264
#ifdef UNIV_DEBUG
258
265
/** If this is set TRUE, the program prints info whenever
260
267
UNIV_INTERN ibool buf_debug_prints = FALSE;
261
268
#endif /* UNIV_DEBUG */
263
#ifdef UNIV_PFS_RWLOCK
264
/* Keys to register buffer block related rwlocks and mutexes with
265
performance schema */
266
UNIV_INTERN mysql_pfs_key_t buf_block_lock_key;
267
# ifdef UNIV_SYNC_DEBUG
268
UNIV_INTERN mysql_pfs_key_t buf_block_debug_latch_key;
269
# endif /* UNIV_SYNC_DEBUG */
270
#endif /* UNIV_PFS_RWLOCK */
272
#ifdef UNIV_PFS_MUTEX
273
UNIV_INTERN mysql_pfs_key_t buffer_block_mutex_key;
274
UNIV_INTERN mysql_pfs_key_t buf_pool_mutex_key;
275
UNIV_INTERN mysql_pfs_key_t buf_pool_zip_mutex_key;
276
UNIV_INTERN mysql_pfs_key_t flush_list_mutex_key;
277
#endif /* UNIV_PFS_MUTEX */
279
#if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK
280
# ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
282
/* Buffer block mutexes and rwlocks can be registered
283
in one group rather than individually. If PFS_GROUP_BUFFER_SYNC
284
is defined, register buffer block mutex and rwlock
285
in one group after their initialization. */
286
# define PFS_GROUP_BUFFER_SYNC
288
/* This define caps the number of mutexes/rwlocks can
289
be registered with performance schema. Developers can
290
modify this define if necessary. Please note, this would
291
be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
292
# define PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER ULINT_MAX
294
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
295
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
297
270
/** A chunk of buffers. The buffer pool is allocated in chunks. */
298
271
struct buf_chunk_struct{
299
272
ulint mem_size; /*!< allocated size of the chunk */
305
278
#endif /* !UNIV_HOTBACKUP */
307
280
/********************************************************************//**
308
Gets the smallest oldest_modification lsn for any page in the pool. Returns
309
zero if all modified pages have been flushed to disk.
310
@return oldest modification in pool, zero if none */
313
buf_pool_get_oldest_modification(void)
314
/*==================================*/
319
ib_uint64_t oldest_lsn = 0;
321
/* When we traverse all the flush lists we don't want another
322
thread to add a dirty page to any flush list. */
323
log_flush_order_mutex_enter();
325
for (i = 0; i < srv_buf_pool_instances; i++) {
326
buf_pool_t* buf_pool;
328
buf_pool = buf_pool_from_array(i);
330
buf_flush_list_mutex_enter(buf_pool);
332
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
335
ut_ad(bpage->in_flush_list);
336
lsn = bpage->oldest_modification;
339
buf_flush_list_mutex_exit(buf_pool);
341
if (!oldest_lsn || oldest_lsn > lsn) {
346
log_flush_order_mutex_exit();
348
/* The returned answer may be out of date: the flush_list can
349
change after the mutex has been released. */
354
/********************************************************************//**
355
Get total buffer pool statistics. */
358
buf_get_total_list_len(
359
/*===================*/
360
ulint* LRU_len, /*!< out: length of all LRU lists */
361
ulint* free_len, /*!< out: length of all free lists */
362
ulint* flush_list_len) /*!< out: length of all flush lists */
370
for (i = 0; i < srv_buf_pool_instances; i++) {
371
buf_pool_t* buf_pool;
373
buf_pool = buf_pool_from_array(i);
374
*LRU_len += UT_LIST_GET_LEN(buf_pool->LRU);
375
*free_len += UT_LIST_GET_LEN(buf_pool->free);
376
*flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
380
/********************************************************************//**
381
Get total buffer pool statistics. */
386
buf_pool_stat_t* tot_stat) /*!< out: buffer pool stats */
390
memset(tot_stat, 0, sizeof(*tot_stat));
392
for (i = 0; i < srv_buf_pool_instances; i++) {
393
buf_pool_stat_t*buf_stat;
394
buf_pool_t* buf_pool;
396
buf_pool = buf_pool_from_array(i);
398
buf_stat = &buf_pool->stat;
399
tot_stat->n_page_gets += buf_stat->n_page_gets;
400
tot_stat->n_pages_read += buf_stat->n_pages_read;
401
tot_stat->n_pages_written += buf_stat->n_pages_written;
402
tot_stat->n_pages_created += buf_stat->n_pages_created;
403
tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
404
tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
405
tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
407
tot_stat->n_pages_not_made_young +=
408
buf_stat->n_pages_not_made_young;
412
/********************************************************************//**
413
Allocates a buffer block.
414
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
419
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
420
ulint zip_size) /*!< in: compressed page size in bytes,
421
or 0 if uncompressed tablespace */
425
static ulint buf_pool_index;
427
if (buf_pool == NULL) {
428
/* We are allocating memory from any buffer pool, ensure
429
we spread the grace on all buffer pool instances. */
430
index = buf_pool_index++ % srv_buf_pool_instances;
431
buf_pool = buf_pool_from_array(index);
434
block = buf_LRU_get_free_block(buf_pool, zip_size);
436
buf_block_set_state(block, BUF_BLOCK_MEMORY);
441
/********************************************************************//**
442
281
Calculates a page checksum which is stored to the page when it is written
443
282
to a file. Note that we must be careful to calculate the same value on
444
283
32-bit and 64-bit architectures.
799
638
#ifndef UNIV_HOTBACKUP
801
# ifdef PFS_GROUP_BUFFER_SYNC
802
/********************************************************************//**
803
This function registers mutexes and rwlocks in buffer blocks with
804
performance schema. If PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER is
805
defined to be a value less than chunk->size, then only mutexes
806
and rwlocks in the first PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER
807
blocks are registered. */
810
pfs_register_buffer_block(
811
/*======================*/
812
buf_chunk_t* chunk) /*!< in/out: chunk of buffers */
815
ulint num_to_register;
818
block = chunk->blocks;
820
num_to_register = ut_min(chunk->size,
821
PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER);
823
for (i = 0; i < num_to_register; i++) {
827
# ifdef UNIV_PFS_MUTEX
828
mutex = &block->mutex;
829
ut_a(!mutex->pfs_psi);
830
mutex->pfs_psi = (PSI_server)
831
? PSI_server->init_mutex(buffer_block_mutex_key, mutex)
833
# endif /* UNIV_PFS_MUTEX */
835
# ifdef UNIV_PFS_RWLOCK
836
rwlock = &block->lock;
837
ut_a(!rwlock->pfs_psi);
838
rwlock->pfs_psi = (PSI_server)
839
? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
841
# endif /* UNIV_PFS_RWLOCK */
845
# endif /* PFS_GROUP_BUFFER_SYNC */
847
639
/********************************************************************//**
848
640
Initializes a buffer control block when the buf_pool is created. */
853
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
854
buf_block_t* block, /*!< in: pointer to control block */
855
byte* frame) /*!< in: pointer to buffer frame */
645
buf_block_t* block, /*!< in: pointer to control block */
646
byte* frame) /*!< in: pointer to buffer frame */
857
648
UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
859
650
block->frame = frame;
861
block->page.buf_pool_index = buf_pool_index(buf_pool);
862
652
block->page.state = BUF_BLOCK_NOT_USED;
863
653
block->page.buf_fix_count = 0;
864
654
block->page.io_fix = BUF_IO_NONE;
887
675
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
888
676
page_zip_des_init(&block->page.zip);
890
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
891
/* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
892
of buffer block mutex/rwlock with performance schema. If
893
PFS_GROUP_BUFFER_SYNC is defined, skip the registration
894
since buffer block mutex/rwlock will be registered later in
895
pfs_register_buffer_block() */
897
mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
898
rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
899
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
900
mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
901
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
902
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
678
mutex_create(&block->mutex, SYNC_BUF_BLOCK);
680
rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
904
681
ut_ad(rw_lock_validate(&(block->lock)));
906
683
#ifdef UNIV_SYNC_DEBUG
907
rw_lock_create(buf_block_debug_latch_key,
908
&block->debug_latch, SYNC_NO_ORDER_CHECK);
684
rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
909
685
#endif /* UNIV_SYNC_DEBUG */
1166
921
/********************************************************************//**
1167
Set buffer pool size variables after resizing it */
1170
buf_pool_set_sizes(void)
1171
/*====================*/
1174
ulint curr_size = 0;
1176
buf_pool_mutex_enter_all();
1178
for (i = 0; i < srv_buf_pool_instances; i++) {
1179
buf_pool_t* buf_pool;
1181
buf_pool = buf_pool_from_array(i);
1182
curr_size += buf_pool->curr_pool_size;
1185
srv_buf_pool_curr_size = curr_size;
1186
srv_buf_pool_old_size = srv_buf_pool_size;
1188
buf_pool_mutex_exit_all();
1191
/********************************************************************//**
1192
Initialize a buffer pool instance.
1193
@return DB_SUCCESS if all goes well. */
1196
buf_pool_init_instance(
1197
/*===================*/
1198
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
1199
ulint buf_pool_size, /*!< in: size in bytes */
1200
ulint instance_no) /*!< in: id of the instance */
922
Creates the buffer pool.
923
@return own: buf_pool object, NULL if not enough memory or error */
932
buf_pool = mem_zalloc(sizeof(buf_pool_t));
1205
934
/* 1. Initialize general fields
1206
935
------------------------------- */
1207
mutex_create(buf_pool_mutex_key,
1208
&buf_pool->mutex, SYNC_BUF_POOL);
1209
mutex_create(buf_pool_zip_mutex_key,
1210
&buf_pool->zip_mutex, SYNC_BUF_BLOCK);
1212
buf_pool_mutex_enter(buf_pool);
1214
if (buf_pool_size > 0) {
1215
buf_pool->n_chunks = 1;
1216
void *chunk_ptr= mem_zalloc((sizeof *chunk));
1217
buf_pool->chunks = chunk = static_cast<buf_chunk_t *>(chunk_ptr);
1219
UT_LIST_INIT(buf_pool->free);
1221
if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
1225
buf_pool_mutex_exit(buf_pool);
1230
buf_pool->instance_no = instance_no;
1231
buf_pool->old_pool_size = buf_pool_size;
1232
buf_pool->curr_size = chunk->size;
1233
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1235
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
1236
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
1238
buf_pool->last_printout_time = ut_time();
936
mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
937
mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
939
buf_pool_mutex_enter();
941
buf_pool->n_chunks = 1;
942
buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
944
UT_LIST_INIT(buf_pool->free);
946
if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
953
srv_buf_pool_old_size = srv_buf_pool_size;
954
buf_pool->curr_size = chunk->size;
955
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
957
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
958
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
960
buf_pool->last_printout_time = time(NULL);
1240
962
/* 2. Initialize flushing fields
1241
963
-------------------------------- */
1243
mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1244
SYNC_BUF_FLUSH_LIST);
1246
965
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1247
966
buf_pool->no_flush[i] = os_event_create(NULL);
969
buf_pool->ulint_clock = 1;
1250
971
/* 3. Initialize LRU fields
1251
972
--------------------------- */
1253
/* All fields are initialized by mem_zalloc(). */
1255
buf_pool_mutex_exit(buf_pool);
973
/* All fields are initialized by mem_zalloc(). */
975
buf_pool_mutex_exit();
977
btr_search_sys_create(buf_pool->curr_size
978
* UNIV_PAGE_SIZE / sizeof(void*) / 64);
980
/* 4. Initialize the buddy allocator fields */
981
/* All fields are initialized by mem_zalloc(). */
1260
986
/********************************************************************//**
1261
free one buffer pool instance */
987
Frees the buffer pool at shutdown. This must not be invoked before
988
freeing all mutexes. */
1264
buf_pool_free_instance(
1265
/*===================*/
1266
buf_pool_t* buf_pool) /* in,own: buffer pool instance
1269
994
buf_chunk_t* chunk;
1270
995
buf_chunk_t* chunks;
1278
1003
os_mem_free_large(chunk->mem, chunk->mem_size);
1281
mem_free(buf_pool->chunks);
1282
hash_table_free(buf_pool->page_hash);
1283
hash_table_free(buf_pool->zip_hash);
1286
/********************************************************************//**
1287
Creates the buffer pool.
1288
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
1293
ulint total_size, /*!< in: size of the total pool in bytes */
1294
ulint n_instances) /*!< in: number of instances */
1297
const ulint size = total_size / n_instances;
1299
ut_ad(n_instances > 0);
1300
ut_ad(n_instances <= MAX_BUFFER_POOLS);
1301
ut_ad(n_instances == srv_buf_pool_instances);
1303
/* We create an extra buffer pool instance, this instance is used
1304
for flushing the flush lists, to keep track of n_flush for all
1305
the buffer pools and also used as a waiting object during flushing. */
1306
void *buf_pool_void_ptr= mem_zalloc(n_instances * sizeof *buf_pool_ptr);
1307
buf_pool_ptr = static_cast<buf_pool_struct *>(buf_pool_void_ptr);
1309
for (i = 0; i < n_instances; i++) {
1310
buf_pool_t* ptr = &buf_pool_ptr[i];
1312
if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
1314
/* Free all the instances created so far. */
1321
buf_pool_set_sizes();
1322
buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
1324
btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
1329
/********************************************************************//**
1330
Frees the buffer pool at shutdown. This must not be invoked before
1331
freeing all mutexes. */
1336
ulint n_instances) /*!< in: numbere of instances to free */
1340
for (i = 0; i < n_instances; i++) {
1341
buf_pool_free_instance(buf_pool_from_array(i));
1344
mem_free(buf_pool_ptr);
1345
buf_pool_ptr = NULL;
1348
/********************************************************************//**
1349
Drops adaptive hash index for a buffer pool instance. */
1352
buf_pool_drop_hash_index_instance(
1353
/*==============================*/
1354
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
1355
ibool* released_search_latch) /*!< out: flag for signalling
1356
whether the search latch was
1359
buf_chunk_t* chunks = buf_pool->chunks;
1360
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
1362
while (--chunk >= chunks) {
1364
buf_block_t* block = chunk->blocks;
1366
for (i = chunk->size; i--; block++) {
1367
/* block->is_hashed cannot be modified
1368
when we have an x-latch on btr_search_latch;
1369
see the comment in buf0buf.h */
1371
if (!block->is_hashed) {
1375
/* To follow the latching order, we
1376
have to release btr_search_latch
1377
before acquiring block->latch. */
1378
rw_lock_x_unlock(&btr_search_latch);
1379
/* When we release the search latch,
1380
we must rescan all blocks, because
1381
some may become hashed again. */
1382
*released_search_latch = TRUE;
1384
rw_lock_x_lock(&block->lock);
1386
/* This should be guaranteed by the
1387
callers, which will be holding
1388
btr_search_enabled_mutex. */
1389
ut_ad(!btr_search_enabled);
1391
/* Because we did not buffer-fix the
1392
block by calling buf_block_get_gen(),
1393
it is possible that the block has been
1394
allocated for some other use after
1395
btr_search_latch was released above.
1396
We do not care which file page the
1397
block is mapped to. All we want to do
1398
is to drop any hash entries referring
1401
/* It is possible that
1402
block->page.state != BUF_FILE_PAGE.
1403
Even that does not matter, because
1404
btr_search_drop_page_hash_index() will
1405
check block->is_hashed before doing
1406
anything. block->is_hashed can only
1407
be set on uncompressed file pages. */
1409
btr_search_drop_page_hash_index(block);
1411
rw_lock_x_unlock(&block->lock);
1413
rw_lock_x_lock(&btr_search_latch);
1415
ut_ad(!btr_search_enabled);
1006
buf_pool->n_chunks = 0;
1420
1009
/********************************************************************//**
1421
1010
Drops the adaptive hash index. To prevent a livelock, this function
1422
1011
is only to be called while holding btr_search_latch and while
1434
1023
ut_ad(!btr_search_enabled);
1026
buf_chunk_t* chunks = buf_pool->chunks;
1027
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
1439
1029
released_search_latch = FALSE;
1441
for (i = 0; i < srv_buf_pool_instances; i++) {
1442
buf_pool_t* buf_pool;
1444
buf_pool = buf_pool_from_array(i);
1446
buf_pool_drop_hash_index_instance(
1447
buf_pool, &released_search_latch);
1031
while (--chunk >= chunks) {
1032
buf_block_t* block = chunk->blocks;
1033
ulint i = chunk->size;
1035
for (; i--; block++) {
1036
/* block->is_hashed cannot be modified
1037
when we have an x-latch on btr_search_latch;
1038
see the comment in buf0buf.h */
1040
if (!block->is_hashed) {
1044
/* To follow the latching order, we
1045
have to release btr_search_latch
1046
before acquiring block->latch. */
1047
rw_lock_x_unlock(&btr_search_latch);
1048
/* When we release the search latch,
1049
we must rescan all blocks, because
1050
some may become hashed again. */
1051
released_search_latch = TRUE;
1053
rw_lock_x_lock(&block->lock);
1055
/* This should be guaranteed by the
1056
callers, which will be holding
1057
btr_search_enabled_mutex. */
1058
ut_ad(!btr_search_enabled);
1060
/* Because we did not buffer-fix the
1061
block by calling buf_block_get_gen(),
1062
it is possible that the block has been
1063
allocated for some other use after
1064
btr_search_latch was released above.
1065
We do not care which file page the
1066
block is mapped to. All we want to do
1067
is to drop any hash entries referring
1070
/* It is possible that
1071
block->page.state != BUF_FILE_PAGE.
1072
Even that does not matter, because
1073
btr_search_drop_page_hash_index() will
1074
check block->is_hashed before doing
1075
anything. block->is_hashed can only
1076
be set on uncompressed file pages. */
1078
btr_search_drop_page_hash_index(block);
1080
rw_lock_x_unlock(&block->lock);
1082
rw_lock_x_lock(&btr_search_latch);
1084
ut_ad(!btr_search_enabled);
1450
1087
} while (released_search_latch);
1679
1309
goto shrink_again;
1684
buf_pool->old_pool_size = buf_pool->curr_pool_size;
1313
srv_buf_pool_old_size = srv_buf_pool_size;
1686
buf_pool_mutex_exit(buf_pool);
1315
buf_pool_mutex_exit();
1687
1316
btr_search_enable();
1690
1319
/********************************************************************//**
1691
Shrinks the buffer pool. */
1696
ulint chunk_size) /*!< in: number of pages to remove */
1700
for (i = 0; i < srv_buf_pool_instances; i++) {
1701
buf_pool_t* buf_pool;
1702
ulint instance_chunk_size;
1704
instance_chunk_size = chunk_size / srv_buf_pool_instances;
1705
buf_pool = buf_pool_from_array(i);
1706
buf_pool_shrink_instance(buf_pool, instance_chunk_size);
1709
buf_pool_set_sizes();
1712
/********************************************************************//**
1713
Rebuild buf_pool->page_hash for a buffer pool instance. */
1716
buf_pool_page_hash_rebuild_instance(
1717
/*================================*/
1718
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
1320
Rebuild buf_pool->page_hash. */
1323
buf_pool_page_hash_rebuild(void)
1324
/*============================*/
1723
1327
ulint n_chunks;
1329
hash_table_t* page_hash;
1724
1330
hash_table_t* zip_hash;
1725
hash_table_t* page_hash;
1727
buf_pool_mutex_enter(buf_pool);
1333
buf_pool_mutex_enter();
1729
1335
/* Free, create, and populate the hash table. */
1730
1336
hash_table_free(buf_pool->page_hash);
1808
buf_flush_list_mutex_exit(buf_pool);
1809
buf_pool_mutex_exit(buf_pool);
1812
/********************************************************************
1813
Determine if a block is a sentinel for a buffer pool watch.
1814
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
1817
buf_pool_watch_is_sentinel(
1818
/*=======================*/
1819
buf_pool_t* buf_pool, /*!< buffer pool instance */
1820
const buf_page_t* bpage) /*!< in: block */
1822
ut_ad(buf_page_in_file(bpage));
1824
if (bpage < &buf_pool->watch[0]
1825
|| bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
1827
ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
1828
|| bpage->zip.data != NULL);
1833
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
1834
ut_ad(!bpage->in_zip_hash);
1835
ut_ad(bpage->in_page_hash);
1836
ut_ad(bpage->zip.data == NULL);
1837
ut_ad(bpage->buf_fix_count > 0);
1841
/****************************************************************//**
1842
Add watch for the given page to be read in. Caller must have the buffer pool
1844
@return NULL if watch set, block if the page is in the buffer pool */
1849
ulint space, /*!< in: space id */
1850
ulint offset, /*!< in: page number */
1851
ulint fold) /*!< in: buf_page_address_fold(space, offset) */
1855
buf_pool_t* buf_pool = buf_pool_get(space, offset);
1857
ut_ad(buf_pool_mutex_own(buf_pool));
1859
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
1861
if (UNIV_LIKELY_NULL(bpage)) {
1862
if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
1863
/* The page was loaded meanwhile. */
1866
/* Add to an existing watch. */
1867
bpage->buf_fix_count++;
1871
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
1872
bpage = &buf_pool->watch[i];
1874
ut_ad(bpage->access_time == 0);
1875
ut_ad(bpage->newest_modification == 0);
1876
ut_ad(bpage->oldest_modification == 0);
1877
ut_ad(bpage->zip.data == NULL);
1878
ut_ad(!bpage->in_zip_hash);
1880
switch (bpage->state) {
1881
case BUF_BLOCK_POOL_WATCH:
1882
ut_ad(!bpage->in_page_hash);
1883
ut_ad(bpage->buf_fix_count == 0);
1885
/* bpage is pointing to buf_pool->watch[],
1886
which is protected by buf_pool->mutex.
1887
Normally, buf_page_t objects are protected by
1888
buf_block_t::mutex or buf_pool->zip_mutex or both. */
1890
bpage->state = BUF_BLOCK_ZIP_PAGE;
1891
bpage->space = space;
1892
bpage->offset = offset;
1893
bpage->buf_fix_count = 1;
1895
ut_d(bpage->in_page_hash = TRUE);
1896
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
1899
case BUF_BLOCK_ZIP_PAGE:
1900
ut_ad(bpage->in_page_hash);
1901
ut_ad(bpage->buf_fix_count > 0);
1908
/* Allocation failed. Either the maximum number of purge
1909
threads should never exceed BUF_POOL_WATCH_SIZE, or this code
1910
should be modified to return a special non-NULL value and the
1911
caller should purge the record directly. */
1914
/* Fix compiler warning */
1918
/********************************************************************//**
1919
Rebuild buf_pool->page_hash. */
1922
buf_pool_page_hash_rebuild(void)
1923
/*============================*/
1927
for (i = 0; i < srv_buf_pool_instances; i++) {
1928
buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
1932
/********************************************************************//**
1933
Increase the buffer pool size of one buffer pool instance. */
1936
buf_pool_increase_instance(
1937
/*=======================*/
1938
buf_pool_t* buf_pool, /*!< in: buffer pool instane */
1939
ulint change_size) /*!< in: new size of the pool */
1941
buf_chunk_t* chunks;
1944
buf_pool_mutex_enter(buf_pool);
1945
chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks));
1947
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
1949
chunk = &chunks[buf_pool->n_chunks];
1951
if (!buf_chunk_init(buf_pool, chunk, change_size)) {
1954
buf_pool->old_pool_size = buf_pool->curr_pool_size;
1955
buf_pool->curr_size += chunk->size;
1956
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1957
mem_free(buf_pool->chunks);
1958
buf_pool->chunks = chunks;
1959
buf_pool->n_chunks++;
1962
buf_pool_mutex_exit(buf_pool);
1965
/********************************************************************//**
1966
Increase the buffer pool size. */
1975
for (i = 0; i < srv_buf_pool_instances; i++) {
1976
buf_pool_increase_instance(
1977
buf_pool_from_array(i),
1978
change_size / srv_buf_pool_instances);
1981
buf_pool_set_sizes();
1413
buf_pool_mutex_exit();
1984
1416
/********************************************************************//**
1988
1420
buf_pool_resize(void)
1989
1421
/*=================*/
1992
ulint min_change_size = 1048576 * srv_buf_pool_instances;
1994
buf_pool_mutex_enter_all();
1996
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1998
buf_pool_mutex_exit_all();
2002
} else if (srv_buf_pool_curr_size + min_change_size
2003
> srv_buf_pool_size) {
2005
change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
2008
buf_pool_mutex_exit_all();
2010
/* Disable adaptive hash indexes and empty the index
2011
in order to free up memory in the buffer pool chunks. */
2012
buf_pool_shrink(change_size);
2014
} else if (srv_buf_pool_curr_size + min_change_size
2015
< srv_buf_pool_size) {
2017
/* Enlarge the buffer pool by at least one megabyte */
2019
change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
2021
buf_pool_mutex_exit_all();
2023
buf_pool_increase(change_size);
2025
srv_buf_pool_size = srv_buf_pool_old_size;
2027
buf_pool_mutex_exit_all();
1423
buf_pool_mutex_enter();
1425
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1427
buf_pool_mutex_exit();
2032
buf_pool_page_hash_rebuild();
2035
/****************************************************************//**
2036
Remove the sentinel block for the watch before replacing it with a real block.
2037
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
2038
the block has been replaced with the real block.
2039
@return reference count, to be added to the replacement block */
2042
buf_pool_watch_remove(
2043
/*==================*/
2044
buf_pool_t* buf_pool, /*!< buffer pool instance */
2045
ulint fold, /*!< in: buf_page_address_fold(
2047
buf_page_t* watch) /*!< in/out: sentinel for watch */
2049
ut_ad(buf_pool_mutex_own(buf_pool));
2051
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
2052
ut_d(watch->in_page_hash = FALSE);
2053
watch->buf_fix_count = 0;
2054
watch->state = BUF_BLOCK_POOL_WATCH;
2057
/****************************************************************//**
2058
Stop watching if the page has been read in.
2059
buf_pool_watch_set(space,offset) must have returned NULL before. */
2062
buf_pool_watch_unset(
1431
if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
1433
buf_pool_mutex_exit();
1435
/* Disable adaptive hash indexes and empty the index
1436
in order to free up memory in the buffer pool chunks. */
1437
buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
1439
} else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
1441
/* Enlarge the buffer pool by at least one megabyte */
1444
= srv_buf_pool_size - srv_buf_pool_curr_size;
1445
buf_chunk_t* chunks;
1448
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1450
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
1453
chunk = &chunks[buf_pool->n_chunks];
1455
if (!buf_chunk_init(chunk, mem_size)) {
1458
buf_pool->curr_size += chunk->size;
1459
srv_buf_pool_curr_size = buf_pool->curr_size
1461
mem_free(buf_pool->chunks);
1462
buf_pool->chunks = chunks;
1463
buf_pool->n_chunks++;
1466
srv_buf_pool_old_size = srv_buf_pool_size;
1467
buf_pool_mutex_exit();
1470
buf_pool_page_hash_rebuild();
1473
/********************************************************************//**
1474
Moves the block to the start of the LRU list if there is a danger
1475
that the block would drift out of the buffer pool. */
1478
buf_block_make_young(
2063
1479
/*=================*/
2064
ulint space, /*!< in: space id */
2065
ulint offset) /*!< in: page number */
1480
buf_page_t* bpage) /*!< in: block to make younger */
2068
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2069
ulint fold = buf_page_address_fold(space, offset);
2071
buf_pool_mutex_enter(buf_pool);
2072
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
2073
/* The page must exist because buf_pool_watch_set()
2074
increments buf_fix_count. */
2077
if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
2078
mutex_t* mutex = buf_page_get_mutex(bpage);
2081
ut_a(bpage->buf_fix_count > 0);
2082
bpage->buf_fix_count--;
2085
ut_a(bpage->buf_fix_count > 0);
2087
if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
2088
buf_pool_watch_remove(buf_pool, fold, bpage);
1482
ut_ad(!buf_pool_mutex_own());
1484
/* Note that we read freed_page_clock's without holding any mutex:
1485
this is allowed since the result is used only in heuristics */
1487
if (buf_page_peek_if_too_old(bpage)) {
1489
buf_pool_mutex_enter();
1490
/* There has been freeing activity in the LRU list:
1491
best to move to the head of the LRU list */
1493
buf_LRU_make_block_young(bpage);
1494
buf_pool_mutex_exit();
2092
buf_pool_mutex_exit(buf_pool);
2095
/****************************************************************//**
2096
Check if the page has been read in.
2097
This may only be called after buf_pool_watch_set(space,offset)
2098
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
2099
@return FALSE if the given page was not read in, TRUE if it was */
2102
buf_pool_watch_occurred(
2103
/*====================*/
2104
ulint space, /*!< in: space id */
2105
ulint offset) /*!< in: page number */
2109
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2110
ulint fold = buf_page_address_fold(space, offset);
2112
buf_pool_mutex_enter(buf_pool);
2114
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
2115
/* The page must exist because buf_pool_watch_set()
2116
increments buf_fix_count. */
2118
ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
2119
buf_pool_mutex_exit(buf_pool);
2124
1498
/********************************************************************//**
2125
1499
Moves a page to the start of the buffer pool LRU list. This high-level
2126
function can be used to prevent an important page from slipping out of
1500
function can be used to prevent an important page from from slipping out of
2127
1501
the buffer pool. */
2131
1505
/*================*/
2132
1506
buf_page_t* bpage) /*!< in: buffer block of a file page */
2134
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
2136
buf_pool_mutex_enter(buf_pool);
1508
buf_pool_mutex_enter();
2138
1510
ut_a(buf_page_in_file(bpage));
2140
1512
buf_LRU_make_block_young(bpage);
2142
buf_pool_mutex_exit(buf_pool);
2145
/********************************************************************//**
2146
Sets the time of the first access of a page and moves a page to the
2147
start of the buffer pool LRU list if it is too old. This high-level
2148
function can be used to prevent an important page from slipping
2149
out of the buffer pool. */
2152
buf_page_set_accessed_make_young(
2153
/*=============================*/
2154
buf_page_t* bpage, /*!< in/out: buffer block of a
2156
unsigned access_time) /*!< in: bpage->access_time
2157
read under mutex protection,
2160
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
2162
ut_ad(!buf_pool_mutex_own(buf_pool));
2163
ut_a(buf_page_in_file(bpage));
2165
if (buf_page_peek_if_too_old(bpage)) {
2166
buf_pool_mutex_enter(buf_pool);
2167
buf_LRU_make_block_young(bpage);
2168
buf_pool_mutex_exit(buf_pool);
2169
} else if (!access_time) {
2170
ulint time_ms = ut_time_ms();
2171
buf_pool_mutex_enter(buf_pool);
2172
buf_page_set_accessed(bpage, time_ms);
2173
buf_pool_mutex_exit(buf_pool);
1514
buf_pool_mutex_exit();
2177
1517
/********************************************************************//**
2663
1963
/********************************************************************//**
2664
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
2665
the buf_block_t itself or a member of it
2666
@return TRUE if ptr belongs to a buf_block_t struct */
2669
buf_pointer_is_block_field(
2670
/*=======================*/
2671
const void* ptr) /*!< in: pointer not dereferenced */
2675
for (i = 0; i < srv_buf_pool_instances; i++) {
2678
found = buf_pointer_is_block_field_instance(
2679
buf_pool_from_array(i), ptr);
2688
/********************************************************************//**
2689
1964
Find out if a buffer block was created by buf_chunk_init().
2690
1965
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2693
1968
buf_block_is_uncompressed(
2694
1969
/*======================*/
2695
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
2696
const buf_block_t* block) /*!< in: pointer to block,
1970
const buf_block_t* block) /*!< in: pointer to block,
2699
ut_ad(buf_pool_mutex_own(buf_pool));
1973
ut_ad(buf_pool_mutex_own());
2701
1975
if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2702
1976
/* The pointer should be aligned. */
2706
return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
1980
return(buf_pointer_is_block_field((void *)block));
2709
1983
/********************************************************************//**
2720
1994
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2721
1995
buf_block_t* guess, /*!< in: guessed block or NULL */
2722
1996
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2723
BUF_GET_NO_LATCH, or
2724
BUF_GET_IF_IN_POOL_OR_WATCH */
2725
1998
const char* file, /*!< in: file name */
2726
1999
ulint line, /*!< in: line where called */
2727
2000
mtr_t* mtr) /*!< in: mini-transaction */
2729
2002
buf_block_t* block;
2731
unsigned access_time;
2732
2004
ulint fix_type;
2733
2005
ibool must_read;
2735
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2738
ut_ad(mtr->state == MTR_ACTIVE);
2739
2008
ut_ad((rw_latch == RW_S_LATCH)
2740
2009
|| (rw_latch == RW_X_LATCH)
2741
2010
|| (rw_latch == RW_NO_LATCH));
2742
2011
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
2743
ut_ad(mode == BUF_GET
2744
|| mode == BUF_GET_IF_IN_POOL
2745
|| mode == BUF_GET_NO_LATCH
2746
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH);
2012
ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
2013
|| (mode == BUF_GET_NO_LATCH));
2747
2014
ut_ad(zip_size == fil_space_get_zip_size(space));
2748
2015
ut_ad(ut_is_2pow(zip_size));
2749
2016
#ifndef UNIV_LOG_DEBUG
2750
2017
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2752
buf_pool->stat.n_page_gets++;
2753
fold = buf_page_address_fold(space, offset);
2019
buf_pool->n_page_gets++;
2756
buf_pool_mutex_enter(buf_pool);
2022
buf_pool_mutex_enter();
2759
2025
/* If the guess is a compressed page descriptor that
2779
2045
if (block == NULL) {
2780
block = (buf_block_t*) buf_page_hash_get_low(
2781
buf_pool, space, offset, fold);
2046
block = (buf_block_t*) buf_page_hash_get(space, offset);
2785
if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2789
2050
if (block == NULL) {
2790
2051
/* Page not in buf_pool: needs to be read from file */
2792
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2793
block = (buf_block_t*) buf_pool_watch_set(
2794
space, offset, fold);
2796
if (UNIV_LIKELY_NULL(block)) {
2802
buf_pool_mutex_exit(buf_pool);
2804
if (mode == BUF_GET_IF_IN_POOL
2805
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2053
buf_pool_mutex_exit();
2055
if (mode == BUF_GET_IF_IN_POOL) {
2810
if (buf_read_page(space, zip_size, offset)) {
2812
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
2815
fprintf(stderr, "InnoDB: Error: Unable"
2816
" to read tablespace %lu page no"
2817
" %lu into the buffer pool after"
2819
"InnoDB: The most probable cause"
2820
" of this error may be that the"
2821
" table has been corrupted.\n"
2822
"InnoDB: You can try to fix this"
2824
" innodb_force_recovery.\n"
2825
"InnoDB: Please see reference manual"
2826
" for more details.\n"
2827
"InnoDB: Aborting...\n",
2829
BUF_PAGE_READ_MAX_RETRIES);
2060
buf_read_page(space, zip_size, offset);
2834
2062
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2835
2063
ut_a(++buf_dbg_counter % 37 || buf_validate());
2863
2087
case BUF_BLOCK_ZIP_DIRTY:
2864
2088
bpage = &block->page;
2865
2089
/* Protect bpage->buf_fix_count. */
2866
mutex_enter(&buf_pool->zip_mutex);
2090
mutex_enter(&buf_pool_zip_mutex);
2868
2092
if (bpage->buf_fix_count
2869
2093
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2870
2094
/* This condition often occurs when the buffer
2871
2095
is not buffer-fixed, but I/O-fixed by
2872
2096
buf_page_init_for_read(). */
2873
mutex_exit(&buf_pool->zip_mutex);
2097
mutex_exit(&buf_pool_zip_mutex);
2874
2098
wait_until_unfixed:
2875
2099
/* The block is buffer-fixed or I/O-fixed.
2876
2100
Try again later. */
2877
buf_pool_mutex_exit(buf_pool);
2101
buf_pool_mutex_exit();
2878
2102
os_thread_sleep(WAIT_FOR_READ);
2883
2107
/* Allocate an uncompressed page. */
2884
buf_pool_mutex_exit(buf_pool);
2885
mutex_exit(&buf_pool->zip_mutex);
2108
buf_pool_mutex_exit();
2109
mutex_exit(&buf_pool_zip_mutex);
2887
block = buf_LRU_get_free_block(buf_pool, 0);
2111
block = buf_LRU_get_free_block(0);
2890
buf_pool_mutex_enter(buf_pool);
2114
buf_pool_mutex_enter();
2891
2115
mutex_enter(&block->mutex);
2894
buf_page_t* hash_bpage;
2896
hash_bpage = buf_page_hash_get_low(
2897
buf_pool, space, offset, fold);
2118
buf_page_t* hash_bpage
2119
= buf_page_hash_get(space, offset);
2899
2121
if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2900
2122
/* The buf_pool->page_hash was modified
2901
while buf_pool->mutex was released.
2123
while buf_pool_mutex was released.
2902
2124
Free the block that was allocated. */
2904
2126
buf_LRU_block_free_non_file_page(block);
2958
2194
block->page.buf_fix_count = 1;
2959
2195
buf_block_set_io_fix(block, BUF_IO_READ);
2960
rw_lock_x_lock_func(&block->lock, 0, file, line);
2962
UNIV_MEM_INVALID(bpage, sizeof *bpage);
2196
rw_lock_x_lock(&block->lock);
2964
2197
mutex_exit(&block->mutex);
2965
mutex_exit(&buf_pool->zip_mutex);
2198
mutex_exit(&buf_pool_zip_mutex);
2966
2199
buf_pool->n_pend_unzip++;
2968
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2201
buf_buddy_free(bpage, sizeof *bpage);
2970
buf_pool_mutex_exit(buf_pool);
2203
buf_pool_mutex_exit();
2972
2205
/* Decompress the page and apply buffered operations
2973
while not holding buf_pool->mutex or block->mutex. */
2206
while not holding buf_pool_mutex or block->mutex. */
2974
2207
success = buf_zip_decompress(block, srv_use_checksums);
2977
if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
2209
if (UNIV_LIKELY(success)) {
2978
2210
ibuf_merge_or_delete_for_page(block, space, offset,
2979
2211
zip_size, TRUE);
2982
2214
/* Unfix and unlatch the block. */
2983
buf_pool_mutex_enter(buf_pool);
2215
buf_pool_mutex_enter();
2984
2216
mutex_enter(&block->mutex);
2985
2217
block->page.buf_fix_count--;
2986
2218
buf_block_set_io_fix(block, BUF_IO_NONE);
3002
2240
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3004
2242
mutex_enter(&block->mutex);
3005
#if UNIV_WORD_SIZE == 4
3006
/* On 32-bit systems, there is no padding in buf_page_t. On
3007
other systems, Valgrind could complain about uninitialized pad
3009
2243
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
3011
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
3012
if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
3014
/* Try to evict the block from the buffer pool, to use the
3015
insert buffer (change buffer) as much as possible. */
3017
if (buf_LRU_free_block(&block->page, TRUE, NULL)
3019
mutex_exit(&block->mutex);
3020
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
3021
/* Set the watch, as it would have
3022
been set if the page were not in the
3023
buffer pool in the first place. */
3024
block = (buf_block_t*) buf_pool_watch_set(
3025
space, offset, fold);
3027
if (UNIV_LIKELY_NULL(block)) {
3029
/* The page entered the buffer
3030
pool for some reason. Try to
3035
buf_pool_mutex_exit(buf_pool);
3037
"innodb_change_buffering_debug evict %u %u\n",
3038
(unsigned) space, (unsigned) offset);
3040
} else if (buf_flush_page_try(buf_pool, block)) {
3042
"innodb_change_buffering_debug flush %u %u\n",
3043
(unsigned) space, (unsigned) offset);
3048
/* Failed to evict the page; change it directly */
3050
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
3052
2245
buf_block_buf_fix_inc(block, file, line);
2246
buf_pool_mutex_exit();
2248
/* Check if this is the first access to the page */
2250
accessed = buf_page_is_accessed(&block->page);
2252
buf_page_set_accessed(&block->page, TRUE);
3054
2254
mutex_exit(&block->mutex);
3056
/* Check if this is the first access to the page */
3058
access_time = buf_page_is_accessed(&block->page);
3060
buf_pool_mutex_exit(buf_pool);
3062
buf_page_set_accessed_make_young(&block->page, access_time);
2256
buf_block_make_young(&block->page);
3064
2258
#ifdef UNIV_DEBUG_FILE_ACCESSES
3065
2259
ut_a(!block->page.file_page_was_freed);
3681
2825
control block (bpage), in order to avoid the
3682
2826
invocation of buf_buddy_relocate_block() on
3683
2827
uninitialized data. */
3684
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3685
bpage = static_cast<buf_page_struct *>(buf_buddy_alloc(buf_pool, sizeof *bpage, &lru));
3687
/* Initialize the buf_pool pointer. */
3688
bpage->buf_pool_index = buf_pool_index(buf_pool);
2828
data = buf_buddy_alloc(zip_size, &lru);
2829
bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3690
2831
/* If buf_buddy_alloc() allocated storage from the LRU list,
3691
it released and reacquired buf_pool->mutex. Thus, we must
2832
it released and reacquired buf_pool_mutex. Thus, we must
3692
2833
check the page_hash again, as it may have been modified. */
3693
if (UNIV_UNLIKELY(lru)) {
3695
watch_page = buf_page_hash_get_low(
3696
buf_pool, space, offset, fold);
3699
&& !buf_pool_watch_is_sentinel(buf_pool,
3702
/* The block was added by some other thread. */
3704
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
3705
buf_buddy_free(buf_pool, data, zip_size);
2834
if (UNIV_UNLIKELY(lru)
2835
&& UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
2837
/* The block was added by some other thread. */
2838
buf_buddy_free(bpage, sizeof *bpage);
2839
buf_buddy_free(data, zip_size);
3712
2845
page_zip_des_init(&bpage->zip);
3713
2846
page_zip_set_size(&bpage->zip, zip_size);
3714
bpage->zip.data = static_cast<unsigned char *>(data);
2847
bpage->zip.data = data;
3716
mutex_enter(&buf_pool->zip_mutex);
2849
mutex_enter(&buf_pool_zip_mutex);
3717
2850
UNIV_MEM_DESC(bpage->zip.data,
3718
2851
page_zip_get_size(&bpage->zip), bpage);
3720
2852
buf_page_init_low(bpage);
3722
2853
bpage->state = BUF_BLOCK_ZIP_PAGE;
3723
2854
bpage->space = space;
3724
2855
bpage->offset = offset;
3727
2857
#ifdef UNIV_DEBUG
3728
2858
bpage->in_page_hash = FALSE;
3729
2859
bpage->in_zip_hash = FALSE;
4129
3239
#endif /* UNIV_DEBUG */
4131
3241
mutex_exit(buf_page_get_mutex(bpage));
4132
buf_pool_mutex_exit(buf_pool);
4135
/*********************************************************************//**
4136
Asserts that all file pages in the buffer are in a replaceable state.
4140
buf_all_freed_instance(
4141
/*===================*/
4142
buf_pool_t* buf_pool) /*!< in: buffer pool instancce */
4149
buf_pool_mutex_enter(buf_pool);
4151
chunk = buf_pool->chunks;
4153
for (i = buf_pool->n_chunks; i--; chunk++) {
4155
const buf_block_t* block = buf_chunk_not_freed(chunk);
4157
if (UNIV_LIKELY_NULL(block)) {
4159
"Page %lu %lu still fixed or dirty\n",
4160
(ulong) block->page.space,
4161
(ulong) block->page.offset);
4166
buf_pool_mutex_exit(buf_pool);
4171
/*********************************************************************//**
4172
Invalidates file pages in one buffer pool instance */
3242
buf_pool_mutex_exit();
3245
/*********************************************************************//**
3246
Invalidates the file pages in the buffer pool when an archive recovery is
3247
completed. All the file pages buffered must be in a replaceable state when
3248
this function is called: not latched and not modified. */
4175
buf_pool_invalidate_instance(
4176
/*=========================*/
4177
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
3251
buf_pool_invalidate(void)
3252
/*=====================*/
4182
buf_pool_mutex_enter(buf_pool);
4184
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
4186
/* As this function is called during startup and
4187
during redo application phase during recovery, InnoDB
4188
is single threaded (apart from IO helper threads) at
4189
this stage. No new write batch can be in intialization
4190
stage at this point. */
4191
ut_ad(buf_pool->init_flush[i] == FALSE);
4193
/* However, it is possible that a write batch that has
4194
been posted earlier is still not complete. For buffer
4195
pool invalidation to proceed we must ensure there is NO
4196
write activity happening. */
4197
if (buf_pool->n_flush[i] > 0) {
4198
buf_pool_mutex_exit(buf_pool);
4199
buf_flush_wait_batch_end(buf_pool, static_cast<buf_flush>(i));
4200
buf_pool_mutex_enter(buf_pool);
4204
buf_pool_mutex_exit(buf_pool);
4206
ut_ad(buf_all_freed_instance(buf_pool));
3256
ut_ad(buf_all_freed());
4210
3260
while (freed) {
4211
freed = buf_LRU_search_and_free_block(buf_pool, 100);
3261
freed = buf_LRU_search_and_free_block(100);
4214
buf_pool_mutex_enter(buf_pool);
3264
buf_pool_mutex_enter();
4216
3266
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
4217
3267
ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
4219
buf_pool->freed_page_clock = 0;
4220
buf_pool->LRU_old = NULL;
4221
buf_pool->LRU_old_len = 0;
4222
buf_pool->LRU_flush_ended = 0;
4224
memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
4225
buf_refresh_io_stats(buf_pool);
4227
buf_pool_mutex_exit(buf_pool);
4230
/*********************************************************************//**
4231
Invalidates the file pages in the buffer pool when an archive recovery is
4232
completed. All the file pages buffered must be in a replaceable state when
4233
this function is called: not latched and not modified. */
4236
buf_pool_invalidate(void)
4237
/*=====================*/
4241
for (i = 0; i < srv_buf_pool_instances; i++) {
4242
buf_pool_invalidate_instance(buf_pool_from_array(i));
3269
buf_pool_mutex_exit();
4246
3272
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4247
3273
/*********************************************************************//**
4248
Validates data in one buffer pool instance
3274
Validates the buffer buf_pool data structure.
4249
3275
@return TRUE */
4252
buf_pool_validate_instance(
4253
/*=======================*/
4254
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
4257
3282
buf_chunk_t* chunk;
4781
3719
buf_get_modified_ratio_pct(void)
4782
3720
/*============================*/
4787
ulint flush_list_len = 0;
4789
buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
4791
ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
3724
buf_pool_mutex_enter();
3726
ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
3727
/ (1 + UT_LIST_GET_LEN(buf_pool->LRU)
3728
+ UT_LIST_GET_LEN(buf_pool->free));
4793
3730
/* 1 + is there to avoid division by zero */
3732
buf_pool_mutex_exit();
4798
3737
/*********************************************************************//**
4799
3738
Prints info of the buffer i/o. */
4802
buf_print_io_instance(
4803
/*==================*/
4804
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
4805
FILE* file) /*!< in/out: buffer where to print */
3743
FILE* file) /*!< in/out: buffer where to print */
4807
3745
time_t current_time;
4808
3746
double time_elapsed;
4811
3749
ut_ad(buf_pool);
3750
size = buf_pool->curr_size;
4813
buf_pool_mutex_enter(buf_pool);
4814
buf_flush_list_mutex_enter(buf_pool);
3752
buf_pool_mutex_enter();
4817
3755
"Buffer pool size %lu\n"
4818
3756
"Free buffers %lu\n"
4819
3757
"Database pages %lu\n"
4820
"Old database pages %lu\n"
4821
3758
"Modified db pages %lu\n"
4822
3759
"Pending reads %lu\n"
4823
3760
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
4824
(ulong) buf_pool->curr_size,
4825
3762
(ulong) UT_LIST_GET_LEN(buf_pool->free),
4826
3763
(ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4827
(ulong) buf_pool->LRU_old_len,
4828
3764
(ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
4829
3765
(ulong) buf_pool->n_pend_reads,
4830
3766
(ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
4833
3769
+ buf_pool->init_flush[BUF_FLUSH_LIST],
4834
3770
(ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4836
buf_flush_list_mutex_exit(buf_pool);
4838
3772
current_time = time(NULL);
4839
3773
time_elapsed = 0.001 + difftime(current_time,
4840
3774
buf_pool->last_printout_time);
3775
buf_pool->last_printout_time = current_time;
4843
"Pages made young %lu, not young %lu\n"
4844
"%.2f youngs/s, %.2f non-youngs/s\n"
4845
3778
"Pages read %lu, created %lu, written %lu\n"
4846
3779
"%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
4847
(ulong) buf_pool->stat.n_pages_made_young,
4848
(ulong) buf_pool->stat.n_pages_not_made_young,
4849
(buf_pool->stat.n_pages_made_young
4850
- buf_pool->old_stat.n_pages_made_young)
4852
(buf_pool->stat.n_pages_not_made_young
4853
- buf_pool->old_stat.n_pages_not_made_young)
4855
(ulong) buf_pool->stat.n_pages_read,
4856
(ulong) buf_pool->stat.n_pages_created,
4857
(ulong) buf_pool->stat.n_pages_written,
4858
(buf_pool->stat.n_pages_read
4859
- buf_pool->old_stat.n_pages_read)
4861
(buf_pool->stat.n_pages_created
4862
- buf_pool->old_stat.n_pages_created)
4864
(buf_pool->stat.n_pages_written
4865
- buf_pool->old_stat.n_pages_written)
3780
(ulong) buf_pool->n_pages_read,
3781
(ulong) buf_pool->n_pages_created,
3782
(ulong) buf_pool->n_pages_written,
3783
(buf_pool->n_pages_read - buf_pool->n_pages_read_old)
3785
(buf_pool->n_pages_created - buf_pool->n_pages_created_old)
3787
(buf_pool->n_pages_written - buf_pool->n_pages_written_old)
4866
3788
/ time_elapsed);
4868
n_gets_diff = buf_pool->stat.n_page_gets
4869
- buf_pool->old_stat.n_page_gets;
4873
"Buffer pool hit rate %lu / 1000,"
4874
" young-making rate %lu / 1000 not %lu / 1000\n",
4876
(1000 - ((1000 * (buf_pool->stat.n_pages_read
4877
- buf_pool->old_stat.n_pages_read))
4878
/ (buf_pool->stat.n_page_gets
4879
- buf_pool->old_stat.n_page_gets))),
4881
(1000 * (buf_pool->stat.n_pages_made_young
4882
- buf_pool->old_stat.n_pages_made_young)
4885
(1000 * (buf_pool->stat.n_pages_not_made_young
4886
- buf_pool->old_stat.n_pages_not_made_young)
3790
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
3791
fprintf(file, "Buffer pool hit rate %lu / 1000\n",
3793
(1000 - ((1000 * (buf_pool->n_pages_read
3794
- buf_pool->n_pages_read_old))
3795
/ (buf_pool->n_page_gets
3796
- buf_pool->n_page_gets_old))));
4889
3798
fputs("No buffer pool page gets since the last printout\n",
4893
/* Statistics about read ahead algorithm */
4894
fprintf(file, "Pages read ahead %.2f/s,"
4895
" evicted without access %.2f/s\n",
4896
(buf_pool->stat.n_ra_pages_read
4897
- buf_pool->old_stat.n_ra_pages_read)
4899
(buf_pool->stat.n_ra_pages_evicted
4900
- buf_pool->old_stat.n_ra_pages_evicted)
3802
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
3803
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
3804
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
3805
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4903
3807
/* Print some values to help us with visualizing what is
4904
3808
happening with LRU eviction. */
4906
3810
"LRU len: %lu, unzip_LRU len: %lu\n"
4907
3811
"I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
4908
static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->LRU)),
4909
static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->unzip_LRU)),
3812
UT_LIST_GET_LEN(buf_pool->LRU),
3813
UT_LIST_GET_LEN(buf_pool->unzip_LRU),
4910
3814
buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4911
3815
buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4913
buf_refresh_io_stats(buf_pool);
4914
buf_pool_mutex_exit(buf_pool);
3817
buf_pool_mutex_exit();
3820
/**********************************************************************//**
3821
Refreshes the statistics used to print per-second averages. */
3824
buf_refresh_io_stats(void)
3825
/*======================*/
3827
buf_pool->last_printout_time = time(NULL);
3828
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
3829
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
3830
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
3831
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4917
3834
/*********************************************************************//**
4918
Prints info of the buffer i/o. */
4923
FILE* file) /*!< in/out: buffer where to print */
4927
for (i = 0; i < srv_buf_pool_instances; i++) {
4928
buf_pool_t* buf_pool;
4930
buf_pool = buf_pool_from_array(i);
4931
buf_print_io_instance(buf_pool, file);
4935
/**********************************************************************//**
4936
Refreshes the statistics used to print per-second averages. */
4939
buf_refresh_io_stats(
4940
/*=================*/
4941
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
4943
buf_pool->last_printout_time = ut_time();
4944
buf_pool->old_stat = buf_pool->stat;
4947
/**********************************************************************//**
4948
Refreshes the statistics used to print per-second averages. */
4951
buf_refresh_io_stats_all(void)
4952
/*==========================*/
4956
for (i = 0; i < srv_buf_pool_instances; i++) {
4957
buf_pool_t* buf_pool;
4959
buf_pool = buf_pool_from_array(i);
4961
buf_refresh_io_stats(buf_pool);
4965
/**********************************************************************//**
4966
Check if all pages in all buffer pools are in a replacable state.
4967
@return FALSE if not */
3835
Asserts that all file pages in the buffer are in a replaceable state.
4970
3839
buf_all_freed(void)
4971
3840
/*===============*/
4975
for (i = 0; i < srv_buf_pool_instances; i++) {
4976
buf_pool_t* buf_pool;
4978
buf_pool = buf_pool_from_array(i);
4980
if (!buf_all_freed_instance(buf_pool)) {
3847
buf_pool_mutex_enter();
3849
chunk = buf_pool->chunks;
3851
for (i = buf_pool->n_chunks; i--; chunk++) {
3853
const buf_block_t* block = buf_chunk_not_freed(chunk);
3855
if (UNIV_LIKELY_NULL(block)) {
3857
"Page %lu %lu still fixed or dirty\n",
3858
(ulong) block->page.space,
3859
(ulong) block->page.offset);
3864
buf_pool_mutex_exit();
4988
3869
/*********************************************************************//**
4989
3870
Checks that there currently are no pending i/o-operations for the buffer