news 2026/9/13 2:37:30

达梦数据库定时备份与清理任务实战:从图形化配置到自动化运维

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
达梦数据库定时备份与清理任务实战:从图形化配置到自动化运维

接手达梦数据库(DM)的第一周,我通常只干一件事:确认定时备份和清理备份任务有没有跑起来。很多从 MySQL、Oracle 转过来的 DBA,习惯性地把备份脚本丢进 crontab 就完事,结果一个月后发现备份目录占满了磁盘,数据库直接连不上。达梦和 Oracle 很像,自带一套完备的作业调度器,完全可以在数据库内部把“定时全备 + 增量备份 + 过期备份清理”串成一条自动流水线。这篇文章就围绕达梦数据库的定时备份与清理备份任务,把图形化配置、SQL 脚本方式、清理策略和故障排查讲透,适合刚接触 DM 的 DBA,也适合那些已经搭好任务但偶尔出问题的朋友。

1. 先想清楚备份策略,再动手建任务

1.1 备份与清理是同一件事的两面

很多人建备份任务的时候,只想着“每天凌晨两点做个全备”,完全没想过备份文件怎么处理。结果磁盘被撑爆,数据库拒绝写入,业务直接挂掉。这种事故我见过不止一次,而且基本每次都是同一个原因:只配了备份,没配清理。

备份和清理必须当成一套完整方案来设计。备份负责把数据安全网织起来,清理负责让这套安全网不把服务器拖垮。打个比方,家里的保险柜再结实,如果柜门永远关不上、里面塞满了过期文件,真正要用的时候反而找不到东西。备份文件也不是越多越好,无限制堆积会让恢复时很难定位到正确的备份集,也会持续占用磁盘空间,最终影响生产库的正常写入。

所以建任何备份任务之前,先回答三个问题:

  • 业务最多能容忍丢多少数据?这决定了备份频率和归档日志的保留时间。
  • 如果真的需要恢复,希望多久恢复回来?这决定了全量备份的频率和网络/磁盘恢复速度的匹配度。
  • 磁盘空间能放多少天的备份?这决定了清理策略的保留周期。

这三个问题想清楚了,后面建任务就是纯操作。

1.2 不同业务场景下的备份节奏怎么定

达梦支持全量备份和增量备份,两种搭配使用比较合理。全量备份相当于拍一张完整快照,是恢复的基线;增量备份记录自上次备份以来的变化,用于减少数据丢失窗口。

我一般给客户的默认建议是:

业务级别全量备份增量备份归档日志保留全量保留周期
核心生产库每天 1 次每 2~4 小时 1 次3~7 天15~30 天
一般业务库每天 1 次每 6~8 小时 1 次2~3 天14 天
开发测试库每周 2~3 次不强制1~2 天7~14 天

这不是死标准,需要结合 RPO(恢复点目标)和 RTO(恢复时间目标)来调整。比如一个系统允许丢 10 分钟数据,那增量备份间隔就不能超过 10 分钟,同时归档日志至少要保留到下一次全量备份完成。如果恢复时间要求在 4 小时内,那么全量备份最好每天都做,并且把备份集存放在本机高速磁盘上,避免恢复时还要先从异地拉文件。

还有一个经常被忽略的点:备份任务本身会占用 IO 和 CPU。全量备份尽量放在业务低峰期,比如凌晨 2 点到 4 点;增量备份可以放在业务相对平稳的时间段。如果同一台服务器上跑了多个达梦实例,建议错开备份时间,否则磁盘 IO 很容易被打满。

2. 定时备份的底层逻辑:达梦Job引擎与前置准备

2.1 达梦的作业调度器和备份命令

达梦自带一套作业调度机制,简单说就是数据库内部的定时任务系统。它通过在系统表里登记作业信息,由数据库后台进程在指定时间触发执行。这套机制和 Oracle 的 DBMS_JOB / DBMS_SCHEDULER 非常相似,如果你之前接触过 Oracle,上手会非常快。

用达梦自己的调度器来管理备份,比单纯依赖操作系统 crontab 有一个天然优势:作业的执行状态、历史记录、失败原因都记录在数据库内部,排查问题时可以直接用 SQL 查,不用去翻操作系统的日志。而且这套机制对数据库实例状态敏感,实例不启动,作业就不会跑,但也不会出现“操作系统 crontab 启动了、数据库还挂着”的混乱状态。

