Monday, July 9, 2018

SQL Manual Advisor !!!


source
Find the SQL Id from AWR or ADDM/OEM session .

1)

DECLARE
  l_sql_tune_task_id  VARCHAR2(100);
BEGIN
  l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (
                          sql_id      => '2utumtd0rxyjs',
                          scope       => DBMS_SQLTUNE.scope_comprehensive,
                          time_limit  => 500,
                          task_name   => '2utumtd0rxyjs_tuning_task11',
                          description => 'Tuning task1 for statement 2utumtd0rxyjs');
  DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
END;
/

2)

EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => '2utumtd0rxyjs_tuning_task11');

3)

set long 65536
set longchunksize 65536
set linesize 100
select dbms_sqltune.report_tuning_task('2utumtd0rxyjs_tuning_task11') from dual;

4)

SELECT TASK_NAME, STATUS FROM DBA_ADVISOR_LOG WHERE TASK_NAME ;

5)

execute dbms_sqltune.drop_tuning_task('6rrj026359w6w_tuning_task11');




-------Example :

Last login: Thu Apr 26 16:17:29 2018 from 172.20.210.31
[root@smssvr ~]# su - oracle
[oracle@smssvr ~]$ sqlplus smsuser/smsuser

SQL*Plus: Release 11.2.0.3.0 Production on Mon Jul 9 13:45:32 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> DECLARE
  l_sql_tune_task_id  VARCHAR2(100);
BEGIN
  l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (
                          sql_id      => '2utumtd0rxyjs',
                          scope       => DBMS_SQLTUNE.scope_comprehensive,
                          time_limit  => 500,
                          task_name   => '2utumtd0rxyjs_tuning_task11',
                          description => 'Tuning task1 for statement 2utumtd0rxyjs');
  DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
END;
/  2    3    4    5    6    7    8    9   10   11   12 

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => '2utumtd0rxyjs_tuning_task11');

PL/SQL procedure successfully completed.

SQL> set long 65536
set longchunksize 65536
set linesize 100
select dbms_sqltune.report_tuning_task('2utumtd0rxyjs_tuning_task11') from dual;SQL> SQL> SQL>

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : 2utumtd0rxyjs_tuning_task11
Tuning Task Owner  : SMSUSER
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 500
Completion Status  : COMPLETED
Started at         : 07/09/2018 13:46:41
Completed at       : 07/09/2018 13:46:41


DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Schema Name: SMSUSER
SQL ID     : 2utumtd0rxyjs
SQL Text   : select * from (select * from PBL_SMS_MSG where MSG_SENT_FLAG='0'
             and MOD(SMS_ID,5)= 2 order by SMS_ID asc)  temp_tbl WHERE rownum
             <= 50 ORDER BY rownum

-------------------------------------------------------------------------------
FINDINGS SECTION (2 findings)
-------------------------------------------------------------------------------


DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  A potentially better execution plan was found for this statement.

  Recommendation (estimated benefit: 96.51%)
  ------------------------------------------
  - Consider accepting the recommended SQL profile to use parallel execution
    for this statement.
    execute dbms_sqltune.accept_sql_profile(task_name =>
            '2utumtd0rxyjs_tuning_task11', task_owner => 'SMSUSER', replace
            => TRUE, profile_type => DBMS_SQLTUNE.PX_PROFILE);

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------

  Executing this query parallel with DOP 32 will improve its response time
  96.51% over the original plan. However, there is some cost in enabling
  parallel execution. It will increase the statement's resource consumption by
  an estimated 11.55% which may result in a reduction of system throughput.
  Also, because these resources are consumed over a much smaller duration, the
  response time of concurrent statements might be negatively impacted if
  sufficient hardware capacity is not available.

  The following data shows some sampled statistics for this SQL from the past
  week and projected weekly values when parallel execution is enabled.

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------

                                 Past week sampled statistics for this SQL
                                 -----------------------------------------
  Number of executions                                                   0
  Percent of total activity                                              0
  Percent of samples with #Active Sessions > 2*CPU                       0
  Weekly DB time (in sec)                                                0

                              Projected statistics with Parallel Execution
                              --------------------------------------------
  Weekly DB time (in sec)                                                0

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------

