MySQL锁等待超时排查指南:从事务到索引的完整突围
凌晨两点半手机告警群突然弹出消息生产环境的订单接口开始陆续报错。打开日志一看清一色的MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction接口调用方那边已经开始积压重试。这个报错在做 Java MySQL 的项目里太经典了几乎每一个稍微有点并发量的系统都会遇到一次。它的字面意思很简单——当前事务等待获取行锁超时了InnoDB 直接把这个事务回滚掉。但真正头疼的是定位到“谁在占着锁不释放”这个环节往往比解决报错本身花的时间还多。这篇博文就把我这次完整排查的过程记录下来从日志分析到系统表查询从根因定位到代码改造希望能给同样被这个报错折磨过的朋友一条清晰的排查路径。这个报错的本质是锁等待超时不是死锁也不是数据库挂了。它适合所有用 MySQL 作为业务数据库、使用 Spring 事务管理或者自己手写事务的开发者阅读尤其是那些经常在夜里被告警叫醒的兄弟们。搞清楚它背后的原理和定位方法你不仅能在下次遇到时迅速救火还能顺手把事务设计里那些埋着的雷排掉。1. 线上报错从日志定位到异常全貌1.1 异常日志的完整模样先还原一下我当时日志里的真实报错方便大家对号入座。如果你是 Spring Boot MyBatis 的项目大概率看到的是这样一段堆栈org.springframework.dao.CannotAcquireLockException: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction ### The error may exist in com/xxx/mapper/OrderMapper.java (best guess) ### The error occurred while setting parameters ### SQL: UPDATE t_order SET status ? WHERE order_no ? ### Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction两个关键信息底层异常类是MySQLTransactionRollbackExceptionSpring 把它包装成了CannotAcquireLockExceptionSQL 是一条很常规的UPDATE。很多人第一次看到这个报错会以为是 SQL 语法问题或者怀疑数据库连接池不够用其实都不对。这条报错的含义非常具体当前事务在执行 UPDATE 时需要获取目标行上的排他锁X锁但等了好久都没等到超过了 InnoDB 的锁等待超时阈值默认 50 秒于是 InnoDB 把当前事务直接回滚并抛出异常。注意抛异常的时候是“先回滚再抛”不是“等锁失败就只报个错”那么轻描淡写——事务里之前做的所有写操作都会被撤销。这里有个特别容易混淆的知识点是不是一执行 UPDATE 就会立刻拿锁不一定。如果 UPDATE 语句走了索引通常只会把命中的行锁住但如果没走索引InnoDB 会扫描聚簇索引把扫描过程中碰到的行都加上锁锁范围会急剧扩大后面的事务排队等锁的时间自然就上去了。1.2 为什么业务代码会抛这个异常从调用链上看MyBatis 执行 UPDATE 时是正常提交 SQL 给 MySQL 的MySQL 那边等锁超时后返回错误码1205ER_LOCK_WAIT_TIMEOUTJDBC 驱动把它翻译成MySQLTransactionRollbackExceptionSpring 的异常转换机制又包装成CannotAcquireLockException。对业务代码来说感知到的就是一次事务回滚。但是这里有一个“延迟暴露”的特点特别坑人。你的业务方法里可能早就执行了好几条 SQL锁等待超时发生在最后一条 UPDATE 上异常抛出后整个事务回滚但前面几条 SQL 对数据库的修改已经真实发生过了。如果中间有人把事务配置成了REQUIRES_NEW或者嵌套了独立事务那部分修改就不会被回滚掉数据会处于一种“半成功半失败”的中间状态。所以排查这类问题的时候不能只盯着报错那一条 SQL 看要把整个事务方法里的所有写操作都列出来。还有一个点需要说清楚这个异常和死锁是两码事。死锁报错是Deadlock found when trying to get lock; try restarting transaction那是两个事务互相持有对方想要的锁InnoDB 检测到后会主动牺牲其中一个事务。而Lock wait timeout是纯粹的“等待超时”另一个事务持有锁的时间太长或者压根就是没提交也没回滚把锁攥在手里不放。2. 排查锁等待的三板斧2.1 第一板斧查事务表 innodb_trx定位这种问题最直接的手段就是登录 MySQL 实例查information_schema里的事务视图。我当时第一件事就是跑下面这条 SQLSELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query, trx_rows_locked, trx_rows_modified FROM information_schema.INNODB_TRX ORDER BY trx_started;重点看三样东西trx_state正在跑的事务如果处于RUNNING状态且trx_started时间非常早基本可以断定是“长事务”嫌疑人。trx_query事务当前正在执行的 SQL注意这个字段经常是 NULL因为事务可能在空闲状态比如等外部调用返回但锁并没有释放。trx_mysql_thread_id对应的 MySQL 连接线程 ID这个后面 kill 会话要用。在我那次排查里查出来的结果很典型有一个事务trx_started已经是 8 分钟之前trx_stateRUNNINGtrx_queryNULL。也就是说有个事务在 8 分钟前就开启了期间执行过写操作之后就一直保持空闲锁一直没释放。而报错的那个业务事务正好需要更新同一行数据于是排队等到超时。看到这里问题的方向已经清晰了一大半锁的源头是一个长时间未提交的空闲事务。但仅仅知道“有长事务”还不够还得继续追这个长事务是哪个应用的哪个连接它到底锁了哪些行2.2 第二板斧锁定谁在等谁查到疑似长事务后下一步就是看锁的等待关系。MySQL 5.7 及之前版本用INNODB_LOCK_WAITS和INNODB_LOCKS两张表串起来查8.0 版本这两张表改成了performance_schema.data_lock_waits和performance_schema.data_locks。我当时的环境是 MySQL 5.7用下面这条联表 SQL 直接定位锁等待链路SELECT r.trx_id AS wait_trx_id, r.trx_mysql_thread_id AS wait_thread_id, r.trx_query AS wait_query, b.trx_id AS block_trx_id, b.trx_mysql_thread_id AS block_thread_id, b.trx_query AS block_query FROM information_schema.INNODB_LOCK_WAITS w JOIN information_schema.INNODB_TRX r ON w.requesting_trx_id r.trx_id JOIN information_schema.INNODB_TRX b ON w.blocking_trx_id b.trx_id;这条 SQL 输出的结果里wait_trx_id是正在等锁的事务block_trx_id是持有锁不放的事务。我当时查出来的结果是报错的订单 UPDATE 在等一个早已开启的事务而且那个事务的连接线程 ID 对应的还是测试环境的 IP——后来一查才知道是有人直接用 Navicat 手动查了一遍数据没提交也没回滚连接就一直挂着行锁就这么被锁了一晚上。这里有个关键细节block_query很多时候是 NULL因为阻塞者可能处于空闲状态当前并没有在执行任何 SQL。你不能因为trx_query是 NULL 就认为它没有持有锁锁是在执行 UPDATE/DELETE/INSERT 时获得的之后哪怕事务空闲锁也会一直持有到事务结束。2.3 第三板斧看 InnoDB 状态详情如果系统表里的信息还不够或者你想看到更完整的锁信息就得祭出 InnoDB 自带的诊断命令SHOW ENGINE INNODB STATUS\G输出结果里重点看TRANSACTIONS段落里面会列出当前活跃事务、锁等待信息甚至能打印出等锁事务具体在等哪一行记录的锁。格式类似这样---TRANSACTION 323223, ACTIVE 8 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 12345, OS thread handle 140123456789, query id 98765 ... UPDATE t_order SET status PAID WHERE order_no 20250101001 ------- TRX HAS BEEN WAITING 8 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 100 page no 8 n bits 72 index PRIMARY of table test.t_order trx id 323223 lock_mode X locks rec but not gap waiting这段信息非常直白事务323223在等表t_order主键索引上某一行记录的排他锁等锁的来源 SQL 就是那条 UPDATE。不过说实话SHOW ENGINE INNODB STATUS输出内容比较长且杂生产环境我只把它当辅助手段主要定位工具还是系统表联表查询信息更精确、更好解析。3. 深挖根因事务为什么会“卡”住3.1 事务边界过长是头号元凶锁等待的本质是两个事务访问了同一行数据且其中一个长期持有锁。而“长期持有锁”最常见的原因就是事务边界太长。我见过太多代码把事务开在 Controller 层或者 Service 层的外层方法上一个事务里面包含了多次 RPC 调用、远程接口等待、甚至还有慢查询。比如下面这种反面教材Override Transactional(rollbackFor Exception.class) public void processOrder(OrderDTO dto) { // 1. 更新订单状态 orderMapper.updateStatus(dto.getOrderNo(), PAYING); // 2. 调用支付网关可能耗时 2~3 秒甚至更久 String payResult payClient.pay(dto); // 3. 再写一条流水 payRecordMapper.insert(dto.getOrderNo(), payResult); }这个事务从第 1 步开始就持有了t_order对应行的 X 锁第 2 步调支付网关如果网络抖动或者对方超时重试这行锁就被一直攥着。高并发场景下其他线程在更新同一行订单时只能排队等到第 50 秒超时阈值一过直接抛Lock wait timeout exceeded。3.2 慢 SQL 把锁攥得太久另一个常见原因是事务内部的 SQL 本身特别慢。注意这里的“慢”不一定是全表扫描那种肉眼可见的慢也可能是一条很简单的 UPDATE 因为索引失效或者数据量暴增从几毫秒退化到几秒钟。事务持有锁的时间跟 SQL 执行时间几乎成正比一条 UPDATE 跑了 5 秒意味着后面所有想更新同一行的事务至少要多等 5 秒。排查慢 SQL 的手段大家都熟开启慢查询日志或者直接查performance_schema.events_statements_summary_by_digest这类统计表。我当时顺便看了一眼t_order表的索引情况发现order_no字段虽然建了唯一索引但是状态更新的 WHERE 条件里还有个额外的status PAYING条件而status字段没有索引。MySQL 在优化器选择执行计划的时候可能会选择先通过order_no唯一索引找到记录再回表过滤status这倒是没多大问题但如果哪天优化器抽风走错索引锁范围就可能扩大。3.3 索引失效导致锁定范围失控这是锁等待问题里最隐蔽也最危险的场景。InnoDB 的行锁是基于索引实现的如果 UPDATE 语句的 WHERE 条件无法命中索引InnoDB 会对聚簇索引主键索引做全表扫描并且对扫描过程中访问到的每一行加锁而不是只锁住最终需要更新的那几行。举个例子UPDATE t_order SET status CANCELLED WHERE buyer_phone 13800138000;如果buyer_phone上没有索引执行这行 SQL 的时候InnoDB 会扫描整张表把扫描路径上的所有行都加上 X 锁直到找到匹配的行。扫描结束前整张表上符合条件的记录甚至更多全被锁住了。另一个事务想更新一条完全不相关订单的状态也会阻塞在这个全表锁上。这种问题用EXPLAIN一看一个准EXPLAIN SELECT * FROM t_order WHERE buyer_phone 13800138000;如果type是ALL或者key是 NULL恭喜你这就是锁爆炸的根源。所以遇到锁等待别急着调超时参数先检查更新条件字段的索引情况。3.4 隐式提交与外部调用干扰还有一个很多人没注意到的坑事务方法里如果调用了会自动提交连接的代码或者执行了 DDL 语句事务边界会被悄无声息地打断。比如直接用JdbcTemplate执行了一些操作而连接是从同一个DataSource获取的默认autocommittrue那这段操作会独立提交但事务上下文感知不到锁的行为就会变得很奇怪。外部调用的问题更恶心。有一次我排查一个锁等待发现阻塞事务的 SQL 是SELECT ... FOR UPDATE但对应线程卡在了一个很正常的查询上。后来翻代码才看到事务里调了一个 HTTP 接口那个接口内部查询了同一张表而且用了SELECT FOR UPDATE两个锁在同一事务里叠加把等锁时间拉得更长。在事务里做网络调用是大忌这句话我已经说腻了但还是不断有人踩。4. 从解围到根治实操方案详解4.1 临时解围如何安全处理阻塞会话线上已经出故障了第一要务是恢复服务。最直接的办法是杀掉阻塞事务对应的 MySQL 会话释放锁。根据前面INNODB_TRX查出来的trx_mysql_thread_id执行-- 先确认一下这个线程对应的连接信息避免误杀 SELECT * FROM information_schema.PROCESSLIST WHERE ID 12345; -- 确认无误后杀掉 KILL 12345;杀会话之前一定要确认两件事一是这个连接是不是应用连接池里的核心连接杀了之后连接池会自动重连业务影响有限二是这个事务里有没有重要业务操作正在执行。我当时排查看下来阻塞的是一个 Navicat 手动查询连接属于运维操作的漏网之鱼杀掉完全没风险。如果阻塞事务是应用自身的长事务那就要评估一下能不能杀、杀了之后业务方能不能自愈。这里有个非常实用的细节KILL 一个事务连接InnoDB 会立刻回滚这个事务锁随之释放。但如果是 Debezium 这类 CDC 工具在读 binlog或者有从库在同步回滚操作也可能产生大量 binlog 事件要注意观察主从延迟。4.2 参数调整innodb_lock_wait_timeout 怎么设innodb_lock_wait_timeout这个参数控制了事务等待行锁的超时时间默认 50 秒。很多人遇到超时第一步就把它调大比如调成 120 秒这其实是治标不治本的思维——等锁时间变长了接口响应时间也跟着变长用户侧的体验更差而且事务长时间挂起还会拖垮连接池。我个人的建议是默认值 50 秒对于大多数业务系统太长对于需要快速失败的接口又太短。更合理的思路是根据业务接口的 SLA 来设置。比如你要求接口在 3 秒内返回那锁等待时间超过 1 秒就该让事务快速失败并抛出异常而不是傻等 50 秒。通过配置中心动态调整或者连接参数指定都可以SET GLOBAL innodb_lock_wait_timeout 5; SET SESSION innodb_lock_wait_timeout 5;注意这个参数是动态的可以同时设置全局和会话级别。调小之后应用端一定要做好异常捕获和重试逻辑否则快速失败和成功请求的比例会变得很难看。4.3 代码改造事务与锁的正确姿势解决完眼前的故障根因还得靠代码层面解决。我总结了一套事务与锁的最佳实践基本上可以覆盖大部分场景事务范围要最小化。只把真正需要原子性保证的写操作放在事务里查询、RPC、外部接口调用全部移出事务。假如必须在一个方法里完成状态更新和后续动作可以把事务拆成两个独立事务第一个事务只做 UPDATE第二个事务处理后续逻辑中间用消息队列或本地消息表来保证最终一致性。public void processOrder(OrderDTO dto) { // 不在事务里 PayResult payResult payClient.pay(dto); // 事务里只做最短的写操作 orderService.updateStatus(dto.getOrderNo(), payResult.getStatus()); // 后续可以再发消息异步处理 mqSender.send(PayResultEvent.of(dto.getOrderNo())); }业务上要设计好锁的获取顺序。如果多个事务会更新多张表的同一批记录尽量让他们按相同顺序加锁从源头规避死锁风险同时也能让锁等待的时间更可预期。写操作必须走索引。在 UPDATE/DELETE 的 WHERE 条件涉及的所有过滤字段上建立合适的索引不仅能让 SQL 变快还能把锁的粒度精确控制在目标行上。用EXPLAIN检查执行计划避免出现typeALL或者keyNULL。增加锁等待监控和告警。把information_schema.INNODB_TRX的长事务查询做成定时任务发现超过阈值的长事务就告警把锁等待时间也纳入监控。这样再遇到类似问题可以在用户感知之前就发现苗头。5. 避坑指南这些问题我也都遇到过5.1 死锁与锁等待的区别很多人把死锁和锁等待混为一谈排查方向完全跑偏。死锁Deadlock found when trying to get lock是多个事务互相持有对方需要的锁形成循环等待InnoDB 的死锁检测机制会立刻发现并回滚其中一个事务通常不需要等 50 秒。而锁等待是单纯的一边倒一个事务在持有锁另一个事务在排队等它没有循环。排查死锁要开innodb_print_all_deadlocks参数把死锁信息打印到 error log 里SET GLOBAL innodb_print_all_deadlocks ON;排查锁等待则重点看INNODB_TRX和INNODB_LOCK_WAITS。两者虽然都和锁有关但定位逻辑完全不同别搞混。5.2 无法定位到具体 SQL 怎么办有时候INNODB_TRX.trx_query是 NULLINNODB_LOCK_WAITS也看不到等待关系这时候别急按下面顺序排查打开performance_schema的语句事件采集查events_statements_current表可以看到每个连接当前正在执行的 SQL。开启慢查询日志把阈值调到 1 秒观察报错时段是否有慢 SQL 在拖后腿。查 binlog 或者应用侧日志反推报错时哪个事务在执行哪个方法。如果performance_schema没开有些 MySQL 版本需要重启实例才能生效生产环境要注意维护窗口。这也是我建议平时就把performance_schemaON保持开启的原因关键时刻信息量差太多了。5.3 别忽略连接池的影响这个问题很容易被忽略连接池的大小配置跟锁等待有直接关系。假如应用连接池最大连接数是 20某个时刻有 15 个连接都在等同一行锁剩下 5 个连接即使拿到了锁也处理不了新请求因为线程都阻塞在等锁上了。表面上看是锁等待问题实际上是连接池被等锁的线程占满。遇到这种情况单纯 kill 会话或者调超时参数都不够得从根上控制并发度。比如对热点行更新做限流或者引入分布式锁把同一个订单的更新操作串行化减少同时等锁的线程数量。我当时就把订单支付接口改成了基于 Redis 的分布式锁同一个订单号同时只能有一个请求在跑锁等待的问题明显改善。5.4 监控不是摆设要真用起来最后说一句大实话很多锁等待问题之所以变成事故是因为监控报警没做到位或者做了但没人响应。我在这次排查结束后专门把长事务监控加到了运维告警平台规则很简单——执行时间超过 5 秒的事务自动告警超过 30 秒直接推送到钉钉群。另外也把innodb_lock_wait_timeout调到了 5 秒让事务快速失败配合应用端的重试机制用户基本无感知。监控方案的 SQL 也不复杂放到定时任务里跑就完事SELECT trx_mysql_thread_id, trx_started, trx_query FROM information_schema.INNODB_TRX WHERE trx_started NOW() - INTERVAL 5 SECOND;查到结果就发告警哪怕不是锁等待一个事务空转 5 秒也本身就值得警惕。线上问题处理完之后把过程沉淀成文档、把监控补上这步才是让团队从“救火队员”变成“预防大师”的关键。这次排查下来我最大的体会有两点。第一Lock wait timeout exceeded这个报错其实是 InnoDB 在帮你提前暴露问题它的出现意味着数据库的并发控制机制已经守住了底线真正需要反思的是应用层的事务设计。第二排查锁问题不要一上来就调参数、杀进程先看事务表、再看锁等待关系、最后查执行计划一套连招打下来90% 的问题都能在十分钟内定位。把这个排查思路沉淀成你自己的 SOP下次再遇到这个报错你就能心平气和地打开终端而不是半夜对着屏幕叹气了。