备份命令的核心语法如下:

-- 全量备份 BACKUP DATABASE FULL BACKUPSET '/dm/backup/full/FULL_20250101_0200'; -- 增量备份(需要先有全量备份作为基线) BACKUP DATABASE INCREMENT WITH BACKUPDIR '/dm/backup/full' BACKUPSET '/dm/backup/incr/INCR_20250101_0800';

注意,增量备份里的WITH BACKUPDIR指的是全量备份集所在的目录,数据库要根据这个目录找到增量基准备份集。很多新手在这里出错,目录写错了,增量备份就会失败。

2.2 联机备份的前置条件:打开归档模式

达梦的全量备份可以在非归档模式下做,但增量备份和基于时间点的恢复必须依赖归档日志。实际生产环境我强烈建议打开归档模式,否则数据库崩溃后,只能恢复到上一次完整备份的时间点,中间的所有数据变更都会丢失。

打开归档模式的 SQL 大致如下:

-- 需要数据库处于 mount 状态 ALTER DATABASE MOUNT; ALTER DATABASE ADD ARCHIVELOG 'DEST=/dm/arch, TYPE=local, FILE_SIZE=512, SPACE_LIMIT=8192'; ALTER DATABASE ARCHIVELOG; ALTER DATABASE OPEN;

这段 SQL 在不同版本上可能会有细微差异,而且如果实例是正在运行的生产库,执行前一定要确认维护窗口,或者通过 DM 管理工具图形化配置。配置完成后用下面两条 SQL 验证:

SELECT ARCH_MODE, STATUS FROM V$DATABASE; SELECT * FROM V$ARCHIVED_LOG ORDER BY SEQ DESC;

ARCH_MODE显示为ARCHIVELOG就说明归档已经打开。归档目录的大小限制也要提前规划好,SPACE_LIMIT单位为 MB,建议至少留出能存放 3 天以上归档日志的容量。归档空间写满会导致数据库无法写入新日志,这是达梦库“突然连不上”的高发原因之一。

2.3 备份目录与磁盘空间规划

目录规划这事看似无关紧要,实际上出过很多问题。有人把所有备份都塞进一个目录,时间一长,全量、增量、临时文件混在一起,清理脚本根本没法写。我的习惯是严格按照层级建目录:

/data/dmarch -- 归档日志 /data/dmbackup /full -- 全量备份集 /incr -- 增量备份集 /logs -- 备份日志

目录建好后,用df -h确认所在文件系统容量。估算磁盘空间时,有一个简单经验:备份集大小通常接近数据库实际使用容量,增量备份则取决于变更量。要安全运行 N 天保留周期,磁盘空间至少需要“全备大小 × 保留天数 + 增量平均大小 × 保留份数 + 归档日志保留容量 + 20% 余量”。

举个例子,一个 500GB 的核心库,每天全备一次,保留 14 天,那么全备就需要约 7TB 空间;如果再加每小时归档 2GB、保留 3 天,还要额外 150GB 左右。所以磁盘规划一定不能只看“今天够不够用”,要看“保留周期内够不够用”。

3. 用DM管理工具创建定时备份任务

3.1 没有对象导航栏怎么办

用 DM 管理工具(也就是达梦自带的图形化客户端)配置定时任务是最直观的方式。但不少新用户装完工具,连上数据库后发现左侧没有对象导航栏,整个界面空荡荡的,以为安装出了问题。

这个问题其实很简单:菜单栏里点击“窗口”——“视图”——勾选“对象导航”,左侧导航栏就会出来。如果还是没有,检查一下是不是窗口被折叠成小图标了,拖动左侧边缘拉开即可。这个小问题虽然不影响命令行操作,但如果你要图形化配置定时任务,没有导航栏是寸步难行的。

导航栏中会显示“代理”节点,定时任务的创建、启停、历史记录都在这里管理。

3.2 创建备份作业的完整步骤