2- Index Finding (see explain plans section below)
--------------------------------------------------
  The execution plan of this statement can be improved by creating one or more
  indices.

  Recommendation (estimated benefit: 96.53%)
  ------------------------------------------
  - Consider running the Access Advisor to improve the physical schema design
    or creating the recommended index.
    create index SMSUSER.IDX$$_0D3B0001 on SMSUSER.PBL_SMS_MSG("SMS_ID");

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------

  Rationale
  ---------
    Creating the recommended indices significantly improves the execution plan
    of this statement. However, it might be preferable to run "Access Advisor"
    using a representative SQL workload as opposed to a single statement. This
    will allow to get comprehensive index recommendations which takes into
    account index maintenance overhead and additional space consumption.

-------------------------------------------------------------------------------
ADDITIONAL INFORMATION SECTION

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------
- The optimizer could not merge the view at line ID 3 of the execution plan.
  The optimizer cannot merge a view that contains an "ORDER BY" clause unless
  the statement is a "DELETE" or an "UPDATE" and the parent query is the top
  most query in the statement.

-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------

1- Original

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
-----------
Plan hash value: 1665088640

----------------------------------------------------------------------------------------
| Id  | Operation                | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |             |    50 | 20750 | 11890   (1)| 00:02:23 |
|   1 |  SORT ORDER BY           |             |    50 | 20750 | 11890   (1)| 00:02:23 |
|*  2 |   COUNT STOPKEY          |             |       |       |            |          |
|   3 |    VIEW                  |             |   236 | 97940 | 11889   (1)| 00:02:23 |
|*  4 |     SORT ORDER BY STOPKEY|             |   236 | 54516 | 11889   (1)| 00:02:23 |

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
|*  5 |      TABLE ACCESS FULL   | PBL_SMS_MSG |   236 | 54516 | 11888   (1)| 00:02:23 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(ROWNUM<=50)
   4 - filter(ROWNUM<=50)
   5 - filter("MSG_SENT_FLAG"=0 AND MOD("SMS_ID",5)=2)

2- Using New Indices

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
--------------------
Plan hash value: 1607373448

-------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                |    50 | 20750 |   412   (1)| 00:00:05 |
|   1 |  SORT ORDER BY                 |                |    50 | 20750 |   412   (1)| 00:00:05 |
|*  2 |   COUNT STOPKEY                |                |       |       |            |          |
|   3 |    VIEW                        |                |    51 | 21165 |   411   (1)| 00:00:05 |
|*  4 |     TABLE ACCESS BY INDEX ROWID| PBL_SMS_MSG    |  4711 |  1062K|   411   (1)| 00:00:05 |

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
|*  5 |      INDEX FULL SCAN           | IDX$$_0D3B0001 |  2882 |       |    38   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(ROWNUM<=50)
   4 - filter("MSG_SENT_FLAG"=0)
   5 - filter(MOD("SMS_ID",5)=2)

3- Using Parallel Execution

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
---------------------------
Plan hash value: 1687965353

----------------------------------------------------------------------------------------------------
----------------------
| Id  | Operation                     | Name        | Rows  | Bytes | Cost (%CPU)| Time     |    TQ
 |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------
----------------------
|   0 | SELECT STATEMENT              |             |    50 | 20750 |   414   (1)| 00:00:05 |
 |      |            |

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
|   1 |  SORT ORDER BY                |             |    50 | 20750 |   414   (1)| 00:00:05 |
 |      |            |
|*  2 |   COUNT STOPKEY               |             |       |       |            |          |
 |      |            |
|   3 |    PX COORDINATOR             |             |       |       |            |          |
 |      |            |
|   4 |     PX SEND QC (ORDER)        | :TQ10001    |   236 | 97940 |   413   (1)| 00:00:05 |  Q1,01
 | P->S | QC (ORDER) |
|   5 |      VIEW                     |             |   236 | 97940 |   413   (1)| 00:00:05 |  Q1,01
 | PCWP |            |
|*  6 |       SORT ORDER BY STOPKEY   |             |   236 | 54516 |   413   (1)| 00:00:05 |  Q1,01

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
 | PCWP |            |
|   7 |        PX RECEIVE             |             |    50 | 20750 |   414   (1)| 00:00:05 |  Q1,01
 | PCWP |            |
|   8 |         PX SEND RANGE         | :TQ10000    |    50 | 20750 |   414   (1)| 00:00:05 |  Q1,00
 | P->P | RANGE      |
