前言:本文主要分为两部分。第一部分是在工作中遇到的SQL0294N报错以及相关的分析、处理过程。第二部分是在个人虚拟机上对db2untag指令的试验。
0背景:预投产环境,已建好ord数据库。但是由于应用侧做规划时字符集规划错误,数据库字符集在创建数据库时已经指定,创建完成后无法修改,所以只能删除并重建数据库ord。重建数据库表空间时提示容器重用,报SQL0294N错误。
1断开所有应用连接后,删除ORD数据库,成功
db2 force applications all db2 deactivate db ord db2 drop db ord DB20000I The DROP DATABASE command completed successfully. |
2新建数据库ORD,成功
db2 "create database ORD automatic storage yes on /db2node02 dbpath on /db2node02 using codeset UTF-8 territory cn restrictive" |
3配置完参数,成功
db2 activate database ord db2 connect to ord db2 "update db cfg for ORD using NEWLOGPATH /db2log02" |
4新建缓冲池,成功
db2 "CREATE BUFFERPOOL ord_BP8K IMMEDIATE SIZE 40000 PAGESIZE 8K" |
5新建表空间,报错SQL0294N,容器已经在使用中。
db2 "create tablespace ts_ord_dat01 pagesize 8k managed by database using (device '/dev/rts_ord_01_1' 50g,device '/dev/rts_ord_01_2' 50g,device '/dev/rts_ord_01_3' 50g) bufferpool ord_BP8K "
SQL0294N The container is already in use. |
出现这个报错时我很纳闷,想当然地以为数据库已经删除成功了,表空间的容器就不会再存在了。
纳闷归纳闷,有问题还是要解决。我的第一反应是删除容器重建容器,建完容器之后再建表空间。
rmlv ts_ord_01_1 rmlv ts_ord_01_2 rmlv ts_ord_01_3
mklv -y ts_ord_01_1 ord1vg 200 mklv -y ts_ord_01_2 ord1vg 200 mklv -y ts_ord_01_3 ord1vg 200
chown db2inst2:db2grp2 /dev/rts_ord_01_1 chown db2inst2:db2grp2 /dev/rts_ord_01_2 chown db2inst2:db2grp2 /dev/rts_ord_01_3
db2 "create tablespace ts_ord_dat01 pagesize 8k managed by database using (device '/dev/rts_ord_01_1' 50g,device '/dev/rts_ord_01_2' 50g,device '/dev/rts_ord_01_3' 50g) bufferpool ord_BP8K "
SQL0294N The container is already in use. |
做到这一步依然报错SQL0294N,我一时间没有头绪,不知道原因出在哪里。第一次建表空间报错应该是因为没有执行删容器的指令,第二次建表空间,容器已经删除重建了,依然报错。对于DB2的报错,最直接的办法就是查询官方文档寻找答案。
6查阅官方文档,关于SQL0294N报错:
SQL0294N 容器已在使用中。 说明 无法共享表空间容器。导致此错误的可能原因包括下列各项。 · CREATE TABLESPACE 或 ALTER TABLESPACE 语句包括了另一个表空间已在使用的容器。 · CREATE TABLESPACE 或 ALTER TABLESPACE 语句包括了来自这样的表空间的容器:它已被删除但还未落实删除语句。 · 用来添加数据库分区的 ALTER DATABASE PARTITION 语句使用了在同一物理数据库分区上的 LIKE 数据库分区的容器。因此这些容器已在使用中。 · CREATE TABLESPACE 或 ALTER TABLESPACE 语句正在尝试在单个物理数据库分区的多个逻辑数据库分区上使用同一容器。不能将同一容器用于同一物理数据库分区上的多个数据库分区。 · ADD DATABASE PARTITION 命令或 API 使用了来自同一物理数据库分区上 LIKE 数据库分区的系统临时表空间的容器。因此这些容器已在使用中。 · CREATE TABLESPACE 语句、ALTER TABLESPACE 语句或 CREATE DATABASE 命令包括了不再存在、但未正确删除的另一个数据库中的 DMS 容器。该容器实际上未在使用中,但是它被标记为正在使用。因此,在取消其标记之前,DB2 数据服务器将不允许对其进行使用。然而,当取消其标记时,验证该容器是否未在被同一数据库或另一个数据库使用是很重要的。取消容器的标记时,如果它正在使用中,那么所涉及的数据库将损坏。 · REORG 尝试自动选择要使用的 DMS 临时表空间,虽然存在一个具有合适页大小的 DMS 临时表空间,但它当前正被另一 REORG 命令使用。 · REDISTRIBUTE 命令的 ADD DBPARTITIONNUM 选项(此选项用于添加数据库分区)将根据编号最小的数据库分区上的表空间的表空间容器名,实现在新添加的数据库分区上创建表空间容器名。如果这些容器名指定了绝对路径,并且新的数据库分区与使用相同容器名的数据库分区在同一物理设备上,那么已经在使用新分区的容器。 · RESTORE DATABASE 命令在数据库中找到了不再存在、但是未正确删除的容器。 · 为传输操作创建了临时登台数据库,然后尝试了在该临时登台数据库仍存在的情况下在目标数据库上创建表空间。 用户响应 确保容器唯一。 · 对于 CREATE 或 ALTER TABLESPACE 语句,对表空间指定不同的容器。 · 对于包括来自已删除表空间的容器的 CREATE 或 ALTER TABLESPACE 语句,落实删除语句之后再次尝试,或指定不同的容器。 · 对于 ALTER DATABASE PARTITION 语句,使用 WITHOUT TABLESPACES 子句重新发出该语句,然后使用 ALTER TABLESPACE 语句为新的数据库分区创建唯一的容器。 · 对于环境包括一个物理数据库分区上多个逻辑数据库分区的 CREATE 或 ALTER TABLESPACE 语句,确保未对这样的逻辑数据库分区指定相同的容器。 · 对于 ADD DATABASE PARTITION 命令或 API,使用 WITHOUT TABLESPACES 子句重新发出该语句,然后使用 ALTER TABLESPACE 语句在新数据库分区上为系统临时表空间创建唯一的容器。 · 如果尝试使用一个属于不再存在但未正确删除的数据库的 DMS 容器,那么可以使用 db2untag 实用程序来从容器除去 DB2 容器标记。当除去了此标记时,DB2 就认为该容器是可用的,且可以在 CREATE TABLESPACE 语句、ALTER TABLESPACE 语句或 CREATE DATABASE 命令中使用该容器。 注意:使用 db2untag 时要特别小心。如果您对数据库仍在使用的容器发出 db2untag 命令,那么最初使用该容器的数据库以及现在正在使用该容器的数据库都将毁坏。 · 对于 REORG,一旦使用所需表空间的初始 REORG 完成,请重新提交该命令,或者提供另一具有合适页大小的临时表空间供使用。 · 对于 REDISTRIBUTE 命令,选择不使用 ADD DBPARTITIONNUM 选项,而是改为执行以下操作:在发出 REDISTRIBUTE 命令之前,发出附带了 WITHOUT TABLESPACES 子句的 ALTER DATABASE PARTITION GROUP 语句,然后使用 ALTER TABLESPACE 语句为新数据库分区创建唯一的容器。 · 对于 RESTORE DATABASE 命令(容器属于一个不再存在、但是未正确删除的数据库),请除去此容器。 注意:在除去容器之前,确保该容器没有正在被另一个数据库使用。 · 如果为传输操作创建了临时登台数据库,那么在不再需要改临时登台数据库之后除去该登台数据库,然后在目标上尝试因存在该登台数据库而被阻止的操作。 sqlcode:-294 sqlstate:42730 |
7解决方法:
根据官方文档和实际情况判断,本例应该属于这种情况:“如果尝试使用一个属于不再存在但未正确删除的数据库的 DMS 容器,那么可以使用 db2untag 实用程序来从容器除去 DB2 容器标记。当除去了此标记时,DB2 就认为该容器是可用的,且可以在 CREATE TABLESPACE 语句、ALTER TABLESPACE 语句或 CREATE DATABASE 命令中使用该容器。”
注意:使用 db2untag 时要特别小心。如果您对数据库仍在使用的容器发出 db2untag 命令,那么最初使用该容器的数据库以及现在正在使用该容器的数据库都将毁坏。
8具体操作:
对容器进行db2untag -f操作,类比创建lv的语句。
mklv -y ts_ord_01_1 ord1vg 200 mklv -y ts_ord_01_2 ord1vg 200 mklv -y ts_ord_01_3 ord1vg 200 |
则对应的db2untag语句为:
db2untag -f ts_ord_01_1 db2untag -f ts_ord_01_2 db2untag -f ts_ord_01_3 |
9对容器执行db2untag后,再进行创建表空间语句,创建成功。
db2 "create tablespace ts_ord_dat01 pagesize 8k managed by database using (device '/dev/rts_ord_01_1' 50g,device '/dev/rts_ord_01_2' 50g,device '/dev/rts_ord_01_3' 50g) bufferpool ord_BP8K " |
10以上是在预投产环境的操作记录。总结这次报错,重建数据库时,我们需要在删除旧数据库前,先执行以下指令,把表空间容器正确删除,然后才删库。
db2 "alter tablespace ts_ord_dat01 drop (device '/dev/rts_ord_01_1' ,device '/dev/rts_ord_01_2' ,device '/dev/rts_ord_01_3' )“ |
在虚拟机上试验db2untag
0查阅官方文档时,我留意到文档里的注意事项:使用 db2untag 时要特别小心。如果您对数据库仍在使用的容器发出 db2untag 命令,那么最初使用该容器的数据库以及现在正在使用该容器的数据库都将毁坏。于是想虚拟机上搞破坏,尝试db2untag正常容器的危害。
1查看表空间:
[db2inst1@localhost ~]$ db2pd -d sample -tab
Database Member 0 -- Database SAMPLE -- Active -- Up 0 days 00:15:10 -- Date 2017-02-28 14:41:47
Tablespace Configuration: Address Id Type Content PageSz ExtentSz Auto Prefetch BufID BufIDDisk FSC NumCntrs MaxStripe LastConsecPg Name 0x00007F784F825CC0 0 DMS Regular 8192 4 Yes 4 1 1 Off 1 0 3 SYSCATSPACE (省略无关内容) 0x00007F784F850860 5 DMS Large 8192 32 Yes 32 1 1 Off 1 0 31 IBMDB2SAMPLEXML 0x00007F784F8597A0 6 DMS Large 8192 32 Yes 32 2 2 Off 1 0 31 TS_SAMPL
Tablespace Statistics: Address Id TotalPgs UsablePgs UsedPgs PndFreePgs FreePgs HWM Max HWM State MinRecTime NQuiescers PathsDropped TrackmodState 0x00007F784F825CC0 0 16384 16380 16240 0 140 16240 16240 0x00000000 0 0 No n/a (省略无关内容) 0x00007F784F850860 5 4096 4064 1440 0 2624 1440 1440 0x00000000 0 0 No n/a 0x00007F784F8597A0 6 5000 4960 96 0 4864 96 96 0x00000000 0 0 No n/a
Tablespace Autoresize Statistics: Address Id AS AR InitSize IncSize IIP MaxSize LastResize LRF 0x00007F784F825CC0 0 Yes Yes 33554432 -1 No None None No (省略无关内容) 0x00007F784F850860 5 Yes Yes 33554432 -1 No None None No 0x00007F784F8597A0 6 No No 0 0 No 0 None No
Tablespace Storage Statistics: Address Id DataTag Rebalance SGID SourceSGID 0x00007F784F825CC0 0 0 No 0 - (省略无关内容) 0x00007F784F850860 5 -1 No 0 - 0x00007F784F8597A0 6 0 No - -
Containers: Address TspId ContainNum Type TotalPgs UseablePgs PathID StripeSet Container 0x00007F784CFFE480 0 0 File 16384 16380 0 0 /home/db2inst1/db2inst1/NODE0000/SAMPLE/T0000000/C0000000.CAT (省略无关内容) 0x00007F784F859560 5 0 File 4096 4064 0 0 /home/db2inst1/db2inst1/NODE0000/SAMPLE/T0000005/C0000000.LRG 0x00007F784F8624A0 6 0 File 5000 4960 - 0 /home/db2inst1/ts_sampl/sampl_container
|
DB2中,每个表空间可以有多个容器,容器可以是文件、路径、裸设备,一个容器只能属于一个表空间。
2对正常容器执行db2untag
这里对ID为5的容器“下手”:
[db2inst1@localhost ~]$ db2untag -f /home/db2inst1/db2inst1/NODE0000/SAMPLE/T0000005/C0000000.LRG
db2untag: A service tool to remove the DB2 tag on a tablespace container.
The tag is used to prevent DB2 from reusing a container in more than one tablespace. If a tablespace/database is destroyed thru unnatural means, then the tag can be left behind preventing future DB2 use of the resource.
WARNING: This tool should only be used by informed sysadmins.
User will not be prompted. Using file </home/db2inst1/db2inst1/NODE0000/SAMPLE/T0000005/C0000000.LRG>
version = 214 db seed = 0 tbspSeed = 5 contID = 0 created = 1 used = 1 poolLSN = 000000000003C62E CSum = 276C6861
Instance = db2inst1 Database = SAMPLE
Container tag has been removed successfully. |
3去掉正常容器的标记后,查看表空间状态:
[db2inst1@localhost ~]$ db2 list tablespaces show detail |grep -i stat State = 0x0000 State = 0x0000 State = 0x0000 State = 0x0000 State = 0x0000 State = 0x4000 [db2inst1@localhost ~]$ db2tbst 4000 State = Offline and not accessible [db2inst1@localhost ~]$ db2 list tablespaces show detail
Tablespaces for Current Database Tablespace ID = 5 Name = IBMDB2SAMPLEXML Type = Database managed space Contents = All permanent data. Large table space. State = 0x4000 Detailed explanation: Offline |
该表空间处于Offline状态:如果表空间的一个或多个容器存在问题,比如被重命名、移动、修改或者损坏时,表空间就处于该状态。当修复容器后,可以重启数据库来消除该异常状态。或者执行ALTER TABLESPACE ... SWITCH ONLINE来消除该状态。
4尝试使其处于online状态,但是没有成功,无法进入该表空间:
[db2inst1@localhost ~]$ db2 "alter tablespace IBMDB2SAMPLEXML switch online" DB21034E The command was processed as an SQL statement because it was not a valid Command Line Processor command. During SQL processing it returned: SQL0293N Error accessing a table space container. SQLSTATE=57048 |
5由于无法进入该表空间,所以也无法访问该表空间上的表:
[db2inst1@localhost ~]$ db2 "select * from product"
PID NAME PRICE PROMOPRICE PROMOSTART PROMOEND DESCRIPTION ---------- ------ -------- -------------- ---------- ---------- -------------- SQL0290N Table space access is not allowed. SQLSTATE=55 |
6对于不在该表空间上的表可以正常访问:
[db2inst1@localhost ~]$ db2 "select * from employee fetch first 5 rows only"
EMPNO FIRSTNME MIDINIT LASTNAME WORKDEPT PHONENO HIREDATE JOB EDLEVEL SEX BIRTHDATE SALARY BONUS COMM ------ ------------ ------- --------------- -------- ------- ---------- -------- ------- --- ---------- ----------- ----------- ----------- 000010 CHRISTINE I HAAS A00 3978 1995-01-01 PRES 18 F 1963-08-24 152750.00 1000.00 4220.00 000020 MICHAEL L THOMPSON B01 3476 2003-10-10 MANAGER 18 M 1978-02-02 94250.00 800.00 3300.00 000030 SALLY A KWAN C01 4738 2005-04-05 MANAGER 20 F 1971-05-11 98250.00 800.00 3060.00 000050 JOHN B GEYER E01 6789 1979-08-17 MANAGER 16 M 1955-09-15 80175.00 800.00 3214.00 000060 IRVING F STERN D11 6423 2003-09-14 MANAGER 16 M 1975-07-07 72250.00 500.00 2580.00
5 record(s) selected. |
试验过后,加深了官方文档中关于db2untag危害的理解。使用 db2untag 时要特别小心。如果您对数据库仍在使用的容器发出 db2untag 命令,那么最初使用该容器的数据库以及现在正在使用该容器的数据库都将毁坏。
同时这次试验又留下了一个问题:如何恢复被误取消标记表空间容器?暂时没有找到办法,这个问题需要继续深入研究。