以 DM 管理工具为例,创建一个每天凌晨 2 点执行全量备份的作业:

  1. 用 SYSDBA 账号登录数据库实例。
  2. 在左侧对象导航中找到“代理”节点。首次使用代理功能时,右键“代理”,选择“创建代理环境”,达梦会在数据库中初始化作业管理相关的系统对象。
  3. 在“代理”节点下找到“作业”,右键选择“新建作业”,填入作业名称,比如JOB_BACKUP_FULL
  4. 在“作业步骤”页面点击“添加”,步骤类型选择“SQL 脚本”,然后在“命令”输入框里写下备份语句:
BACKUP DATABASE FULL BACKUPSET '/data/dmbackup/full/FULL_' || TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MI');

这里使用TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MI')是为了让每次生成的备份集目录名不重复,避免达梦备份集重名导致冲突。

  1. 步骤“成功操作”和“失败操作”建议都选择“退出报告成功/失败”,这样作业历史里能看到明确结果。
  2. 点击“确定”保存作业。

3.3 调度计划与启动作业

作业保存后,还需要配置调度计划。右键该作业选择“属性”,切到“调度”页面,新建一个调度:

  • 调度名称填写SCHED_FULL_0200
  • 调度类型选择“重复执行”。
  • 频率按需设置:每天一次。
  • 开始时间填02:00:00
  • 结束日期可以不填,让作业长期运行。

保存后,选中作业,右键“启动作业”。如果作业状态显示为“已启动”,就说明调度已经生效了。

之后可以在“代理”节点下的“作业历史记录”里查看每次执行情况。如果某次失败,历史记录里会给出失败原因,比如目录不存在、权限不足、磁盘空间不够等。这一步非常重要,很多人配置完作业从来不回头看一眼历史记录,直到两周后发现备份目录是空的才来排查,那时候就晚了。

4. 用系统存储过程创建备份任务:可批量复制的SQL方案

4.1 SP_CREATE_JOB系列完整示例

图形化方式适合单个实例快速配置,但如果要一次性给十套库批量部署备份任务,还是用系统存储过程更靠谱。达梦提供了一套创建作业的系统过程,可以在 disql 或任何客户端里直接执行。

完整创建作业的 SQL 示例如下:

-- 1. 创建作业 CALL SP_CREATE_JOB('JOB_BACKUP_FULL', 1, 0, '', 0, 0, '', 0, '', 0); -- 2. 创建作业步骤,执行全量备份 CALL SP_CREATE_JOB_STEP( 'JOB_BACKUP_FULL', 'STEP_BACKUP_FULL', 0, 'BACKUP DATABASE FULL BACKUPSET ''/data/dmbackup/full/FULL_'' || TO_CHAR(SYSDATE, ''YYYYMMDD_HH24MI'')', 1, 1, 0, 0, NULL, 0 ); -- 3. 创建调度计划:每天 02:00 执行 CALL SP_CREATE_JOB_SCHEDULE( 'JOB_BACKUP_FULL', 'SCHED_FULL_0200', 1, 1, 1, 0, 0, 0, NULL, '2024-01-01 02:00:00', NULL, '' ); -- 4. 启动作业 CALL SP_START_JOB('JOB_BACKUP_FULL');

这段脚本在不同 DM 版本上参数定义可能略有差异,如果执行报错,建议先执行SELECT * FROM SYS.SYSPROCESS或者查一下当前版本的《达梦数据库系统管理员手册》中对这几个系统过程的参数说明。最稳妥的方式是在 DM 管理工具里手工创建一个作业,然后查看它自动生成的创建脚本,把参数对照着抄下来。

4.2 Job状态怎么看、第二天没跑怎么查

用系统存储过程创建的作业,管理起来没有图形化那么直观,但查询状态并不难。达梦内部维护了几个与作业相关的系统视图,常用的有:

-- 查看作业基本信息 SELECT * FROM SYSJOB.SYSJOBS; -- 查看作业步骤 SELECT * FROM SYSJOB.SYSJOBSTEPS; -- 查看作业调度 SELECT * FROM SYSJOB.SYSJOBSCHEDULES; -- 查看作业历史 SELECT * FROM SYSJOB.SYSJOBHISTORY ORDER BY 1 DESC;

