祥积宫 无限进步

【DB2 数据库】05 模拟故障排查系列:表空间自动扩容(AUTORESIZE)实验

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

前面的实验里,我已经分别验证了两种手工扩容方式:

  • ADD
  • EXTEND

但在真实运维里,除了手工扩容,还经常会碰到另外一个问题:

表空间能不能自己长大?

这篇文章要解决的就是这个问题。

这次我单独创建了一个新的小表空间 TS3,专门验证下面 3 件事:

  • 开启 AUTORESIZE 后,表空间是否真的会自动扩容
  • 自动扩容时,DB2 是新增容器,还是把原来的容器直接做大
  • 到了 MAXSIZE 上限后,表空间会不会再次被打满

如果说上一篇文章解决的是:

手工扩容到底怎么做

那么这一篇解决的就是:

自动扩容到底是怎么工作的

二、实验环境

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

这次实验故意不再复用已经做过很多手工动作的 TS2,而是单独做一个新的 TS3,这样现象会更干净,结论也更适合写成一篇独立文章。

三、为什么这篇要单独写

很多人第一次接触表空间扩容时,脑子里容易把这几件事混在一起:

  • ADD
  • EXTEND
  • AUTORESIZE

但这三者虽然都和“空间变大”有关,本质上并不是一回事。

前两篇已经把手工扩容讲清楚了,这一篇就单独把 AUTORESIZE 拆出来讲。

这样整条知识线就会更完整:

  1. 先构造表空间打满
  2. 再通过手工扩容恢复
  3. 再对比不同扩容方式
  4. 最后验证自动扩容的真实表现

四、实验设计思路

这次实验的设计很简单,但很有代表性。

1. 先创建一个很小的表空间

TS3 初始只有 1000 pages,这样后面很容易被写满。

2. 开启自动扩容

TS3 配置:

  • AUTORESIZE YES
  • INCREASESIZE 100 PERCENT
  • MAXSIZE 8000 K

这意味着:

  • 初始容量比较小
  • 空间不够时,它会按当前大小的 100% 自动增长
  • 但自动增长不是无限的,会受到 MAXSIZE 限制

3. 再用大字段测试表持续插数

我创建了表 T4(id int, c1 varchar(3000)),明确放进 TS3,再持续插入大字段数据。

这样做的目的是让表空间容量变化变得非常明显。

五、实验开始前的 TS3 状态

在真正大量插入数据之前,我先确认了 TS3 的初始状态。

当时 TS3 的关键信息如下:

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

从这里可以确认:

  • TS3 初始总页数确实只有 1000
  • 当前只有 1 个容器
  • 这是一个非常适合观察自动扩容的小表空间

六、第一阶段:先验证自动扩容确实发生了

接下来,我没有直接插到极限,而是先做第一阶段验证:

如果没有自动扩容,理论上它应该很快失败;如果还能继续写,就说明扩容已经发生。

插入到第一阶段后,我先查看 T4 的记录数:

db2 "select count(*) from T4"

1
-----------
       1200

  1 record(s) selected.

1200 条能成功写入,这已经说明一件事:

TS3 不可能还停留在最初那 1000 页的状态。`

也就是说,AUTORESIZE 确实已经发生了作用。

七、第二阶段:继续插到再次打满

为了验证自动扩容是不是“无限生效”,我继续向 T4 插入数据。

继续插入后,记录数最终变成:

db2 "select count(*) from T4"

1
-----------
       1823

  1 record(s) selected.

然后再次查看 TS3 状态,得到的真实结果如下:

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

这一组结果非常关键,因为它一次性说明了两件事:

1. 自动扩容确实发生过

Total pages 已经从最初的 1000 增长到了 1984

这说明表空间容量已经不是最初那一小块了。

2. 它后来又被打满了

现在已经出现:

  • Used pages = 1952
  • Free pages = 0

这说明:

自动扩容虽然发生了,但最后空间还是被吃光了。

八、为什么看到的是 1984,而不是理论上的 2000

实验设计时,我最初按“页大小 4KB、最大 8000K”去估算,理论上很容易先想到:

8000K ÷ 4K = 2000 pages

但实际跑出来看到的是:

  • Total pages = 1984
  • Useable pages = 1952

这并不表示实验失败,反而是很有价值的现场结论。

因为在 DB2 9.7 的 DMS 表空间里,最终看到的页数并不一定会是我们手工估算出来的那个“整值”,它会受到以下因素影响:

  • 表空间管理页开销
  • extent 对齐
  • DB2 内部页分配方式

所以这次实验里最应该记住的,不是“必须正好看到 2000”,而是:

  • 它确实从 1000 长大到了更大的值
  • 它确实没有新增容器
  • 它最终还是再次打满

这才是 AUTORESIZE 实验最重要的结论。

九、自动扩容后,容器到底发生了什么

很多人看到“表空间变大了”,会下意识以为:

是不是自动帮我新增了一个容器文件?

所以这一步一定要看容器详情。

实验时执行:

db2 list tablespace containers for 7 show detail

真实输出如下:

Tablespace Containers for Tablespace 7

Container ID                         = 0
Name                                 = /DB2_DATA/TESTDB/ts3/ts3_01.dat
Type                                 = File
Total pages                          = 1984
Useable pages                        = 1952
Accessible                           = Yes

这一段输出特别有说服力,因为它把最关键的问题说明白了:

  • 仍然只有 1 个容器
  • 容器名还是原来的 /DB2_DATA/TESTDB/ts3/ts3_01.dat
  • 变化的是这个容器本身的页数,从初始的小容量长大了

也就是说:

AUTORESIZE 的表现更接近“把原来的容器自动做大”,而不是“自动给你 ADD 一个新容器”。`

这正是它和 ADD 的核心区别之一。

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

到这里,这次实验已经把 AUTORESIZE 最重要的三层结论都跑出来了。

1. AUTORESIZE 可以自动扩容

如果没有自动扩容,T4 不可能顺利插到 1200 条,更不可能继续到 1823 条。

2. AUTORESIZE 不会新增容器数量

表空间从头到尾:

  • Number of containers = 1

容器详情里也始终只有:

  • ts3_01.dat

3. AUTORESIZE 不是无限扩容

当达到上限后,表空间还是会再次打满。

这次最直接的证据就是:

  • Free pages = 0

所以在实际运维里,千万不要把 AUTORESIZE 理解成:

开了以后就永远不会再满。

真正正确的理解应该是:

AUTORESIZE 只是按规则自动扩,仍然受增长策略和 MAXSIZE 约束。

十一、实验结束后的收尾动作

为了让环境先回到可控状态,我在实验结束后执行了:

db2 "drop table T4"
db2 terminate

执行结果:

DB20000I  The SQL command completed successfully.
DB20000I  The TERMINATE command completed successfully.

这样做的意义是:

  • 删除测试表,结束本轮数据写入实验
  • 终止当前会话,避免把实验连接一直挂着

如果后面希望把环境彻底还原得更干净,还可以再单独决定是否删除 TS3 表空间本身。

十二、这篇实验里最值得记住的 4 个观察点

这次实验里,我认为最值得初学者反复记住的不是命令本身,而是下面 4 个观察点:

1. 看扩容前总页数

  • 初始:Total pages = 1000

2. 看扩容后总页数

  • 自动扩容后:Total pages = 1984

3. 看容器数量有没有变化

  • 整个过程中:Number of containers = 1

4. 看最终是否再次打满

  • 最终:Free pages = 0

这 4 个点连起来,才是真正完整的运维判断链。

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

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

  1. AUTORESIZE 能让表空间自动变大。
  2. AUTORESIZE 变大的是原来的容器,不是自动新增新容器。
  3. AUTORESIZE 不是无限扩容,到达上限后表空间仍然会再次打满。

十四、到这里,表空间扩容这条线已经基本完整了

写到这里,其实关于表空间容量故障,已经串起了一条非常完整的学习路径:

  1. 构造表空间打满
  2. 观察打满后的状态
  3. ADD 恢复
  4. 区分 ADDEXTEND
  5. 验证 AUTORESIZE

这一套做下来,基本已经把日常运维里最常见的表空间容量问题讲清楚了。

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

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

  • 继续写 MAXSIZE 调整与再次恢复
  • 转去做“容器路径异常 / 权限异常”故障演练

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

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

因为做到这里,读者已经知道:

  • 表空间怎么满
  • 怎么扩
  • 自动扩容怎么工作

下一步就很适合进入:

空间没问题,但容器文件本身出问题时,DB2 会怎样报错,又该怎么排。

Linux