相关新闻

限流算法核心取舍:令牌桶与漏桶该如何选型

限流算法核心取舍:令牌桶与漏桶该如何选型

限流算法的核心取舍:令牌桶和漏桶,到底该怎么选先聊一个大多数后端同学都经历过的场景。某个周三下午,运营那边突然上了一波活动,流量瞬间从平时的几百 QPS 冲到几千甚至上万,服务端监控开始飘红,数据库连接…

2026/9/21 0:14:19 阅读更多 →
线上服务器变慢?从负载飙升到揪出定时任务的实战排障指南

线上服务器变慢?从负载飙升到揪出定时任务的实战排障指南

线上服务器突然变慢,我花了2小时才定位到一个定时任务——聊聊Linux系统排障那些事这事发生在上周三,值班群里突然有人喊“线上页面打开好慢”。我赶紧上机器看了一眼,load average 直接飙到了 12 多,CPU 使用率看着也不算离谱&am…

2026/9/19 13:21:09 阅读更多 →
MATLAB视频读取与运动目标检测实战路径

MATLAB视频读取与运动目标检测实战路径

简介:这是用MATLAB实现视频图像读取与运动目标检测的完整项目源码,面向计算机视觉入门者及需要快速搭建检测流程的开发者,解决视频目标检测任务中的常见痛点。资源围绕视频帧提取、差分/背景建模、运动目标分割等核心环节,提供经过…