如果第二天发现备份任务没跑,按下面这个链路排查:

  1. 先看SYSJOBSENABLED字段是否为 1,值为 0 说明作业被禁用了,需要执行CALL SP_ENABLE_JOB('JOB_BACKUP_FULL');
  2. 再看SYSJOBSCHEDULES里的调度开始时间和频率配置,重点检查是否把调度写成了“仅一次执行”。
  3. 接着看SYSJOBHISTORY,如果历史记录里根本没有这条作业的执行信息,多半是调度配置没生效;如果有执行记录但状态为失败,则要看具体的错误消息。
  4. 最后检查数据库系统时间与服务器时间是否一致。达梦作业调度按数据库所在操作系统的时间执行,如果服务器时区设置错误,作业可能在错误的时间点触发。

这套排查顺序我用了很久,基本能覆盖 90% 的“作业没跑”问题。

5. 清理备份任务:策略设计与两种落地方式

5.1 先算清楚“保留多久”再写清理逻辑

清理任务的本质是“删除过期备份”,但删多删少很有讲究。删得太激进,可能把恢复必需的备份集干掉;删得太保守,磁盘空间又撑不住。

设计保留周期时,一个常用的策略是“阶梯保留”:近期的备份多留,远期的少留。比如:

  • 最近 3 天的增量备份全部保留。
  • 最近 14 天的全量备份保留。
  • 15~30 天的全量备份可只保留每周一份。

这种策略既能保证近期有小粒度恢复点,又能把长期历史备份控制在合理容量内,适合大多数业务场景。实际落地时可以写脚本筛选,比如全备文件名的日期后缀是周一、周六,就保留下来作为周备份,其他过期全备删除。

不过这里要特别提醒:删除全量备份之前,一定先确认没有增量备份依赖该全量备份。如果 14 天前的一个全备已经被后续的增量备份引用,强行删除会导致后续所有增量备份不可用,整条恢复链路全部断裂。

5.2 方式一:BACKUP命令自动保留备份集

如果你的 DM 版本支持BACKUP ... KEEP参数,那么可以在备份语句里直接指定保留周期,数据库会按周期自动淘汰过期备份集。语法思路大致如下:

BACKUP DATABASE FULL BACKUPSET '/data/dmbackup/full/FULL_20250101' KEEP 20160;

这里的KEEP 20160表示保留 20160 分钟,即 14 天。具体是否支持、单位是什么,一定要以你当前版本的《达梦数据库 SQL 语言使用手册》为准,我在不同版本上见过参数写法不完全一致的情况。

这种方式的好处是备份和清理在逻辑上是一体的,数据库不会误删还在引用中的备份集。缺点是灵活性有限,如果希望只保留每周一份的周备份,靠 KEEP 参数本身实现不了,还得额外写脚本处理。

5.3 方式二:定时Job调用OS命令清理

最通用、最可控的清理方式还是写一个 shell 脚本,放到定时作业里执行。

先写清理脚本/data/dmbackup/cleanup.sh

#!/bin/bash # 清理超过14天的全量备份目录 find /data/dmbackup/full -maxdepth 1 -type d -name "FULL_*" -mtime +14 -exec rm -rf {} \; # 清理超过3天的增量备份目录 find /data/dmbackup/incr -maxdepth 1 -type d -name "INCR_*" -mtime +3 -exec rm -rf {} \; # 清理超过3天的归档日志 find /data/dmarch -maxdepth 1 -type f -name "*.log" -mtime +3 -delete

注意,达梦备份集在磁盘上是一个目录,所以清理全备和增备用-type d,归档日志是普通文件用-type f。脚本里的-mtime是按文件的修改时间计算的,备份目录生成时目录的系统修改时间就是备份完成时间,这个没有问题。

然后给脚本加执行权限:

chmod +x /data/dmbackup/cleanup.sh

接着用达梦作业调度器来定时执行这个脚本。还是用SP_CREATE_JOB系列过程,但步骤类型那一位参数要改成“操作系统命令”类型。

