MySQL慢查询日志实战指南:从开启配置到SQL优化完整流程

搞MySQL性能排查的人,迟早都会跟慢查询日志打交道。我之前排查过一个持续了一整天的接口超时问题,最后定位到是一句没走索引的UPDATE把整库拖住了。当时要是没开着慢查询日志,光靠猜,不知道要折腾多久。所以说慢查询日志是MySQL性能分析里最便宜、最值得先开的一项能力,一点不过分。

这篇不是讲理论,我直接把慢查询日志从“是什么”到“怎么开”,再到“拿到日志之后怎么做优化”这条线完整带一遍。适合刚接触MySQL优化的人,也适合已经开了慢日志但不知道怎么用的人。全文以MySQL 5.7和8.0为主,命令和配置都给你可以直接抄的版本。

1. 慢查询日志:一条SQL从“慢”到“被发现”的完整旅程

1.1 慢查询日志到底记录了什么

慢查询日志(Slow Query Log)是MySQL官方提供的、用来记录执行时间超过指定阈值的SQL语句的日志。默认阈值是10秒,也就是说一条SQL执行时间超过10秒,才会被写入慢日志文件。

这个描述看着简单,但很多人理解有偏差。我拆开说。

第一,它记录的是“执行完成”的语句。如果一条SQL因为锁等待一直卡住,还没执行完,那它暂时不会出现在慢日志里,等它执行完、超时、或者被kill掉之后,才可能被记录。这里有个容易忽略的点:一条SQL的“执行时间”是从服务器收到请求开始,到返回结果结束的整个过程,不是单纯的计算时间。所以慢日志里的Query_time实际上包含了解析、优化、执行、发送结果的全过程。

第二,它不只记录SELECT。UPDATE、DELETE、INSERT这类写操作如果很慢,同样会记录。很多人只盯着慢查询日志里的SELECT,结果把慢UPDATE漏掉了,这不对。

第三,默认情况下,它不记录没走索引的查询,除非你额外开启log_queries_not_using_indexes参数。这个参数我建议在开发环境打开,生产环境要慎重,因为一旦打开,日志量会暴涨,后面我会专门讲。

1.2 为什么每个后端和DBA都应该先看它

MySQL里能观察SQL执行情况的手段不少,比如performance_schema、sys schema、general log、慢查询日志。但慢查询日志在实际排查中的优先级非常高,原因有几个。

一是成本低。开慢日志对线上的性能影响很小,几乎可以忽略,特别是用FILE输出模式的时候。它不像general log那样记录所有SQL,不会产生海量写入,也不会明显拖慢数据库。

二是信息足够定位问题。一条慢日志记录里包含了执行时间、锁等待时间、扫描行数、返回行数、执行SQL原文。有了这些信息,你基本能判断这条SQL的问题是出在没走索引、扫描行数过大、还是锁等待太久。

三是不依赖外部工具。官方自带的mysqldumpslow就能做初步聚合,不用装额外的监控系统。很多中小团队没有性能监控平台,慢日志就是最朴素的“监控系统”。

1.3 慢日志和“死锁”“阻塞”到底是什么关系

热词里有个“慢查询 死锁 语句阻塞”,很多人会混在一起。这里先说清楚:慢查询日志记录的是“某条SQL执行得慢”,而死锁和阻塞是“SQL执行慢的两种可能原因”。

死锁本身不会直接写进慢查询日志,它是两个或多个事务互相持有对方需要的锁,导致谁也走不下去。MySQL检测到死锁后,会回滚其中一个事务,让另一个继续。这个“被牺牲”的事务,如果执行时间超过long_query_time阈值,它对应的SQL的慢日志记录里,Lock_time和Query_time通常会异常偏高。

阻塞就更直接了。事务A锁住了某一行,事务B去更新同一行,B只能等A提交或回滚。如果A一直不提交,B就一直在等锁,直到innodb_lock_wait_timeout(默认50秒)报错。这种情况下,B的SQL执行时间会超过阈值,被记进慢日志,而且Lock_time会非常显眼。

所以我的排查习惯是:先看慢日志里的Lock_time,如果Lock_time占比高,那基本可以断定问题不是SQL本身慢,而是并发锁冲突。这个思路后面第五部分会用一个完整案例展开。

需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。

2. 配置前必修课:慢查询日志的核心参数与版本差异

2.1 核心参数逐个拆解

配置慢查询日志之前,先把参数搞明白。下面这几个是最常用的,我按重要程度排个序。

参数名 默认值 作用 是否动态生效
slow_query_log OFF 慢查询日志总开关,1或ON表示开启
slow_query_log_file 主机名-slow.log 慢日志文件路径 是(需确认文件可写)
long_query_time 10 SQL执行时间超过该值才记录,单位秒,可设小数如0.1 是,但已建立的连接不生效
log_queries_not_using_indexes OFF 记录所有未使用索引的SQL,即使执行很快
min_examined_row_limit 0 扫描行数小于该值的SQL不记录,用于过滤小查询
log_throttle_queries_not_using_indexes 0 每分钟最多记录多少条未使用索引的SQL,0为不限
log_output FILE 日志输出方式:FILE(文件)、TABLE(表)、FILE,TABLE(都写)

这里重点解释两个坑。

第一个是long_query_time。这个参数是支持小数的,所以在MySQL 5.7以上版本里,你可以设置成0.5、0.3甚至0.1,用来抓那些“不是特别慢,但积累起来很要命”的SQL。但是注意,它是按秒算的,不是毫秒。设置long_query_time=0.1表示100毫秒,不是1毫秒。

第二个是“已建立的连接不生效”。这句话很关键。你执行SET GLOBAL long_query_time=1之后,已经存在的数据库连接用的还是旧值,只有新建立的连接才用新值。所以实际生效之后,建议你重新连一下客户端再验证,否则你会看到“我改了怎么没反应”的假象。

2.2 MySQL 5.7 与 MySQL 8.0 的差异点

MySQL 8.0相对5.7,在慢日志方面有几个差异值得注意。

第一,默认值层面,两者默认都是关闭慢日志,但文件路径规则稍有不同。5.7默认写到datadir下的主机名-slow.log,8.0也一样,不过8.0的安装包多了一些sys schema的辅助视图,官方推荐通过sys.schema_unused_indexes这类表辅助定位索引问题,慢日志本身还是那套逻辑。

第二,MySQL 8.0支持SET PERSIST,可以把参数持久化到mysqld-auto.cnf文件里,重启后依然生效。MySQL 5.7只能用SET GLOBAL临时设置,然后改my.cnf,不然一重启就丢。这个差别在生产环境很重要。

第三,8.0对权限体系更严格。5.7里需要SUPER权限才能改全局变量,8.0改成了SYSTEM_VARIABLES_ADMIN权限。普通开发账号一般是改不了的,得DBA来操作。

第四,8.0里如果使用log_output=TABLE,查询mysql.slow_log表时,sql_text字段默认是utf8mb3字符集,如果SQL里有特殊字符,可能出现显示异常,5.7里也有类似问题但没这么扎眼。

2.3 只开日志不调参数,等于没开

