祥积宫 无限进步

【DB2 数据库】07 模拟故障排查系列:表空间容器不可访问(路径异常)实验

一、这篇文章要解决什么问题

上一篇文章里,我已经验证了这样一类故障:

容器文件还在,但权限被改坏,DB2 无法访问。

但在真实运维里,除了权限异常,还有另一类非常常见的故障:

DB2 记录中的容器路径还在,但操作系统上的那个文件路径已经失效了。

比如:

  • 文件被误改名
  • 文件被挪走
  • 挂载点异常后,原路径下不再是原来的容器文件

这篇文章就专门验证这类“路径异常”。

这次实验的目标有 4 个:

  • 人为制造一个“容器路径失效”的故障
  • 观察业务层会报什么错
  • 观察表空间和容器状态如何变化
  • 验证把路径恢复后,业务是否能恢复

如果说上一篇讲的是:

容器文件在,但没有权限

那么这一篇讲的就是:

容器文件权限没问题,但原路径上的文件已经不在了。

二、实验环境

  • 操作系统:SUSE Linux Enterprise Server 12 SP5
  • DB2 版本:DB2 v9.7.0.6 Fix Pack 6
  • 实例:db2inst1
  • 数据库:TESTDB
  • 实验表空间:TS4
  • 容器文件:/DB2_DATA/TESTDB/ts4/ts4_01.dat
  • 测试表:T5

这次实验继续沿用上一篇“权限异常”实验里的 TS4T5,因为这套对象已经非常适合继续做容器访问类故障演练。

三、实验前先打快照

这类实验属于主动制造故障,所以开始前我建议先打一个快照:

11-准备做TS4容器路径异常实验

原因很简单:

  • 这次会直接改动容器文件名
  • 会让表空间短时间不可访问
  • 如果中途做乱了,快照可以快速回到干净起点

四、故障前的基线状态

在真正注入故障前,我先确认了 TS4 当前是正常的。

1. 表空间状态正常

实验开始前,TS4 的状态如下:

Tablespace ID                        = 8
Name                                 = TS4
Type                                 = Database managed space
Contents                             = All permanent data. Regular table space.
State                                = 0x0000
  Detailed explanation:
    Normal
Total pages                          = 1000
Useable pages                        = 960
Used pages                           = 160
Free pages                           = 800
High water mark (pages)              = 160
Page size (bytes)                    = 4096
Extent size (pages)                  = 32
Prefetch size (pages)                = 32
Number of containers                 = 1

2. 容器当前可访问

继续看容器详情:

Tablespace Containers for Tablespace 8

Container ID                         = 0
Name                                 = /DB2_DATA/TESTDB/ts4/ts4_01.dat
Type                                 = File
Total pages                          = 1000
Useable pages                        = 960
Accessible                           = Yes

3. 这时业务也是正常的

在开始做路径异常之前,T5 已经可以正常访问。

所以这次实验的起点很清楚:

  • TS4 = Normal
  • 容器 Accessible = Yes
  • 业务可访问

五、这次故障是怎么构造的

这次实验我没有删文件,而是用了一个更安全、更容易恢复的办法:

直接把容器文件改名。

故障注入前,目录状态如下:

总用量 4000
-rw------- 1 db2inst1 db2iadm1 4096000 4月   8 10:59 ts4_01.dat

然后执行:

mv /DB2_DATA/TESTDB/ts4/ts4_01.dat /DB2_DATA/TESTDB/ts4/ts4_01.dat.bak

改名后目录变成:

总用量 4000
-rw------- 1 db2inst1 db2iadm1 4096000 4月   8 11:34 ts4_01.dat.bak

这一步的本质是:

  • DB2 仍然认为容器路径是 /DB2_DATA/TESTDB/ts4/ts4_01.dat
  • 但操作系统上这个文件名已经不存在了

所以这就是一个非常典型的:

容器路径失效

六、故障发生后,业务层先出现了什么现象

和上一篇一样,我先从业务层观察,而不是先看管理命令。

1. 查询失败

执行:

db2 "select count(*) from T5"

真实返回:

1
-----------
SQL0290N  Table space access is not allowed.  SQLSTATE=55039

2. 写入也失败

执行:

db2 "insert into T5 values (3, repeat('Q',3000))"

真实返回:

DB21034E  The command was processed as an SQL statement because it was not a
valid Command Line Processor command.  During SQL processing it returned:
SQL0290N  Table space access is not allowed.  SQLSTATE=55039

这一步很值得注意,因为从业务层表面看,这次和上一篇“权限异常”非常像:

  • 都是 SQL0290N
  • 都表现为表空间不允许访问

