【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
这次实验继续沿用上一篇“权限异常”实验里的 TS4 和 T5,因为这套对象已经非常适合继续做容器访问类故障演练。
三、实验前先打快照
这类实验属于主动制造故障,所以开始前我建议先打一个快照:
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 = 12. 容器当前可访问
继续看容器详情:
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 = Yes3. 这时业务也是正常的
在开始做路径异常之前,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=550392. 写入也失败
执行:
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:
Offline2. 容器变成不可访问
再看容器详情:
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 tablespaceslist 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 DeniedPath access permission
而这次“路径异常”实验,在当前这段时间窗口里,真正更关键的是:
SQLB_CONTAINER_NOT_ACCESSIBLEError 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 = 12. 容器保持可访问
Accessible = Yes3. 查询恢复正常
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. 容器状态和表空间状态可以帮助你快速确认“确实是表空间级故障”
这次你能看到:
OfflineAccessible = 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 依然是个不错的选择。
十六、把这篇文章压缩成三句话
最后把这次实验压缩成三句话:
- 容器文件路径失效,会直接导致表空间
Offline。 - 业务层表面上仍然可能报
SQL0290N,所以不能只看 SQL 报错判断根因。 - 路径恢复后,容器和业务可能不是完全同步瞬时恢复,要连续观察状态变化。
十七、下一篇最自然写什么
如果继续沿着 DB2 运维故障排查这条线往下写,下一篇最自然的方向有两个:
- 做“日志空间异常”实验
- 做“实例启动 / 异常退出”实验
如果更偏实战值班,我会更推荐下一篇写:
【DB2 数据库】08 模拟故障排查系列:事务日志打满(LOG FULL)实验
因为前面几篇已经把“表空间和容器”这一类问题讲得很完整了,下一步非常适合切到另一类生产里更高频的故障:
日志满
这类问题在实际值班中比“手工改坏容器路径”更常遇到,而且非常适合继续做成一整条实验链。