⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buf0rea.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************The database buffer read(c) 1995 Innobase OyCreated 11/5/1995 Heikki Tuuri*******************************************************/#include "buf0rea.h"#include "fil0fil.h"#include "mtr0mtr.h"#include "buf0buf.h"#include "buf0flu.h"#include "buf0lru.h"#include "ibuf0ibuf.h"#include "log0recv.h"#include "trx0sys.h"#include "os0file.h"#include "srv0start.h"extern ulint srv_read_ahead_rnd;extern ulint srv_read_ahead_seq;extern ulint srv_buf_pool_reads;/* The size in blocks of the area where the random read-ahead algorithm countsthe accessed pages when deciding whether to read-ahead */#define	BUF_READ_AHEAD_RANDOM_AREA	BUF_READ_AHEAD_AREA/* There must be at least this many pages in buf_pool in the area to starta random read-ahead */#define BUF_READ_AHEAD_RANDOM_THRESHOLD	(5 + BUF_READ_AHEAD_RANDOM_AREA / 8)/* The linear read-ahead area size */#define	BUF_READ_AHEAD_LINEAR_AREA	BUF_READ_AHEAD_AREA/* The linear read-ahead threshold */#define BUF_READ_AHEAD_LINEAR_THRESHOLD	(3 * BUF_READ_AHEAD_LINEAR_AREA / 8)/* If there are buf_pool->curr_size per the number below pending reads, thenread-ahead is not done: this is to prevent flooding the buffer pool withi/o-fixed buffer blocks */#define BUF_READ_AHEAD_PEND_LIMIT	2/************************************************************************Low-level function which reads a page asynchronously from a file to thebuffer buf_pool if it is not already there, in which case does nothing.Sets the io_fix flag and sets an exclusive lock on the buffer frame. Theflag is cleared and the x-lock released by an i/o-handler thread. */staticulintbuf_read_page_low(/*==============*/			/* out: 1 if a read request was queued, 0 if the page			already resided in buf_pool, or if the page is in			the doublewrite buffer blocks in which case it is never			read into the pool, or if the tablespace does not			exist or is being dropped */	ulint*	err,	/* out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are			trying to read from a non-existent tablespace, or a			tablespace which is just now being dropped */	ibool	sync,	/* in: TRUE if synchronous aio is desired */	ulint	mode,	/* in: BUF_READ_IBUF_PAGES_ONLY, ...,			ORed to OS_AIO_SIMULATED_WAKE_LATER (see below			at read-ahead functions) */	ulint	space,	/* in: space id */	ib_longlong tablespace_version, /* in: if the space memory object has			this timestamp different from what we are giving here,			treat the tablespace as dropped; this is a timestamp we			use to stop dangling page reads from a tablespace			which we have DISCARDed + IMPORTed back */	ulint	offset)	/* in: page number */{	buf_block_t*	block;	ulint		wake_later;	*err = DB_SUCCESS;	wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;	mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;		if (trx_doublewrite && space == TRX_SYS_SPACE		&& (   (offset >= trx_doublewrite->block1		        && offset < trx_doublewrite->block1		     		+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)		    || (offset >= trx_doublewrite->block2		        && offset < trx_doublewrite->block2		     		+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) {		ut_print_timestamp(stderr);		fprintf(stderr,"  InnoDB: Warning: trying to read doublewrite buffer page %lu\n",			(ulong) offset);		return(0);	}#ifdef UNIV_LOG_DEBUG	if (space % 2 == 1) {		/* We are updating a replicate space while holding the		log mutex: the read must be handled before other reads		which might incur ibuf operations and thus write to the log */		fputs("Log debug: reading replicate page in sync mode\n",			stderr);		sync = TRUE;	}#endif	if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {		/* Trx sys header is so low in the latching order that we play		safe and do not leave the i/o-completion to an asynchronous		i/o-thread. Ibuf bitmap pages must always be read with                syncronous i/o, to make sure they do not get involved in                thread deadlocks. */				sync = TRUE;	}	/* The following call will also check if the tablespace does not exist	or is being dropped; if we succeed in initing the page in the buffer	pool for read, then DISCARD cannot proceed until the read has	completed */	block = buf_page_init_for_read(err, mode, space, tablespace_version,								offset);	if (block == NULL) {				return(0);	}#ifdef UNIV_DEBUG	if (buf_debug_prints) {		fprintf(stderr,                        "Posting read request for page %lu, sync %lu\n",							   (ulong) offset,		       					   (ulong) sync);	}#endif	ut_a(block->state == BUF_BLOCK_FILE_PAGE);	*err = fil_io(OS_FILE_READ | wake_later,			sync, space,			offset, 0, UNIV_PAGE_SIZE,			(void*)block->frame, (void*)block);	ut_a(*err == DB_SUCCESS);	if (sync) {		/* The i/o is already completed when we arrive from		fil_read */		buf_page_io_complete(block);	}			return(1);}	/************************************************************************Applies a random read-ahead in buf_pool if there are at least a thresholdvalue of accessed pages from the random read-ahead area. Does not read anypage, not even the one at the position (space, offset), if the read-aheadmechanism is not activated. NOTE 1: the calling thread may own latches onpages: to avoid deadlocks this function must be written such that it cannotend up waiting for these latches! NOTE 2: the calling thread must wantaccess to the page given: this rule is set to prevent unintended read-aheadsperformed by ibuf routines, a situation which could result in a deadlock ifthe OS does not support asynchronous i/o. */staticulintbuf_read_ahead_random(/*==================*/			/* out: number of page read requests issued; NOTE			that if we read ibuf pages, it may happen that			the page at the given page number does not get			read even if we return a value > 0! */	ulint	space,	/* in: space id */	ulint	offset)	/* in: page number of a page which the current thread			wants to access */{	ib_longlong	tablespace_version;	buf_block_t*	block;	ulint		recent_blocks	= 0;	ulint		count;	ulint		LRU_recent_limit;	ulint		ibuf_mode;	ulint		low, high;	ulint		err;	ulint		i;	if (srv_startup_is_before_trx_rollback_phase) {	        /* No read-ahead to avoid thread deadlocks */	        return(0);	}	if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {		/* If it is an ibuf bitmap page or trx sys hdr, we do                no read-ahead, as that could break the ibuf page access                order */		return(0);	}	/* Remember the tablespace version before we ask te tablespace size	below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we	do not try to read outside the bounds of the tablespace! */	tablespace_version = fil_space_get_version(space);	low  = (offset / BUF_READ_AHEAD_RANDOM_AREA)					* BUF_READ_AHEAD_RANDOM_AREA;	high = (offset / BUF_READ_AHEAD_RANDOM_AREA + 1)					* BUF_READ_AHEAD_RANDOM_AREA;	if (high > fil_space_get_size(space)) {		high = fil_space_get_size(space);	}	/* Get the minimum LRU_position field value for an initial segment	of the LRU list, to determine which blocks have recently been added	to the start of the list. */		LRU_recent_limit = buf_LRU_get_recent_limit();	mutex_enter(&(buf_pool->mutex));	if (buf_pool->n_pend_reads >			buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {		mutex_exit(&(buf_pool->mutex));		return(0);	}		/* Count how many blocks in the area have been recently accessed,	that is, reside near the start of the LRU list. */	for (i = low; i < high; i++) {		block = buf_page_hash_get(space, i);		if ((block)		    && (block->LRU_position > LRU_recent_limit)		    && block->accessed) {			recent_blocks++;		}	}	mutex_exit(&(buf_pool->mutex));		if (recent_blocks < BUF_READ_AHEAD_RANDOM_THRESHOLD) {		/* Do nothing */		return(0);	}	/* Read all the suitable blocks within the area */	if (ibuf_inside()) {		ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;	} else {		ibuf_mode = BUF_READ_ANY_PAGE;	}	count = 0;	for (i = low; i < high; i++) {		/* It is only sensible to do read-ahead in the non-sync aio		mode: hence FALSE as the first parameter */		if (!ibuf_bitmap_page(i)) {			count += buf_read_page_low(&err, FALSE, ibuf_mode					| OS_AIO_SIMULATED_WAKE_LATER,				        space, tablespace_version, i);			if (err == DB_TABLESPACE_DELETED) {				ut_print_timestamp(stderr);				fprintf(stderr,"  InnoDB: Warning: in random readahead trying to access tablespace\n""InnoDB: %lu page no. %lu,\n""InnoDB: but the tablespace does not exist or is just being dropped.\n",					(ulong) space, (ulong) i);			}		}	}	/* In simulated aio we wake the aio handler threads only after	queuing all aio requests, in native aio the following call does	nothing: */		os_aio_simulated_wake_handler_threads();#ifdef UNIV_DEBUG	if (buf_debug_prints && (count > 0)) {		fprintf(stderr,			"Random read-ahead space %lu offset %lu pages %lu\n",						(ulong) space, (ulong) offset,		       				(ulong) count);	}#endif /* UNIV_DEBUG */        ++srv_read_ahead_rnd;	return(count);}/************************************************************************High-level function which reads a page asynchronously from a file to thebuffer buf_pool if it is not already there. Sets the io_fix flag and setsan exclusive lock on the buffer frame. The flag is cleared and the x-lockreleased by the i/o-handler thread. Does a random read-ahead if it seemssensible. */ulintbuf_read_page(/*==========*/			/* out: number of page read requests issued: this can			be > 1 if read-ahead occurred */	ulint	space,	/* in: space id */	ulint	offset)	/* in: page number */{	ib_longlong	tablespace_version;	ulint		count;	ulint		count2;	ulint		err;	tablespace_version = fil_space_get_version(space);	count = buf_read_ahead_random(space, offset);	/* We do the i/o in the synchronous aio mode to save thread	switches: hence TRUE */	count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,					tablespace_version, offset);        srv_buf_pool_reads+= count2;	if (err == DB_TABLESPACE_DELETED) {	        ut_print_timestamp(stderr);		fprintf(stderr,"  InnoDB: Error: trying to access tablespace %lu page no. %lu,\n""InnoDB: but the tablespace does not exist or is just being dropped.\n",				 (ulong) space, (ulong) offset);	}	/* Flush pages from the end of the LRU list if necessary */	buf_flush_free_margin();	return(count + count2);}/************************************************************************Applies linear read-ahead if in the buf_pool the page is a border page ofa linear read-ahead area and all the pages in the area have been accessed.Does not read any page if the read-ahead mechanism is not activated. Notethat the the algorithm looks at the 'natural' adjacent successor andpredecessor of the page, which on the leaf level of a B-tree are the nextand previous page in the chain of leaves. To know these, the page specifiedin (space, offset) must already be present in the buf_pool. Thus, thenatural way to use this function is to call it when a page in the buf_poolis accessed the first time, calling this function just after it has beenbufferfixed.NOTE 1: as this function looks at the natural predecessor and successorfields on the page, what happens, if these are not initialized to anysensible value? No problem, before applying read-ahead we check that thearea to read is within the span of the space, if not, read-ahead is notapplied. An uninitialized value may result in a useless read operation, butonly very improbably.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -