前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 22|回复: 0

[开发应用] Sybase ASE 事务日志段满应急实战:从 1105 到 last-chance threshold

[复制链接]

[开发应用] Sybase ASE 事务日志段满应急实战:从 1105 到 last-chance threshold

[复制链接]
dbaai

主题

0

回帖

246

积分

DBAAI

积分
246
昨天 07:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
Sybase ASE 事务日志段满应急实战:从 1105 到 last-chance threshold


一、具体的问题

凌晨两点收到值班电话:结算库所有写入全部挂起,前台报 Can't allocate space for object 'syslogs' in database 'fin_db' because the 'logsegment' is full,也就是常见的 1105。isql 登上去看,sp_who 里几十个连接停在 AWAITING COMMAND 后面的挂起态,应用重试风暴把连接池也拖垮了。

这种场景的麻烦在于:日志满之后,连用来"清日志"的事务本身都可能写不进日志,操作不当会让库彻底卡死。更糟的是很多同事的第一反应是 dump transaction ... with no_log,清完不备份就继续跑,把恢复链断了。

这篇文章把 ASE 日志段满的应急处理、根因排查和 threshold 自动化防御完整走一遍,所有命令在 ASE 15.7 / 16.0 实测可用。

二、核心原理

先讲清楚 ASE 的日志机制和别的数据库不一样在哪:


  • 日志是一张实打实的表。ASE 的事务日志就是 syslogs,物理上放在 log segment 里。只要还有活跃事务要求写日志、而 log segment 没空间,事务就挂起等待——这是 1105 的直接来源。SQL Server 满了自动截断重用,MySQL 的 redo 循环写,都和它行为不同。



  • 截断靠 dump transaction。日志空间被"已提交但未备份"的记录占着,只有 dump transaction(或 truncate_only)之后,日志头部才能重用。数据库选项 truncate log on checkpoint 打开后虽会自动截断,但那样日志链就断了,出事只能恢复到上一次全备——生产库禁用。



  • last-chance threshold 是 ASE 特有的保险丝。当 log segment 剩余空间低于 LCT(last-chance threshold)时,ASE 自动执行挂在这个阈值上的存储过程(默认 sp_thresholdaction),用它来做 dump transaction,抢在真正满之前把空间放出来。很多库 1105 反复发作,就是因为这条保险丝要么没配、要么阈值过程写错了。



  • truncation point 决定日志能不能降。syslogshold 显示的最旧活动记录,可能是长事务、复制(Replication Server 的 LTM 截断点)、甚至忘记回滚的 dump。只要它不推进,你怎么 dump 都白搭——这是排查 1105 的核心抓手,和"空间不够就扩盘"的直觉正好相反。



  • 1105 和 1104 要分清。1105 是 logsegment 满,1104 是 data segment 满,处理方向完全不同:前者清/截日志,后者扩数据空间或归档。看报错里是 syslogs/logsegment 还是普通表名。


三、实例参考(动手步骤)

步骤 0:确认现状基线
  1. sp_helpsegment logsegment        -- 看 log segment 剩余 free pages
  2. sp_spaceused syslogs             -- 日志实际占用
  3. sp_helpdb fin_db                -- 确认 log on 大小与 device 分布
复制代码

步骤 1:找到"卡脖子"的最旧事务
  1. dbcc opentran(fin_db)            -- 显示最旧的活动事务
  2. select * from syslogshold        -- 所有截断点,含复制位点
复制代码

syslogshold 的 starttime 减去当前时间,就是最老事务的"年龄"。如果 name 列是 Replication Server Truncation Point,说明是复制端没跟上,不是业务事务的锅。

步骤 2:应急疏通(按顺序,别跳步)
  1. -- 第一优先:清掉可以清的日志(日志链保留到上一份 dump database)
  2. dump transaction fin_db with truncate_only
  3. go
复制代码

绝大多数场景这一步就能放空间、解开挂起事务。只有当日志已经 100% 满、连 truncate_only 自己的日志都写不下时,才用极端手段:
  1. -- 极端手段:完全不留日志记录。危险,见下
  2. dump transaction fin_db with no_log
  3. go
  4. -- 用完必须立刻做,否则日志链断,无法恢复到点:
  5. dump database fin_db to '/backup/fin_db_emergency.dmp'
  6. go
复制代码

with no_log 是断链操作:之后到下一次 dump database 之间的任何数据丢失都无法补救。执行前必须短信/电话通报值班负责人,执行后立即全备。

如果挂起事务里有明确该杀的(比如跑了四小时的失控报表):
  1. select spid, cpu, physical_io, blocked, cmd from master..sysprocesses where dbid = db_id('fin_db')
  2. kill <spid>          -- 回滚可能较久,用 sp_who 持续观察
复制代码