|*  9 |          SORT ORDER BY STOPKEY|             |    50 | 20750 |   414   (1)| 00:00:05 |  Q1,00
 | PCWP |            |
|  10 |           PX BLOCK ITERATOR   |             |   236 | 54516 |   412   (0)| 00:00:05 |  Q1,00
 | PCWC |            |
|* 11 |            TABLE ACCESS FULL  | PBL_SMS_MSG |   236 | 54516 |   412   (0)| 00:00:05 |  Q1,00
 | PCWP |            |

DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
----------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(ROWNUM<=50)
   6 - filter(ROWNUM<=50)
   9 - filter(ROWNUM<=50)
  11 - filter("MSG_SENT_FLAG"=0 AND MOD("SMS_ID",5)=2)


DBMS_SQLTUNE.REPORT_TUNING_TASK('2UTUMTD0RXYJS_TUNING_TASK11')
----------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------

Monday, July 2, 2018

pre_page_sga parameter !!


Question:  Can you please explain the pre_page_sga parameter? How does pre_page_sga work with RAC?

Answer: At instance startup time, Oracle only allocates SGA RAM when needed, but you can avoid this by setting pre_page_sga=true.  With pre_page_sga=true, Oracle will pre-allocate all of the the SGA RAM at startup time.  This will increase the time required to start the database instance, but it will ensure that the RAM is immediately available for the SGA at run-time.

Sunday, July 1, 2018

Huge Page Configuration in Oracle !



Supporting Doc :

Actual memory , which is used by system runtime :
# grep PageTables /proc/meminfo
PageTables:      1244880 kB
Default Settings :
$ grep Huge /proc/meminfo
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB










hugePage Script to find out the recommended settings :
#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk {'print $2'}`
# Start from 1 pages to be on the safe side and guarantee 1 free HugePage
NUM_PG=1
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"`
do
   MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
   if [ $MIN_PG -gt 0 ]; then
      NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
   fi
done
# Finish with results
case $KERN in
   '2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
          echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
   '2.6' | '3.8' | '3.10' | '4.1' ) echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    *) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End


Recommended setting for number of HugePages :
$ ./hugepages_setting.sh 
Recommended setting: vm.nr_hugepages = 305
$

1)      Set this value to /etc/sysctl.conf :
vm.nr_hugepages=306
sysctl –p

     2) Add the following entries into the "/etc/security/limits.conf" script or "/etc/security/limits.d/99-grid-oracle-limits.conf" script, where the setting is at least the size of the HugePages allocation in KB (HugePages * Hugepagesize). In this case the value is 306*2048=626688.
* soft memlock 626688
* hard memlock 626688

Check the MEMORY_TARGET parameters are not set for the database and SGA_TARGET and PGA_AGGREGATE_TARGET parameters are being used instead.

3)Restart the server and restart the database services as required. Check the HugePages information again.
 $ grep Huge /proc/meminfo
AnonHugePages:         0 kB
HugePages_Total:     306
HugePages_Free:       98
HugePages_Rsvd:       93
HugePages_Surp:        0
Hugepagesize:       2048 kB
$

Force Oracle to use HugePages (USE_LARGE_PAGES)

Sizing the number of HugePages correctly is important because prior to 11.2.0.3, if the whole SGA doesn't fit into the available HugePages, the instance will start up without using any. From 11.2.0.3 onward, the SGA can run partly in HugePages and partly not, so the impact of this issue is not so great. Incorrect sizing may not be obvious to spot. Later releases of the database display a "Large Pages Information" section in the alert log during startup.
****************** Large Pages Information *****************
 
Total Shared Global Region in Large Pages = 602 MB (100%)
 
Large Pages used by this instance: 301 (602 MB)
Large Pages unused system wide = 5 (10 MB) (alloc incr 4096 KB)
Large Pages configured system wide = 306 (612 MB)
Large Page size = 2048 KB
***********************************************************
If you are running Oracle 11.2.0.2 or later, you can set the USE_LARGE_PAGES initialization parameter to "only" so the database fails to start if it is not backed by hugepages. You can read more about this here.
ALTER SYSTEM SET use_large_pages=only SCOPE=SPFILE;
SHUTDOWN IMMEDIATE;
STARTUP;
On startup the "Large Page Information" in the alert log reflects the use of this parameter.
****************** Large Pages Information *****************
Parameter use_large_pages = ONLY
 
