MySQL 5.7 OOM问题诊断——就是这么简单

风清扬又道:“单以武学而论,这些魔教长老们也不能说真正已窥上乘武学之门。他们不懂得,招数是死的,发招之人却是活的。死招数破得再妙,遇上了活招数,免不了缚手缚脚,只有任人屠戮。这个‘活’字,你要牢牢记住了。学招时要活学,使招时要活使。倘若拘泥不化,便练熟了几千万手绝招,遇上了真正高手,终究还是给人家破得干干净净。”

今天,来谈谈MySQL的OOM(out of memory)问题诊断。之前,这类问题的定位对于普通用户来说并不怎么简单。但是在MySQL 5.7中,OOM问题的定位变得极其容易。还没掌握的小伙伴赶快来看下吧。通常来说,发生OOM时可在系统日志找到类似的日志提示:

[3207032.031552] bash invoked oom-killer: gfp_mask=0x280da,order=0, oom_score_adj=0

[3207032.031561] bash cpuset=/ mems_allowed=0-1

[3207032.031566] CPU: 1 PID: 5019 Comm: bash Not tainted3.10.0-327.22.2.el7.x86_64 #1

[3207032.031568] Hardware name: Huawei Technologies Co.,

[3207032.031570] ffff8802322b7300 00000000922e27ce ffff8803f0c9baf8 ffffffff816360fc

[3207032.031576] ffff8803f0c9bb88 ffffffff8163109c ffff88003547bde0 ffff88003547bdf8

[3207032.031579] 0000000000000206 ffff8802322b7300 ffff8803f0c9bb70 ffffffff81128c7f

[3207032.031583] Call Trace:

[3207032.031596] [<ffffffff816360fc>] dump_stack+0x19/0x1b

[3207032.031600] [<ffffffff8163109c>] dump_header+0x8e/0x214

[3207032.031614] [<ffffffff81128c7f>] ? delayacct_end+0x8f/0xb0

[3207032.031620] [<ffffffff8116d20e>] oom_kill_process+0x24e/0x3b0

[3207032.031623] [<ffffffff8116cd76>] ? find_lock_task_mm+0x56/0xc0

[3207032.031626] [<ffffffff8116da36>] out_of_memory+0x4b6/0x4f0

[3207032.031630] [<ffffffff81173c26>] __alloc_pages_nodemask+0xaa6/0xba0

[3207032.031637] [<ffffffff811b7eba>] alloc_pages_vma+0x9a/0x150

[3207032.031643] [<ffffffff81197a85>] handle_mm_fault+0xb85/0xf50

[3207032.031648] [<ffffffff81641d80>] __do_page_fault+0x150/0x450

[3207032.031651] [<ffffffff816420a3>] do_page_fault+0x23/0x80

[3207032.031656] [<ffffffff8163e308>] page_fault+0x28/0x30

MySQL 5.7的库performance_schema新增了以下这几张表,用于从各维度查看内存的消耗:

  • memory_summary_by_account_by_event_name

  • memory_summary_by_host_by_event_name

  • memory_summary_by_thread_by_event_name

  • memory_summary_by_user_by_event_name

  • memory_summary_global_by_event_name

简单来说,就是可以根据用户、主机、线程、账号、全局的维度对内存进行监控。同时库sys也就这些表做了进一步的格式化,可以使得用户非常容易的观察到每个对象的内存开销:

细心的同学可能会发现,默认情况下performance_schema只对performance_schema进行了内存开销的统计。但是在对OOM进行诊断时,需要对所有可能的对象进行内存监控。因此,还需要做下面的设置:

mysql> update performance_schema.setup_instruments set

enabled = 'yes' where name like 'memory%';

Query OK, 310 rows affected (0.00 sec) Rows matched: 380 Changed: 310 Warnings: 0

但是这种在线打开内存统计的方法仅对之后新增的内存对象有效:

如想要对全局生命周期中的对象进行内存统计,必须在配置文件中进行设置,然后重启:

通过上面的结果,有小伙伴是不是已经发现可疑的内存使用了呢?memory/innodb/os0file这个对象使用了1.42G内存,而整个数据库实例的Buffer

Pool只有1.05G。那么这时就可以去bugs.mysql.com上去搜索下。果不其然,是一官方已知问题,并已在5.7.14中修复。

