s1: innodb aio原理及相关bug分析

18
InnoDB AIO 原理及相关bug分析 淘宝希羽

Upload: hui-liu

Post on 06-Jul-2015

1.382 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: S1: InnoDB AIO原理及相关bug分析

InnoDB AIO 原理及相关bug分析

淘宝希羽

Page 2: S1: InnoDB AIO原理及相关bug分析

议程

• InnoDB AIO参数设置

• InnoDB模拟AIO原理

• 读写线程如何调用及诊断

• 主线程帮什么忙

• DDL丢表问题分析及解决

Page 3: S1: InnoDB AIO原理及相关bug分析

InnoDB AIO 参数设置

• innodb_file_io_threads – 自从5.1 plugin 和5.5版本被舍弃 – built-in版本默认值为4,意味着:

• innodb_read_io_threads=1 • innodb_write_io_threads=1 • 一个insert buffer线程 • 一个log线程

• 在SSD 环境, 拥有更强的IO能力,典型设置: – innodb_thread_concurrency=64 – innodb_read_io_threads=8 – innodb_write_io_threads=8 – innodb_io_capacity=2000

Page 4: S1: InnoDB AIO原理及相关bug分析

InnoDB IO 工作流程

Page 5: S1: InnoDB AIO原理及相关bug分析

InnoDB 模拟AIO: 初始化

• srv/srv0start.c: innobase_start_or_create_for_mysql

Page 6: S1: InnoDB AIO原理及相关bug分析

InnoDB模拟AIO: 关键的数据结构

• struct os_aio_array_t,4个实例

– mutex

– not_full/is_empty (os_event_t)

– n_slots/n_segments/n_reserved

– slots (os_aio_slot_t)

• struct os_aio_slot_t

n_slot=n_[read|write]_segs*n_per_seg

slot[0] pos|reserved|..

… … slot[n_slot]

Page 7: S1: InnoDB AIO原理及相关bug分析

InnoDB模拟AIO: 工作线程和唤醒线程句柄

• 工作线程句柄 fil/fil0fil.c:fil_aio_wait

– os_aio_simulated_handle

• 唤醒AIO线程句柄(多处调用)

– os_aio_simulated_wake_handler_thread

– 典型场景:找不到可用slot时强制唤醒 slot[0] slot[1] …slot[k]… slot[n-1]

if found slot that needs read/write io, call os_file_read/write

else wait for event

broadcast in wake_handler

Page 8: S1: InnoDB AIO原理及相关bug分析

InnoDB 模拟AIO: 核心函数os_aio_simulated_handle

- 获取segment slots - 如果slot被保留并且io_already_done, 那么goto

slot_io_done(释放slot及io_already_done); - 如果任何slot被保留时间>2s, 那么选择最老的以防止饥饿; - 如果没有找到上述条件的slot, 选择被保留且offset最小的slot. - 上述两个条件均未找到slot(被保留的),则 goto wait_for_io; - 否则必然到到一个slot,再继续找到slot’被保留且与之前找到

slot有连续的IO,再找到与slot’有如此关系的slot’’ …(找到64个) - memcpy 上述找到的 slot的buf到 combined_buf - 调用os_file_read/os_file_write来完成读/写. 可能的优化余地:增大slot及批量写的slot数目 Native AIO slot数目为AIO的1/8, 调用os_aio_linux_handle

Page 9: S1: InnoDB AIO原理及相关bug分析

读写线程如何调用及诊断: 一切以调用fil_io为开始

• fil_io – fil_mutex_enter_and_prepare_for_io

– fil_node_prepare_for_io

– os_aio • os_aio_simulated_handle

– os_file_pwrite (lseek && write && [flush])

– fil_node_complete_io

• fil_flush

• 读同步,写异步

Page 10: S1: InnoDB AIO原理及相关bug分析

读写线程如何调用及诊断: 文件IO的诊断信息

• fil_node_prepare_for_io – 从fil_system->LRU将node移走(被占用) – n_pending++

• fil_node_complete_io – n_pending-- – modification_counter++ (set to flush_counter when freed) – 将node->space 加到fil_system->unflushed_spaces – 将node回到fil_system->LRU

• fil_flush – space->n_pending_flushes++ – n_pending_flushes++ – os_file_flush – n_pending_flushes— – space->n_pending_flushes--

Page 11: S1: InnoDB AIO原理及相关bug分析

主线程帮什么忙

• 调用buf_flush_batch来刷肮页和唤醒AIO

– 以不同的负荷来刷脏页(以当前IO的繁忙程度来分配IO能力)

– 从flush_list刷页块(相邻页也被刷)

• buf_flush_list->buf_flush_batch(BUF_FLUSH_LIST)

– 最终调用 buf_flush_buffered_writes

• 从缓存中的doublewrite 刷可能的buffer到存储

• 如果使用模拟AIO,则要唤醒AIO线程

Page 12: S1: InnoDB AIO原理及相关bug分析

flush_list和LRU_list

• 两种刷页方式的特点

– 所有页先从buffer pool刷到缓存中的doublewrite

• 主线程周期性触发(修改页比例 > 脏页比例), 从flush_list中刷

• 工作线程主动刷(没有可用的空闲blocks),从LRU_list中刷

– doublewrite组成: 128 pages, each 16K, all 2M

– 始于buf_flush_page: 将 flushable 页从buffer pool 写到某个文件

buf_flush_page buf_flush_write_block_low buf_flush_post_to_doublewrite_buf

fil_io (no trx_dwb)

buf_flush_buffer_writes

Page 13: S1: InnoDB AIO原理及相关bug分析

DDL表丢失问题背景

• #62100

• DDL失败后表丢失

• 过去一年在线上操作经历5次

• 自2008年就在buglist中存在

• 2011年下提交patch

• 2012年初Mark&Inaam讨论改进patch

• MySQL 5.5.22融入patch

Page 14: S1: InnoDB AIO原理及相关bug分析

DDL 丢表分析: 基本信息

• fil_rename_tablespace

– 设置stop_ios=TURE

– 等待直到n_pending==0 && n_pending_flushes==0

– 设置stop_ios=FALSE

• fil_mutex_enter_and_prepare_for_io

– 等待直到stop_ios = FALSE

• 被阻塞直到超时, mysqld最终abort

Page 15: S1: InnoDB AIO原理及相关bug分析

DDL丢表分析: 关键的backtrace

Page 16: S1: InnoDB AIO原理及相关bug分析

DDL丢表分析: 自问自答

• 为什么n_pending > 0? – 没有活动的写线程

• 没有写线程没有被唤醒? – 被阻塞在doublewrite->mutex

• 谁拥有doublewrite->mutex – srv_master 线程拥有但被阻塞

• 为什么DDL异常下不能正确回滚? – 没有正确设置参数以告知调用者

• 其它风险? – 对DDL操作的中间临时表的写是否延时

Page 17: S1: InnoDB AIO原理及相关bug分析

DDL丢表解决方法

• 在等待时间过长时强制唤醒AIO线程

• 正确设置回滚的标记

• 修正max_open_files的判断逻辑位置

Page 18: S1: InnoDB AIO原理及相关bug分析

最后

• 讨论时间