Total Shared Global Region in Large Pages = 602 MB (100%)
 
Large Pages used by this instance: 301 (602 MB)
Large Pages unused system wide = 5 (10 MB) (alloc incr 4096 KB)
Large Pages configured system wide = 306 (612 MB)
Large Page size = 2048 KB
***********************************************************
Attempting to start the database when there aren't enough HugePages to hold the SGA will now return the following error.
SQL> STARTUP
ORA-27137: unable to allocate large pages to create a shared memory segment
Linux-x86_64 Error: 12: Cannot allocate memory
SQL> 
The "Large Pages Information" section of the alert log output describes the startup failure and the appropriate action to take.
****************** Large Pages Information *****************
Parameter use_large_pages = ONLY
 
Large Pages unused system wide = 0 (0 KB) (alloc incr 4096 KB)
Large Pages configured system wide = 0 (0 KB)
Large Page size = 2048 KB
 
ERROR:
  Failed to allocate shared global region with large pages, unix errno = 12.
  Aborting Instance startup.
  ORA-27137: unable to allocate Large Pages to create a shared memory segment
 
ACTION:
  Total Shared Global Region size is 608 MB. Increase the number of
  unused large pages to atleast 304 (608 MB) to allocate 100% Shared Global
  Region with Large Pages.
***********************************************************






Tuesday, April 10, 2018

Calculate ASM Disk Space : Part 02

source :
http://www.oraclenext.com/2016/10/calculating-asm-diskgroup-usable-size.html


Calculating ASM diskgroup Usable Size



Sometimes sizing information of an ASM diskgroup returned by “lsdg” command from “asmcmd” prompt (similar information is also available under v$asm_diskgroup view) leaves DBAs perplexed. Sizing information and usable space for diskgroups with EXTERNAL REDUNDANCY is quite easy to understand, but when it comes to NORMAL or HIGH redundancy diskgroups, it is not very straightforward. Here I would explain ASM diskgroup space calculation in detail to make it easier to understand. Before I explain how to calculate usable space in an ASM diskgroup, some useful information to note is as follows
  • Diskgroups with EXTERNAL REDUNDANCY don’t mirror any data at all
  • Diskgroups with NORMAL REDUNDANCY keep 2 copies of each extant (ASM extent, which is made up of one or more ASM Allocation Units) on 2 different ASM failure groups in that diskgroup.  
  • Diskgroups with HIGH REDUNDANCY keep 3 copies of each extant (ASM extent, which is made up of one or more ASM Allocation Units) on 3 different ASM failure groups in that diskgroup.  
  • By default each ASM disk is in its own FAILURE GROUP, unless disks are put in a specific failure group during diskgroup creation.
  • Disks which are prone to become unavailable together; are usually put in a single failure group. For example, if we have 2 disk controllers with each controller having 10 disks in it, all disks from each controller should be in a single failure group because in case of a controller failure, all 10 disks of that controller would become unavailable. In ASM mirroring, ASM would always keep copies of an extent on the disks in different failure groups; thus keeping a copy of data always available in case a controller failure makes all 10 disks unavailable in the failure group.
  • If we use lsdg command, or query sizing details of a diskgroup from v$asm_diskgroup we find following columns with sizing details
TOTAL_MB: Total size of a diskgroup in MB (adding up space of all disks in the diskgroup)

FREE_MB: Current free space available in the diskgroup. In case of external redundancy, full space listed under this column is available for the usage. In case of normal redundancy, divide this value by 2 to get actual amount of space that can be utilized since 2 copies of each extent have to be stored. In case of high redundancy, this value should be divided by 3 because total 3 copies of data are to be stored in this free space.

REQUIRED_MIRROR_FREE_MB: Value under this column shows the amount of space required to re-mirror or “restore redundancy” of the data in case of a worst failure that can be tolerated by this diskgroup. In case of normal redundancy, a diskgroup can tolerate loss of one failure group and in case of high redundancy; diskgroup can tolerate loss of 2 failure groups. After the loss, this much space would be required to re-mirror (or restore redundancy of) the diskgroup. After a failure, rebalance will happen and redundancy will be restored, and then value under this column would be updated to a new value to show current requirement to restore redundancy in case of a failure.