通过类似方法Inside君已经定位了5起OOM问题。当然,这里Inside君只是给了一个思路,活学活用,才能达到无招胜有招的至臻境界。

转载于:https://www.cnblogs.com/xibuhaohao/p/10838460.html

<think>我们正在讨论的是MySQL中`mysqld_safe`和`mysqld`两个进程的区别。根据引用内容,我们可以总结如下: 1. **mysqld_safe** 是一个启动脚本,用于启动和监控 **mysqld** 进程(即MySQL服务器主进程)。 2. **mysqld_safe** 是 **mysqld** 的父进程(引用[1]和引用[3])。 3. 在Linux系统中,当我们通过服务脚本(如`/etc/init.d/mysql start`)启动MySQL时,实际上执行的是`mysqld_safe`(引用[1])。 4. `mysqld_safe` 提供了一些安全特性,例如在服务器崩溃时自动重启,以及将错误日志重定向到文件等(引用[2]和引用[4])。 **两者核心区别**: | 特性 | mysqld_safe | mysqld (直接运行) | |--------------|------------------------------------------------|---------------------------------------| | **进程性质** | 守护进程脚本(Shell脚本) | 数据库主进程(二进制程序) | | **主要功能** | 启动、监控、重启mysqld,管理日志和错误处理 | 实际处理SQL请求和数据存储 | | **运行方式** | 作为mysqld的父进程,通过`nohup`后台运行mysqld | 可直接在前台运行(调试时) | | **崩溃恢复** | 支持自动重启(默认行为) | 自身无重启机制 | | **日志管理** | 重定向错误日志到文件(通过`--log-error`选项) | 依赖启动参数配置日志 | ### 详细解析 #### 1. **启动流程差异** - **通过`mysqld_safe`启动**(生产环境标准方式): ```bash /bin/sh /path/to/mysqld_safe --defaults-file=/etc/my.cnf ``` 该脚本会: - 解析配置文件(如`my.cnf`) - 设置环境变量(如`LD_LIBRARY_PATH`) - 用`nohup`启动`mysqld`并脱离终端(引用[3]): ```bash nohup /path/to/mysqld ... > /dev/null 2>&1 & ``` - 持续监控`mysqld`进程状态(引用[1]) - **直接运行`mysqld`**(仅限调试): ```bash /path/to/mysqld --defaults-file=/etc/my.cnf ``` - 进程直接在前台运行(占用终端) - 崩溃后不会自动重启 - 日志输出直接到终端(除非手动重定向) #### 2. **监控与容错机制** - `mysqld_safe` 会监控子进程 `mysqld` 的状态。如果 `mysqld` 意外终止(如段错误),`mysqld_safe` 会自动重启它(引用[4]展示了重启失败场景)。 - 直接运行 `mysqld` 无此保护——进程退出后服务即中断。 #### 3. **日志与错误处理** - `mysqld_safe` 强制将 `mysqld` 的标准错误(stderr)重定向到日志文件(通过 `--log-error` 指定位置),这是生产环境的关键特性(引用[4]中的错误日志路径为`/var/log/mysqld.log`)。 - 直接运行 `mysqld` 时,错误信息默认打印到控制台(除非显式配置日志文件)。 #### 4. **环境配置** - `mysqld_safe` 会在启动前设置必要的运行时环境(如库路径、核心文件生成配置),而直接运行 `mysqld` 需手动配置(引用[2]中提到的`--basedir`、`--datadir`等参数)。 --- ### 为什么生产环境必须用`mysqld_safe`? 1. **高可用保障**:自动重启机制避免服务长时间中断。 2. **日志集中管理**:确保错误日志持久化存储(关键于故障排查)。 3. **安全隔离**:通过`--user`选项以非root身份运行`mysqld`(引用[3]中`--user=mysql`)。 > **注意**:在MySQL 5.7+版本中,官方推荐使用`systemd`管理服务(如`systemctl start mysqld`),其底层仍调用`mysqld_safe`或直接集成其功能[^5]。 --- ### 操作示例:如何查看进程树 ```bash $ pstree -p | grep mysql |-mysqld_safe(6488)---mysqld(3324)-+-{mysqld}(3326) |-{mysqld}(3327) ... ``` - 进程ID 6488:`mysqld_safe`(父进程) - 进程ID 3324:`mysqld`(子进程) --- ### 常见问题分析 **Q: 为什么`mysqld_safe`会报`Killed`错误?** 如引用[4]所示: ```log /usr/bin/mysqld_safe: line 183: 23638 Killed ... ``` 原因:底层`mysqld`进程被系统杀死(通常因OOM或手动`kill -9`)。此时`mysqld_safe`会尝试重启,但若资源不足将循环失败。 --- §§相关问题§§ 1. 如何配置`mysqld_safe`的自动重启策略? 2. 在`systemd`管理的系统中,`mysqld_safe`是否仍然需要? 3. `mysqld_safe`和`mysqld`的内存使用关系是怎样的? 4. 如何诊断`mysqld_safe`频繁重启`mysqld`的问题?</think>### MySQL 中 `mysqld_safe` 与 `mysqld` 进程的区别解析 #### 一、核心区别概览 | **特性** | **`mysqld_safe`** | **直接运行 `mysqld`** | |------------------|-------------------------------------------------|----------------------------------------| | **进程性质** | 守护进程脚本(Shell脚本) | 数据库主进程(二进制程序) | | **主要功能** | 启动/监控/重启 `mysqld`,提供安全保护 | 实际执行数据库操作(SQL处理、存储等) | | **运行方式** | 通过 `/bin/sh` 解释执行 | 直接执行二进制文件 | | **进程关系** | `mysqld_safe` 是 `mysqld` 的父进程(引用[1][3]) | 无父进程保护 | | **崩溃恢复** | 支持自动重启(核心功能) | 崩溃后直接退出 | | **日志管理** | 自动重定向错误日志(引用[4]) | 需手动配置日志输出 | --- #### 二、详细功能对比 1. **`mysqld_safe` 的核心作用** - **进程监控与重启** 持续监控 `mysqld` 状态,在其崩溃时自动重启(引用[4]中体现的容错机制): ```bash while true; do mysqld "$@" & # 启动mysqld wait $! # 监控退出状态 [ $? -eq 0 ] && break # 正常退出则终止循环 sleep 2 # 异常退出时等待后重启 done ``` - **安全增强** 强制以非root用户运行(通过 `--user=mysql` 参数,引用[3]),降低权限风险。 2. **`mysqld` 的核心作用** - **数据库引擎** 直接处理SQL查询、事务管理、数据存储等核心功能。 - **配置加载** 解析 `my.cnf` 配置文件,初始化存储引擎和内存池。 --- #### 三、启动流程差异(以标准服务启动为例) ```mermaid graph TD A[/etc/init.d/mysql start] --> B[调用 mysqld_safe 脚本] B --> C[/bin/sh 解释执行 mysqld_safe] C --> D[加载环境变量和配置] D --> E[用 nohup 启动 mysqld 进程] E --> F[持续监控 mysqld 状态] F -- 崩溃 --> E F -- 正常退出 --> G[结束] ``` > **关键点**: > - 直接运行 `mysqld` 会跳过蓝色流程(监控/保护层) > - 生产环境必须通过 `mysqld_safe` 启动(引用[1][3]) --- #### 四、典型场景分析 1. **崩溃恢复场景**(引用[4]) ```log /usr/bin/mysqld_safe: line 183: 23638 Killed MySQL Daemon failed to start. Starting mysqld: [FAILED] ``` - `mysqld_safe` 检测到 `mysqld` 被 `kill -9` 强制终止 - 尝试重启失败后抛出错误(若直接运行 `mysqld` 则无此提示) 2. **版本切换场景**(引用[2]) 通过 `--mysqld-version=max` 启动定制版本: ```bash mysqld_safe --mysqld-version=max # 实际启动 mysqld-max ``` --- #### 五、生产环境实践建议 1. **必须使用 `mysqld_safe` 的场景** - 高可用部署(需自动恢复) - 安全合规要求(非root用户运行) - 日志集中管理需求 2. **直接运行 `mysqld` 的调试场景** ```bash # 仅用于调试(无保护机制) /usr/sbin/mysqld --console --debug ``` > **总结**:`mysqld_safe` 是 MySQL 服务的安全守护层,提供关键的保护和运维功能;而 `mysqld` 是实际执行数据库操作的引擎进程。两者协同构成完整的 MySQL 服务[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值