简介本资源是一份面向数据库运维工程师与PostgreSQL高可用架构实践者的完整技术方案文档聚焦Postgres主从流复制与pgpool-II协同构建生产级高可用数据库集群。内容系统覆盖流复制原理WAL日志实时同步、同步/异步模式对比、pgpool-II核心能力连接池管理、自动故障切换、读写分离与负载均衡及全链路部署实操包含环境准备、主备库配置、pgpool参数调优、健康检查与故障模拟等关键环节。资源为单个773KB的Word文档.docx结构清晰含四章二十余节含版本控制表、详细目录、配置命令示例与网络/权限/时钟等前置检查清单便于按步骤落地验证。目前已有472人学习下载适合中高级DBA快速掌握PostgreSQLpgpool高可用方案的设计逻辑、配置要点与排错路径。1. PostgreSQL主从流复制pgpool高可用方案不是堆机器而是让两台PostgreSQL真正“互为备份、各司其职”你有没有遇到过这种场景线上PostgreSQL主库突然夯住DBA手抖敲下systemctl restart postgresql结果应用连不上、监控告警炸屏、业务方电话直接打到值班手机上更糟的是备库明明开着却没人敢切——因为不确定它到底同步到哪一秒、wal是否堆积、连接池会不会把读请求发错地方。这不是玄学是配置没闭环。这份《Postgres主从流复制pgpool高可用方案》文档不是教你怎么装软件而是把一套在RHEL/CentOS生产环境里跑过半年以上、经受过3次真实主库宕机切换的双节点高可用链路掰开揉碎讲清楚WAL日志怎么从master实时推到standby、pgpool如何识别主备状态并自动漂移VIP、为什么备库能接只读但绝不能接写、以及最关键的——failover后怎么确保新主库的sequence和replication slot不丢不乱。它面向的是已经能独立部署单实例PostgreSQL、但还没亲手搭过跨组件高可用链路的中级DBA或后端工程师。如果你正卡在“配完pgpool连不上”“备库显示in recovery但查不到数据”“切换后应用报错duplicate key”这些具体翻车点这篇就是为你写的血泪复盘笔记。2. 流复制底层机制WAL不是日志文件而是数据库状态的“原子快照流”2.1 WAL的本质不是磁盘日志而是内存状态的持续快照很多人误以为WAL是“写完SQL再落盘的日志”其实完全相反WAL是PostgreSQL事务提交前必须完成的强制步骤。当一个INSERT执行时数据页变更先写入shared_buffers内存同时对应的WAL record含LSN、XID、page offset、变更内容被强制刷入WAL buffer事务COMMIT时walsender进程立即将该WAL record通过TCP stream推送给standby的walreceiver只有walreceiver返回ACKmaster才允许事务返回成功。这个过程绕过了文件系统缓存直通磁盘或由wal_sync_method控制所以WAL才是数据库一致性的唯一权威来源。提示pg_wal目录下的文件名如000000010000000000000001本质是LSN的十六进制编码前8位是timeline ID后16位是log segment编号。备库通过pg_stat_replication中的sent_lsn、write_lsn、flush_lsn、replay_lsn四个值精确判断自己落后master多少字节——这才是“同步延迟”的真实定义不是看pg_is_in_recovery()返回true就万事大吉。2.2 同步 vs 异步不是开关而是LSN确认策略的硬约束文档里提到synchronous_commit on和synchronous_standby_names但没说清它们如何协同工作。实际机制是当synchronous_commit remote_write时master必须等到至少一个standby的walreceiver将WAL写入本地磁盘write_lsn追上才返回客户端成功当synchronous_commit on等价于remote_apply时master必须等到standby的startup进程将WAL replay到内存replay_lsn追上才允许事务提交。这意味着同步模式下standby的replay_lsn必须严格等于master的flush_lsn否则事务会hang住。而异步模式下master只管自己flush_lsnstandby的replay_lsn可能落后几秒甚至几分钟取决于网络和I/O。生产环境选同步还是异步本质是在“数据零丢失”和“写入延迟可控”之间做取舍没有中间态。2.3 12.x版本的配置断层recovery.conf消失但逻辑没变PostgreSQL 12彻底移除了recovery.conf把所有恢复参数合并进postgresql.conf。但这不是简化而是把隐式逻辑显性化。关键变化有三点primary_conninfo不再写在独立文件而是作为postgresql.conf中primary_conninfo host192.168.1.10 port5432 userrepl passwordxxx存在trigger_file参数被废弃改用promote_trigger_file /tmp/pg_failover.trigger且该文件必须由外部脚本如pgpool的failover_command创建recovery_target_timeline latest成为默认行为无需手动配置。注意如果你在12.x备库的postgresql.conf里还看到recovery_target_timeline current说明配置模板没更新这会导致failover后新主库无法接受新WAL直接卡死。2.4 备库只读的底层限制不是配置项而是WAL replay的天然属性hot_standby on只是打开只读查询的开关真正的限制来自WAL replay机制standby的startup进程在replay WAL时会对涉及的page加BufferPin锁此时任何DML都会因无法获取AccessExclusiveLock而报错cannot execute INSERT in a read-only transaction。但这里有个坑如果standby的max_standby_streaming_delay设置过大如30s当master产生大量WAL时standby会主动cancel掉长时间运行的SELECT导致应用报错canceling statement due to conflict with recovery。这不是bug是为避免查询阻塞WAL replay的保护机制。2.5 验证流复制健康度的三板斧命令别只信pg_is_in_recovery()要交叉验证三个维度# 1. 查master当前WAL位置和同步状态 psql -U postgres -c SELECT pg_current_wal_lsn(), pg_walfile_name(pg_current_wal_lsn()), pg_stat_replication.* FROM pg_stat_replication; # 2. 查standby的replay进度必须在standby节点执行 psql -U postgres -c SELECT pg_last_wal_replay_lsn(), pg_last_wal_receive_lsn(), pg_is_in_recovery(); # 3. 计算延迟字节数master上执行需替换standby的application_name psql -U postgres -c SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS byte_lag FROM pg_stat_replication WHERE application_name standby1;byte_lag 1MB健康byte_lag 10MB且持续增长检查standby磁盘I/O或网络丢包replay_lsn为空standby未启动recovery或WAL接收中断。3. pgpool-II配置核心不是代理层而是PostgreSQL集群的“状态感知中枢”3.1 pgpool如何发现主备靠的是show pool_nodes不是DNS或VIP很多新手以为pgpool通过VIP或hostname自动识别主库其实完全错误。pgpool的health_check_period参数会定期默认10秒向每个backend节点发送SELECT 1根据返回结果和backend_flag标记节点状态。但真正的主库识别依赖watchdog或failover_command脚本的输出。例如在pgpool.conf中failover_command /var/log/pgpool/failover.sh %d %H %P %r %R当pgpool检测到backend 0原master失联时会执行该脚本并传入%d0 %H192.168.1.10 %P5432 %r192.168.1.11 %R5432脚本内部必须完成在standby节点执行pg_ctl promote修改/etc/hosts或DNS指向新VIP更新pgpool的pool_hba.conf允许新主库连接。没有这一步pgpool永远认为backend 0是主库即使它已宕机。3.2 连接池的“连接复用”真相不是长连接而是连接池生命周期管理connection_cache on常被误解为“保持与PostgreSQL的长连接”实际机制是pgpool为每个client connection维护一个backend connection池当client断开时pgpool不会立即关闭backend connection而是将其放回空闲池当下一个client以相同user/db参数连接时pgpool直接复用该backend connection。但backend connection本身仍受PostgreSQL的idle_in_transaction_session_timeout控制。如果应用开启事务后不提交也不rollbackpgpool的backend connection会被PostgreSQL强制kill导致pgpool日志出现backend connection is closed by remote host。3.3 读写分离的边界pgpool不解析SQL只按规则路由pgpool的load_balance_mode on仅对SELECT语句生效且不区分是否带FOR UPDATE、是否在事务中。这意味着BEGIN; SELECT * FROM users; UPDATE orders SET statusdone; COMMIT;—— 第一条SELECT被路由到standby第二条UPDATE因非SELECT被发往masterSELECT * FROM users FOR UPDATE;—— 因FOR UPDATE是写操作语义pgpool会将其发往master即使语法是SELECT。更危险的是如果应用在事务中混合读写pgpool无法保证事务一致性。解决方案只有两个在应用层显式指定/*NO LOAD BALANCE*/ SELECT ...注释关闭load_balance_mode所有流量走master用pgpool仅作连接池和故障转移。3.4 watchdog机制不是可选插件而是双pgpool节点高可用的刚需单pgpool节点是单点故障。要实现pgpool自身高可用必须启用watchdog。其原理是两个pgpool节点通过wd_hostname互相心跳选举出一个active节点负责VIP漂移和failover决策另一个standby节点监听active状态。关键配置是delegate_IPVIP地址和ifconfig_path如/sbin/ifconfig。如果ifconfig_path路径错误watchdog会静默失败VIP永不漂移。验证命令# 在任意pgpool节点执行 pgpool -m fast stop pgpool -n -d 21 | grep -i watchdog # 正常应输出watchdog is running和delegate IP is assigned3.5 避坑pgpool常见问题排查现象→原因→解决现象1psql -h 127.0.0.1 -p 9999 -U postgres连接超时但直连5432端口正常原因pgpool未启动或listen_addresses localhost未包含客户端IP或防火墙拦截9999端口。解决检查pgpool.conf中listen_addresses是否为*或包含客户端网段执行ss -tlnp | grep 9999确认端口监听用iptables -L -n | grep 9999检查规则。现象2show pool_nodes;显示所有节点status down但psql -h standby_ip可连原因pgpool的health_check_user用户无权限或health_check_password未在pool_passwd中加密。解决在master执行pg_md5 -m -f /etc/pgpool-II/pool_passwd health_check_user生成密码确认health_check_user在PostgreSQL中存在且有CONNECT权限。现象3failover后新主库无法接受写入报错FATAL: database system is starting up原因failover_command脚本未正确执行pg_ctl promote或promote_trigger_file路径与postgresql.conf中配置不一致。解决登录新主库检查pg_is_in_recovery()返回f查看pg_log中是否有database system is ready to accept connections确认postgresql.conf中promote_trigger_file指向的文件已被删除promote后自动清理。现象4show pool_status;中num_init_children远大于max_pool连接数爆炸原因应用未正确关闭连接pgpool的child_life_time默认300秒未触发清理。解决调小child_life_time 60在应用层确保connection.close()被调用启用connection_life_time 300强制回收空闲连接。现象5VIP漂移后旧master重启变成新standby但WAL同步停滞原因旧master的recovery.conf或12.x的postgresql.conf中primary_conninfo仍指向已失效的旧standby IP。解决在旧master的配置中将primary_conninfo的host参数改为新主库IP执行pg_ctl reload检查pg_stat_replication确认新主库有该节点的连接记录。4. pg_rman备份实战不是dump而是WALbasebackup的原子快照组合4.1 pg_rman与pg_dump的本质区别时间点恢复能力pg_dump导出的是SQL文本只能恢复到dump时刻的逻辑状态无法应对误删表、drop database等DDL事故而pg_rman基于pg_basebackup和WAL归档能实现PITRPoint-in-Time Recovery。其原理是pg_rman backup --backup-modefull调用pg_basebackup生成基础备份basebackup同时记录起始LSNpg_rman backup --backup-modeincremental只备份自上次full backup以来变更的WAL段恢复时pg_rman restore --recovery-target-time2023-10-01 12:00:00先解压basebackup再按时间顺序重放WAL直到目标时间戳。提示pg_rman show命令列出的所有备份其TLITimeline ID必须连续否则PITR会失败。如果主库发生过failover新主库的TLI会1此时必须用pg_rman validate检查备份链完整性。4.2 归档配置的致命细节archive_command必须返回0postgresql.conf中archive_mode on和archive_command是WAL归档的开关。但很多文档忽略一点archive_command脚本执行后shell exit code必须为0否则PostgreSQL会停止归档并报错archive command failed with exit code 1。典型错误配置# 错误rsync失败时exit code非0但脚本未捕获 archive_command rsync -a %p /backup/wal/%f # 正确强制返回0归档失败日志到pg_log archive_command rsync -a %p /backup/wal/%f 2/var/log/postgresql/archive.log || true4.3 pg_rman初始化不是建目录而是注册备份仓库pg_rman init命令会在指定目录创建.pg_rman元数据库存储所有备份的LSN、时间、大小信息。但必须确保该目录位于PostgreSQL数据目录之外且postgres用户有读写权限。常见错误目录在/var/lib/pgsql/data下导致pg_rman与PostgreSQL争抢文件锁目录属主为rootpostgres用户无法写入。正确做法# 创建独立备份目录 sudo mkdir -p /backup/pg_rman sudo chown postgres:postgres /backup/pg_rman sudo chmod 700 /backup/pg_rman # 切换到postgres用户初始化 sudo -u postgres pg_rman init -B /backup/pg_rman4.4 全量增量备份脚本的关键逻辑文档附件中的pg_rman_full.sh和pg_rman_archive.sh需按周期执行。但生产环境必须加入校验环节#!/bin/bash # pg_rman_full.sh - 每周日凌晨执行 BACKUP_DIR/backup/pg_rman DATE$(date %Y%m%d) # 1. 执行全量备份 sudo -u postgres pg_rman backup -B $BACKUP_DIR --backup-modefull --with-server-log # 2. 验证备份完整性关键 if sudo -u postgres pg_rman validate -B $BACKUP_DIR; then echo Full backup $DATE validated OK # 3. 清理7天前的备份保留最近3个full sudo -u postgres pg_rman delete -B $BACKUP_DIR --oldest --force else echo Full backup $DATE validation FAILED! | mail -s PG_RMAN ALERT admincompany.com exit 1 fi没有validate步骤的备份等于没备份。4.5 PITR恢复的四步不可逆操作恢复不是pg_rman restore一条命令而是原子流程停库sudo systemctl stop postgresql必须停止所有PostgreSQL进程清空数据目录sudo rm -rf /var/lib/pgsql/data/*注意不是data目录本身执行restoresudo -u postgres pg_rman restore -B /backup/pg_rman --recovery-target-time2023-10-01 12:00:00创建recovery.signaltouch /var/lib/pgsql/data/recovery.signal12.x必需10.x用recovery.conf。注意第3步的--recovery-target-time必须早于误操作时间且不能晚于备份链中最后一个WAL的时间。用pg_rman show查START_TIME和END_TIME确认范围。5. 故障切换全流程验证从模拟宕机到业务回归的12分钟实操5.1 主库PostgreSQL进程级宕机测试最常见场景这是最贴近真实的故障主库PostgreSQL服务崩溃但服务器和pgpool仍在运行。步骤如下# Step 1: 在master节点模拟进程崩溃 sudo systemctl stop postgresql # 或 kill -9 pgrep -f postgres -D /var/lib/pgsql/data # Step 2: 立即在pgpool节点检查状态30秒内 psql -h 127.0.0.1 -p 9999 -U postgres -c show pool_nodes; # 预期node_id0 statusdown, node_id1 statusup and roleprimary # Step 3: 检查VIP是否漂移到standby ssh standby_node ip addr show | grep 192.168.1.100 # 预期输出包含inet 192.168.1.100/24 # Step 4: 验证新主库可写在standby节点执行 psql -h 127.0.0.1 -p 5432 -U postgres -c CREATE TABLE test_failover(id SERIAL); INSERT INTO test_failover VALUES(1);关键观察点从systemctl stop到show pool_nodes显示新主库应在45秒内完成取决于health_check_timeout和failover_command执行时间。如果超时检查pgpool.conf中failover_command脚本是否卡在pg_ctl promote权限问题。5.2 pgpool节点级宕机VIP漂移的黄金5分钟当运行pgpool的服务器宕机watchdog必须在5分钟内完成VIP漂移。验证方法# 在active pgpool节点模拟宕机 sudo systemctl stop pgpool # 在standby pgpool节点每10秒检查 watch -n 10 ip addr show | grep 192.168.1.100 echo VIP acquired || echo waiting... # 预期2-3分钟后输出VIP acquired # 同时检查新active节点的pgpool日志 tail -f /var/log/pgpool/pgpool.log | grep -i delegate IP # 预期出现delegate IP is assigned to this node血泪经验如果VIP不漂移90%概率是watchdog配置中other_pgpool_hostname指向了错误IP或heartbeat_destination端口默认9000被防火墙拦截。用nc -zv standby_pgpool_ip 9000测试连通性。5.3 切换后应用连接恢复的三个必检项failover成功不等于业务恢复。必须验证连接字符串是否指向VIP应用配置的jdbc:postgresql://192.168.1.100:9999/mydb而非直连192.168.1.10:5432pgpool的allow_sql_comments on是否开启某些ORM框架如Hibernate生成的SQL带/* generated by hibernate */注释若此参数关闭pgpool会拒绝该SQL新主库的max_connections是否足够原standby的max_connections可能小于master切换后并发连接数突增会导致too many clients错误。5.4 旧主库重入集群的“消毒”流程旧master恢复后不能直接systemctl start postgresql必须重置为standby# 在旧master节点原master现需变standby sudo systemctl stop postgresql sudo rm -rf /var/lib/pgsql/data/* # 从新主库拉取basebackup关键 sudo -u postgres pg_basebackup -h 192.168.1.100 -D /var/lib/pgsql/data -P -U repl -R # 启动自动进入recovery模式 sudo systemctl start postgresql-R参数会自动生成standby.signal和postgresql.auto.conf比手动配置可靠十倍。5.5 一份能放进巡检脚本的健康检查清单把以下命令写成/usr/local/bin/pg_health_check.sh每天凌晨cron执行#!/bin/bash # 检查1流复制延迟 Lag$(psql -U postgres -t -c SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) FROM pg_stat_replication WHERE application_namestandby1; 2/dev/null) if [ -z $Lag ] || [ $Lag -gt 10485760 ]; then # 10MB echo REPLICATION LAG CRITICAL: ${Lag} bytes | mail -s PG ALERT admincompany.com fi # 检查2pgpool节点状态 Nodes$(psql -h 127.0.0.1 -p 9999 -U postgres -t -c show pool_nodes; 2/dev/null | wc -l) if [ $Nodes -ne 2 ]; then echo PGPOOL NODES MISMATCH: expected 2, got $Nodes | mail -s PG ALERT admincompany.com fi # 检查3最近备份有效性 if ! sudo -u postgres pg_rman validate -B /backup/pg_rman 2/dev/null; then echo PG_RMAN BACKUP INVALID | mail -s PG ALERT admincompany.com fi从那以后我每次上线新集群都强制走一遍这个脚本再加一次手动failover演练。不是信不过文档是信不过自己漏掉的那一个chmod 700。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
机器学习算法优化与硬件协同设计的效率革命 1. 机器学习效率革命的背后推手在波士顿查尔斯河畔的那栋标志性玻璃建筑里,一群穿着连帽衫的研究人员正用数学公式重新定义人工智能的边界。他们最近发表在NeurIPS上的论文显示,通过改进传统反向传播算法,模型训练时间缩短了40%——这相当于每… · 2026/11/4 23:18:44
Redis SCAN命令原理与华为云优化实践 1. Redis SCAN命令基础解析Redis的SCAN命令是遍历大量键值对时的高效解决方案,它通过游标式迭代避免了KEYS命令可能引发的服务阻塞问题。在华为云Redis环境中,这个命令的工作机制与开源版本保持兼容,但在底层实现上针对云环境做了优化。1.1 S… · 2026/11/4 23:17:38
MySQL字符集与校对规则实战解析 1. MySQL字符集与校对规则深度解析最近在排查一个线上SQL报错时,遇到了Illegal mix of collations这个看似简单却隐藏着不少细节的问题。作为MySQL数据库中最基础却又最容易被忽视的配置项,字符集和校对规则的选择直接影响着数据存储、查询性能和多语言支… · 2026/11/4 23:17:38
智算集群性能诊断实战:Benchmark、监控与故障排查体系 1. 从一次训练任务卡死说起:智算集群为什么需要"听诊器"凌晨两点,训练任务突然卡在某个 step 不动了。日志没有报错,GPU 利用率从 95% 掉到 3%,nvidia-smi 显示显存还占着,但计算单元几乎空转。这种场景做 A… · 2026/11/4 23:56:28
AI工程化落地:从工业质检到大模型托管平台 1. 这次两个消息放在一起,其实是同一件事的两面先说结论:西门子与宝洁扩大AI质检合作,和Kimi K3接入AWS Bedrock,表面上一个在讲工业制造,一个在讲大模型生态,看起来风马牛不相及。但把这两条放在同一天的A… · 2026/11/4 23:56:28
MySQL函数实战:提升数据库操作效率的20个技巧 1. MySQL函数概述与使用场景MySQL作为最流行的关系型数据库之一,其内置函数库是数据处理的核心工具集。这些函数可以大致分为日期时间、字符串处理、数学计算、系统信息等几大类,几乎覆盖了日常开发中的所有数据处理需求。在实际项目中,我经常… · 2026/11/4 23:56:28
Maven下载安装与settings.xml配置:JDK、本地仓库、镜像避坑 1. 先把 Maven 这件事说清楚:它到底解决什么问题聊 Maven 下载安装之前,我想先花点篇幅把“这东西是干嘛的”讲透。因为我在带新人的时候发现一个很普遍的现象:很多人装 Maven 装得挺顺,mvn -v也能出结果,但对着一堆po… · 2026/11/4 23:56:28
电商数据处理自动化:流批一体与智能管道的实践 1. 电商数据处理的现状与挑战电商行业经过近十年的高速发展,已经积累了海量的用户行为数据、交易数据和商品数据。根据我过去参与的几个大型电商平台数据中台建设的经验,目前主流电商平台日均产生的数据量普遍在TB级别,大促期间甚至可以达到P… · 2026/11/4 23:56:28
智能可观测性平台:从数据孤岛到自动化运维 1. 项目背景与行业痛点去年某次深夜告警让我记忆犹新:某核心业务系统突发性能劣化,运维团队花了3小时才定位到是某个第三方API的异常返回触发了业务逻辑的死循环。这种传统运维的被动响应模式,正是当下企业数字化转型中面临的典型困境。随着微… · 2026/11/4 23:55:21
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38