USABLE_FILE_MB: Value under this column shows the amount of space that can be used/allocated from the diskgroup. This value can be negative (as you will see in bellow examples) which would mean that there is not enough space available in the diskgroup to re-mirror (restore redundancy) after the worst failure this diskgroup can tolerate.
Here the point to note is that value under REQUIRED_MIRROR_FREE_MB does not mean that this amount of space has been reserved and cannot be used, but this value only tells us that if we want to restore redundancy (2 way redundancy for normal and 3 way for high redundancy) after a failure, we should keep this much space available (never use it) – and negative value under USABLE_FILE_MB actually tells us that we have started utilizing space which was reserved for restoring redundancy.

Formula to calculate USABLE_FILE_MB
For External redundancy
USABLE_FILE_MB = FREE_MB
For Normal Redundancy
USABLE_FILE_MB = (FREE_MB – REQUIRED_MIRROR_FREE_MB) / 2
For High Redundancy
USABLE_FILE_MB = (FREE_MB – REQUIRED_MIRROR_FREE_MB) / 3
Following examples would explain how disk space is allocated and used in an ASM diskgroup. I have total 6 disks with 4G size each to work with during these examples.

External Redundancy
Let’s create a disk group with EXTERNAL REDUNDANCY.
CREATE DISKGROUP data EXTERNAL REDUNDANCY DISK 'ORCL:DISK1','ORCL:DISK2','ORCL:DISK3', 'ORCL:DISK4', 'ORCL:DISK5', 'ORCL:DISK6';

lsdg command shows that TOTAL_MB and USABLE_FILE_MB is 24G; as full disk space is available and will be utilized to store the data - no mirroring would be done. Alternatively you can query same information from v$asm_sidkgroup as you can see below.
ASMCMD> lsdg data
State    Type    Rebal      Sector  Block       AU       Total_MB  Free_MB  Req_mir_free_MB  Usable_file_MB  Offline_disks  Voting_files  Name
MOUNTED  EXTERN  N    512     4096  1048576     24564   24504                0                       24504                  0                       N           DATA/


SQL>  select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where group_number=2;

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564             24505                0                                                               24504

After creating a tablespace of 6g size, space usage of diskgroup can be seen.
SQL> create tablespace mytbs datafile '+data' size 6g;
SQL>  select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where group_number=2;

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564             18357                0                                                               18357

Normal Redundancy
Now we create a diskgroup using these 6 disks, with Normal Redundancy.

SQL> CREATE DISKGROUP data NORMAL REDUNDANCY DISK 'ORCL:DISK1','ORCL:DISK2','ORCL:DISK3', 'ORCL:DISK4','ORCL:DISK5','ORCL:DISK6';

Diskgroup created.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564             24405                4094                                                          10155











REQUIRED_MIRROR_FREE_MB is 4094 which is equal to the size of biggest failure group (each disk is in its own failure group here) so that in case of one disk/failuregroup failure, the mirroring can be re-done using this free space.
Now we create a tablespace with 6G size in +DATA diskgroup and check size.

SQL> create tablespace mytbs datafile '+data' size 6g;

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564             12109                4094                                                          4007
As you see that FREE_MB has decreased from 24405 MB to 12109 (almost half). This shows that although 6G space was used by newly added tablespace, but actually 12G was consumed because of 2 way mirroring. USABLE_FILE_MB space reduced from 10155 MB to 4007 MB i.e. (12109 – 4094) /2 => 4007.
Let’s add another 4000 MB in mytbs tablespace
SQL> alter tablespace mytbs add datafile '+data' size 4000m;

Tablespace altered.

SQL> select sum(bytes/1024/1024) from dba_data_files where tablespace_name='MYTBS';

SUM(BYTES/1024/1024)
--------------------
               10144

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564             4104                  4094                                                            5

USABLE_FILE_MB has now been reduced from 4007 MB to 5 MB only, after consuming further 4000 MB. FREE_MB is now 4104 MB because 4000 MB addition in the tablespace actually consumed 8000 MB because of 2 way mirroring.

High Redundancy
Now let’s create a high redundancy diskgroup and see how space usage works.
SQL> drop tablespace mytbs;

Tablespace dropped.

ASM Instance
SQL> drop diskgroup data;

Diskgroup dropped.

SQL> CREATE DISKGROUP data HIGH REDUNDANCY DISK 'ORCL:DISK1','ORCL:DISK2','ORCL:DISK3', 'ORCL:DISK4', 'ORCL:DISK5','ORCL:DISK6';

