HOME

DB2 表空间扩容

文章目录11 节

这篇文章记录一次 DB2 9.7 DMS 表空间手工扩容实验:我先把 ASSP_CLOB 写满,稳定复现 SQL0289N,再对已有容器执行 EXTEND 50M,最后重试原失败写入,确认数据库恢复正常。

本文已对数据库名、主机名和存储目录做脱敏处理,但保留 DB2 版本、表空间名、页数、错误码和实测结果。文中的 LABDB 和容器路径必须按实际环境替换。

一、实验环境

项目实验值
操作系统SUSE Linux Enterprise Server 12 SP5
DB2 版本DB2 v9.7.0.6 Fix Pack 6
实例用户db2inst1
数据库LABDB(脱敏名)
目标表空间ASSP_CLOB
表空间类型DMS / LARGE
页大小4 KiB
容器数量1
自动扩容AUTORESIZE=NO
扩容方式手工 EXTEND

这次实验中,ASSP_CLOB 是独立的实验表空间,只存放测试表的 CLOB 数据。不应在与其他业务表共用的生产表空间中模仿“写满”步骤。

二、先分清文件系统和 DB2 表空间

DB2 容器扩容前,先确认底层文件系统是否有足够剩余空间:

  • 如果文件系统已经有足够空间,可以直接扩展 DB2 容器。
  • 如果文件系统也已经接近用满,必须先完成虚拟磁盘、LVM 和文件系统扩容。
  • 不能因为 DB2 表空间不足,就默认必须新增硬盘。

风险等级:INFO(只读)

作用: 核对 /db2data 所在文件系统、挂载点和块设备。 注意事项: 这些命令不修改存储。如果剩余空间不足,应另行制定底层扩容和回退方案,不要直接复制 pvcreatelvextend -l +100%FREE 一类高风险命令。

df -h /db2data
findmnt /db2data
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,WWN,SERIAL

本次实验前,/db2data 仍有约 85 GiB 可用,因此不需要修改 LVM 或文件系统。

三、查询表空间 ID

风险等级:INFO(只读)

作用: 连接目标数据库,查找 ASSP_CLOB 的表空间 ID、总页数、可用页数、页大小和当前状态。 需替换: LABDB 是脱敏后的数据库别名。

db2 connect to LABDB
db2 list tablespaces show detail

本次实验查到:

Tablespace ID                        = 6
Name                                 = ASSP_CLOB
Type                                 = Database managed space
Contents                             = All permanent data. Large table space.
Page size (bytes)                    = 4096
Number of containers                 = 1

表空间 ID 由数据库当前目录决定,不能在其他数据库中永久假定为 6

四、由 ID 查询真实容器路径

风险等级:INFO(只读)

作用: 查看表空间 6 的容器 ID、真实路径、总页数、可用页数和可访问状态。 注意事项: 后续 EXTEND 必须使用这里返回的已有容器路径。

db2 list tablespace containers for 6 show detail

扩容前容器状态如下,其中路径已脱敏:

Container ID                         = 0
Name                                 = /db2data/labdb/tablespaces/assp_clob_01
Type                                 = File
Total pages                          = 25600
Useable pages                        = 25568
Accessible                           = Yes

25600 × 4 KiB = 100 MiB,这就是扩容前的容器大小。

五、用可分配页面计算使用率

风险等级:INFO(只读)

作用: 查询各表空间的总容量、可分配容量、已用容量、剩余容量和真实使用率。 计算边界: TBSP_TOTAL_PAGES 包含管理页,因此使用率以 TBSP_USABLE_PAGES 为分母。1024.0 用于保留 MiB 小数,避免整数除法截断。

db2 "
SELECT
    SUBSTR(TBSP_NAME, 1, 20) AS NAME,
    TBSP_TYPE AS TYPE,
    DECIMAL(BIGINT(TBSP_TOTAL_PAGES) * TBSP_PAGE_SIZE / 1024.0 / 1024.0, 12, 2) AS TOTAL_MIB,
    DECIMAL(BIGINT(TBSP_USABLE_PAGES) * TBSP_PAGE_SIZE / 1024.0 / 1024.0, 12, 2) AS USABLE_MIB,
    DECIMAL(BIGINT(TBSP_USED_PAGES) * TBSP_PAGE_SIZE / 1024.0 / 1024.0, 12, 2) AS USED_MIB,
    DECIMAL(BIGINT(TBSP_FREE_PAGES) * TBSP_PAGE_SIZE / 1024.0 / 1024.0, 12, 2) AS FREE_MIB,
    DECIMAL(TBSP_USED_PAGES * 100.0 / NULLIF(TBSP_USABLE_PAGES, 0), 5, 2) AS USED_PCT,
    TBSP_AUTO_RESIZE_ENABLED AS AUTO_RESIZE
FROM SYSIBMADM.TBSP_UTILIZATION
ORDER BY USED_PCT DESC
"

六、把 ASSP_CLOB 写满并复现 SQL0289N

实验表 DB2INST1.TSX_CLOB_FILL 的普通数据、索引和 CLOB 分别放在 ASSPASSP_INDEXASSP_CLOB。扩容前,该表已有 1600 行测试数据,我从第 17 批继续填充。

风险等级:DANGER(故意耗尽表空间)

作用: 每批插入 100 个 32 KB CLOB,直到 ASSP_CLOB 无法分配新页面。 执行对象: 仅限独立实验库中的 DB2INST1.TSX_CLOB_FILL不可直接用于生产: 如果其他表也使用 ASSP_CLOB,此操作会导致其他写入同样失败。 恢复路径: 准备足够的文件系统空间并事先确认容器路径,出现 SQL0289N 后通过 EXTEND 增加容量。

