I was never 100% clear to me you could remove a disk from a diskgroup wtih EXTERNAL redundancy without having data loss, so let’s to a test.
We are going to do it on Oracle GI 19c, but I don’t see why it should not work on older versions. But please always try to replicate the same on a lab before doing it on a live DB.
1:- Add a new disk for the test:
[root@olinux8 ~]# asmcmd afd_label DATA2 /dev/sdc
[root@olinux8 ~]# asmcmd afd_lslbl
--------------------------------------------------------------------------------
Label Duplicate Path
================================================================================
DATA /dev/sda
DATA2 /dev/sdc <<------
FRA /dev/sdb
[root@olinux8 ~]#
[oracle@olinux8 ~]$ asmcmd lsdsk --candidate -p
Group_Num Disk_Num Incarn Mount_Stat Header_Stat Mode_Stat State Path
0 0 0 CLOSED PROVISIONED ONLINE NORMAL AFD:DATA2
[oracle@olinux8 ~]$
SQL> alter diskgroup DATA add disk 'AFD:DATA2';
Diskgroup altered.
set linesize 190
column "Diskgroup" format A20
column "Imbalance" format 99.9 Heading "Percent|Imbalance"
column "Variance" format 99.9 Heading "Percent|Disk Size|Variance"
column "MinFree" format 99.9 Heading "Minimum|Percent|Free"
column "DiskCnt" format 9999 Heading "Disk|Count"
column "Type" format A10 Heading "Diskgroup|Redundancy"
SELECT g.group_number, g.name "Diskgroup",
100*(max((d.total_mb-d.free_mb)/d.total_mb)-min((d.total_mb-d.free_mb)/d.total_mb))/max((d.total_mb-d.free_mb)/d.total_mb) "Imbalance",
100*(max(d.total_mb)-min(d.total_mb))/max(d.total_mb) "Variance",
100*(min(d.free_mb/d.total_mb)) "MinFree",
count(*) "DiskCnt",
g.type "Type"
FROM v$asm_disk d, v$asm_diskgroup g
WHERE d.group_number = g.group_number and
d.group_number <> 0 and
d.state = 'NORMAL' and
d.mount_status = 'CACHED'
GROUP BY g.group_number,g.name, g.type;
Percent Minimum
Percent Disk Size Percent Disk Diskgroup
GROUP_NUMBER Diskgroup Imbalance Variance Free Count Redundancy
------------ -------------------- --------- --------- ------- ----- ----------
1 DATA 1.0 .0 97.6 2 EXTERN
2 FRA .0 .0 96.4 1 EXTERN
SQL>
col PATH format a20
set linesize 190
col FREE_MB
set pagesize 50
select group_number, path, header_status, total_mb, free_mb from v$asm_disk order by 1,2;
GROUP_NUMBER PATH HEADER_STATU TOTAL_MB FREE_MB
------------ -------------------- ------------ ---------- ----------
1 AFD:DATA MEMBER 51200 49952
1 AFD:DATA2 MEMBER 51200 49964
2 AFD:FRA MEMBER 30720 29606
SQL>
2:- Add a new datafile to see if space from both disks are used:
SQL> alter tablespace USERS add datafile size 10G autoextend on NEXT 1073741824 maxsize 32767M;
Tablespace altered.
SQL> select group_number, path, header_status, total_mb, free_mb from v$asm_disk order by 1,2;
GROUP_NUMBER PATH HEADER_STATU TOTAL_MB FREE_MB
------------ -------------------- ------------ ---------- ----------
1 AFD:DATA MEMBER 51200 44828
1 AFD:DATA2 MEMBER 51200 44840 <--- space added across both disks
2 AFD:FRA MEMBER 30720 29606
SQL> select name,total_mb,free_mb,total_mb-free_mb used_mb, (free_mb/total_mb)*100 as "% Free space" from V$ASM_DISKGROUP;
NAME TOTAL_MB FREE_MB USED_MB % Free space
--------------- ---------- ---------- ---------- ------------
DATA 102400 89668 12732 87.5664063
FRA 30720 29606 1114 96.3736979
3:- Create a new table and populate (not needed on a real enviroment as it would be already populated)
SQL> CREATE TABLE testtable
( dept_id number(10) NOT NULL,
dept_name varchar2(50) NOT NULL) tablespace USERS; 2 3
Table created.
SQL>
BEGIN
FOR loop_counter IN 1..1000000 LOOP
INSERT INTO sys.testtable (dept_id, dept_name)
VALUES (loop_counter, 'Depart Name');
END LOOP;
COMMIT;
END;
/
SQL> select count(*) from sys.testtable;
COUNT(*)
----------
2201000
SQL> select * from sys.testtable;
DEPT_ID DEPT_NAME
---------- --------------------------------------------------
....
971316 Depart Name
971317 Depart Name
971318 Depart Name
971319 Depart Name
971320 Depart Name
971321 Depart Name
971322 Depart Name
971323 Depart Name
971324 Depart Name
971325 Depart Name
2201000 rows selected.
SQL>
4:- Check asm status before the drop:
SQL> select name,total_mb,free_mb,total_mb-free_mb used_mb, (free_mb/total_mb)*100 as "% Free space" from V$ASM_DISKGROUP;
NAME TOTAL_MB FREE_MB USED_MB % Free space
-------------------- ---------- ---------- ---------- ------------
DATA 102400 89668 12732 87.5664063
FRA 30720 28946 1774 94.2252604
SQL>
SQL> select group_number, disk_number, mode_status, header_status, state, name, path from v$asm_disk;
GROUP_NUMBER DISK_NUMBER MODE_ST HEADER_STATU STATE NAME PATH
------------ ----------- ------- ------------ -------- -------------------- --------------------
1 0 ONLINE MEMBER NORMAL DATA AFD:DATA
2 0 ONLINE MEMBER NORMAL FRA AFD:FRA
1 1 ONLINE MEMBER NORMAL DATA2 AFD:DATA2
SQL>
5:- Drop disk and monitor rebalance:
SQL> alter diskgroup DATA drop disk 'DATA2';
Diskgroup altered.
SQL>
SQL> select * from v$asm_operation;
GROUP_NUMBER OPERA PASS STAT POWER ACTUAL SOFAR EST_WORK EST_RATE EST_MINUTES ERROR_CODE CON_ID
------------ ----- --------- ---- ------ -------- ------ ---------- ---------- ----------- ---------- -------
1 REBAL COMPACT WAIT 1 1 0 0 0 0 0
1 REBAL REBALANCE RUN 1 1 906 1587 31541 0 0
1 REBAL REBUILD DONE 1 1 0 0 0 0 0 0
SQL> /
no rows selected
SQL>
6:- Check asm status post drop:
SQL> select name,total_mb,free_mb,total_mb-free_mb used_mb, (free_mb/total_mb)*100 as "% Free space" from V$ASM_DISKGROUP;
NAME TOTAL_MB FREE_MB USED_MB % Free space
-------------------- ---------- ---------- ---------- ------------
DATA 51200 38480 12720 75.15625 <<-- about the same usage
FRA 30720 28946 1774 94.2252604
SQL>
7:- Validate if you can still access DB data without errors/corruption:
SQL> select * from sys.testtable;
DEPT_ID DEPT_NAME
---------- --------------------------------------------------
....
971316 Depart Name
971317 Depart Name
971318 Depart Name
971319 Depart Name
971320 Depart Name
971321 Depart Name
971322 Depart Name
971323 Depart Name
971324 Depart Name
971325 Depart Name
2201000 rows selected.
SQL>
That’s it!
Comments