InnoDB redo log thread cpu usage

简介: InnoDB 在8.0 里面把写redo log 角色的各个线程都独立出来, 每一个thread 都处于wait 状态, 同样用户thread 调用log_write_up_to 以后, 也会进入wait 状态.这里的wait 等待最后都是通过调用 os_event_wait_for 来实现, 而 os_event_wait_for 是先spin + wait 的方式实现.所以这里有两个参数会影响os_event_wait_for 函数:spins_limit,timeout.

InnoDB 在8.0 里面把写redo log 角色的各个线程都独立出来, 每一个thread 都处于wait 状态, 同样用户thread 调用log_write_up_to 以后, 也会进入wait 状态.

这里的wait 等待最后都是通过调用 os_event_wait_for 来实现, 而 os_event_wait_for 是先spin + wait 的方式实现.

os_event_wait_for

inline static Wait_stats os_event_wait_for(os_event_t &event,
​ uint64_t spins_limit,
​ uint64_t timeout,
​ Condition condition = {})

所以这里有两个参数会影响os_event_wait_for 函数

  1. spins_limit
  2. timeout

在include/os0event.ic 里面, os_event_wait_for 是把spin 和 os_event_t 结合起来使用的一个例子.

简单来说就是先spin 一段时间, 然后在进入pthread_cond_wait() 函数, 所以spins_limit 控制spin 的次数, timeout 控制pthread_cond_wait() wait的时间

具体来说

在进行pthread_cond_wait 之前, 先通过PAUSE 指令来做spin loop, 在每一次的spin loop 的时候, 同时检查当前的条件是否满足了, 如果满足 当前这个os_event_wait_for 就不经过pthread_cond_wait 的sleep 就可以直接退出了, 如果不满足, 才会进入到 pthread_cond_wait

在具体执行pthread_cond_wait 的时候, 当超时被唤醒的时候, 也会动态调整pthread_cond_wait 的timeout 时间, 在每4次超时返回以后, 会把当前的timeout 时间* 2. 然后最大的timeout 时间是100ms

// 1. timeout
// 2. timeout
// 3. timeout
// 4. timeout
// 5. 2 * timeout
// ...
// 9. 4 * timeout
// ...
// 13. 8 * timeout

InnoDB 这里做的很细致, 8.0 新增加的这几个log_writer, log_flusher, log_write_notifier, log_flusher_notifier, log_closer 等等thread 都可以调整spin 的次数, 以及每次spin 的时间.

线程名称 innodb_log_xxx_spin_delay innodb_log_xxx_timeout
log_writer innodb_log_writer_spin_delay innodb_log_xxx_timeout
log_flusher innodb_log_flusher_spin_delay innodb_log_flusher_timeout
log_write_notifier innodb_log_write_notifier_spin_delay innodb_log_write_notifier_timeout
log_flush_notifier innodb_log_flush_notifier_spin_delay innodb_log_flush_notifier_timeout
log_closer innodb_log_closer_spin_delay innodb_log_closer_timeout

srv_log_spin_cpu_abs_lwm && srv_log_spin_cpu_pct_hwm

同时 InnoDB 也会统计运行过程中的cpu 利用率来判断spin 最多可以执行多少次.

struct Srv_cpu_usage {
int n_cpu;
double utime_abs;
double stime_abs;
double utime_pct;
double stime_pct;
};

在这里主要用到 srv_cpu_usage.utime_abs和srv_cpu_usage.utime_pct.

innodb主线程会每隔一段时间(>= 100ms), 执行 srv_update_cpu_usage() 更新cpu_usage, 记录在srv_cpu_usage内.

srv_cpu_usage.utime_abs表示平均每微秒时间内所有用户态cpu 执行的时间总和, 比如一个进程使用了16core, 那么就会统计16core 上总的时间

比如说,系统是4核,这一次的更新间隔是200us,cpu 0-3的用户态时间分别为100us, 80us, 110us, 110us,则srv_cpu_usage.utime_abs 为(100+80+110+110)* 100 / 200 = 200;

srv_cpu_usage.utime_pct则是平均每微秒时间内用户态cpu 的百分比, 其实就是总的时间除以cpu 个数, srv_cpu_usage.utime_pct = srv_cpu_usage.utime_abs / n_cpus.

可以调整的两个参数对于cpu 的利用率限制:

srv_log_spin_cpu_abs_lwm(默认值80)

srv_log_spin_cpu_pct_hwm (默认值50)

srv_log_spin_cpu_abs_lwm: 表示的是平均每微秒时间内, 用户态cpu 时间的最小值, 平均每微秒用户态cpu 时间超过这个值, 才会spin

srv_log_spin_cpu_pct_hwm: 表示的是用户态cpu 利用率, 当cpu 使用率小于这个值的时候, 才会spin

