InnoDB总结

InnoDB体系结构


Buffer与磁盘

1.page是InnoDB磁盘I/O的最小单位,数据存放于page中,对应内存为一个个buffer

2.buffer有三种状态

①free buffer:从未被使用过的buffer

②clean buffer:内存中buffer里面的数据和磁盘page的数据一致

③dirty buffer:内存中新写入的,还没有刷新到磁盘,跟磁盘中的数据不一致

3.对应三种不同的Buffer状态,InnoDB是通过三条双向链表来进行管理的

①free list:每次page调用到内存中,都会先判断free buffer的使用情况,如果不够用,就会从flush list链表和lru list中进行释放

②lru list:数据和磁盘一致,最近最少使用的buffer

③flush buffer:dirty buffer串成的链.一般是把最近最少被弄脏的数据串起来

各大刷新线程以及作用

master thread

后台线程中的主线程,优先级最高,内部有四个循环


main loop{


          if( key == background){


          //后台循环线程


          background loop


          }


          if( key == flush ){


          //刷新线程


          flush loop


          }


          if (key == suspend ){


          //暂停线程


          suspend loop


          }



主循环内又分为两种操作

每1s的操作

          //(1)redo log日志缓冲刷新到磁盘,即使这个事务还没提交 备注:binlog的是指写一次 redo log会在过程就开始写

          //(2)刷新脏页到磁盘

          //(3)执行合并插入缓冲的操作

          //(4)产生checkpoint

          //(5)清除无用的table cache

          //(6)如果当前没有用户活动,就可能会切换到background loop

每10s的操作 基本和1s的相同

          //(1)redo log日志缓冲刷新到磁盘,即使这个事务还没提交

          //(2)刷新脏页到磁盘

          //(3)执行合并插入缓冲的操作

          //(4)产生checkpoint

          //(5)删除无用的undo页

然后是四大I/O线程

1.read thread  负责数据库的读,默认4个

2.write thread  负责数据库的写,默认4个

3.redo log thread  负责把日志缓冲区的内容刷新到redo log文件中

4.change buffer thread  负责把change buffer中的内容刷新到磁盘

脏页刷新线程

page cleaner thread

无用undo页删除线程

purge thread

checkpoint推进线程

当redo log发生切换时,推进check point


write pos是当前记录的位置,一边写一边后移,写到3号末尾就回到0号开头.

checkpoint是当前要擦除的位置,也是往后移并且循环的,擦除前需要把记录更新到数据文件.

锁监控线程

lock monitor thread检测死锁

数据库报错的监控线程

erro monitor thread

内存的刷新机制

首先,mysql是先写日志,再写数据文件

其次,redo log,记录的是数据修改后的值

结合之前的图


为了保证性能,一般都是写到缓存后就立即返回了,然后异步的将缓存中的数据刷新到磁盘

控制redo log buffer中的数据刷新到磁盘的参数(备注,buffer和cache都可以理解为缓存,只是buffer主要针对的是I/O方面,cache主要针对cpu方面)

innodb_flush_log_at_trx_commit

有三个值0,1,2

0:每隔1s就会将redo log buffer中的数据写入到redo log 文件,同时进行刷盘操作.但有一个问题是,每次事务提交并不会触发redo log thread 将日志缓冲区中的数据写入到redo log 文件中

1:每次事务提交,都会触发redo log thread将日志缓冲区中的数据写入文件,并刷新到磁盘

2:每次事务提交,都会把redo log buffer中的数据写入到redo log文件,但不会同时刷新到磁盘

一般都设为1,和控制Binlog的参数sync_binlog都设置为1

binlog文件

Mysql的二进制文件

binlog和redo log的三点区别

1.redo log是InnoDB引擎特有的;binlog是Mysqlde Server层实现的,所有引擎都可以使用

2.redo log是物理日志,记录的是在"某个数据页上做了什么修改"(同时可以引申出后面要说的double write);binlog是逻辑日志,记录的是语句的原始逻辑,比如"给id=2这一行的c字段加1"

3.redo log 是循环写的,空间固定会用完(所以会有checkpoint和刷新到磁盘);binlog是追加写的,当文件写到一定大小后会切换到下一个,并不会覆盖之前的日志.

他们的使用场景

1.binlog可以作为数据恢复使用,主从复制搭建

2.redo log作为异常宕机或者介质故障后的数据恢复使用

那么他们是怎么配合的?

假设我们执行

updatetableasetc=c+1whereid=2;


这里主要用到了两阶段提交

两阶段提交分为prepare和commit阶段

准备阶段(transaction prepare):事务SQL先写入redo log buffer,然后做一个准备标记,再将log buffer中的数据刷新到redo log

提交阶段(commit):将事务产生的binlog写入文件,刷入磁盘

再在redo log 中做一个事务提交的标记,并把binlog写成功的标记也一并写入到redo log文件。

那他们是怎么保证一致性的呢?

情况一:准备阶段,redo log刷新到了磁盘,但是binlog写盘前发生了mysql实例crash.

这时我们redo log是没有binlog提交的日志的,所以我们可以通过回滚来保证数据库一致性

情况二:binlog写盘成功,这时mysql实例crash

进行数据恢复时,只需要使用redo log重做一次就好了。

redo log 和binlog的写入时机

binlog的写入时机

事务执行过程中,先把日志写入到binlog cache,事务提交时,再把binlog cache写入到Binlog文件中

系统会给每一个线程分配一个binlog cache,参数binlog_cache_size可以用于控制单个线程内binlog_cache所占内存的大小,如果超过这个数,就要暂存到磁盘(磁盘swap)

一个事务的binlog是不能被拆开的,因此不论事务有多大,也要确保一次性写入.

一般分为write和异步刷新,而write和fsync的时机,是由参数sync_binlog控制的

1.sync_binlog=0时,每次提交事务都只write,不fsync

2.sync_binlog=1时,每次提交事务都会执行fsync

3.sync_binlog=N(n>1),每次提交事务都write,但累计N个事务才fsync

一般都设置为1

redo log的写入时机

可以参考以上的两阶段提交

此外,也是先写入到redo log buffer,再write到磁盘,再进行磁盘持久化(fsync)

这里和binlog不同的是,redo log是事务执行过程中就会直接写入到redo log buffer中,然后会被我们画的主线程里的几个线程持久化到磁盘,也就是事务可能没提交,但我们的redo log已经持久化到磁盘了。

除了每1s的轮询操作会写入外(这种场景已经刷盘了),还有另外两种场景

场景一.

redo log buffer占用的空间即将达到innodb_log_buffer_size一半的时候,后台回主动写盘

,注意这个时候并没有刷盘,只是留在了文件系统的page cache

场景二

并行的事务提交的时候,顺带将这个事务的redo log buffer持久化到磁盘

此外为看保证数据页不会被多次执行重复的redo log,还有一个组提交的概念

使用日志逻辑序列号(log sequence number,LSN)来对应redo log的一个个写入点,每次写入长度为length的redo log,LSN的值就会加上length

假设三个并发事务(trx1,trx2,trx3)在prepare阶段,都写完redo log,持久化到磁盘的过程,对应的LSN分别是50,120和160

假设trx1是第一个到的,那么他会被选为这组的组长leader

等trx1要开始写盘的时候,组内有三个事务,这个时候LSN也变成了160

那么trx1去写盘的时候,带的LSN就是160,等trx1写完返回时,LSN小于等于160的redo log就已经被持久化到磁盘了

那么trx2和trx3就可以直接返回了。

所以,一次组提交了,组员越多,节省的磁盘Iops效果越好.

进一步推导,在并发更新的场景下,第一个事务写完redo log buffer以后,接下来的fsync越晚调用,组员就会越多,就节省i/o时间(感觉和redis的pipeline有点类似,将多个命令执行一次i/o操作,有点异曲同工之妙)

所以Mysql做的优化就是拖时间

它把redo log做fsync的时间拖到了binlog write之后

流程图如下


这样一来,binlog也可以组提交了

所以这里又有个参数可以控制I/O性能瓶颈了

1.binlog_group_commit_sync_delay表示延迟多少微秒后才会调用fsync

2.binlog_group_commit_sync_no_delay_count,表示累积多少次以后才会调用fsync

最后再来看一下

InnoDB的三大特性

插入缓冲(change buffer)

两次写(double write)

自适应哈希索引(adaptive hash index)

(1)插入缓冲

和磁盘打交道,最主要的性能问题就是I/O.

而插入缓冲的作用就是把普通索引上的DML操作从随机I/O变成顺序I/O

原理

先判断插入的普通索引页是否在缓冲池中,如果在就可以直接插入,不在的话就需要先放到change_buffer中,然后进行change_buffer和普通索引的合并操作,可以将多个操作合并为一个操作中

(2)两次写(double write)

它主要用来保证数据写入的安全性

我们前面提到,redo log是物理日志,如果页都损坏了,是没办法进行恢复的,所以我们需要一个数据页的备份.

可以通过innodb_doublewrite为0来关闭双写缓冲.

(3)自适应哈希索引

主要用于监控我们的查询是否可以通过建立哈希索引得到优化,可以的话,它会自动帮助我们完成这件事.

可以通过innodb_adaptive_hash_index来进行控制,默认是开启的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容