所以如果只看 SQL 报错,很容易把这两类故障混在一起。

七、再看管理视角:表空间和容器状态

接着我再从 DB2 管理视角去看 TS4

1. 表空间被打成 Offline

查看 TS4 状态时,看到:

Tablespace ID                        = 8
Name                                 = TS4
Type                                 = Database managed space
Contents                             = All permanent data. Regular table space.
State                                = 0x4000
  Detailed explanation:
    Offline

2. 容器变成不可访问

再看容器详情:

Tablespace Containers for Tablespace 8

Container ID                         = 0
Name                                 = /DB2_DATA/TESTDB/ts4/ts4_01.dat
Type                                 = File
Total pages                          = 1000
Useable pages                        = 960
Accessible                           = No

到这里,表空间和容器状态已经清楚说明:

  • 表空间 Offline
  • 容器 Accessible = No

也就是说,对 DB2 来说:

虽然目录还在,但它需要的那个容器文件路径已经不可用了。

八、为什么说这次和“权限异常”在表面上很像

这次实验里,一个很重要的学习点就是:

路径异常权限异常 在 DB2 的表面现象上几乎一样。

两者都会看到:

  • 业务层:SQL0290N
  • 表空间层:Offline
  • 容器层:Accessible = No

所以真正区分这两类问题,不能只看:

  • SQL 报错
  • list tablespaces
  • list tablespace containers

真正能区分根因的,关键还是:

db2diag.log

九、诊断日志里,路径异常是怎么体现的

为了避免混进上一篇“权限异常”实验的旧日志,我专门截取了这次路径异常发生之后的时间窗口。

2026-04-08 11:35 之后,可以看到非常关键的日志:

FUNCTION: DB2 UDB, buffer pool services, sqlbDMSDoContainerOp, probe:810
MESSAGE : ZRC=0x8402001E=-2080243682=SQLB_CONTAINER_NOT_ACCESSIBLE
          "Container not accessible"
DATA #1 : <preformatted>
Error checking container 0 (/DB2_DATA/TESTDB/ts4/ts4_01.dat) for tbsp 8.  Rc = 860F000A

后面继续可以看到:

MESSAGE : ADM6081W  The table space "TS4" (ID "8") is in the OFFLINE state and
          is not accessible.

以及:

MESSAGE : ZRC=0x80020035=-2147352523=SQLB_NOT_ALLOWED_RECOVERY_P
          "Access not allowed. Tblspc Recovery Pend."

这说明这次故障的核心是:

  • DB2 在检查容器时发现原容器不可访问
  • 然后把 TS4 打成 Offline
  • 业务访问因此失败

这次和权限异常的真正区别

上一篇“权限异常”实验里,日志会明确出现:

  • OSERR: EACCES (13)
  • Access Denied
  • Path access permission

而这次“路径异常”实验,在当前这段时间窗口里,真正更关键的是:

  • SQLB_CONTAINER_NOT_ACCESSIBLE
  • Error checking container 0 ... Rc = 860F000A

所以可以这样总结:

  • 权限异常:文件在,但没有权限打开
  • 路径异常:DB2 记录中的那个容器路径已经失效

十、恢复动作也很简单

因为这次只是把文件改名了,所以恢复动作也非常直接:

mv /DB2_DATA/TESTDB/ts4/ts4_01.dat.bak /DB2_DATA/TESTDB/ts4/ts4_01.dat

恢复后目录变回:

总用量 4000
-rw------- 1 db2inst1 db2iadm1 4096000 4月   8 11:34 ts4_01.dat

这一步做的事情本质上就是:

把 DB2 预期的那个原始容器路径重新还回来。

十一、恢复路径后,不是完全瞬时恢复

这次实验里最有价值的细节,就出现在恢复阶段。

文件路径恢复以后,我先检查了容器状态,看到:

Tablespace Containers for Tablespace 8

Container ID                         = 0
Name                                 = /DB2_DATA/TESTDB/ts4/ts4_01.dat
Type                                 = File
Total pages                          = 1000
Useable pages                        = 960
Accessible                           = Yes

这说明从容器视角看,底层文件已经回来了。

但是就在同一个时刻,再去查业务表 T5,仍然报:

SQL0290N  Table space access is not allowed.  SQLSTATE=55039

这一步特别有价值,因为它说明:

容器先恢复为 Accessible = Yes,不等于业务访问会在同一瞬间马上恢复。

也就是说,这次路径异常实验里,我们实际看到了一个短暂的状态收敛过程。

