MySQL是怎么保证数据不丢失的

binlog的写入机制

事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 

写到 binlog 文件中。

系统给 binlog cache 分配了一片内存,每个线程一个,参数 binlog_cache_size 用于控

制单个线程内 binlog cache 所占内存的大小。如果超过了这个参数规定的大小,就要暂

存到磁盘。

事务提交的时候,执行器把 binlog cache 里的完整事务写入到 binlog 中,并清空

binlog cache。

每个线程有自己 binlog cache,但是共用同一份 binlog 文件。

write过程:

指的就是指把日志写入到文件系统的 page cache,并没有把数据持久化

到磁盘,所以速度比较快。

fsync过程:

才是将数据持久化到磁盘的操作。一般情况下,我们认为 fsync 才占磁

盘的 IOPS。

write 和 fsync 的时机,是由参数 sync_binlog 控制的:

1. sync_binlog=0 的时候,表示每次提交事务都只 write,不 fsync;

2. sync_binlog=1 的时候,表示每次提交事务都会执行 fsync;

3. sync_binlog=N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才

fsync。

因此,在出现 IO 瓶颈的场景里,将 sync_binlog 设置成一个比较大的值,可以提升性

能。在实际的业务场景中,考虑到丢失日志量的可控性,一般不建议将这个参数设成 0,

比较常见的是将其设置为 100~1000 中的某个数值。

但是,将 sync_binlog 设置为 N,对应的风险是:如果主机发生异常重启,会丢失最近 N

个事务的 binlog 日志。

binlog的日志格式

1.  statement

记录到 binlog 里的是语句原文,因此可能会出现这样一种情

况:在主库执行这条 SQL 语句的时候,用的是索引 a;而在备库执行这条 SQL 语句的时

候,却使用了索引 t_modified。出现同样一条sql语句,选择索引不一致的情况。

2. row

3. mixed(前两种的混合)

mixed 格式的 binlog 现在已经用得不多

redo log 的写入机制

事务在执行过程中,生成的 redo log 是要先写到 redo log buffer 的。

redo log buffer 里面的内容,不需要每次生成后都要直接持久化到磁盘。

如果事务执行期间 MySQL 发生异常重启,那这部分日志就丢了。由于事务并没有提交,

所以这时日志丢了也不会有损失。

事务还没提交的时候,redo log buffer 中的部分日志有可能被持久化到磁盘。


MySQL redo log 存储状态

redo log 可能存在三种状态:

1. 存在 redo log buffer 中,物理上是在 MySQL 进程内存中,就是图中的红色部分;

2. 写到磁盘 (write),但是没有持久化(fsync),物理上是在文件系统的 page cache 里

面,也就是图中的黄色部分;

3. 持久化到磁盘,对应的是 hard disk,也就是图中的绿色部分。

日志写到 redo log buffer 是很快的,wirte 到 page cache 也差不多,但是持久化到磁盘

的速度就慢多了。

为了控制 redo log 的写入策略,InnoDB 提供了 innodb_flush_log_at_trx_commit 参

数,它有三种可能取值:

1. 设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中 ;

2. 设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘;

3. 设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache。

InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 write 写

到文件系统的 page cache,然后调用 fsync 持久化到磁盘。

事务执行中间过程的 redo log 也是直接写在 redo log buffer 中的,这些 redo

log 也会被后台线程一起持久化到磁盘。也就是说,一个没有提交的事务的 redo log,也

是可能已经持久化到磁盘的。

实际上,除了后台线程每秒一次的轮询操作外,还有两种场景会让一个没有提交的事务的

redo log 写入到磁盘中。

1. redo log buffer 占用的空间即将达到 innodb_log_buffer_size 一半的时

候,后台线程会主动写盘。注意,由于这个事务并没有提交,所以这个写盘动作只是

write,而没有调用 fsync,也就是只留在了文件系统的 page cache。

2. 另一种是,并行的事务提交的时候,顺带将这个事务的 redo log buffer 持久化到磁

盘。

通常我们说 MySQL 的“双 1”配置,指的就是 sync_binlog 和innodb_flush_log_at_trx_commit 

都设置成 1。

也就是说,一个事务完整提交前,需要等待两次刷盘,一次是 redo log(prepare 阶段),

一次是 binlog。

这意味着我从 MySQL 看到的 TPS 是每秒两万的话,每秒就会写四万次磁盘。

但是,我用工具测试出来,磁盘能力也就两万左右,怎么能实现两万的

TPS?

组提交(group commit)机制

WAL 机制是减少磁盘写,可是每次提交事务都要写 redo log和 binlog,这磁盘读写次数

也没变少呀?

  WAL 机制主要得益于两个方面:

1. redo log 和 binlog 都是顺序写,磁盘的顺序写比随机写速度要快;

2. 组提交机制,可以大幅度降低磁盘的 IOPS 消耗。

如果你的 MySQL 现在出现了性能瓶颈,而且瓶颈在 IO 上,可以通过哪些方法来提升性能呢?

针对这个问题,可以考虑以下三种方法:

1. 设置 binlog_group_commit_sync_delay 和

binlog_group_commit_sync_no_delay_count 参数,减少 binlog 的写盘次数。

2. 将 sync_binlog 设置为大于 1 的值(比较常见是 100~1000)。这样做的风险是,主

机掉电时会丢 binlog 日志。

3. 将 innodb_flush_log_at_trx_commit 设置为 2。这样做的风险是,主机掉电的时候会

丢数据。

不建议你把 innodb_flush_log_at_trx_commit 设置成 0。因为把这个参数设置成 0,

表示 redo log 只保存在内存中,这样的话 MySQL 本身异常重启也会丢数据,风险太

大。而 redo log 写到文件系统的 page cache 的速度也是很快的,所以将这个参数设置

成 2 跟设置成 0 其实性能差不多,但这样做 MySQL 异常重启时就不会丢数据了,相比之

下风险会更小。

一般情况下,把生产库改成“非双 1”配置,是设置

innodb_flush_logs_at_trx_commit=2、sync_binlog=1000

在什么时候会把线上生产库设置成“非双 1”?

场景:

1. 业务高峰期。一般如果有预知的高峰期,DBA 会有预案,把主库设置成“非双 1”。

2. 备库延迟,为了让备库尽快赶上主库。@永恒记忆和 @Second Sight 提到了这个场

景。

3. 用备份恢复主库的副本,应用 binlog 的过程。

4. 批量导入数据的时候。

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