分类:蟠木朽株

共 21 篇文章
深入数据库执行计划
深入数据库执行计划

专门写这一篇文章,是因为曾经遇到过有同事不熟悉数据库,甚至没用过 EXPLAIN,当遇到慢 SQL 之后,第一反应往往是问有经验的人。所以,本文不会假定你对数据库有很高的熟悉程度,但是写 SQL、建索引这些还是得会的,部分超出范围的内容也都有讲解。执行 EXPLAIN,屏幕上很快出现一堆内容:type=range、cost=35.50、Bitmap Heap Scan、USE TEMP B-TREE。如果使用过或者阅读过文档,看到这里可能会觉得问题已经有了答案,但实际上,排查

2026-09-24•约 13.0 千字
OpenTelemetry 全景监控
OpenTelemetry 全景监控

服务出了问题,通常先从指标发现异常,再到链路中定位耗时,最后结合日志查明原因。实际使用时,这三类数据往往来自不同的采集工具,字段名称也不一致。指标里叫 service,日志里可能叫 app_name;链路中有 trace_id,日志却没有记录。数据虽然都在,查询时却很难互相关联。业务代码如果直接使用某家监控厂商的 SDK,问题会更麻烦。更换后端时,不仅要迁移数据和仪表盘,还可能要重新修改各个服务的埋点代码。OpenTelemetry 用一套通用规范解决采集环节的问题,下文简称

2026-09-21•约 15.5 千字
古老的 RADIUS 协议
古老的 RADIUS 协议

第一次听到 /'reɪdiəs/ 联想到的单词肯定是 Radius,但是如果听到的是 RADIUS 协议,就不得不怀疑自己的耳朵了,半径协议是什么?当然,如果是看到 RADIUS 这个词就不会有这个疑惑,全大写意味着是首字母的缩写形式,就像 HTTP 协议一样。但是和 HTTP 协议一样,RADIUS 的全称 Remote Authentication Dial-In User Service 理解起来一样不怎么直观。远程用户拨号认证服务,这个短语看起来就有点儿古老,名称里面

2026-09-11•约 11.4 千字
PostgreSQL 与 InnoDB 的存储路径
PostgreSQL 与 InnoDB 的存储路径

假设有一张再普通不过的订单表:主键是 id,用户经常按 status 查询,后台又不断更新订单状态。CREATE TABLE orders ( id bigint PRIMARY KEY, status varchar(32) NOT NULL, buyer_id bigint NOT NULL, total decimal(12, 2) NOT NULL, note varchar(500), created_a

2026-09-02•约 13.9 千字
Go 请你喝一杯绿茶
Go 请你喝一杯绿茶

如果 CPU profile 里 runtime.gcBgMarkWorker、对象扫描和分配路径长期霸榜,GC 才值得被请出来背锅。高频 JSON 解码、临时字符串和一地鸡毛的小对象,都会把 GC 累得够呛;锁竞争、网络调用和慢查询造成的延迟,则不是给 GC 换个名字就能治好的。Go 1.26 默认启用 Green Tea。它没有突然变成分代 GC,也不会把对象搬来搬去;底子仍是并发、非移动的标记—清扫。变化发生在标记阶段:以前更像追着一个个对象满堆跑,现在尽量把同一段堆内

2026-08-31•约 8.9 千字
PostgreSQL 如何选择索引
PostgreSQL 如何选择索引

明明建了索引,数据库为什么不用?这是数据库问题里最常见、也最容易误判的一类。表上有索引,查询条件里也写了索引列,EXPLAIN 却给出一个 Seq Scan。把 enable_seqscan 关掉,索引突然又能用了。于是很自然地会得出结论:规划器选错了,或者它的成本估算与实际情况不符。但「能用某个索引」和「使用它成本最低」是两回事。索引先找到的是行的位置,不一定是查询最终需要的行;找到位置之后,还可能要读取表页、检查 MVCC 可见性、过滤误命中、排序、回表取列。若条件会返回

2026-08-30•约 16.9 千字