十二、再检查时,表空间和业务都恢复了

继续等待并再次检查后,TS4 最终恢复成了正常状态。

1. 表空间恢复为 Normal

Tablespace ID                        = 8
Name                                 = TS4
Type                                 = Database managed space
Contents                             = All permanent data. Regular table space.
State                                = 0x0000
  Detailed explanation:
    Normal
Total pages                          = 1000
Useable pages                        = 960
Used pages                           = 160
Free pages                           = 800
High water mark (pages)              = 160
Page size (bytes)                    = 4096
Extent size (pages)                  = 32
Prefetch size (pages)                = 32
Number of containers                 = 1

2. 容器保持可访问

Accessible                           = Yes

3. 查询恢复正常

db2 "select count(*) from T5"

1
-----------
          2

  1 record(s) selected.

4. 写入也恢复正常

再执行:

db2 "insert into T5 values (3, repeat('Q',3000))"

成功返回:

DB20000I  The SQL command completed successfully.

最后再查:

db2 "select count(*) from T5"

1
-----------
          3

  1 record(s) selected.

这就说明这次故障已经完全闭环了:

  • 路径恢复
  • 容器恢复
  • 表空间恢复
  • 查询恢复
  • 写入恢复

十三、这次实验到底证明了什么

到这里,这次实验已经证明了下面这些非常实战的结论:

1. 容器路径失效,会直接把表空间打成 Offline

哪怕权限没问题,只要 DB2 记录中的容器路径对应不上真实文件,表空间照样会不可访问。

2. 业务层第一表现仍然可能是 SQL0290N

也就是说,单看 SQL 报错,很难区分:

  • 权限异常
  • 路径异常

3. 容器状态和表空间状态可以帮助你快速确认“确实是表空间级故障”

这次你能看到:

  • Offline
  • Accessible = No

这比只盯着 SQL 更接近根因。

4. 真正区分权限异常和路径异常,要看 db2diag.log

这是这篇实验最关键的价值。

可以简单记成:

  • 权限异常:更容易看到 EACCES / Access Denied
  • 路径异常:更容易看到容器检查失败、容器不可访问

5. 路径恢复后,业务恢复可能存在短暂延迟

这次你亲手看到:

  • 文件刚改回去时,容器已经 Accessible = Yes
  • 但业务不是同一瞬间马上恢复

这个细节很重要,因为它提醒我们:

底层资源恢复后,不要只看一次现象就下结论。

最好连续看:

  • 容器状态
  • 表空间状态
  • 业务访问状态

十四、和上一篇“权限异常实验”怎么一起理解

到这里,容器不可访问这一类故障,其实已经跑出了两组非常适合对比学习的实验:

1. 权限异常

  • 文件还在
  • 但没有权限打开

2. 路径异常

  • 权限没问题
  • 但 DB2 预期路径上的文件已经不在

两者共同点是:

  • 业务报 SQL0290N
  • 表空间 Offline
  • 容器 Accessible = No

两者区别是:

  • 根因不同
  • 日志细节不同
  • 恢复后的收敛节奏也可能不同

这就是非常典型的“表象相似、根因不同”的生产故障。

十五、实验结束后的收尾

这次实验结束后,最简单的收尾动作仍然是:

db2 "drop table T5"
db2 terminate

如果你想把环境彻底清理干净,也可以进一步执行:

db2 connect to TESTDB
db2 "drop tablespace TS4"
db2 terminate

但如果后面还想继续沿着“存储层 / 容器层故障”往下做,保留 TS4 依然是个不错的选择。

十六、把这篇文章压缩成三句话

最后把这次实验压缩成三句话:

  1. 容器文件路径失效,会直接导致表空间 Offline
  2. 业务层表面上仍然可能报 SQL0290N,所以不能只看 SQL 报错判断根因。
  3. 路径恢复后,容器和业务可能不是完全同步瞬时恢复,要连续观察状态变化。

十七、下一篇最自然写什么

如果继续沿着 DB2 运维故障排查这条线往下写,下一篇最自然的方向有两个:

  • 做“日志空间异常”实验
  • 做“实例启动 / 异常退出”实验

如果更偏实战值班,我会更推荐下一篇写:

【DB2 数据库】08 模拟故障排查系列:事务日志打满(LOG FULL)实验

因为前面几篇已经把“表空间和容器”这一类问题讲得很完整了,下一步非常适合切到另一类生产里更高频的故障:

日志满

这类问题在实际值班中比“手工改坏容器路径”更常遇到,而且非常适合继续做成一整条实验链。

Linux 存储