当前位置: 首页 > news >正文

mysql性能优化-延迟写和异步写优化

一、写操作的基本原理

在 MySQL 中,写操作涉及的步骤较为复杂,通常包括以下几个关键过程:

  1. 写入缓冲区:数据被写入缓冲区,等待后续的磁盘 I/O 操作。
  2. 事务日志(redo log 和 binlog)记录:对于事务型存储引擎(如 InnoDB),MySQL 会将每次的写操作记录到 redo logbinlog 中,以保证数据的一致性和可靠性。
  3. 刷盘操作:最终,数据被写入到磁盘(即持久化)。

在这个过程中,磁盘 I/O 是影响写操作性能的主要瓶颈,因为磁盘的读写速度远远低于内存的访问速度。为了提升性能,MySQL 通过引入延迟写异步写技术,来减少每次写操作时的等待时间。

二、延迟写(Delayed Write)

延迟写是一种通过缓冲写操作来减少磁盘 I/O 的技术。MySQL 并不是在每次接收到写请求后立刻将数据写入磁盘,而是先将数据写入内存缓冲区,等待合适的时机(如缓冲区满或定时器到期)再进行批量写入磁盘。这种做法可以有效减少写操作的次数,提升写入性能。

1. InnoDB Buffer Pool 的延迟写机制

对于 InnoDB 存储引擎,Buffer Pool 是用于缓存数据页和索引页的内存区域。当进行写操作时,数据首先被写入 Buffer Pool 中,并标记为 “脏页”(Dirty Page),表示该页的内容已经被修改但还未写入磁盘。InnoDB 会根据一定的策略将这些脏页写入磁盘,而不是每次写操作立即触发 I/O。

2. 延迟写的优势
  • 减少磁盘 I/O 次数:通过延迟写机制,可以将多个小的写操作合并为一次大的写操作,显著减少磁盘写入次数,降低 I/O 压力。
  • 提高写操作吞吐量:由于写操作不需要等待立即刷盘,因此可以提高写入的并发处理能力。
  • 改善系统性能:延迟写机制使得系统能够更有效地利用内存和磁盘资源,提升整体性能。
3. 配置与优化

innodb_max_dirty_pages_pct 参数控制 Buffer Pool 中允许的脏页比例。默认情况下,当脏页占比达到一定百分比时,InnoDB 会触发写入操作。

SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct';

默认值通常是 75%,这意味着当脏页占用 Buffer Pool 的 75% 时,InnoDB 会开始将脏页刷到磁盘。适当增大该值可以减少写入频率,从而提高性能,但同时也会增加宕机时丢失更多数据的风险。

SET GLOBAL innodb_max_dirty_pages_pct = 80;

优化策略

  • 增大 Buffer Pool:通过增大 innodb_buffer_pool_size,可以容纳更多数据在内存中,从而减少磁盘写入的频率。
SET GLOBAL innodb_buffer_pool_size = 8G;
  • 控制脏页比例:在高并发写场景下,可以适当增大 innodb_max_dirty_pages_pct,以延长数据在内存中的停留时间。
4. 延迟写的风险

虽然延迟写能够提升写操作性能,但它也增加了数据丢失的风险。如果系统崩溃或发生意外,尚未刷盘的脏页数据会丢失。因此,延迟写适用于对性能要求高但数据丢失风险较低的场景,或者可以通过其他手段(如 binlog)进行数据恢复。

三、异步写(Asynchronous Write)

异步写是一种让写操作不阻塞应用的技术。当进行写操作时,MySQL 不会等待数据写入磁盘完成后再返回给客户端,而是将数据写入缓冲区后立即返回,后台线程会异步地将数据写入磁盘。这大大减少了写操作的等待时间,提升了系统的并发处理能力。

1. InnoDB 的异步写机制

InnoDB 存储引擎使用异步写来处理大量的写入操作,主要涉及以下几种异步写机制:

  • 异步提交:MySQL 将数据写入 redo log 后立即返回客户端,而不是等待事务日志刷入磁盘。innodb_flush_log_at_trx_commit 参数决定了这种异步提交的行为。

    • innodb_flush_log_at_trx_commit=0:表示 MySQL 会定期刷新事务日志(通常每秒一次),但不会在每次提交事务时刷新日志。
    • innodb_flush_log_at_trx_commit=1:表示每次事务提交时都会立即将日志刷到磁盘,最安全但最慢。
    • innodb_flush_log_at_trx_commit=2:表示每次提交事务时只将日志写入操作系统缓存,不会立即刷盘,稍微提高了性能,但数据安全性稍差。
    SET GLOBAL innodb_flush_log_at_trx_commit = 2;
    
2. 配置与优化

异步写的配置主要围绕 innodb_flush_log_at_trx_commit 参数。对于性能要求较高而数据安全性要求较低的系统,可以选择 innodb_flush_log_at_trx_commit=2,以提升写操作的性能。