我见过不少团队,打开slow_query_log之后发现慢日志里什么都没有,就以为线上很健康。真相往往不是没有慢SQL,而是long_query_time默认10秒太高了。

大多数互联网业务,查询超过1秒就值得关注,超过3秒基本就是在报警边缘。所以我一般建议:

  • 开发环境:long_query_time设为0.1,再开启log_queries_not_using_indexes,尽可能暴露所有潜在问题。
  • 生产环境:从1秒开始,稳定后再考虑0.5秒。不要一上来就设0.1,否则日志量和写入压力会翻几倍。

这个“先1秒,再逐步收紧”的思路,比一次性抓得很细更实用,也更好交代。

3. 从零开启慢查询日志:本地MySQL与Docker容器的完整操作

3.1 本地安装场景的配置步骤

本地装了MySQL,想开慢日志,最简单的做法是改my.cnf(Linux)或my.ini(Windows)。

在[mysqld]段落下面加这几行:

ini复制[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 0
min_examined_row_limit = 100

解释一下这几项。

slow_query_log = 1是总开关。slow_query_log_file指定日志文件绝对路径。注意这个路径要保证MySQL进程有写权限,我踩过一次坑:路径写对了,但目录属主是root,MySQL根本写不进去,启动时还不报错,只是在执行慢SQL时悄悄不写日志,排查了半天。

long_query_time = 1是阈值。log_queries_not_using_indexes建议先保持0,等确认日志量可控再开。min_examined_row_limit = 100的意思是,扫描行数低于100的SQL不记录,这个能过滤掉一堆扫描少量行但不走索引的琐碎查询。

改完配置,重启MySQL:

bash复制systemctl restart mysqld

然后登录MySQL确认参数:

sql复制SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';

如果看到slow_query_log为ON,long_query_time为1,就说明开好了。

3.2 Docker容器中的MySQL怎么开慢日志

现在很多人直接用Docker跑MySQL,开慢日志的方式稍微有点不一样。

如果你的MySQL容器已经跑起来了,最快的验证方式是在容器内执行SQL:

bash复制docker exec -it mysql8 mysql -uroot -p
sql复制SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow.log';

这种方式的缺点是:容器一旦重启,所有全局设置都会丢失。因为SET GLOBAL只是改了内存里的值,没有写进配置文件。

要永久生效,推荐用挂载配置的方式。先把宿主机上的my.cnf写好,然后启动容器时挂载进去:

bash复制docker run -d \
  --name mysql8 \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=yourpassword \
  -v /etc/mysql/conf.d/slow.cnf:/etc/mysql/conf.d/slow.cnf \
  -v /opt/mysql-data:/var/lib/mysql \
  mysql:8.0

注意挂载到/etc/mysql/conf.d/目录下,Docker官方镜像会自动读取这个目录下的.cnf文件。slow.cnf内容就是上一节那几行[mysqld]配置。

还有一个细节:如果MySQL的datadir是挂载的宿主机目录,慢日志文件默认也会写在datadir里。你可以在宿主机上直接tail这个文件:

bash复制tail -f /opt/mysql-data/slow.log

因为Docker容器内路径是/var/lib/mysql/slow.log,宿主机上就是/opt/mysql-data/slow.log。

3.3 验证慢日志是否真正生效

配置完之后,光看参数是ON还不够,得实际造一条慢SQL验证。

先执行一条延时查询,MySQL里可以用SLEEP函数:

sql复制SELECT SLEEP(2);

如果你设置的long_query_time是1秒,这条SLEEP(2)执行完就该进慢日志。去看日志文件:

bash复制tail -50 /var/log/mysql/slow.log

能看到类似这样的记录:

text复制# Query_time: 2.000350  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0
SET timestamp=1710000000;
SELECT SLEEP(2);

看到Query_time: 2.000350,说明慢日志真的在工作。

注意一句:不要在业务高峰期在线上库里执行SLEEP测试,即使只是一条SLEEP(2),也会占用一个连接资源。我一般是在测试环境或者凌晨低峰期做。

3.4 将慢日志输出到表:log_output=TABLE的用法

除了写文件,MySQL还允许把慢日志写进mysql.slow_log表。设置方式:

sql复制SET GLOBAL log_output = 'TABLE';

此时慢日志会写入mysql.slow_log,你可以用SQL查询:

sql复制SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10\G

表模式的优势是可以直接用SQL聚合分析,比如按db字段分组看哪个库慢SQL最多:

sql复制SELECT db, COUNT(*) AS cnt, ROUND(AVG(query_time), 2) AS avg_query_time
FROM mysql.slow_log
GROUP BY db
ORDER BY cnt DESC;

但表模式有个非常坑的副作用:写慢日志本身会成为一条INSERT语句,而且这条INSERT还可能触发额外的磁盘写入,导致数据库负载反而升高。所以生产环境我建议优先用FILE,表模式适合在测试环境临时用。后面第六部分我再展开讲它的坑。

4. 读懂慢日志:字段解析与 mysqldumpslow/pt-query-digest 实战

4.1 一条典型慢日志逐字段拆解

拿到慢日志文件后,第一件事是能看懂一条记录。我随便摘一条典型的:

text复制# Time: 2025-01-15T14:23:45.123456Z
# User@Host: app_user[app_user] @  [192.168.1.10]  Id: 12345
# Query_time: 3.876543  Lock_time: 0.321234 Rows_sent: 10  Rows_examined: 8654321
SET timestamp=1736951025;
SELECT a.id, b.name, a.order_no
FROM orders a
LEFT JOIN users b ON a.user_id = b.id
WHERE a.status = 1
ORDER BY a.create_time DESC
LIMIT 10;

逐行解释。

# Time行是SQL执行结束的时间点。8.0默认带时区信息,5.7可能是本地时间,这个看log_timestamps参数。

# User@Host行是执行这条SQL的账号和客户端IP。这个信息在定位“是哪个业务方产生了慢SQL”时非常有用。

Query_time是整条SQL的执行总耗时,也是判断慢不慢的核心指标。Lock_time是InnoDB层等待行锁、表锁、元数据锁等锁的耗时。注意,这不是“加锁操作本身”的耗时,而是“等待获取锁”的耗时。Rows_sent是实际返回给客户端的行数,Rows_examined是存储引擎扫描了多少行。

这里有个重要公式:Rows_examined远大于Rows_sent,几乎可以断定这条SQL有性能问题。比如上面这条,扫描了865万行,只返回10行,典型的没走索引或者索引选择失败。

SET timestamp=...是SQL开始执行的时间戳,下一行紧跟的才是真正的SQL语句。

看慢日志时,我习惯先看Rows_examined和Lock_time这两个字段。Rows_examined大,说明SQL本身扫描量大,优先看索引;Lock_time占比高,说明有锁等待,优先看并发事务。

4.2 mysqldumpslow:官方自带的轻量聚合工具

慢日志文件如果只有几十条,肉眼翻没问题。但如果每小时生成上千条,就得聚合分析了。MySQL自带的mysqldumpslow就是干这个的。

基本用法:

bash复制mysqldumpslow -s c -t 10 /var/log/mysql/slow.log

-s c表示按“出现次数”排序,-t 10表示只显示前10条。

其他常用排序方式:

  • -s t:按查询时间总和排序
  • -s l:按锁等待时间排序
  • -s r:按返回行数排序

还可以用-g过滤关键字:

bash复制mysqldumpslow -s c -g "orders" -t 20 /var/log/mysql/slow.log

这条命令会找出所有SQL文本里包含“orders”的慢SQL,并按出现次数排序。

mysqldumpslow有个特点:它会自动把SQL里的数字和字符串变量替换成N和S,也就是说不同参数的同类SQL会被聚合成同一条。比如SELECT * FROM orders WHERE id = 100SELECT * FROM orders WHERE id = 200,会被聚合成SELECT * FROM orders WHERE id = N。这个特性对聚合分析同类慢SQL非常有用。

但在容器里跑mysqldumpslow有个注意点:官方MySQL镜像里不一定自带这个工具,有的精简镜像没有。你可以用docker exec进容器试一下,没有就得在宿主机装MySQL客户端工具,或者用下面的pt-query-digest代替。

4.3 pt-query-digest:进阶分析的正确打开方式

pt-query-digest是Percona Toolkit里的核心工具,分析慢日志比mysqldumpslow强大得多。

安装方法,CentOS系:

bash复制yum install -y percona-toolkit

Ubuntu系:

bash复制apt-get install -y percona-toolkit

基本用法:

bash复制pt-query-digest /var/log/mysql/slow.log

输出结果分三部分:总体摘要、按Query_time排序的前N条SQL、每条SQL的详细统计。

总体摘要里最关键的是Profile部分,它会列出消耗时间最多的SQL类型。举个实际例子:

text复制# Profile
# Rank Query ID           Response time  Calls R/Call  V/M   Item
# ==== ================== ============== ===== ======= ===== ====
# 1    0xA1B2C3D4E5F60708 12586.5092 58.6%  832 15.1275  0.01 SELECT public.orders
# 2    0x1122334455667788 4521.2345 21.0%  156 28.9823  0.05 SELECT public.users

Rank 1这条SELECT orders表,总耗时占了全部慢SQL的58.6%,平均一次15秒,一共执行了832次。这种数据拿给业务方看,完全不需要争论,问题在哪一目了然。

pt-query-digest还支持按时间范围分析、导出特定条件的SQL等,比如:

bash复制pt-query-digest --since "2025-01-15 12:00:00" --until "2025-01-15 14:00:00" /var/log/mysql/slow.log

只看某段时间内的慢SQL,在定位“为什么这两小时接口超时”时特别有用。

4.4 分析慢日志时的几个实用习惯

根据我个人的实践,整理几个分析习惯:

  • 慢日志文件按天切割,分析时只拉当天的,不然文件太大,工具处理也慢。
  • 先用pt-query-digest看总体Profile,找到Top 5的SQL,再回到慢日志文件里看这5条的详细SQL文本。
  • 值得优化的SQL标准:总耗时占比高、出现次数多、单次扫描行数巨大。三条占两条,就该动手。
  • 别忽略Rows_examined小但频繁出现的SQL,这类往往是指数选择错误,一次只扫几千行,但每秒调用上百次,累积起来也很要命。

5. 慢日志只是起点:三个典型场景的优化复盘

5.1 场景一:分页查询越来越慢,索引和覆盖索引怎么救

慢日志里最常见的一类问题就是深分页。SELECT * FROM orders ORDER BY create_time DESC LIMIT 100000, 20这种SQL,越往后翻越慢,慢日志里大量出现。

原因看执行过程就明白了:MySQL要先扫描前100020行,然后丢弃前100000行,只返回最后20行。扫描的行数(Rows_examined)会随着页码增大而线性增长,查询自然越来越慢。

解决思路有三个,按复杂度从低到高排。

第一,改成游标分页,也叫keyset pagination。如果业务允许,不要用LIMIT加偏移量,改成基于上次查询的最后一条记录id,比如:

sql复制SELECT * FROM orders
WHERE create_time < '2025-01-15 00:00:00'
ORDER BY create_time DESC
LIMIT 20;

这样每次查询MySQL都能直接走索引定位到起点,扫描的行数大约就是20行,不会越翻越慢。

第二,如果必须保留LIMIT分页,用延迟关联优化:

sql复制SELECT a.*
FROM orders a
INNER JOIN (
    SELECT id
    FROM orders
    ORDER BY create_time DESC
    LIMIT 100000, 20
) b ON a.id = b.id
ORDER BY a.create_time DESC;

先把要返回的主键id查出来,再通过主键回表查询完整数据。子查询里只查id,能走覆盖索引,回表次数限制在20次,避免扫描上万行再回表上万次。

第三,保证排序字段有合适的索引。上面的SQL如果ORDER BY create_time没有索引,MySQL会先建临时文件排序,扫描行数直接翻倍。在create_time上建单列索引,或者建(create_time)联合索引,都能让ORDER BY直接走索引有序性。

第四,用Redis做热点分页缓存。这个对应热词里的“分页查询慢怎么用redis优化”。但要说句实在话:分页缓存的适用场景有限,只适合数据基本不变、浏览量大、可以容忍短时间数据延迟的业务。比如排行榜、公告列表。

实现上,最简单的是把前N页的查询结果序列化后存Redis,设置5到30秒过期:

python复制def get_page_orders(page, size):
    cache_key = f"orders:page:{page}:{size}"
    data = redis.get(cache_key)
    if data:
        return json.loads(data)
    orders = db.query("SELECT ... ORDER BY create_time LIMIT %s, %s", page, size)
    redis.setex(cache_key, 30, json.dumps(orders))
    return orders

注意几点:缓存key必须包含分页参数,否则不同页串数据;过期时间不要设太长,否则用户翻页时看到的是旧数据;冷门页不要缓存,否则Redis里全是垃圾数据。更稳妥的做法是只缓存第一页,后面的页走数据库。

5.2 场景二:慢日志里的Lock_time异常,死锁和阻塞排查

慢日志里如果出现很多Lock_time很大的记录,但Query_time本身不算离谱,这时候别急着去优化SQL,先处理锁问题。

我处理过一个典型case。业务反馈每天10点左右系统卡顿,慢日志里有一批UPDATE语句,单看执行很简单:

sql复制UPDATE inventory SET stock = stock - 1 WHERE product_id = 100;

Query_time大概2秒,Lock_time占了1.8秒。SQL本身没问题,product_id上有索引,扫描行数为1。问题在并发。

10点是活动秒杀开始时间,大量请求同时更新同一个商品库存,形成行锁竞争。每个事务都想拿同一行的X锁,后到的只能等前面提交。

排查步骤记录一下。

先确认当前是否有长时间运行的事务:

sql复制SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id,
       trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started;

重点看trx_started很早但trx_state是RUNNING的事务,这种多半是没提交的“僵尸事务”。

再查锁等待关系:

sql复制SELECT
  r.trx_id AS waiting_trx_id,
  r.trx_mysql_thread_id AS waiting_thread,
  b.trx_id AS blocking_trx_id,
  b.trx_mysql_thread_id AS blocking_thread,
  b.trx_query AS blocking_query
FROM performance_schema.data_lock_waits w
JOIN information_schema.innodb_trx r ON w.REQUESTING_ENGINE_TRANSACTION_ID = r.trx_id
JOIN information_schema.innodb_trx b ON w.BLOCKING_ENGINE_TRANSACTION_ID = b.trx_id;

最后用:

sql复制SHOW ENGINE INNODB STATUS\G

看LATEST DETECTED DEADLOCK段落,确认死锁发生的具体SQL。

优化方案要看业务。秒杀场景下的库存扣减,常见做法:

  • 把事务尽量做短,先扣库存再异步通知,不要在事务里插入远程调用。
  • 减少锁粒度,比如把单条库存记录拆分成多条库存桶,先随机选桶再扣。
  • 对确实需要串行的热点库存,用Redis原子扣减先挡一层,流量削平后再异步落库。

慢日志在这里的作用是“报警器”,它告诉你系统里锁等待已经很严重了,但根因往往要结合业务逻辑看。

5.3 场景三:一条SQL从慢到快的完整过程

最后给一个纯SQL优化的完整前后对比。慢日志里经常出现这类语句:

sql复制SELECT order_no, user_id, amount, status, create_time
FROM orders
WHERE status = 1
ORDER BY create_time DESC
LIMIT 20;

orders表有500万行,status字段的值只有0、1、2三种,create_time上有索引。

执行计划看起来可能不差,但实际经常慢。为什么?因为status = 1查询出的记录可能占全表的30%,MySQL优化器会认为“用索引没意义,直接全表扫描更快”,于是放弃create_time索引,走全表扫描,再用filesort排序。Rows_examined是500万,Query_time自然就上去了。

优化思路:

第一,组合索引。建一个(status, create_time)联合索引:

sql复制ALTER TABLE orders ADD INDEX idx_status_create_time (status, create_time);

这样MySQL可以先用status过滤,再直接按create_time顺序取数据,排序也能走索引,避免filesort。

第二,如果只查那4个字段,进一步用覆盖索引:

sql复制ALTER TABLE orders ADD INDEX idx_status_create_time_cover (status, create_time, order_no, user_id, amount);

让查询的所有字段都在索引里,这样连回表都省了,InnoDB直接从索引叶子节点拿数据。

加了覆盖索引后,Rows_examined从500万直接降到几十,Query_time从2.3秒降到几毫秒。这种效果在慢日志上看最直观:优化前的慢日志里这条SQL每天都出现,优化后再也不出现了。

需要注意一点:冗余联合索引会拖慢写入性能,尤其是订单表这种写操作频繁的表,加索引前要评估写入量。一般我会建议先加(status, create_time)二列索引,不够再加覆盖列。索引不是越多越好,能解决问题就好。

6. 慢查询日志的真坑:膨胀轮转、TABLE模式与误判预防

6.1 日志文件无限增长:轮转策略怎么设计

慢查询日志最大的坑就是日志文件无限膨胀。线上业务如果慢SQL多,一天能生成几个G的日志,磁盘满了之后,数据库会出各种幺蛾子。

Linux下最简单的方式是用logrotate按天切割。以CentOS为例,在/etc/logrotate.d/下新建一个mysql文件:

text复制/var/log/mysql/slow.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 640 mysql mysql
    sharedscripts
    postrotate
        /usr/bin/mysqladmin -uroot -p密码 flush-logs
    endscript
}

daily表示每天切割一次,rotate 14保留14份,compress压缩旧日志。

关键点在于postrotate里的mysqladmin flush-logs。这一步是让MySQL关闭当前日志文件并创建新文件。如果没有flush-logs,慢日志会继续写进已经被改名的旧文件,切割就白切了。

如果你用的是Docker容器,logrotate在宿主机上跑会比较绕。我现在的做法是:把慢日志写到宿主机挂载目录,然后用宿主机crontab每天凌晨执行一次切割:

bash复制0 0 * * * docker exec mysql8 bash -c "mysqladmin -uroot -p密码 flush-logs"

然后在宿主机上对/opt/mysql-data/slow.log做mv改名,再执行上面的flush-logs。顺序不能反,先mv再flush-logs。

6.2 log_output=TABLE的教训:mysql.slow_log表也会膨胀

前面提到log_output=TABLE把慢日志写入mysql.slow_log表。看起来方便,实际上问题很多。

第一个问题是mysql.slow_log表一样会膨胀。慢SQL多的时候,这张表能涨到几十个G,而且它本身也是InnoDB表,查询这张表反而会产生新的慢查询,形成恶性循环。

第二个问题是清理方式有讲究。直接DELETE FROM mysql.slow_log在小数据量时没问题,但表很大的时候,DELETE会产生大量undo和binlog,导致主从延迟,甚至拖垮数据库。正确做法是清空表:

sql复制TRUNCATE TABLE mysql.slow_log;

但TRUNCATE会重置自增ID,而且需要DROP权限,普通账号不一定有。

第三个问题是慢日志表如果涨得太快,会影响备份。mysqldump备份时默认会备份mysql库,一张几十个G的slow_log表会让备份时间变长不少。所以用TABLE模式一定要配上定时清理,还要在备份脚本里排除这个表。

我的建议是:生产环境老老实实用FILE,把日志文件交给logrotate管理。TABLE模式只适合测试环境快速分析。

6.3 误判预防:为什么日志里会出现一堆“不算慢”的SQL

开了log_queries_not_using_indexes之后,慢日志里会出现大量“没走索引但执行很快”的SQL,比如:

sql复制SELECT name FROM regions WHERE code = '110000';

regions表一共几千行,扫描全表也就几毫秒,但因为没走索引,被记录进来了。这种情况不是问题SQL,是过度记录。

避免误判的关键参数是min_examined_row_limit。这个参数的意思是:扫描行数低于这个值的SQL,即使没走索引,也不记录。

我的配置建议是:

ini复制slow_query_log = 1
long_query_time = 1
log_queries_not_using_indexes = 1
min_examined_row_limit = 1000
log_throttle_queries_not_using_indexes = 100

长话短说:

  • min_examined_row_limit=1000,过滤掉扫描小表的查询,避免无意义记录。
  • log_throttle_queries_not_using_indexes=100,限制每分钟最多记录100条未走索引的SQL,防止某一次bug导致日志爆炸。

这几个参数配合起来,慢日志的“信噪比”会高很多。

6.4 长事务与慢日志的关系

还有一个容易误导人的地方:慢日志里没有记录某条SQL,不代表数据库没有问题。

长事务就是一个典型。一个事务里执行了很多条SQL,每条都很快(小于long_query_time),但整个事务从开始到提交持续了几分钟。这种情况下,不会产生慢日志,但事务本身占用了大量连接、锁资源,甚至导致其他SQL阻塞而变慢。

所以排查阻塞问题时,不能只依赖慢日志。我会同时查information_schema.innodb_trx,找trx_started时间过长的空闲事务:

sql复制SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id,
       TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_sec
FROM information_schema.innodb_trx
WHERE trx_state = 'RUNNING'
ORDER BY trx_started
LIMIT 10;