2026/9/19 23:25:54 阅读更多 →

最新新闻

儿童网页设计入门到精通:别再只背语法,直接上项目

儿童网页设计入门到精通:别再只背语法,直接上项目

儿童网页设计入门到精通:别再只背语法,直接上项目 看了一堆教程还是不会写项目?这大概是很多想入行前端或者做少儿编程教育的转岗伙伴最大的困惑。…

2026/9/22 1:58:03 阅读更多 →
吉他节拍器怎么用:图解原理与后端思维实战指南

吉他节拍器怎么用:图解原理与后端思维实战指南

吉他节拍器怎么用:图解原理与后端思维实战指南 官方文档翻了三页还云里雾里?别慌,吉他节拍器怎么用这事儿,其实没那么玄乎。很多转行搞后端的朋友,一看到“节拍”、“频率”、“同步”这些词就头大,觉得这是搞音乐的专业设备,跟写代码八竿子打不着。…

2026/9/22 1:58:03 阅读更多 →
赛睿rival踩坑实录:版本升级API全变了?这份完整示例救急

赛睿rival踩坑实录:版本升级API全变了?这份完整示例救急

赛睿rival踩坑实录:版本升级API全变了?这份完整示例救急 版本升级后 API 全变了,你写的代码直接报错,是不是想砸电脑?别急,赛睿rival…