CALL SP_CREATE_JOB('JOB_CLEANUP_BACKUP', 1, 0, '', 0, 0, '', 0, '', 0); CALL SP_CREATE_JOB_STEP( 'JOB_CLEANUP_BACKUP', 'STEP_CLEANUP', 1, -- 这一步类型为操作系统命令 '/data/dmbackup/cleanup.sh', 1, 1, 0, 0, NULL, 0 ); CALL SP_CREATE_JOB_SCHEDULE( 'JOB_CLEANUP_BACKUP', 'SCHED_CLEANUP_0330', 1, 1, 1, 0, 0, 0, NULL, '2024-01-01 03:30:00', NULL, '' ); CALL SP_START_JOB('JOB_CLEANUP_BACKUP');

这里把清理时间放在备份完成之后的 4 点前,也就是备份任务执行完 1 小时后再清理,避免清理任务先于备份任务执行,把当天的新备份误删。

生产环境执行删除操作前,我还有一个个人习惯:先把删除动作改成“移动”,脚本里用mv把过期备份挪到一个隔离目录,观察一两天确认没有恢复需求,再真正删除。等脚本稳定运行一段时间后,再改回直接删除。

5.4 三种调度方式的优缺点对比

清理任务和备份任务都可以用不同载体实现,我整理了一张对比表,方便你按实际情况选:

实现方式优点缺点适用场景
DM 管理工具图形化作业可视化,操作直观,历史记录友好批量部署效率低,依赖客户端连接单实例快速配置
系统存储过程 SP_CREATE_JOB可脚本化,方便批量复制,不依赖图形界面参数晦涩,版本差异需要核对多实例批量部署
操作系统 crontab + shell 脚本简单直接,不受数据库状态影响脱离数据库统一管理,缺少内部执行历史清理任务、外部调度

我的实际建议是:备份任务用达梦数据库自带的作业机制来管,因为恢复时需要依赖数据库内部的备份历史记录;清理任务则可以根据习惯灵活选择,如果你对 shell 更熟悉,直接用 crontab 调脚本也完全可行。

6. 任务验证、故障排查与运维习惯

6.1 备份完整性验证清单

任务配置完成后,并不是“看着跑了”就万事大吉。我见过太多备份任务每天成功执行,但等到真要恢复时才发现备份集损坏或者不会用。所以每个备份任务至少要配上下面这三项验证:

  1. 备份历史检查。用 SQL 查询V$BACKUP_HISTORY,确认每次备份的开始时间、结束时间、备份类型和状态。
SELECT START_TIME, FINISH_TIME, BACKUP_TYPE, BACKUPSET_DIR, STATUS FROM V$BACKUP_HISTORY ORDER BY START_TIME DESC;

STATUS = 0表示成功,非 0 表示失败。建议每周至少看一次这个视图。

  1. 备份文件大小检查。如果全量备份集的大小出现断崖式下降,比如以前都是 500GB,这次只有 50GB,大概率是备份过程中有异常,或者数据库里大量数据文件被设置为跳过备份状态。备份集目录下可以用du -sh快速确认大小。

  2. 备份完整性测试。有条件的话,在测试实例上做一次还原恢复,确认备份集可以正常打开。光看历史记录只能说明“备份命令执行成功”,不能证明“备份数据一定能被恢复”。

6.2 高频故障排查链路:从备份失败到数据库连不上

备份相关的异常,最严重的不是备份失败本身,而是备份过程把生产库拖挂。这里整理几条高频故障的完整排查链路。

故障一:备份任务报错,但数据库正常运行。

按顺序检查:备份目录是否存在且可写;文件系统剩余空间是否充足;是否已有同名备份集存在;当前是否有其他备份任务在并发执行。达梦同一时间一般只允许一个备份任务执行,如果上一次备份因为某种原因没正常结束,下一次任务可能无法启动,需要查V$BACKUP_HISTORY里是否有状态异常未闭合的记录,必要时手动清理。

故障二:数据库“突然连不上”,重启后也起不来。

这类情况大概率不是数据库软件问题,而是磁盘被备份文件和归档日志写满了。数据库实例在归档日志写满时,会无法记录新的日志信息,整个实例表现为连接失败、无响应。排查时用df -h看磁盘使用率,如果归档目录已经 100%,先清理过期归档释放空间,再启动数据库。这个故障在只配备份不配清理的环境里高发,也是我反复强调备份清理必须一起配的原因。