看到duration_sec超过300秒的事务,就要警惕,它们往往是锁等待的源头。慢日志负责发现问题SQL,事务表负责找出持有锁的“元凶”,两者配合才完整。

6.5 我的实际经验总结

最后啰嗦几句我这几年的习惯。

新接手的MySQL实例,我第一件事一定是开慢查询日志,long_query_time设1秒,log_queries_not_using_indexes先不开。运行两三天后再开着两个参数去分析,同时用logrotate把日志切割配好。

每次优化完一条慢SQL,不是看执行计划变快了就完事,而是要回到慢日志里观察它后续是否还出现。我会在分析当天做一个全量快照,一周后再跑一次pt-query-digest对比,用数据说话:慢SQL数量下降了多少,总耗时下降了百分之几。这个方法比凭感觉判断靠谱得多。

慢日志不是银弹,它解决的是“定位哪些SQL有问题”这一步。真正难的是后面根据业务场景做最合适的优化,这可能涉及加索引、改SQL、调参、改表结构,甚至引入缓存。但如果没有慢日志这一步,后面的优化都是盲人摸象。把这一步做扎实,你的MySQL性能排查就已经赢了一半。

内容推荐

从源码到上线:构建专属数字化订货平台全流程解析
订货系统源码 · B2B订货系统 · 二次开发
在B2B业务数字化转型中,订货系统是企业打通订单、库存、价格与财务流程的关键基础设施。相比SaaS平台的固定模板,基于订货系统源码进行私有化部署,意味着企业能获得完全自主的数据资产与深度定制能力,满足多级价格、复杂审批、渠道权限等个性化业务规则。然而,从源码选型、运行环境搭建、二次开发到历史数据迁移与并发扣减,每一步都隐藏着工程风险。本文以实际落地经验为视角,拆解数字化订货平台的六大核心模块,梳理部署与二开的关键原则,并结合UAT测试、权限隔离、备份恢复等高频痛点,为正在评估自建订货系统的企业提供一套可复用的实施路径,助力真正构建出符合自身业务节奏的专属数字化订货平台。
C#上位机开发必备:HslControls工业控件库使用指南
C#上位机 · HslControls · WinForm
工业上位机软件界面开发中,开发者常需通过GDI+绘制仪表盘、趋势曲线等可视化元素,重复造轮子导致效率低下。WinForm作为主流桌面框架,搭配专业的工业控件库可显著提升开发效率。HslControls正是面向C#上位机场景的开源控件库,它将设备状态指示、管道动画、数据表格等高频组件封装为现成类,通过属性绑定实现数据驱动刷新,极大简化了界面逻辑。该库适用于设备监控、流程示意等典型工控场景,并可与HslCommunication通信库协同构建完整上位机系统。本文从实际使用角度,系统梳理其控件体系、引用方式、实战案例及常见问题,为C#工控开发者提供一份可落地的选型参考。
P2G与碳捕集综合能源系统双目标优化:epsilon约束法复现详解
综合能源系统 · P2G · 碳捕集
综合能源系统通过电、热、气、碳多能耦合,是实现低碳转型的重要载体。在碳捕集与电转气(Power-to-Gas, P2G)技术共同作用下,系统运行需同时兼顾运维成本与碳排放控制,构成典型的多目标优化问题。epsilon约束法通过将一个目标转化为约束条件,在非凸可行域内系统化求解帕累托前沿,相比线性加权法具有更强的全局搜索能力,在综合能源系统优化领域得到广泛应用。该方法可以清晰展示经济性与低碳性之间的权衡关系,为调度决策提供多方案选择。本文以P2G与碳捕集设备的热电联供系统为对象,详细讲解数学模型构建、目标函数拆分、耦合约束处理以及基于Matlab+Yalmip的epsilon约束法实现流程,并给出常见调试经验,适合作为相关方向研究复现与技术实践的参考。
无需管理员权限:用PowerShell脚本一键清理Windows内存
内存清理 · PowerShell脚本 · Windows内存管理
电脑卡顿、内存占用过高,往往与Windows内存管理机制中的工作集和待机列表有关。理解虚拟内存与进程工作集的工作原理,是精准优化系统性能的基础。通过调用系统API对进程工作集进行修剪,可以将不活跃的内存页释放回系统,从而缓解资源紧张。这一技术无需安装第三方工具,也无需管理员权限,适合企业办公、运维等受限环境下的快速响应。在实际工程中,可利用PowerShell脚本结合计划任务实现自动化内存回收,并配合性能监视器验证效果。本文正是从这一通用技术思路出发,详细讲解如何编写无管理员权限的内存清理脚本,并提供开机自启、日志记录及故障排查的完整方案,帮助你在不借助额外软件的前提下,有效延缓系统死机与重启的频率。
JuiceFS 5.3:分布式文件系统如何支撑5000亿文件与RDMA低延迟
分布式文件系统 · 元数据 · RDMA
在大数据与AI训练场景中,文件系统的瓶颈往往不是容量,而是元数据管理能力。当文件数达到亿级,传统单点元数据服务会因内存和锁竞争而性能骤降,这一现象在分布式文件系统中尤为突出。RDMA(远程直接内存访问)技术通过内核旁路与零拷贝,将网络时延从百微秒降至微秒级,为高频元数据操作和缓存分发提供了新思路。分布式文件系统通过动态分片与多级索引,可实现千亿级文件的弹性扩展,同时保持POSIX语义一致性与可运维性。该架构适合AI训练、海量日志、数据湖等场景,能显著降低长期基础设施成本。本文结合实践,剖析JuiceFS 5.3如何融合5000亿文件规模与RDMA支持,并给出部署建议。
Spring Boot + MyBatis-Plus 连接 MySQL 完整实践指南
Spring Boot · MyBatis-Plus · MySQL
后端开发中,Spring Boot、MyBatis-Plus 与 MySQL 的组合是 Java 业务系统最常见的起步配置。Spring Boot 通过自动装配简化项目骨架搭建,MyBatis-Plus 在 MyBatis 基础上提供通用 CRUD、分页插件、逻辑删除等增强能力,而 MySQL 作为主流关系型数据库承担数据持久化。理解了自动配置与 Mapper 增强的原理,就能快速搭建数据访问层,提升开发效率。该方案适合信息管理、后台系统及中小型互联网应用,围绕数据源配置、版本匹配、分页插件注册与连接池调优等关键点,可有效规避常见坑点。从环境准备到核心代码实践,再到部署提醒,全面梳理 Spring Boot 连接 MySQL 的完整链路,助力工程落地。
CE桥接模拟器:安卓自动内存调试工具原理与实战全解析
安卓自动桥接工具 · CE桥接模拟器 · Cheat Engine
在安卓应用调试与逆向分析中,内存访问一直是开发者与安全研究者的核心诉求。由于安卓应用运行在虚拟机或容器环境中,其进程内存与PC端隔离,传统调试工具无法直接附加。桥接技术应运而生,其原理是在安卓端部署高权限代理,通过读取进程内存映射文件或系统调用实现内存读写,再经由ADB端口转发建立PC与模拟器间的通信隧道。这项技术为动态调试、内存修改、自动化测试等场景提供了高效通道,尤其适用于模拟器环境——root易获取、系统纯净,可大幅降低逆向门槛。从本地单机应用的状态修改到内存结构分析,桥接方案展现出强大的工程价值。本文以安卓自动桥接工具为线索,系统拆解CE桥接模拟器的完整链路,涵盖环境搭建、实操步骤与常见问题排查,帮助读者快速掌握这一实用调试方法论。
Linux命令实战指南:从文件操作到系统监控的效率技巧
Linux命令 · 运维 · 文件操作
在服务器管理与运维工作中,命令行是工程师与系统交互的核心接口,其背后蕴含了进程、权限、文本流与网络通信等基础原理。掌握常用命令不仅能提升日常操作效率,更是故障排查与自动化部署的关键能力。从文件目录的增删改查、文本内容的过滤与替换,到用户权限的精细化控制、网络端口的连通性探测,再到服务状态监控与软件包管理,每一类命令都对应着真实场景中的典型需求。本文不罗列枯燥的语法清单,而是按实际工作流串联cd、rm、find、grep、sed、awk、chmod、systemctl等高频工具,并演示管道、xargs与别名组合的高效用法,帮助读者构建可复用的命令思维,让Linux操作从“背参数”进阶为“靠肌肉记忆”。
WebSocket消息推送排查指南:从连接到订阅,解决收不到、重复与浏览器崩溃
WebSocket · 消息推送 · GoEasy
WebSocket作为实时通信的核心技术,通过长连接实现服务端与客户端的双向消息推送,广泛应用于IM、通知、协作等场景。然而在实际工程中,开发者常会遇到连接反复断开、消息时有时无、重复乱序甚至浏览器崩溃等问题,其根因往往不在协议本身,而在于接入方式、订阅管理、重连机制与视图渲染的配合。本文从WebSocket基础原理出发,梳理消息推送链路上的关键节点,分析Channel不匹配、鉴权失败、心跳超时、离线消息边界、幂等去重、前端生命周期管理等高频故障,并结合Vue、微信小程序、企业微信及Spring Boot等典型集成场景给出可落地的排查思路。无论你是初次接入还是已处于调试阶段,掌握这些定位方法都能帮你快速收敛问题,避免陷入“乱猜代码”的困境。
代码+媒体双杠杆创业者:用100小时MVP快速验证产品,避免过度设计
MVP · 最小可行产品 · 100小时
在创业与产品开发中,MVP(最小可行产品)是降低试错成本、快速验证市场需求的核心方法论。对于同时拥有技术开发与内容创作双重能力的创业者来说,如何平衡产品迭代与内容传播往往成为瓶颈。过度设计、功能堆砌、节奏拖散,导致项目迟迟无法上线。而将项目周期压缩至100小时的MVP开发模式,能有效规避完美主义陷阱,帮助创业者在短时间内完成需求验证、用户反馈收集与内容素材积累。通过垂直切片开发、内容反向倒推选品、三刀法砍需求,以及边开发边输出的媒体杠杆策略,创业者可以用最低成本跑通“产品-内容-用户”闭环。这一方法不仅适用于独立开发者,也适合小团队在资源有限情况下验证产品方向,为后续迭代与增长奠定基础。掌握MVP节奏,是提升创业效率、实现产品市场匹配的必修课。
CST与Matlab联合仿真:超表面编码排布自动化实战指南
CST · Matlab · 联合仿真
在电磁仿真与数值优化领域,工具链的整合正成为提升研发效率的关键。CST作为全波电磁仿真软件,可精确计算单元结构的S参数与相位响应;Matlab凭借强大的矩阵运算与优化算法,适合处理编码排布与阵因子计算。两者的联合仿真,将电磁仿真与算法设计解耦,可实现超表面单元相位提取、编码矩阵生成及全阵验证的自动化流程。这一方法广泛应用于编码超材料、透射型超表面透镜、波束偏折等工程场景,可大幅减少手动建模与反复仿真的人力成本。系统梳理了COM接口、文件交换、单元仿真加阵因子三种技术路线,并结合1-bit超表面透镜实例,给出从CST单元仿真到Matlab编码生成、再到全波验证的完整实践路径,为研究生与预研工程师提供可落地的工程参考。
JavaScript Day02 核心笔记:运算符、流程控制、函数与 DOM 操作实战
JavaScript · 隐式类型转换 · DOM操作
在 JavaScript 学习路径中,理解数据类型与运算符的隐式类型转换是写出可靠逻辑的第一步。很多初学者发现字符串拼接和数值运算结果不一致,根源正是 JS 灵活又易踩坑的转换规则,主动使用 Number() 与全等比较符 === 能有效规避风险。掌握流程控制之后,函数封装与作用域概念成为组织代码的关键,而基础 DOM 操作则让页面具备交互能力,从获取元素到事件监听,一步步实现点击改色、动态增删内容等典型场景。高频数组与字符串方法如 map、filter、includes 更是业务开发中的日常工具,熟练使用能显著提升编码效率。结合控制台调试与报错定位技巧,初学者可以更快养成工程化思维,为后续框架学习打下扎实基础。本文基于 Day02 学习路线,系统拆解从语法细节到实战练习的关键环节。
基于NodeJS的宠物网站毕业设计:从架构到部署全流程解析
NodeJS · 宠物网站 · 毕业设计
在Web开发中,前后端交互、数据库设计和权限控制是构建任何业务系统的通用基础。NodeJS基于Chrome V8引擎,以其非阻塞I/O和事件驱动模型,让开发者能够使用JavaScript统一编写前后端代码,显著提升开发效率。它在快速搭建业务闭环、实现用户登录鉴权、文件上传与数据管理等方面具有天然优势,尤其适合中小型信息管理类系统的工程实践。结合宠物领养与购买场景,利用Express搭建RESTful API,配合MySQL设计用户表、宠物表和订单表并实现状态流转,可以完整覆盖从用户注册到管理员审核的业务链路。该技术思路还可扩展至小程序端和云服务器部署,适用于毕业设计、课程项目及快速原型开发。本文以宠物网站为切入点,系统梳理了从技术选型、数据库设计、接口实现到项目上线的全流程工程方法。
用Markdown与Git搭建本地日记系统:数据自主与长期记录实践
Markdown · Git · 本地日记
在数字化记录时代,个人数据的安全与长期可读性成为内容创作者和知识工作者的核心诉求。Markdown作为轻量级纯文本格式,凭借其开放性、可移植性和与版本控制系统的天然兼容性,正在成为构建个人知识库的基础语言。Git作为分布式版本管理工具,不仅能追溯每一次文件变更,更赋予文本内容以可恢复、可演进的生命力。当笔记与日记不再依赖封闭的云服务,数据的控制权便真正回归用户手中。本文从技术选型出发,探讨如何利用本地文件夹、Markdown语法和Git仓库组合出一套兼具隐私保护与复盘效率的日记系统,帮助你在保障数据安全的同时,建立可持续的个人记录与回顾机制。
从随机项目编号到可交付系统:需求澄清与MVP落地的完整工程实践
项目管理 · 需求澄清 · MVP
在实际软件项目中,需求方有时只会给一个随意的编号或代号,项目起点模糊不清。面对这种情况,高效的项目管理方法比急于编码更为关键。首先需要通过需求澄清明确用户、场景与验收标准,将模糊输入转化为可执行的目标。随后基于项目生命周期与团队维护成本进行技术选型,选择稳妥的工程化底座,避免过度设计。MVP阶段聚焦核心主路径,以最小闭环验证技术可行性,并通过日志、测试和错误处理保障交付质量。这种从概念到实现的方法,适用于内部工具、数据清洗脚本乃至各类以结果为导向的工程任务。本文以日志自动化清洗工具为例,完整拆解了从编号到长期可维护项目的全过程,为独立开发者与项目负责人提供可复用的落地框架。
结合需求响应与分布式电源的IEEE33配电网重构优化
配电网重构 · IEEE33节点 · 需求响应
配电网重构是提升运行经济性与电压质量的重要手段。随着分布式光伏、风电等清洁能源高比例接入,传统单向潮流格局被打破,网损优化和电压控制面临新的挑战。需求响应技术通过价格信号引导用户调整用电行为,为配电网提供灵活的负荷侧调节能力。在工程实践中,常以IEEE33节点系统作为标准测试平台,结合前推回代潮流计算和二进制粒子群算法,对分段开关与联络开关状态进行组合优化。这种协同优化框架能够同时考虑拓扑结构调整、分布式电源出力与用户负荷响应,在保障辐射状运行和安全性约束的前提下,实现网损降低、电压改善与清洁能源充分消纳。该思路可推广至更大规模配电网,支撑高比例可再生能源接入下的运行优化。
SpringBoot微信小程序预约订购系统:从源码到部署全流程解析
SpringBoot · 微信小程序 · 预约订购系统
在数字化服务场景中,预约订购系统已成为连接用户与线下资源的核心工具。这类系统通常采用前后端分离架构,后端基于SpringBoot提供RESTful API,前端通过微信小程序承载交互界面,实现用户授权登录、服务预约、在线下单、订单管理等完整闭环。SpringBoot的自动配置机制与小程序轻量化的特点相结合,大幅降低了项目开发与部署门槛,尤其适合毕业设计、课程设计以及商业MVP快速搭建。从技术原理来看,系统涉及JWT登录态管理、RESTful接口规范、MySQL表结构设计以及预约排班的并发余量控制等关键知识点。在工程实践层面,开发者常遇到SpringBoot版本兼容、数据库导入异常、小程序合法域名配置等典型问题。本文从项目设计思路、核心模块拆解、前后端联调、部署上线四个维度展开,结合真实踩坑记录,帮助开发者快速理解预约订购小程序的完整实现路径,并顺利将源码转化为可运行的线上服务。
OpenHarmony上Flutter电子合同签署开发实践
OpenHarmony · Flutter · 电子合同
跨平台开发框架凭借统一渲染引擎,为多终端应用提供一致体验。OpenHarmony作为开源操作系统,正融合主流跨平台工具链以降低开发门槛。Flutter通过Dart语言的响应式架构实现高效UI构建,并利用平台通道调用系统原生能力。在电子合同签署场景中,设备端需要结合手写签名、交易留痕与后台验签,这对硬件与系统适配提出更高要求。本文基于RK3568开发板,介绍Flutter在OpenHarmony环境下集成电子合同服务的架构设计与实施步骤,并分享真机调试中的典型问题及解决方案,为类似移动端签署系统开发提供参考。
云计算作业实战:高可用Web应用部署从规划到落地
高可用 · 负载均衡 · 健康检查
高可用架构是云计算领域的核心概念,它通过冗余设计和故障自动切换来保障业务连续性。负载均衡作为流量分发的关键组件,依靠健康检查机制实时探测后端服务器状态,一旦发现异常便自动摘除节点,确保请求只被转发到健康实例。这一原理在Web应用部署中尤为重要,无论是课程实践还是生产环境,合理规划VPC、安全组和对象存储,都能显著提升系统的可靠性与安全性。本文从工程实践角度,完整拆解基于公有云平台部署高可用Web应用的流程,涵盖资源规划、网络配置、核心功能实现、监控告警与故障演练,并附上常见踩坑清单与面试话术,帮助读者将一次课程作业转化为可落地的实战经验。
EKF与UKF在窄带信号时变频率估计中的对比分析
卡尔曼滤波 · EKF · UKF
在信号处理与状态估计领域,如何对非平稳窄带信号的瞬时频率进行实时追踪,是雷达、通信及振动监测等工程实践中常遇到的难题。传统傅里叶变换受限于时频分辨率矛盾,难以刻画频率的连续变化。卡尔曼滤波作为典型的递推状态估计方法,通过建立相位与频率的状态空间模型,可有效应对这一非线性动态系统估计问题。扩展卡尔曼滤波(EKF)与无迹卡尔曼滤波(UKF)是两种主流解决路线:前者借助一阶线性化近似,实现简单、计算高效;后者基于sigma点采样逼近非线性分布,在低信噪比和频率突变场景下具有更强的鲁棒性。本文基于Matlab仿真,从滤波原理、算法实现到参数调优,系统对比两者在时变频率追踪中的精度、收敛速度与抗发散能力,帮助工程人员在实时性与准确性之间做出合理选择。
已经到底了哦
精选内容
热门内容
最新内容
Spring Boot校友录管理系统:从数据库设计到部署上线全流程
管理系统是企业级Web应用中最常见的项目形态,其核心在于业务建模与数据持久化。Spring Boot作为Java开发主流框架,通过自动配置与生态整合,显著降低了项目搭建成本;配合MyBatis-Plus等ORM工具,可高效实现单表增删改查与复杂查询。在校园信息化场景中,校友录管理系统是典型的课程设计选题,覆盖用户登录鉴权、班级与校友信息维护、条件检索、数据统计等核心功能,并涉及分层架构、异常处理、拦截器等关键工程实践,适合用于巩固Java Web开发基础。本文从实际项目出发,完整讲解基于Spring Boot的校友录管理系统的设计与实现,包括技术选型、数据库表结构、后端接口开发、前端页面集成,以及打包部署与常见避坑要点,帮助开发者快速掌握一套可复用、可演示的课设交付方案。
免费批量图片漂白工具推荐:XnConvert、ImageMagick实现照片通透效果
在数字图像处理领域,提亮、降饱和、调整对比度是让照片变得干净通透的常见操作,常被称为“漂白”效果。对于电商产品图、自媒体封面或摄影后期而言,统一风格的批量调色能显著提升工作效率。本文从图像亮度、饱和度与灰雾修正的基础原理出发,介绍如何利用永久免费的图像处理工具实现自动化批次处理:包括图形界面的XnConvert、轻量的IrfanView以及适合脚本化大批量任务的ImageMagick命令行。通过合理设置亮度、饱和度、对比度及色温等关键参数,即可实现高质量的统一调色效果,同时避免过曝、灰雾和肤色失真等问题。这一方案不仅适用性广,且完全本地化处理,兼顾效率与数据安全。若你常处理大量图片,这套免费批量工作流值得深入了解。
数据结构学习框架:从零散知识点到整体认知
数据结构是计算机存储、组织数据的方式,其核心在于根据场景权衡增删改查的代价。学习数据结构的关键是先建立整体认知,理解逻辑结构、存储结构与运算三要素,再按线性、树、图、散列四大类掌握常用结构。数组、链表、栈、队列各有适用场景,二叉树与堆解决层级和优先级问题,图用于网络分析,哈希表则实现键值快速存取。复杂度分析是衡量结构优劣的标尺,理解大O表示法才能做出合理选择。从Redis等工业系统可以看到,教材中的结构正是工程实现的基石。刷题与面试时,将知识点转化为场景题,培养框架思维,才能举一反三。本文梳理出一张数据结构总地图,帮助学习者在期末、考研、面试或工程实践中按图索骥,告别死记硬背。
运维升值靠的不是技术最牛,而是这3种能力
运维工程师的职业发展,常常让人困惑:为什么技术最牛的人,反而不一定是升值最快的人?在Linux运维、桌面运维、云计算运维等岗位上,技术扎实只是基本功,真正决定职业天花板的,是能否将技术能力转化为业务贡献。随着云原生、Kubernetes、DevOps等理念的普及,运维的价值链条正在从"保证系统别挂"向"让系统更稳、更快、更省钱"演进。SRE、平台工程等新兴岗位的涌现,也要求运维具备更全局的视野。升值快的运维,往往赢在三点:理解业务场景、建立稳定性体系、做好向上沟通。如果你正在从传统运维向云原生运维转型,或希望突破职级瓶颈,这篇文章值得一读。
Git版本控制实战指南:核心概念、常用命令与避坑技巧
版本控制是软件开发中记录代码变更、支撑团队协作的基础技术。Git作为目前主流的分布式版本控制系统,相比传统集中式SVN,每个开发者本地都拥有完整历史,即使远程服务器故障也不影响日常提交。其核心设计包括工作区、暂存区、版本库三区模型,配合轻量分支与合并机制,让多人在同一项目上并行开发成为可能。在实际工程中,常用操作如提交、推送、拉取、回滚,以及解决合并冲突,都是必备技能。同时,合理配置SSH密钥、规范提交信息、编写.gitignore文件,能有效提升协作效率并避免敏感信息泄露。本文基于实际踩坑经验,从安装配置到疑难报错,系统梳理Git的日常使用路径,帮助开发者少走弯路。
MySQL不停机迁移实战:双写+binlog同步方案全解析
在业务持续运行的场景下,数据库迁移的核心不再是简单的数据搬运,而是如何实现数据同步、一致性保障与平滑切换。基于日志解析的增量同步机制(如binlog)与双写策略,可以有效缩短同步延迟窗口,在保证数据最终一致的前提下完成架构升级。这种迁移模式广泛应用于云化改造、分库分表演进及跨机房容灾等场景,尤其适合对可用性要求极高的在线业务系统。文章结合一次自建MySQL集群云上迁移的真实案例,详细拆解了基于Canal监听binlog、应用层双写、一致性校验与灰度切换的整体方案,并针对主键冲突、大事务延迟、时区错乱等典型问题给出了可落地的排查思路。无论你刚接触数据迁移,还是已有运维经验,都能从中找到可直接借鉴的工程实践方法。
栈的应用经典:有效括号匹配与相邻重复项消除
在算法与数据结构的学习中,栈是一种极其基础且重要的线性结构,其“后进先出”的特性天然适合处理需要历史状态回溯的场景。无论是编译器中的语法校验,还是编辑器里的撤销操作,栈都在幕后发挥着核心作用。通过栈的原理,我们可以高效解决两类经典问题:一类是符号配对校验,如判断括号是否有效;另一类是相邻元素消除,如删除字符串中的所有相邻重复项。这两类问题本质上都遵循“就近匹配”的规则,是理解栈这一抽象数据类型的绝佳入门示例。在实际工程与算法面试中,掌握栈的灵活运用,尤其是用数组或字符串模拟栈的技巧,往往能让代码更简洁、性能更优。从基础的概念理解到具体的代码实现,再到边界条件的处理,本文将结合经典题目帮助技术爱好者建立清晰的解题模型,为后续学习单调栈等进阶技能打下坚实基础。
系统流程设计:调用、数据、状态三线协同演进的核心方法论
在软件系统架构中,流程设计直接决定系统的稳定性、扩展性与可维护性。任何业务系统都绕不开调用、数据与状态三大核心要素。调用方式从同步阻塞逐步演进到异步解耦、事件驱动,数据管理从简单的数据拷贝发展为对权威源、事件溯源及备份恢复的系统性规划,状态控制则依赖状态机、业务状态与流程节点拆分,并需通过幂等、重试和补偿机制保障分布式一致性。这些设计绝非孤立存在,而是需要作为一个整体协同推进。本文结合微服务与分布式系统的工程实践,解析调用、数据、状态三者的耦合关系,给出从状态机设计到数据流梳理再到调用方式选型的落地路径,为正在构建新系统或重构复杂流程的团队提供可操作的参考框架。
SAP Paging区爆满导致MEMORY_NO_MORE_PAGING?一文讲透排查与调优
SAP系统的内存管理是一个多层协作的体系,扩展内存(EM)、私有堆、Roll区与Paging区各司其职。当Paging区域达到容量上限时,ST22中会出现MEMORY_NO_MORE_PAGING转储,导致业务卡顿甚至中断。很多运维人员误以为是物理内存不足,却忽略了SAP内部换页机制的限制。理解Paging的存储对象和触发条件,是定位问题的关键。通过ST02监控水位、RZ11核对参数,并联动调整rdisp/PG_SHM与rdisp/PG_MAXFS,同时兼顾ztta/roll_extension等关联配置,可以有效解决此类故障。本文从SAP内存模型出发,结合真实案例,梳理一套完整的排查与调参方法,帮助SAP Basis、ABAP开发者及运维人员快速掌握这一经典内存问题的处理思路。
Windows看图效率神器:MagicView支持70+格式,一键生成缩略图
在 Windows 上高效管理图片,核心挑战往往不是打开图片本身,而是缩略图预览的完整性与响应速度。系统自带的资源管理器依赖原生解码组件,对 HEIC、SVG、PSD、PDF 等常见办公与设计格式常常显示为空白图标,导致“HEIC 缩略图不显示”“SVG 预览空白”等问题频繁出现。MagicView 通过集成资源管理器缩略图服务,将 70+ 格式的解析能力共享给系统,无需修改注册表或安装复杂解码器,即可在文件夹中直接呈现真实预览。其“一键生成缩略图”功能更能批量补齐历史文件夹的预览图,大幅提升素材筛选与文件管理效率。无论你是摄影爱好者需要查看 RAW 原片,还是设计师需要快速浏览设计源文件,或仅是普通用户希望解决 PDF 与 HEIC 预览问题,MagicView 都提供了一套免费无广告的轻量解决方案。本文从真实使用场景出发,拆解格式支持逻辑与缩略图生成原理,助你彻底告别 Windows 看图痛点。
已经到底了哦