Innodb_buffer_pool_write_requests:写入buffer pool的请求数。理论上这个数量也等于每一个提交的事务修改的buffer pool中页*次。同一个页在一个事务中只累加一次,多个事务修改同一个page累加多次。原因是每一个事务在commit时都会将自身修改的page添加到flush列表,每次添加一个page,都会累加Innodb_buffer_pool_write_requests。具体的实现是,每一个mtr有一个自身的memory stack来存储修改的page,这个结构是这样的:
m_list :{mtr_buf_t::block_t,mtr_buf_t::block_t,mtr_buf_t::block_t}
mtr_buf_t::block_t:{mtr_memo_slot_t,mtr_memo_slot_t,mtr_memo_slot_t}
mtr_memo_slot_t:<object,type>
其中,m_list是一个集合,
这个操作是在事务提交时,mtr_buf_t::block_t是mtr_buf_t::block_t类型的元素,mtr_memo_slot_t是一个struct结构体,其中有两个元素,一个是指向page的指针,一个是page的类型。描述一下,就是一个mtr事务,有一个m_list名字的集合类型成员;这个集合成员包含了多个mtr_buf_t::block_t类型的元素;mtr_buf_t实际是dyn_buf_t类型,一个mtr_buf_t::block_t类型的元素可以包含的数据默认512字节,最大64k;一个mtr_memo_slot_t元素就是一个对buffer中page的包装,包括一个void指针,一个无符号long,总共16字节。
Innodb_buffer_pool_write_requests在代码中以srv_stats.buf_pool_write_requests变量指代。在下面的buf_flush_note_modification函数中累加。将mtr修改的page塞到m_list中发生在void mtr_t::memo_push(void *object, mtr_memo_type_t type)函数中。
buf0flu.ic
/** This function should be called at a mini-transaction commit, if a page was
modified in it. Puts the block to the list of modified blocks, if it is not
already in it. */
UNIV_INLINE
void buf_flush_note_modification(
buf_block_t *block, /*!< in: block which is modified */
lsn_t start_lsn, /*!< in: start lsn of the mtr that
modified this block */
lsn_t end_lsn, /*!< in: end lsn of the mtr that
modified this block */
FlushObserver *observer) /*!< in: flush observer */
{
#ifdef UNIV_DEBUG
{
/* Allow write to proceed to shared temporary tablespace
in read-only mode. */
ut_ad(!srv_read_only_mode ||
fsp_is_system_temporary(block->page.id.space()));
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(block->page.buf_fix_count > 0);
buf_pool_t *buf_pool = buf_pool_from_block(block);
ut_ad(!buf_flush_list_mutex_own(buf_pool));
}
#endif /* UNIV_DEBUG */
mutex_enter(&block->mutex);
if (end_lsn != 0) {
ut_ad(block->page.newest_modification <= end_lsn);
block->page.newest_modification = end_lsn;
} else {
/* Do nothing. This is the case with no-redo mtr and it
possibly could re-modify some earlier dirtied page, in
which case we don't want to change oldest/newest lsns.
If that's not the case, we will set newest_modification
within buf_flush_insert_into_flush_list call. That's
because we can't read the value now, because we don't
hold the flush list mutex yet. */
}
/* Don't allow to set flush observer from non-null to null,
or from one observer to another. */
ut_ad(block->page.flush_observer == nullptr ||
block->page.flush_observer == observer);
block->page.flush_observer = observer;
if (block->page.oldest_modification == 0) {
buf_pool_t *buf_pool = buf_pool_from_block(block);
buf_flush_insert_into_flush_list(buf_pool, block, start_lsn);
} else if (start_lsn != 0) {
ut_ad(block->page.oldest_modification <= start_lsn);
}
buf_page_mutex_exit(block);
srv_stats.buf_pool_write_requests.inc();
}
//mtr0mtr.h
struct mtr_memo_slot_t {
/** pointer to the object */
void *object;
/** type of the stored object (MTR_MEMO_S_LOCK, ...) */
ulint type;
};
/**
Pushes an object to an mtr memo stack. */
void mtr_t::memo_push(void *object, mtr_memo_type_t type) {
ut_ad(is_active());
ut_ad(object != nullptr);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_SX_LOCK);
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(ut_is_2pow(type));
/* If this mtr has x-fixed a clean page then we set
the made_dirty flag. This tells us if we need
insert the dirtied page to