故障三:清理任务误删了还在用的备份集。

恢复时提示“找不到备份集”或“备份链断裂”。原因通常是清理脚本的find条件写得过宽,比如用了-name "*.bak"结果把其他目录下的重要文件也删了。所以在正式运行清理脚本前,先用ls或者find不带-exec的预览模式跑一遍,看看匹配到的都是什么文件。确认无误后,再让脚本进入生产环境。

6.3 定期恢复演练:备份的最终意义

备份做得再好,如果没验证过恢复流程,本质上就是“自欺欺人”。我以前接过一个客户,备份任务跑了半年,界面全绿,结果一次误删数据要恢复,发现所有备份集都是加密的,但加密密钥当时没有单独保存下来,整个恢复流程彻底卡住。这种情况比没有备份更让人抓狂。

我的建议是每季度至少做一次完整的恢复演练。具体做法:

  1. 准备一台配置接近生产环境的测试服务器。
  2. 安装相同版本的达梦数据库。
  3. 从备份目录拷贝最近一次全量备份和后续增量备份。
  4. 使用 DMRMAN 或者 DM 管理工具的还原功能,按正常恢复流程执行还原。
  5. 恢复完成后,抽查几张关键业务表的数据,确认数据完整且可用。

恢复演练的意义不仅仅是验证备份文件可用,更是验证你的恢复流程文档、操作者对命令的熟练度、以及备份策略本身是否合理。演练中发现的每一个问题,都是真正的“防患于未然”。

7. 最后分享几点长期运维心得

这套备份+清理的作业体系搭建完成之后,日常运维反而变得非常简单。我现在接手任何一套达梦库,第一件事永远是先看三样东西:归档开没开、备份作业跑没跑、磁盘水位多高。这三个没有问题,才敢在这套数据库上承载业务。

有几个细节,是我踩过坑之后总结出来的,分享给你:

一是备份时间不要太贴近整点。凌晨 2 点是默认的低峰期,但每台服务器上可能还有其他实例在跑任务。实际安排时尽量错开 15~30 分钟,比如 2:15 或 2:30,减少资源争抢。

二是给备份作业设置好失败告警。达梦管理工具或者第三方监控平台都支持对数据库日志进行监控。备份失败最好能在 5 分钟内就被人知道,而不是等到月底才从历史记录里翻出来。

三是清理脚本里一定要加日志输出,把每次删除的文件路径和删除时间记录下来。删除操作是不可逆的,有了日志,真出了问题至少能定位是哪条命令删了哪些文件。

四是不要相信“这个版本应该支持”这种判断。达梦版本之间确实存在差异,无论是我上面给的存储过程示例,还是KEEP参数的写法,落地之前都用你自己的环境验证一遍。好在达梦的手册文档比较完整,花十分钟核对一次,能省后面十个小时的排错时间。

数据库备份这件事,平时看起来毫无存在感,但真到了需要恢复的那一天,它就是救命的最后一根稻草。趁现在一切正常运行,把这根稻草扎结实了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 2:35:05

n8n-mcp Docker 部署与连接 n8n 实例故障排查完全指南

n8n-mcp Docker 部署与连接 n8n 实例故障排查完全指南 【免费下载链接】n8n-mcp A MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you 项目地址: https://gitcode.com/GitHub_Trending/n8/n8n-mcp 导读 本指南面向使用 Docke…

作者头像 李华
网站建设 2026/9/13 2:35:02

CookLikeHOC 煮锅系列:老乡鸡小份锅物的标准化配方与出餐 SOP 全解

CookLikeHOC 煮锅系列:老乡鸡小份锅物的标准化配方与出餐 SOP 全解 【免费下载链接】CookLikeHOC 🥢像老乡鸡🐔那样做饭。已添加2026年发布的《老乡鸡菜品溯源报告 2.0中新出现的菜品。主要部分于2024年完工,非老乡鸡官方仓库。文…

作者头像 李华
网站建设 2026/9/13 2:33:10

视觉项目8大核心工具链实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 2:32:55

台达CANopen伺服调试实战:物理层、协议栈与私有陷阱

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华