前言:本文主要分爲兩部分。第一部分是在工作中遇到的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 命令,那麼最初使用該容器的數據庫以及現在正在使用該容器的數據庫都將毀壞。
同時這次試驗又留下了一個問題:如何恢復被誤取消標記表空間容器?暫時沒有找到辦法,這個問題需要繼續深入研究。