2026/9/22 1:58:03 阅读更多 →
中望cad2015面试必坑一文搞懂

中望cad2015面试必坑一文搞懂

中望cad2015面试必坑一文搞懂 面试被问“中望CAD2015底层几何引擎如何优化大规模图纸渲染”时,你卡壳了?别慌,很多人死在原理答不上来。今天用实战案例一文搞懂中望cad2015高频考点,拒绝背八股。…

2026/9/22 1:58:03 阅读更多 →
艺龙旅行网机票查询源码拆解:避坑指南与面试通关

艺龙旅行网机票查询源码拆解:避坑指南与面试通关

艺龙旅行网机票查询源码拆解:避坑指南与面试通关 面试被问“艺龙旅行网机票查询怎么实现的”,你张口就来“爬虫抓数据”?HR直接摇头。 别慌,这不是让你去黑盒测试,而是考察你对高并发、数据一致性及容错机制的理解。…

2026/9/22 1:57:03 阅读更多 →
3个面试坑:纳米手机镀膜性能优化全解析

3个面试坑:纳米手机镀膜性能优化全解析

3个面试坑:纳米手机镀膜性能优化全解析 面试被问“纳米手机镀膜”原理,你张口就卡壳?别慌,这题看似物理,实则考察的是你对 性能优化 底层逻辑的理解。很多后端或算法工程师因为不懂硬件微观结构,答非所问,直接凉凉。…

2026/9/22 1:57:03 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →