mysql的mtr是指什么_关于innodb mtr模块

mtr (mini-transaction)微事务

mtr作用

mtr模块主要保证物理操作的一致性和原子性

1 一致性:通过读写锁来保证

2 原子性:涉及到的物理更新,都记入redo日志

mtr何时使用

1 文件管理:innodb表空间以segment,extent,page的方式管理,segment,extent,page的申请释放,都会修改对应的控制信息。

如fseg_alloc_free_page_general 申请页

对表空间加锁

latch = fil_space_get_latch(space, &flags);mtr_x_lock(latch, mtr);

fseg_alloc_free_page_low->fseg_alloc_free_page_low 写控制信息并记入redo, 部分代码如下

xdes_set_state(ret_descr, XDES_FSEG, mtr);mlog_write_ull(ret_descr + XDES_ID, seg_id, mtr);flst_add_last(seg_inode + FSEG_FREE,ret_descr + XDES_FLST_NODE, mtr);

2 B树操作:(b树包括索引和insert buffer)

这里的读写锁有两种:btree lock,page lock

btree lock 为了防止B树分裂(不确定,还有些疑问?)

例如: 向聚集索引插入一行记录,row_ins_clust_index_entry_low

btree lock

mtr_s_lock(dict_index_get_lock(index), &mtr);

page lock

获取页 buf_page_get_gen

......

rw_lock_x_lock_inline(&(block->lock), 0, file, line);......

mtr_memo_push(mtr, block, fix_type);

redo log

trx_undo_page_report_insert //先以redo log方式写入undo log

page_cur_insert_rec_write_log//写redo log

mtr中的锁

锁均为读写锁,原子操作完成后立即释放(mtr_commit),不需要事务结束时释放

遵守两阶段加锁协议,不会死锁。

mtr中redo log

mtr过程中的redo log会存入自己的动态数组mtr->log中,mtr_commit时将mtr->log刷入 redo log buffer中。

一些思考

1 redo log buffer的 block的大小为512,参见以下注释

/** The next value should be smaller or equal to the smallest sector size used

on any disk. A log block is required to be a portion of disk which is written

so that if the start and the end of a block get written to disk,then the

whole block gets written. This should be true even in most cases of a crash:

if this fails for a log block,then it is equivalent to a media failure in the

log. */

#define OS_FILE_LOG_BLOCK_SIZE512

512 为普通磁盘的扇区大小,对于SSD来说扇区大小为4K

OS_FILE_LOG_BLOCK_SIZE 应设置为可调节参数,对SSD可以设为4096。如果不考虑binlog,可以一定程度上提升写redo的速度,加快commit。

经测试改为

#define OS_FILE_LOG_BLOCK_SIZE 4096

数据库可以正常使用

注:以上测试数据库需正常关闭,然后删除log file文件

2 代码优化

mtr_memo_pop_all 中有如下代码,这是一个O(n2)的查找遍历

offset = dyn_array_get_data_size(memo);

while (offset > 0) {

offset -= sizeof(mtr_memo_slot_t);

slot = static_cast(dyn_array_get_element(memo, offset));

mtr_memo_slot_release(mtr, slot); }

其中dyn_array_get_element是一个遍历查找元素的过程。

改进后,是一个O(n)的遍历

element_size = sizeof(mtr_memo_slot_t);

block = dyn_array_get_first_block(memo);

while (block !=NULL)

{

offset= dyn_block_get_used(block);

while (offset != 0) {

offset -= element_size;

slot = static_cast((void*)(block->data + offset)); mtr_memo_slot_release(mtr, slot);}

ut_ad(offset== 0);

block = dyn_array_get_next_block(memo, block); }

类似的代码出现在以下函数中

mtr_memo_contains (debug)

mtr_memo_pop_all

mtr_memo_note_modifications

mtr_memo_release

ps:以上分析基于5.6.10,最近看5.6.16这块已优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值