همانطور که می دانید، در هر asm disk علاوه بر داده های بانک اطلاعاتی، نوع دیگری از داده هم ذخیره می شود که فراداده مربوط به ان دیسک می باشد و این نوع از داده ها معمولا در قسمت ابتدایی دیسک و به عبارتی در بلاک صفر ذخیره می شوند و کپی ای از ان هم در بلاک 510 برای مسائل امنیتی ذخیره می شود(2088960 bytes / 4096 = 510) البته قسمتی از فراداده داده ذخیره شده در این بلاکها، مربوط به خود دیسک نمی باشد بلکه اطلاعاتی در مورد دیسک گروهی هست که دیسک عضو ان می باشد.
این بلاکها همانند انواع دیگر بلاکها، امکان خرابی دارند و در صورت لزوم باید خرابی ایجاد شده را شناسایی و برطرف کرد و یا در صورتی که این خرابی قابل رفع نباشد، داده های مربوط به بانک اطلاعاتی را از این محیط به محیط بیرون انتقال داد. برای مشاهده اطلاعات دقیق این بلاکها و نیز مدیریت انها در صورتی خرابی، دستوراتی وجود دارد که در این نوشتار به انها خواهیم پرداخت.
دستور AMDU
با کمک این دستور می توان از فایلهای موجود در asm disk دامپ تهیه کرد و یا به عبارتی دیگر، می توان محتویات موجود در دیسک را استخراج نمود. این ابزار از نسخه 11g عرضه شد هر چند برای اوراکل 10g هم می توان ان را بعد از دانلود، نصب نمود. حتی در زمانی که دیسک گروه در حالت dismount قرار دارد می توان از این ابزار استفاده کرد. عمده کاربرد این ابزار به زمانی بر می گردد که به هر دلیلی امکان mount کردن دیسک گروه برای ما وجود ندارد و در عین حال قصد داریم قسمتی از اطلاعات این دیسک گروه را به محیط سیستم عامل منتقل کنیم در این صورت می توانیم با کمک ابزار AMDU، فایلهای مورد نظر را استخراج کنیم. ساختار این دستور برای استخراج فایل، در زیر امده است:
amdu -diskstring ‘<your_path_to_ASM_disks’ -dump ‘<diskgroup>’
زمانی که از این ابزار استفاده می شود، پوشه ای در مسیر جاری با فرمت زیر ساخته می شود:
amdu_YYYY_MM_DD_HH24_MM_SS
در ادامه با چند مثال، تعدادی از کاربردهای ابزار AMDU را نشان خواهیم داد.
مثال 1: استخراج فایل از دیسک گروه به محیط سیستم عامل
در ادامه قصد داریم فایل شماره 257(که یک دیتافایل می باشد) را از دیسک گروه us_group1 که در حالت dismount قرار دارد، استخراج کنیم. برای انجام این تست، ابتدا جدولی را در این دیسک گروه ایجاد کرده و بعد از انجام تست، وجود جدول را مورد بررسی قرار می دهیم.
SQL> create tablespace usef_tbs2 datafile ‘+US_GROUP1’ size 100m;
Tablespace created.
SQL> create table tbl2 tablespace usef_tbs2 as select * from dba_tables;
Table created.
SQL> select count(*) from tbl2;
COUNT(*)
———-
2344
SQL> select name from v$datafile;
NAME
——————————————————————————–
+DATA01/USEFDB/DATAFILE/system.258.958753679
+US_GROUP1/USEFDB/DATAFILE/usef_tbs2.257.958994487
+DATA01/USEFDB/DATAFILE/sysaux.257.958753635
+DATA01/USEFDB/DATAFILE/undotbs1.260.958753737
+US_GROUP1/USEFDB/DATAFILE/usef_tbs1.256.958839057
+DATA01/USEFDB/DATAFILE/users.259.958753735
برای انجام این سناریو، در ادامه دیسک را در حالت dismount قرار می دهیم:
SQL> alter diskgroup us_group1 dismount force;
Diskgroup altered.
با پرس و جو از جدول tbl2، به خطا برخواهیم خورد:
SQL>select count(*) from tbl2;
ORA-01115: IO error reading block from file (block # )
ORA-01110: data file 2: ‘+US_GROUP1/USEFDB/DATAFILE/usef_tbs2.257.958994487’
ORA-15078: ASM diskgroup was forcibly dismounted
در همین حال، قصد داریم با کمک ابزار amdu، دیتافایل مورد نظر را به محیط سیستم عامل و در مسیر /grid بازیابی کنیم :
[grid@hkm4 ~]$ cd /grid/
[grid@hkm4 grid]$ amdu -diskstring ‘/dev/oracleasm/disks/DATA1’ -extract US_GROUP1.257
amdu_2017_11_02_11_35_30/
[grid@hkm4 grid]$ cd amdu_2017_11_02_11_35_30
[grid@hkm4 amdu_2017_11_02_11_35_30]$ ll
-rw-r–r– 1 grid oinstall 3803 Nov 2 11:35 report.txt
-rw-r–r– 1 grid oinstall 104865792 Nov 2 11:35 US_GROUP1_257.f
[grid@hkm4 amdu_2017_11_02_11_35_30]$ pwd
/grid/amdu_2017_11_02_11_35_30
همانطور که در خروجی دیدیم، فایل شماره 257 به نام US_GROUP1_257.f در مسیر /grid/amdu_2017_11_02_11_35_30 استخراج شده است.
در نهایت مسیر این دیتافایل را به مسیر جدید تغییر داده و بانک را در حالت open قرار می دهیم:
chown -R oracle.oinstall /grid/amdu_2017_11_02_11_35_30/US_GROUP1_257.f
SQL> alter database rename file ‘+US_GROUP1/USEFDB/DATAFILE/usef_tbs2.257.958994487’ to ‘/grid/amdu_2017_11_02_11_35_30/US_GROUP1_257.f’;
Database altered.
SQL> alter database open;
Database altered.
SQL> select count(*) from tbl2;
COUNT(*)
———-
2344
نکته: در صورتی که دیسک گروه بیش از یک دیسک در خود داشته باشد، شکل دستور amdu کمی متفاوت خواهد بود و در این صورت باید همه دیسکها را به دستور معرفی کرد:
amdu -diskstring ‘/dev/oracleasm/disks/DATA1′ -diskstring ‘/dev/oracleasm/disks/DATA2′ -extract US_GROUP1.257
مثال 2: استخراج فایل از دیسک گروه حذف شده
در صورتی که به اشتباه دیسک گروهی را حذف کرده باشیم، با کمک ابزار amdu می توانیم دیتافایلهای ان را بازیابی کنیم:
SQL> alter diskgroup us_group1 dismount force;
Diskgroup altered.
SQL> DROP DISKGROUP us_group1 FORCE INCLUDING CONTENTS ;
Diskgroup dropped.
amdu -diskstring ‘/dev/oracleasm/disks/DATA1’ -diskstring ‘/dev/oracleasm/disks/DATA2’ -former -extract US_GROUP1.256
با دستور بالا، فایل شماره 256 از یک دیسک گروه حذف شده!!! استخراج و در مسیر جاری قرار می گیرد.
دستور amdu_extract
علاوه بر دستور amdu، می توان از دستورamdu_extract هم برای استخراج فایل از یک دیسک گروه استفاده کرد که ساختار ان به شکل زیر می باشد:
amdu_extract diskgroup file_name disk_string
مثال: برای اینکه دیتافایل در مسیر /grid استخراج شود، ابتدا مسیر جاری را به /grid تغییر می دهیم:
[grid@hkm4 ~]$ cd /grid
بعد از ورود به asmcmd، برای دیتاقایل مورد نظر نام مستعاری تعریف می کنیم:
[grid@hkm4 grid]$ asmcmd -p
ASMCMD [+] > cd +JADID/USEFDB/DATAFILE/
ASMCMD [+JADID/USEFDB/DATAFILE] > ls
USEF_TBS4.256.959167027
ASMCMD [+JADID/USEFDB/DATAFILE] > mkalias USEF_TBS4.256.959167027 file256
در نهایت با دستور زیر، این دیتافایل را به زیر پوشه /grid انتقال می دهیم:
ASMCMD [+JADID/USEFDB/DATAFILE] > amdu_extract JADID file256 /dev/oracleasm/disks/*
amdu_2017_11_04_11_20_02/
دیتافایل مورد نظر، به مسیر زیر منتقل شده است:
/grid/amdu_2017_11_04_11_20_02/JADID_256.f
دستور kfed
با کمک این ابزار می توان فراداده asm diskای را خواند و یا اصلاح کرد حتی در زمانی که دیسک در حالت dismount باشد و یا امکان مونت شدن نداشته باشد! پس در زمان خرابی هدر دیسک، این دستور می تواند پرکاربرد باشد.
عملیاتهای مختلفی با کمک ابزار KFED قابل انجام می باشد که در این نوشتار، به پرکاربردترین انها که read، write و repair می باشند، خواهیم پرداخت.
دستور زیر مثالی از نحوه خواندن(read) هدر asm disk می باشد که تنها قسمتی از خروجی در ادامه ان دیده می شود:
kfed read /dev/oracleasm/disks/DATA1
kfdhdb.driver.provstr: ORCLDISKDATA1 ; 0x000: length=13
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname: US_GROUP1_0000 ; 0x028: length=14
kfdhdb.grpname: US_GROUP1 ; 0x048: length=9
kfdhdb.fgname: US_GROUP1_0000 ; 0x068: length=14
kfdhdb.secsize: 512 ; 0x0b8: 0x0200
kfdhdb.blksize: 4096 ; 0x0ba: 0x1000
kfdhdb.ausize: 1048576 ; 0x0bc: 0x00100000
همانطور که می بینید، خروجی این دستور اطلاعاتی را در مورد وضیعت دیسک(KFDHDR_MEMBER)، نام گروه(US_GROUP1)، اندازه هر بلاک(4096) و … را ارائه می دهد.
در ادامه با چند مثال، نمونه هایی از کاربردهای ابزار KFED را نشان خواهیم داد.
مثال 1: تعمیر هدر asm disk با کمک KFED
همانطور که دستور زیر نشان می دهد، دو دیسک گروه به حالت مونت در بانک جاری وجود دارند:
SQL> select group_number, name, state, type from v$asm_diskgroup;
GROUP_NUMBER NAME STATE TYPE
———— —————————— ———– ——
1 DATA01 CONNECTED EXTERN
2 US_GROUP1 MOUNTED EXTERN
در سناریوی زیر، ابتدا جدولی به دیسک گروه US_GROUP1 اضافه می کنیم و سپس با مخدوش کردن هدر تنها دیسک این دیسک گروه، نشان خواهیم داد که به چه شکلی دستور kfed می تواند این خرابی را اصلاح کند.
SQL> create tablespace usef_tbs1 datafile ‘+US_GROUP1’ size 100m;
Tablespace created.
SQL> create table tbl1 tablespace usef_tbs1 as select * from v$datafile;
Table created.
SQL> select name from v$datafile;
NAME
——————————————————————————–
+DATA01/USEFDB/DATAFILE/system.258.958753679
+DATA01/USEFDB/DATAFILE/sysaux.257.958753635
+DATA01/USEFDB/DATAFILE/undotbs1.260.958753737
+US_GROUP1/USEFDB/DATAFILE/usef_tbs1.256.958839057
+DATA01/USEFDB/DATAFILE/users.259.958753735
دستور زیر، هدر دیسک مربوط به این دیسک گروه را مخدوش می کند:
dd if=/dev/zero of=/dev/oracleasm/disks/DATA1 bs=4096 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000410305 s, 10.0 MB/s
با اولین راه اندازی مجدد asm instance، خواهیم دید که امکان مونت مجدد این فضا وجود ندارد:
SQL> startup force;
ASM instance started
Total System Global Area 1140850688 bytes
Fixed Size 2933400 bytes
Variable Size 1112751464 bytes
ASM Cache 25165824 bytes
ORA-15032: not all alterations performed
ORA-15017: diskgroup “US_GROUP1” cannot be mounted
ORA-15040: diskgroup is incomplete
ORA-15017: diskgroup “DATA01” cannot be mounted
ORA-15013: diskgroup “DATA01” is already mounted
همانطور که می بینید، دیسک گروه US_GROUP1 نمی تواند مونت شود که در این حالت می توان با کمک ابزار kfed، هدر دیسک مورد نظر را اصلاح کرده و دیسک گروه را به حالت مونت دراورد قبل از ان محتویات هدر را بازبینی خواهیم کرد:
[grid@hkm4 ~]$ kfed read /dev/oracleasm/disks/DATA1
kfbh.endian: 0 ; 0x000: 0x00
kfbh.hard: 0 ; 0x001: 0x00
kfbh.type: 0 ; 0x002: KFBTYP_INVALID
kfbh.datfmt: 0 ; 0x003: 0x00
kfbh.block.blk: 0 ; 0x004: blk=0
kfbh.block.obj: 0 ; 0x008: file=0
kfbh.check: 0 ; 0x00c: 0x00000000
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
kfbh.spare1: 0 ; 0x018: 0x00000000
kfbh.spare2: 0 ; 0x01c: 0x00000000
000000000 00000000 00000000 00000000 00000000 […………….]
Repeat 255 times
KFED-00322: Invalid content encountered during block traversal: [kfbtTraverseBlock][Invalid OSM block type][][0]
[grid@hkm4 ~]$ kfed repair /dev/oracleasm/disks/DATA1
SQL> alter diskgroup US_GROUP1 mount;
Diskgroup altered.
حال با بررسی جدول tbl1، خواهیم یافت که این جدول هم به صورت کامل سالم مانده است:
SQL> select count(*) from tbl1;
COUNT(*)
———-
5
نکته 1: اصلاح هدر دیسک با کمک بلاک شماره 510 موجود در دیسک صورت می پذیرد همانطور که قبلا اورده شد، این بلاک، کپی ای از بلاک شماره صفر می باشد. پس در صورت خرابی بلاک شماره 510، این امکان از بین خواهد رفت(امکان اصلاح از طریق repair). برای مقایسه و مشاهده هر دو بلاک، تنها کافیست از دو دستور زیر استفاده شود که خروجی هر دو دستور یکسان می باشد:
kfed read /dev/oracleasm/disks/DATA1 BLKNUM=510
kfed read /dev/oracleasm/disks/DATA1 BLKNUM=0
نکته 2: امکان بکاپ گیری از بلاکهای شماره 510 و 0 وجود دارد که در صورت خرابی هر دو بلاک، با کمک بکاپ، اصلاح قابل انجام می باشد:
kfed read /dev/oracleasm/disks/DATA1 BLKNUM=510 text=/home/grid/backup510
همچنین برای اصلاح می توان با استفاده از عملیات write، از این بکاپ استفاده کرده و عملیات اصلاح را انجام داد:
dd if=/dev/zero of=/dev/oracleasm/disks/DATA1 bs=4096 count=1
kfed write /dev/oracleasm/disks/DATA1 BLKNUM=0 text=/home/grid/backup510
مثال 2: جستجوی spfile با کمک KFED
برای بازیابی spfile از یک دیسک در حالت dismount هم می توانیم از دستور kfed استفاده کنیم. مثال زیر را ببینید.
ابتدا باید تعیین نمود که کدام یک از دیسکها، spfileای در درون خود دارند:
ll /dev/oracleasm/disks/
brw-rw—- 1 grid oinstall 8, 5 Oct 31 15:05 DATA
brw-rw—- 1 grid oinstall 8, 6 Oct 31 12:56 DATA1
kfed read /dev/oracleasm/disks/DATA1 | grep -E ‘spf|ausize’
kfdhdb.ausize: 1048576 ; 0x0bc: 0x00100000
kfdhdb.spfile: 0 ; 0x0f4: 0x00000000
kfdhdb.spfflg: 0 ; 0x0f8: 0x00000000
kfed read /dev/oracleasm/disks/DATA | grep -E ‘spf|ausize’
kfdhdb.ausize: 1048576 ; 0x0bc: 0x00100000
kfdhdb.spfile: 59 ; 0x0f4: 0x0000003b
kfdhdb.spfflg: 1 ; 0x0f8: 0x00000001
همانطور که می بینید، spfile در افست 59 از دیسک /dev/oracleasm/disks/DATA قرار دارد که می توان با یک دامپ، محتوای ان را استخراج نمود:
dd if=/dev/oracleasm/disks/DATA of=spfile.ora skip=59 bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.0359577 s, 29.2 MB/s
حال با کمک دستور strings که محتوای فایل باینری را تا حد امکان به صورت خوانا نشان می دهد، پارامترهای موجود در spfile را مشخص خواهیم کرد:
strings -7 spfile.ora
+ASM.__oracle_base=’/grid’#ORACLE_BASE set from in memory value
+ASM.asm_diskgroups=”#Manual Dismount
*.asm_diskstring=’/dev/oracleasm/disks/*’
*.asm_power_limit=1
*.large_pool_size=12M
*.remote_login_passwordfile=’EXCLUSIVE’
نکته: چنین روشی بیشتر در زمانی کاربرد دارد که فضا را از سروری به سرور دیگر منتقل کرده باشیم و یا اینکه سیستم عامل تغییر کرده باشد که در این صورت ممکن است دانستن محل ذخیره سازی vote و یا spfile، مفید باشد.
نکته: دستور زیر ادرس فایل vote را نشان می دهد:
kfed read /dev/oracleasm/disks/DATA1 | grep vf
kfdhdb.vfstart: 72 ; 0x0ec: 0x00000048
kfdhdb.vfend: 80 ; 0x0f0: 0x00000050
مثال 3: برگرداندن دیسک گروه حذف شده با کمک KFED
در صورتی که دیسکی از یک دیسک گروه حذف شده باشد و یا این اتفاق در مورد دیسک گروهی رخ داده باشد، می توان با ابزار KFED، این دیسک گروه را مجددا به حالت قبل برگرداند.
مثال:برای انجام این سناریو، ابتدا دیسک گروهی را حذف می کنیم:
SQL> alter diskgroup us_group1 dismount force;
Diskgroup altered.
SQL> DROP DISKGROUP us_group1 FORCE INCLUDING CONTENTS ;
Diskgroup dropped.
سپس با ابزار KFED از هدر دیسک مربوط به این دیسک گروه، دامپی تهیه می کنیم:
[grid@hkm4 ~]$ kfed read /dev/oracleasm/disks/DATA1 aunum=0 blknum=0 text=header.txt
در نهایت کافیست به فایل متنی مربوط به هدر دیسک که از دستور قبلی ایجاد شده، رجوع کرده و عبارت
kfdhdb.hdrsts: 4 ; 0x027: KFDHDR_FORMER
را به عبارت
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
تبدیل کرد:
[grid@hkm4 ~]$ vi header.txt
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
و برای اعمال این فایل متنی به هدر دیسک، از دستور زیر استفاده می شود:
kfed write /dev/oracleasm/disks/DATA1 aunum=0 blknum=0 text=header.txt
SQL> alter diskgroup us_group1 mount;
Diskgroup altered.
با این روش، دیسک گروه حذف شده، دوباره قابل استفاده می باشد بدون انکه داده ای را از دست داده باشیم.
مثال 4: تغییر نام دیسک گروه
همانطور که می دانید با استفاده از دستورات رایج اوراکل، تغییر نام دیسک گروه به سادگی قابل انجام می باشد برای مثال می توان با کمک دستور renamedg، دیسک گروه us_group1 را به us_ggg تغییر نام داد:
renamedg dgname=us_group1 newdgname=us_ggg asm_diskstring=’/dev/oracleasm/disks/*’ verbose=true
حال در صورتی که بخواهیم همین کار با کمک ابزار KFED صورت پذیرد باید مراحل زیر طی شود.
ابتدا دیسک گروه را در حالت dismount قرار می دهیم:
SQL> alter diskgroup US_GGG dismount force;
Diskgroup altered.
سپس اطلاعات هدر دیسک گروه را در فایل header.txt ثبت می کنیم:
kfed read /dev/oracleasm/disks/DATA1 aunum=0 blknum=0 text=header.txt
در این مرحله باید مقدار جاری grpname را به مقدار جدید تغییر داد:
kfdhdb.grpname: JADID ; 0x048: length=5
سپس اطلاعات جدید را در هدر بازنویسی می کنیم:
kfed write /dev/oracleasm/disks/DATA1 aunum=0 blknum=0 text=header.txt
و در نهایت دیسک گروه را مونت می کنیم:
SQL> alter diskgroup jadid mount;
Diskgroup altered.
همچنین در صورتی که دیتافایلی در این مسیر موجود باشد، باید ان را تغییر نام داد:
SQL> alter database rename file ‘+US_GGG/USEFDB/DATAFILE/usef_tbs3.256.959005031’ to ‘+JADID/USEFDB/DATAFILE/usef_tbs3.256.959005031’;
دستور kfod
برای مشاهده لیست asm diskها در لایه OS، می توان از دستور kfod استفاده کرد. به مثال زیر توجه کنید:
مثال 1: نمایش لیست همه دیسکهای عضو و یا کاندید:
kfod disks=all
——————————————————————————–
Disk Size Path User Group
================================================================================
1: 10242 Mb /dev/oracleasm/disks/DATA grid oinstall
2: 10244 Mb /dev/oracleasm/disks/DATA1 grid oinstall
3: 20489 Mb /dev/oracleasm/disks/DATA2 grid oinstall
——————————————————————————–
ORACLE_SID ORACLE_HOME
================================================================================
+ASM /grid/12c
مثال 2:هر کدام از دیسکها عضو چه دیسک گروهی هستند؟
kfod ds=true disks=all
——————————————————————————–
Disk Size Path Disk Group User Group
================================================================================
1: 10242 Mb /dev/oracleasm/disks/DATA DATA01 grid oinstall
2: 10244 Mb /dev/oracleasm/disks/DATA1 US_GROUP1 grid oinstall
3: 20489 Mb /dev/oracleasm/disks/DATA2 # grid oinstall
——————————————————————————–
ORACLE_SID ORACLE_HOME
================================================================================
+ASM /grid/12c
مثال 3: نمایش حجم هر کدام از دیسک گروه ها:
kfod op=groups
——————————————————————————–
Group Size Free Redundancy Name
================================================================================
1: 10244 Mb 10082 Mb EXTERN US_GROUP1
2: 10242 Mb 8150 Mb EXTERN DATA01
مثال 4: هر کدام از دیسکها در چه حالتی قرار دارند؟
kfod status=true asm_diskstring=’/dev/oracleasm/disks/*’ disks=all dscvgroup=true
——————————————————————————–
Disk Size Header Path Disk Group User Group
================================================================================
1: 10242 Mb MEMBER /dev/oracleasm/disks/DATA DATA01 grid oinstall
2: 10244 Mb MEMBER /dev/oracleasm/disks/DATA1 US_GROUP1 grid oinstall
3: 20489 Mb CANDIDATE /dev/oracleasm/disks/DATA2 # grid oinstall
——————————————————————————–
ORACLE_SID ORACLE_HOME
================================================================================
+ASM /grid/12c