Diskgroup created.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564             24405                 8188                                                          5405

REQUIRED_MIRROR_FREE_MB is 8188 which is equal to the size of 2 biggest failure groups (each disk is in its own failure group here) so that in case of 2 disks/failuregroups failure, the mirroring can be re-done using this free space and 3 copies of data exist after re-mirroring.
Now we create a tablespace with 6G size in +DATA diskgroup and check the size.
SQL> create tablespace mytbs datafile '+data' size 6g;

Tablespace created.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564              5964                 8188                                                          -741


After adding 6G (6144 MB) tablespace, FREE_MB has reduced to 5964 i.e. 24405 – (6144 x 3). USABLE_FILE_MB is now in negative which means that there is not enough space available in the diskgroup to restore 3-way redundancy if 2 disks/gailuregroups are gone. At this point if one disk/failuregroup fails, ASM can still restore redundancy because FREE_MB value is more than size of a single disk/failuregroup which is 4G. 
Now I am adding a new file the tablespace to increase size of tablespace from 6144 MM to 8124 MB
SQL>  alter tablespace mytbs add datafile '+data' size 1980m;

Tablespace altered.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB       REQUIRED_MIRROR_FREE_MB         USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ----------------------------------------   ---------------------------
DATA                                24564              18                    8188                                                          -2723

FREE_MB is only 18 MB and if I drop (in order to simulate a disk failure) a disk now, ASM would not be able to restore redundancy even after a disk failure/drop as you can see in the following.
SQL> alter diskgroup data drop disk disk1;
alter diskgroup data drop disk disk1
*
ERROR at line 1:
ORA-15032: not all alterations performed
ORA-15250: insufficient diskgroup space for rebalance completion

Now If I drop a newly added datafile and then try to drop a disk, I would be able to do this because ASM would be able to restore redundancy because sufficient space is available under FREE_MB to perform re-mirroring

SQL> alter tablespace mytbs drop datafile '+DATA/ORCL/DATAFILE/mytbs.257.886505679';

Tablespace altered.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB REQUIRED_MIRROR_FREE_MB USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- --------------   ----------------   -----------------------
DATA                                24564              5964           8188                                                  -741

As you see, FREE_MB is now 5964 M which is sufficient to re-mirror the 4G (maximum) data from a disk if a disk is dropped.

SQL> alter diskgroup data drop disk disk1;

Diskgroup altered.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB      REQUIRED_MIRROR_FREE_MB USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ---------------   --------------------------------------------
DATA                               20470             1870                  8188                                                    -2106

Now we add disk back again and then reduce tablespace size to 5G. by doing this, FREE_MB would be 9036 and this would mean that now ASM can restore a full 3 way redundancy even if we drop di sisks/failuregroups.
SQL>  alter diskgroup data add disk 'ORCL:DISK1';

Diskgroup altered.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB      REQUIRED_MIRROR_FREE_MB USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ---------------   --------------------------------------------
DATA                               20470             5964                  8188                                                    -741


Reduce the file size to 5G and see if we can now drop 2 disks. As long as FREE_MB more than REQUIRED_MIRROR_FREE_MB, we can now drop 2 diks

SQL> alter database datafile '+DATA/ORCL/DATAFILE/mytbs.256.886519815' resize 5g;

Database altered.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB    FREE_MB      REQUIRED_MIRROR_FREE_MB USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- ---------------   --------------------------------------------
DATA                               20470              9036                  8188                                                    282

SQL> alter diskgroup data drop disk disk1;

Diskgroup altered.

SQL> select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB          FREE_MB         REQUIRED_MIRROR_FREE_MB USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- --------------   ---------------------------------------------------
DATA                                20470                   4942                    8188                                                 -1082

SQL> alter diskgroup data drop disk disk2;

Diskgroup altered.

SQL>  select name, TOTAL_MB, FREE_MB, REQUIRED_MIRROR_FREE_MB, USABLE_FILE_MB from v$asm_diskgroup where NAME='DATA';

NAME                             TOTAL_MB           FREE_MB         REQUIRED_MIRROR_FREE_MB   USABLE_FILE_MB
------------------------------ ---------- ---------- ----------------------- -------------------------------------------  --------------------------
DATA                                16376                    848                     8188                                                    -2446