batch=17
while [ "$batch" -le 40 ]; do
  db2 "
  INSERT INTO DB2INST1.TSX_CLOB_FILL (BATCH_NO, PAYLOAD)
  WITH R(N) AS (
    VALUES 1
    UNION ALL
    SELECT N + 1 FROM R WHERE N < 100
  )
  SELECT
    $batch,
    REPEAT(CAST('X' AS CLOB(32K)), 32000)
  FROM R
  " || break

  batch=$((batch + 1))
done

第 17 至第 31 批成功提交,第 32 批失败:

SQL0289N  Unable to allocate new pages in table space "ASSP_CLOB".
SQLSTATE=57011

失败后的实测状态:

成功行数       = 3100
成功批次       = 1 - 31
CLOB 总长度      = 99200000 字节
TBSP_TOTAL_SIZE = 102400 KiB
TBSP_USED_SIZE  = 102272 KiB
TBSP_FREE_SIZE  = 0 KiB
使用率           = 100.00%
AUTORESIZE      = 0

第 32 批是一条原子 SQL 语句,失败时没有留下部分行。

七、手工 EXTEND 现有容器

风险等级:CAUTION(持久扩大 DMS 容器)

作用:ASSP_CLOB 的已有文件容器再增加 50 MiB。 执行前检查: 重新执行 df -hLIST TABLESPACES SHOW DETAILLIST TABLESPACE CONTAINERS ... SHOW DETAIL,确认文件系统容量、表空间 ID 和容器路径。 参数含义: 50M 表示“在当前容量上再增加 50 MiB”,不是“调整到 50 MiB”。 影响: 命令会持久占用底层文件系统空间,不应在未评估收缩和回退方案时重复执行。 完成验证: 扩容后核对容器页数、文件大小、剩余空间和 AUTORESIZE

db2 "
ALTER TABLESPACE ASSP_CLOB
EXTEND (
  FILE '/db2data/labdb/tablespaces/assp_clob_01' 50M
)
"

这个容器的页大小是 4 KiB,因此下面两种写法的增量等价:

12800 页 × 4 KiB = 50 MiB
EXTEND ... 12800
EXTEND ... 50M

扩容后查询到:

Container ID                         = 0
Name                                 = /db2data/labdb/tablespaces/assp_clob_01
Total pages                          = 38400
Useable pages                        = 38368
Accessible                           = Yes

容器文件大小     = 157286400 字节
表空间总容量     = 150 MiB
表空间可用容量   = 149.875 MiB
剩余容量             = 50 MiB
AUTORESIZE                         = 0

容器从 100 MiB 增加到 150 MiB,容器数量仍然是 1,也没有开启自动扩容。

八、重试失败批次

风险等级:CAUTION(继续写入实验数据)

作用: 重新执行原来因空间不足失败的第 32 批,用实际写入验证扩容是否恢复业务能力。 执行对象: 仅限 DB2INST1.TSX_CLOB_FILL

db2 "
INSERT INTO DB2INST1.TSX_CLOB_FILL (BATCH_NO, PAYLOAD)
WITH R(N) AS (
  VALUES 1
  UNION ALL
  SELECT N + 1 FROM R WHERE N < 100
)
SELECT
  32,
  REPEAT(CAST('X' AS CLOB(32K)), 32000)
FROM R
"

这次写入成功:

DB20000I  The SQL command completed successfully.

总行数       = 3200
最大批次     = 32
CLOB 总长度  = 102400000 字节
表空间使用率 = 67.22%
剩余容量     = 50304 KiB
AUTORESIZE   = 0

这证明本次故障确实由 ASSP_CLOB 可分配页面耗尽引起,手工 EXTEND 后,原失败写入可以正常完成。

九、EXTEND 和 ADD 不是一回事

对比项EXTENDADD
操作对象已有容器新容器
容器数量不变增加
原容器文件变大不变
新文件不创建创建
数据重平衡通常不需要可能触发 rebalance
适用场景原路径有足够空间需要新路径或新存储单元

EXTEND 使用的必须是现有容器路径。如果希望新增另一个容器,应使用 ADD,不能在 EXTEND 中填写一个尚未登记的新路径。

十、生产环境操作要点

  1. 先查表空间 ID,再根据 ID 查容器,不要凭经验猜路径。
  2. 同时查表空间剩余页和底层文件系统剩余容量。
  3. 确认容器是 DMS FILE,不要把 SMS、自动存储或其他节点的命令直接套用过来。
  4. EXTEND 50M 是增加 50 MiB,重复执行会继续累加。
  5. 扩容后不只查页数,还要执行实际写入验证。
  6. 手工管理环境要复查 TBSP_AUTO_RESIZE_ENABLED=0,避免把自动扩容当成手工操作的结果。
  7. 不要通过删除容器文件回退表空间扩容,这会破坏数据库。

总结

这次实验完整验证了一条可复现的故障与恢复链路:

ASSP_CLOB 可分配页耗尽

SQL0289N / SQLSTATE=57011

确认表空间 ID 和已有容器路径

EXTEND 50M:100 MiB → 150 MiB

重试第 32 批写入成功

AUTORESIZE 仍为 0

关键不是记住一条 ALTER TABLESPACE,而是形成“文件系统预检、表空间定位、容器路径核对、增量含义确认、扩容后真实写入验证”的完整操作顺序。

DB2 Linux DMS 表空间 存储