在 log_wait_for_write 和log_wait_for_flush 中

会同时判断 srv_log_spin_cpu_abs_lwm 和 srv_log_spin_cpu_pct_hwm 这两个参数,

729 static Wait_stats log_wait_for_write(const log_t &log, lsn_t lsn) {
......
738 if (srv_flush_log_at_trx_commit == 1 ||
739 srv_cpu_usage.utime_abs < srv_log_spin_cpu_abs_lwm ||
740 srv_cpu_usage.utime_pct >= srv_log_spin_cpu_pct_hwm) {
741 max_spins = 0;
742 }
......
763 }

769 static Wait_stats log_wait_for_flush(const log_t &log, lsn_t lsn) {
......
775 if (log.flush_avg_time >= srv_log_wait_for_flush_spin_hwm ||
776 srv_flush_log_at_trx_commit != 1 ||
777 srv_cpu_usage.utime_abs < srv_log_spin_cpu_abs_lwm ||
778 srv_cpu_usage.utime_pct >= srv_log_spin_cpu_pct_hwm) {
779 /* Average flush time is too big, don't spin,
780 also don't spin when trx != 1. */
781 max_spins = 0;
782 }
......
809 }

同时所有的 log_writer, log_flusher, log_write_notifier, log_flush_notifier, log_closer 等等8.0 新增加的redo log 相关的线程在执行os_event_wait_for 之前都会判断

如果 srv_cpu_usage.utime_abs < srv_log_spin_cpu_abs_lwm

也就是当前cpu 用户态执行的时间小于就不允许进行spin 了,

auto max_spins = srv_log_writer_spin_delay;

if (srv_cpu_usage.utime_abs < srv_log_spin_cpu_abs_lwm) {
  max_spins = 0;
}

const auto wait_stats = os_event_wait_for(
    log.writer_event, max_spins, srv_log_writer_timeout, stop_condition);

在低core 的场景中, cpu 本身就少, 所以要尽可能避免cpu 的使用, 因此线上可以把这两个参数设置成规格参数

因此可以综合调整这两个参数, 当cpu 利用率高的时候 调大 srv_log_spin_cpu_abs_lwm, 调小 srv_log_spin_cpu_pct_hwm 降低资源的利用率

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
11月前
|
存储 SQL 关系型数据库
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log、原理、写入过程;binlog与redolog区别、update语句的执行流程、两阶段提交、主从复制、三种日志的使用场景;查询日志、慢查询日志、错误日志等其他几类日志
857 35
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
|
9月前
|
数据库 文件存储 数据安全/隐私保护
YashanDB redo日志文件管理
YashanDB的redo日志文件用于记录数据库物理日志,支持宕机重演和主备复制。 redo日志有4种状态:NEW(新创建)、CURRENT(当前写入)、ACTIVE(未归档或未写盘)和INACTIVE(可复用)。可通过V$LOGFILE视图或直接查看$YASDB_DATA/dbfiles目录来管理redo日志。此外,支持添加、切换和删除redo日志以优化性能或应对磁盘故障等情况,但需注意仅能删除INACTIVE或NEW状态的日志以确保数据安全。
|
11月前
|
存储 缓存 关系型数据库
图解MySQL【日志】——Redo Log
Redo Log(重做日志)是数据库中用于记录数据页修改的物理日志,确保事务的持久性和一致性。其主要作用包括崩溃恢复、提高性能和保证事务一致性。Redo Log 通过先写日志的方式,在内存中缓存修改操作,并在适当时候刷入磁盘,减少随机写入带来的性能损耗。WAL(Write-Ahead Logging)技术的核心思想是先将修改操作记录到日志文件中,再择机写入磁盘,从而实现高效且安全的数据持久化。Redo Log 的持久化过程涉及 Redo Log Buffer 和不同刷盘时机的控制参数(如 `innodb_flush_log_at_trx_commit`),以平衡性能与数据安全性。
527 5
图解MySQL【日志】——Redo Log
|
10月前
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
234 16
|
10月前
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
200 4
|
10月前
|
SQL 存储 关系型数据库
简单聊聊MySQL的三大日志(Redo Log、Binlog和Undo Log)各有什么区别
在MySQL数据库管理中,理解Redo Log(重做日志)、Binlog(二进制日志)和Undo Log(回滚日志)至关重要。Redo Log确保数据持久性和崩溃恢复;Binlog用于主从复制和数据恢复,记录逻辑操作;Undo Log支持事务的原子性和隔离性,实现回滚与MVCC。三者协同工作,保障事务ACID特性。文章还详细解析了日志写入流程及可能的异常情况,帮助深入理解数据库日志机制。
1187 0
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
349 3
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
3955 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
8月前
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
849 54