优化策略

  • 降低刷盘频率:通过设置 innodb_flush_log_at_trx_commit=2,可以减少磁盘刷写的频率,提升写入性能。
  • 适当配置 sync_binlog:在使用 binlog 进行复制的系统中,可以将 sync_binlog 设置为 0,表示 MySQL 不会每次写入 binlog 时都进行刷盘,这可以进一步提高性能。
SET GLOBAL sync_binlog = 0;
3. 异步写的风险

异步写的主要风险在于数据一致性。如果发生系统崩溃,由于日志和数据尚未写入磁盘,可能导致数据丢失或不一致。因此,异步写适用于高性能、低延迟的场景,尤其是在对数据丢失风险有一定容忍度的系统中(如临时数据、日志数据等)。

四、MySQL 的双写机制(Doublewrite Buffer)

为了减少脏页写入时出现崩溃导致数据损坏的风险,InnoDB 引入了双写机制。该机制会将脏页的数据先写入到一个独立的 doublewrite buffer,然后再将数据写入磁盘。即使系统崩溃,也能通过 doublewrite buffer 恢复数据,保证数据一致性。

innodb_doublewrite 参数控制双写机制,默认为开启状态。虽然双写机制稍微增加了写操作的开销,但它能够显著提高数据的安全性。

SHOW VARIABLES LIKE 'innodb_doublewrite';

关闭双写机制可以提高性能,但会增加崩溃恢复的复杂性和风险。通常情况下,建议保持该功能开启,以保障数据安全。

SET GLOBAL innodb_doublewrite = 1;

五、延迟写与异步写的优化实践

在实际的 MySQL 优化中,可以通过调整延迟写和异步写的策略来平衡性能与数据一致性。

1. 针对高并发写操作的优化

对于具有大量并发写操作的系统,如社交网络、日志系统等,可以通过以下方式优化写入性能:

  • 增大 Buffer Pool:通过 innodb_buffer_pool_size 增大内存缓存空间,减少磁盘 I/O。
  • 延长脏页滞留时间:通过增大 innodb_max_dirty_pages_pct 允许更多脏页滞留在内存中。
  • 设置异步刷盘:将 innodb_flush_log_at_trx_commit 设置为 2,减少频繁的刷盘操作。
2. 针对对数据一致性要求

高的场景

对于数据一致性要求高的场景(如金融系统、订单系统等),即使牺牲一些性能,也需要保证数据的安全性:

  • 开启双写机制:保持 innodb_doublewrite 为开启状态,防止崩溃后数据损坏。
  • 设置同步刷盘:将 innodb_flush_log_at_trx_commit 设置为 1,每次提交事务都刷盘,确保数据安全。

六、总结

MySQL 的延迟写和异步写技术可以显著提高写操作的性能,尤其是在高并发、大量写入的场景下,它们通过减少磁盘 I/O 操作、提高写入吞吐量,改善了系统的响应速度。然而,这些技术在提升性能的同时,也带来了数据一致性和持久性方面的风险。

在实际项目中,开发者需要根据业务需求和应用场景权衡性能与数据安全,合理配置 MySQL 的延迟写和异步写机制。通过调整 innodb_buffer_pool_sizeinnodb_flush_log_at_trx_commit 等关键参数,可以在性能和安全性之间找到最佳的平衡点,确保系统在高负载下依然能够稳定高效运行。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python中使用Redis布隆过滤器
  • miniconda环境配置
  • 深度学习自编码器 - 收缩自编码器(CAE)篇
  • 信安 实验1 用Wireshark分析典型TCP/IP体系中的协议
  • OpenCV运动分析和目标跟踪(3)计算图像序列的加权平均值函数accumulateWeighted()的使用
  • PyCharm用法
  • git拉取大文件
  • 数据库基础知识---------------------------(3)
  • solidwork剪裁实体
  • 【软考】计算机软件著作权
  • vscode关闭git的提交提示
  • 第一章 初识SpringBoot
  • 王者荣耀英雄检测数据集
  • QNX Hypervisor(十一)Linux Guest IPC 三
  • 命名空间————————
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【React系列】如何构建React应用程序
  • emacs初体验
  • java小心机(3)| 浅析finalize()
  • js ES6 求数组的交集,并集,还有差集
  • Mithril.js 入门介绍
  • Mocha测试初探
  • Service Worker
  • Spark学习笔记之相关记录
  • TypeScript实现数据结构(一)栈,队列,链表
  • vue-router 实现分析
  • vue的全局变量和全局拦截请求器
  • Xmanager 远程桌面 CentOS 7
  • yii2权限控制rbac之rule详细讲解
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 聊一聊前端的监控
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端学习笔记之观察者模式
  • 小程序开发之路(一)
  • 优秀架构师必须掌握的架构思维
  • ​虚拟化系列介绍(十)
  • # Redis 入门到精通(一)数据类型(4)
  • #### go map 底层结构 ####
  • #define 用法
  • (3)nginx 配置(nginx.conf)
  • (js)循环条件满足时终止循环
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (四)c52学习之旅-流水LED灯
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • *** 2003
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET 设计模式初探
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .Net环境下的缓存技术介绍