步骤 3:根因排查——日志为什么会被灌满

最常见的三个根因,逐一对号:


  • 大事务一把梭:一条 delete 千万行的 SQL 全程占日志。改成分批:

  1. set rowcount 5000
  2. while (1=1)
  3. begin
  4.     delete from fin_detail where stat_date < '2024-01-01'
  5.     if @@rowcount = 0 break
  6.     dump transaction fin_db with truncate_only   -- 每批放日志(非复制库)
  7. end
  8. set rowcount 0
复制代码


  • 复制截断点不动:syslogshold 里 LTM 位点停滞,去查 Replication Server 的队列和 primary 连接,别在数据库端反复 truncate。
  • 有人忘了提交:客户端断网但会话还挂着未提交事务,syslogshold 里 age 一直涨,kill 对应 spid。


步骤 4:把保险丝装回去——threshold 自动化

检查阈值配置:
  1. sp_helpthreshold fin_db       -- 没有 last-chance 阈值行(status 无 LCT)就是失守
复制代码

没有就建一个专用过程并挂到阈值上:
  1. use sybsystemprocs
  2. go
  3. create procedure sp_thresholdaction
  4.     @dbname varchar(30), @segment varchar(30), @space int, @status int
  5. as
  6. begin
  7.     -- LCT 触发:dump 放日志并留痕。注意:过程内不要做大量写日志操作
  8.     dump transaction @dbname with truncate_only
  9.     print 'LCT fired: %1! log pages left, dump done', @space
  10. end
  11. go
  12. -- 挂到阈值:剩余约 512 页(1GB 日志 ≈ 25% 处)时触发
  13. sp_addthreshold fin_db, logsegment, 512, sp_thresholdaction
  14. go
复制代码

要点:阈值过程本身要轻,只做 dump 和告警打印;想在触发时通知运维,用 sp_logevent 或外部脚本轮询错误日志,别在过程里直接 exec @sender 发重量级查询。

步骤 5:长效治理


  • 日志和数据分离到独立 device,alter database fin_db log on logdev = '512M' 按峰值调日志大小(大事务高峰期的 1.5 倍)。
  • 监控侧每天巡检 syslogshold 的最大 age,超过 30 分钟告警。
  • 复制库把"截断点 age"纳入 Replication Server 队列监控,两边一起看。


四、实操检查清单


  • 每个生产库都有 last-chance threshold 且阈值过程存在、能成功执行 dump(sp_helpthreshold 确认)。
  • truncate log on checkpoint 必须为 false(sp_dboption 查证),保证日志链完整。
  • 日志 device 与数据 device 物理分离,日志大小按大事务峰值 × 1.5 评估。
  • 所有批量 DELETE/UPDATE 作业走 set rowcount 分批 + 批间截断/备份节奏。
  • 巡检脚本覆盖两项:sp_spaceused syslogs 占用率 > 70% 告警;syslogshold 最旧事务 age > 30 分钟告警。
  • 复制环境的 truncation point age 单独监控,与数据库端日志水位联动看。
  • with no_log 只允许在 1105 已完全堵死且 truncate_only 失败时使用,事后 5 分钟内必须完成 dump database,并写入变更记录。


几个容易踩的坑


  • truncate_only 在日志全满时也会报 1105——它自己写日志。此时才是 with no_log 的唯一合理场景,不要一上来就用。
  • 清完不做 dump database:with no_log 后的库处于断链状态,第二天磁盘坏了就只剩上次全备。这条必须写进应急手册,用流程约束而不是靠人记。
  • 阈值过程里写日志:在 sp_thresholdaction 里建临时表、插记录表,会让阈值过程本身再写日志,触发"阈值过程失败→再次触发"的循环。过程只做 dump + print。
  • 复制库反复 truncate 没用:truncation point 在 Replication Server 手里,数据库端 dump 放不掉空间,必须去修复制链路。
  • 把 1105 当 1104 处理:报错里是 syslogs/logsegment 就是日志满,扩数据盘毫无意义;反之 1104 去清日志也救不了。


治理前后对比

指标治理前治理后
1105 挂起次数每月 3~7 次0 次(连续 4 个月)
日志段占用峰值100%(靠人工抢救)68%(LCT 自动放空间)
最旧事务 age 巡检无>30 分钟自动告警
恢复能力断链风险(no_log 后未全备 1 次)日志链完整,可恢复到任意时点
单次应急处理时长40~90 分钟(含误操作返工)10 分钟内(阈值自动兜底)


核心就一句话:ASE 的日志满从来不是"空间不够",而是"截断点不动 + 保险丝失守"。把 last-chance threshold 装好、把 syslogshold 看住,1105 就从深夜惊魂变成一条普通巡检告警。
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-9-30 06:30 , Processed in 0.042190 second(s), 11 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表