Browse Docs

Databases

Databases sections in docs

Documentation regarding all Databases.

In this section

  • Oracle
    Oracle sections in docs
    • ๐Ÿ“˜ Oracle Basics

      Oracle DB Diagram

          ---
      	config:
      	  theme: forest
      	  layout: elk
      	---
      	flowchart TD
      	  subgraph s1["Instance DB"]
      	    style s1 fill:#E8F5E9,stroke:#388E3C,stroke-width:2px
      	
      	    subgraph s1a["Background Processes"]
      	      style s1a fill:#FFF9C4,stroke:#FBC02D,stroke-width:1px
      	      n5["PMON (Process Monitor)"]
      	      n6["SMON (System Monitor)"]
      	      n10["RECO (Recoverer Process)"]
      	    end
      	
      	    subgraph s1b["PGA (Process Global Area)"]
      	      style s1b fill:#E3F2FD,stroke:#1976D2,stroke-width:1px
      	      n1["Processes"]
      	    end
      	
      	    subgraph s1c["SGA (System Global Area)"]
      	      style s1c fill:#FFEBEE,stroke:#D32F2F,stroke-width:1px
      	      subgraph n7["Shared Pool (SP)"]
      	        style n7 fill:#F3E5F5,stroke:#7B1FA2,stroke-width:1px
      	        n7a["DC (Dictionary Cache)"]
      	        n7b["LC (Library Cache)"]
      	        n7c["RC (Result Cache)"]
      	      end
      	      n8["DB Cache (DBC)"]
      	      n9["Redo Buffer"]
      	      n3["DBWR (DB Writer)"]
      	      n4["LGWR (Log Writer)"]
      	      n5["PMON (Process Monitor)"]
      	      n6["SMON (System Monitor)"]
      	      n10["RECO (Recoverer Process)"]
      	    end
      	  end
      	
      	  subgraph s2["Database: Physical Files"]
      	    style s2 fill:#FFF3E0,stroke:#F57C00,stroke-width:2px
      	    n11["TBS (Tablespaces, files in .DBF)"]
      	    n12["Redo Log Files"]
      	    n13["Control Files"]
      	    n14["SPFILE (Binary Authentication File)"]
      	    n15["ArchiveLog files"]
      	  end
      	
      	  subgraph s3["Operating System"]
      	    style s3 fill:#E0F7FA,stroke:#00796B,stroke-width:2px
      	    n16["Listener (Port 1521)"]
      	  end
      	
      	  n3 --> n11
      	  n3 --> n7c
      	  n4 --> n12
      	  n6 --> n7a
      	  s3 --> s1
      	  s1c <--> n12
      	  s1c <--> n13
      	  s1c <--> n14
      	  n7b <--> n7c
      	
      	  classDef Aqua stroke-width:1px, stroke-dasharray:none, stroke:#0288D1, fill:#B3E5FC, color:#01579B
      	  classDef Yellow stroke-width:1px, stroke-dasharray:none, stroke:#FBC02D, fill:#FFF9C4, color:#F57F17
      	  classDef Green stroke-width:1px, stroke-dasharray:none, stroke:#388E3C, fill:#C8E6C9, color:#1B5E20
      	  classDef Red stroke-width:1px, stroke-dasharray:none, stroke:#D32F2F, fill:#FFCDD2, color:#B71C1C
      	
      	  class n11,n12,n13,n14,n15 Aqua
      	  class n5,n6,n10 Yellow
      	  class n1 Green
      	  class n7,n8,n9,n3,n4 Red
      

      Explanation

      An Oracle server includes an Oracle Instance and an Oracle Database.

    • ๐Ÿ› ๏ธ Administrations

      Identify the instance

      1echo $ORACLE_SID       # the Oracle instance used before a SQL connection.
      2echo $ORACLE_HOME      # the Oracle home directory.
      

      Load the instance environment:

      1. oraenv
      

      /etc/oratab:

      1+ASM:/u01/oracle/base/product/12.2.0/grid:N
      2ORCL:/u01/oracle/base/product/12.2.0/dbhome_1:N
      

      All running instances:

      1ps -ef | grep pmon
      2oracle  2201     1  0 12:02 ?  00:00:00 ora_pmon_ORCL
      3oracle  30513    1  0 Feb12 ?  00:01:11 asm_pmon_+ASM
      
      1ps -ef | grep ora_pmon | grep -v grep | awk '{print $NF}' | cut -d"_" -f3
      

      With a Clusterware layer

      Check whether an Oracle Clusterware layer is present:

      1ps -ef | grep d.bin
      2# /u01/oracle/base/product/12.2.0/grid/bin/[ohasd|oraagent|evmd|ocssd].bin ...
      
      1srvctl config database
      

      Listeners and processes:

    • โš™๏ธ SPFILE & PFILE

      Configuration via init.ora (PFILE)

      init.<SID>.ora was the way to configure Oracle 8/9. It is the database parameter file โ€” without it the database cannot start. Default location: $ORACLE_HOME/dbs (UNIX) or %ORACLE_HOME%\database (Windows).

      Examples of parameters:

    • ๐Ÿ”ง Installation

      Sources & Docs

      Oracle-Base: DB 19c RAC installation on Oracle Linux 8 (VirtualBox)

      Standards

      Keep every Oracle installation as uniform as possible (easier automation). The points below are all required.

      Example migration: previous install RAC ONE NODE SE (Grid 19.0.0 + udev/ASM, DB 12.2.0.1) โ†’ new RAC Active/Active EE (Grid 19.3 + AFD/ASM, DB 19.10).

      Users & groups

      1grep oracle /etc/passwd     # oracle:x:1521:1521:Oracle User For Database Binaries:/home/oracle:/bin/bash
      2grep oinstall /etc/group    # oinstall:x:1521:oracle
      3grep dba /etc/group         # dba:x:1522:oracle
      

      Filesystems & diskgroups

      • /u01 โ€” a dedicated 100G filesystem (binaries ~25G + full install ~15G).
      • /tmp โ€” minimum 4G.
      • DATA โ€” ~60G raw devices / disks.
      • FRA โ€” minimum 4 disks ร— 20G (or 40G), raw devices / disks.
      • VOT โ€” minimum one 5G disk for the voting disk.

      Network

      • Single instance: minimum two interfaces (public + backup/NFS).
      • RAC: three interfaces:
      1DEVICE  TYPE      CONNECTION
      2ens192  ethernet  Admin
      3ens224  ethernet  Interconnect
      4ens256  ethernet  Backup
      

      One network interface for backups is required to mount an NFS share.

    • ๐Ÿงฉ Clusterware

      Grid

      The grid is the component responsable for Clustering in oracle.

      Grid (couche clusterware) -> ASM -> Disk Group - Oracle Restart = Single instance = 1 Grid (with or without ASM)
      - Oracle RAC OneNode = 2 instances Oracle in Actif/Passif with shared storage - Oracle RAC (Actif/Actif)

      SCAN

       1# As oracle user:
       2srvctl config scan
       3
       4SCAN name: host-env-datad1-scan.domain, Network: 1
       5Subnet IPv4: 192.168.228.0/255.255.255.0/ens192, static
       6Subnet IPv6:
       7SCAN 1 IPv4 VIP: 192.168.228.33
       8SCAN VIP is enabled.
       9SCAN VIP is individually enabled on nodes:
      10SCAN VIP is individually disabled on nodes:
      11SCAN 2 IPv4 VIP: 192.168.228.35
      12SCAN VIP is enabled.
      13SCAN VIP is individually enabled on nodes:
      14SCAN VIP is individually disabled on nodes:
      15SCAN 3 IPv4 VIP: 192.168.228.34
      16SCAN VIP is enabled.
      17SCAN VIP is individually enabled on nodes:
      18SCAN VIP is individually disabled on nodes:
      

      Oracle

      • Instance resources:
       1# As oracle user
       2srvctl config database
       3srvctl config database -d <SID>  
       4srvctl status database -d <SID> 
       5srvctl status nodeapps -n host-env-datad1n1
       6srvctl config nodeapps -n host-env-datad1n1  
       7# ============
       8srvctl stop database -d DB_NAME
       9srvctl stop database -d DB_NAME -o normal
      10srvctl stop database -d DB_NAME -o immediate
      11srvctl stop database -d DB_NAME -o transactional
      12srvctl stop database -d DB_NAME -o abort
      13srvctl stop instance -d DB_NAME -i INSTANCE_NAME
      14# =============
      15srvctl start database -d DB_NAME -n host-env-datad1n1
      16srvctl start database -d DB_NAME -o nomount
      17srvctl start database -d DB_NAME -o mount
      18srvctl start database -d DB_NAME -o open
      19# ============
      20srvctl relocate database -db DB_NAME -node host-env-datad1n1
      21srvctl modify database -d DB_NAME -instance DB_NAME 
      22srvctl restart database -d DB_NAME
      23# === Do not do it
      24srvctl modify instance -db DB_NAME -instance DB_NAME_2 -node host-env-datad1n2
      25srvctl modify database -d DB_NAME -instance DB_NAME 
      26srvctl modify database -d oraclath -instance oraclath
      
      • Cluster resources
       1crs_stat
       2crsctl status res
       3crsctl status res -t
       4crsctl check cluster -all
       5
       6# Example how it should look:
       7/opt/oracle/grid/12.2.0.1/bin/crsctl check cluster -all
       8**************************************************************
       9host-env-datad1n1:
      10CRS-4535: Cannot communicate with Cluster Ready Services
      11CRS-4529: Cluster Synchronization Services is online
      12CRS-4534: Cannot communicate with Event Manager
      13**************************************************************
      14host-env-datad1n2:
      15CRS-4537: Cluster Ready Services is online
      16CRS-4529: Cluster Synchronization Services is online
      17CRS-4533: Event Manager is online
      18**************************************************************
      
      1show parameter cluster
      2
      3NAME                                 TYPE        VALUE
      4------------------------------------ ----------- ------------------------------
      5cdb_cluster                          boolean     FALSE
      6cdb_cluster_name                     string      DB_NAME
      7cluster_database                     boolean     TRUE
      8cluster_database_instances           integer     2
      9cluster_interconnects                string
      
      • Stop/start secondary node:
      1-- Prevent Database to switch over
      2ALTER database cluster_database=FALSE;
      
      1# as root
      2/u01/oracle/base/product/19.0.0/grid/bin/crsctl stop crs -f
      3/u01/oracle/base/product/19.0.0/grid/bin/crsctl disable crs
      4
      5# Shutdown/startup VM or other actions
      6
      7# as root
      8/u01/oracle/base/product/19.0.0/grid/bin/crsctl enable crs
      9/u01/oracle/base/product/19.0.0/grid/bin/crsctl start crs
      
      • Stop/Start properly DB on both nodes:
       1# as oracle user
       2srvctl stop database -d oraclath
       3
       4# As root user, on both nodes:
       5/opt/oracle/grid/12.2.0.1/bin/crsctl stop crs -f
       6/opt/oracle/grid/12.2.0.1/bin/crsctl disable crs
       7
       8# As root user, on both nodes:
       9/opt/oracle/grid/12.2.0.1/bin/crsctl enable crs
      10/opt/oracle/grid/12.2.0.1/bin/crsctl start crs
      11
      12# checks after restart 
      13ps -ef | grep asm_pmon | grep -v "grep"
      14
      15# if ASM is up and running
      16srvctl start database -d oraclath -node host1-env-data1n1.domain
      
      • Listner issue
      1# As oracle user
      2srvctl status scan_listener
      3
      4PRCR-1068 : Failed to query resources
      5CRS-0184 : Cannot communicate with the CRS daemon.
      

      the solution:

    • ๐Ÿ—„๏ธ Tablespace

      Concepts

      A tablespace (TBS) is a logical group of storage for data; each tablespace is made of one or more datafiles (.dbf), created on a disk (TBS = 1.dbf + 2.dbf + โ€ฆ). One datafile belongs to exactly one tablespace; a tablespace can have many datafiles. To grow a database you grow the datafiles of the required tablespace (which needs free space on the filesystem or ASM disk).

      View tablespaces & datafiles

      1SELECT * FROM dba_tablespaces;   -- the tablespaces.
      2SELECT * FROM dba_data_files;    -- the datafiles.
      3SELECT * FROM dba_temp_files;    -- the temporary files.
      
      1SELECT tablespace_name FROM dba_tablespaces;
      

      Size & max size of a tablespace (interactive):

    • ๐Ÿ’ฝ Disks ASM

      Basics

      • Start ASM - The old way:
      1. oraenv     # ora SID = +ASM1 (if second nodes +ASM2 )
      2sqlplus / as sysasm
      3startup
      
      • Start ASM - The new method:
      1srvctl start asm -n ora-node1-hostname
      
      • Check ASM volumes
      1srvctl status asm
      2asmcmd lsdsk
      3asmcmd lsdsk -G DATA
      4srvctl status diskgroup -g DATA
      
      • Check clients connected to ASM volume
       1# List clients
       2asmcmd lsct
       3
       4DB_Name  Status     Software_Version  Compatible_version  Instance_Name  Disk_Group
       5+ASM     CONNECTED        19.0.0.0.0          19.0.0.0.0  +ASM           DATA
       6+ASM     CONNECTED        19.0.0.0.0          19.0.0.0.0  +ASM           FRA
       7ORCL     CONNECTED        12.2.0.1.0          12.2.0.0.0  ORCL           DATA
       8ORCL     CONNECTED        12.2.0.1.0          12.2.0.0.0  ORCL           FRA
       9MYDB  CONNECTED        12.2.0.1.0          12.2.0.0.0  MYDB        DATA
      10MYDB  CONNECTED        12.2.0.1.0          12.2.0.0.0  MYDB        FRA
      11
      12# Files Open
      13asmcmd lsof
      14
      15DB_Name  Instance_Name  Path
      16ORCL     ORCL           +DATA/ORCL/DATAFILE/blob.268.1045299983
      17ORCL     ORCL           +DATA/ORCL/DATAFILE/data.270.1045299981
      18ORCL     ORCL           +DATA/ORCL/DATAFILE/indx.269.1045299983
      19ORCL     ORCL           +DATA/ORCL/control01.ctl
      20ORCL     ORCL           +DATA/ORCL/redo01a.log
      21ORCL     ORCL           +DATA/ORCL/redo02a.log
      22ORCL     ORCL           +DATA/ORCL/redo03a.log
      23ORCL     ORCL           +DATA/ORCL/redo04a.log
      24ORCL     ORCL           +DATA/ORCL/sysaux01.dbf
      25[...]
      
      • Connect to ASM prompt
      1. oraenv # ora SID = +ASM
      2asmcmd
      

      ASMlib

      • ASMlib - provide oracleasm command:
       1# list
       2oracleasm listdisks
       3DATA2
       4FRA1
       5
       6# check
       7oracleasm status
       8Checking if ASM is loaded: yes
       9Checking if /dev/oracleasm is mounted: yes
      10
      11# check one ASM volume
      12oracleasm querydisk -d DATA2
      13Disk "DATA2" is a valid ASM disk on device [8,49]
      14
      15# scan
      16oracleasm scandisks
      17Reloading disk partitions: done
      18Cleaning any stale ASM disks...
      19Scanning system for ASM disks...
      20Instantiating disk "DATA3"
      21
      22# Create, delete, rename
      23oracleasm createdisk DATA3 /dev/sdf1
      24oracleasm deletedisk
      25oracleasm renamedisk
      
      • custom script to list disks handle for ASM (not relevant anymore):
       1cat asmliblist.sh
       2#!/bin/bash
       3for asmlibdisk in `ls /dev/oracleasm/disks/*`
       4  do
       5    echo "ASMLIB disk name: $asmlibdisk"
       6    asmdisk=`kfed read $asmlibdisk | grep dskname | tr -s ' '| cut -f2 -d' '`
       7    echo "ASM disk name: $asmdisk"
       8    majorminor=`ls -l $asmlibdisk | tr -s ' ' | cut -f5,6 -d' '`
       9    device=`ls -l /dev | tr -s ' ' | grep -w "$majorminor" | cut -f10 -d' '`
      10    echo "Device path: /dev/$device"
      11  done
      

      Disks Group

      Disk Group : all disks in teh same DG should have same size. Different type of DG, external means that LUN replication is on storage side. When a disk is added to DG wait for rebalancing before continuing operations.

    • ๐Ÿ” Redo Log & Archivelog

      Redo log principles

      The redo log files keep a trace of every data alteration, so that after a crash they can replay the changes. You need at least two, and they deserve careful attention for both backup and access optimisation.

      In ARCHIVELOG mode the redo logs are archived โ€” keeping a full trace of all changes, not just what fits within the redo log file size. The redo buffer is flushed to disk when it is full, so the redo log files should be at least as large as the redo log buffer (log_buffer).

    • ๐Ÿ’พ Backup & Recovery (RMAN)

      Connect

      1rman
      2RMAN> connect target
      
      1rman target /
      

      With a recovery catalog:

      1rman target sys/<pwd>@orcl catalog repo/<pwd>@rmancat
      
      1RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;   -- enables restoring the CONTROLFILE.
      2RMAN> SHOW ALL;                              -- the whole RMAN configuration.
      

      Backup

      1RMAN> BACKUP DATABASE;                                    -- full backup.
      2RMAN> BACKUP DATABASE PLUS ARCHIVELOG;                    -- full + archived logs.
      3RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE;                -- level 0 = baseline.
      4RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE;                -- level 1 = incremental.
      5RMAN> BACKUP CUMULATIVE INCREMENTAL LEVEL 1 DATABASE;     -- cumulative increments.
      6RMAN> BACKUP AS COMPRESSED BACKUPSET DATABASE;            -- compressed full backup.
      7RMAN> BACKUP ARCHIVELOG UNTIL TIME 'sysdate - 1/24' ALL DELETE INPUT;
      

      Run a script:

    • ๐Ÿ“ฆ Export / Import (Data Pump)

      Export

      • EXP (legacy): the old export utility โ€” produces a binary dump (superseded by Data Pump).
      • EXPDP (Data Pump): produces binary dump files, used with DIRECTORY objects.
      1exp  user/password@host FULL=Y        # full legacy (binary) export.
      2expdp user/password@host FULL=Y DIRECTORY=DUMP DUMPFILE=full.dmp
      
      1# full DB, excluding statistics
      2nohup expdp 'system/<password>'@orcl FULL=Y DIRECTORY=DUMP \
      3  DUMPFILE=expdp_orcl_full_$(date +%Y-%m-%d).dmp \
      4  LOGFILE=expdp_orcl_$(date +%Y-%m-%d).log EXCLUDE=statistics
      5
      6# one schema
      7nohup expdp system/<password>@orcl SCHEMAS=my_schema DIRECTORY=DUMP \
      8  DUMPFILE=my_schema_$(date +%Y-%m-%d)_%U.dmp \
      9  LOGFILE=my_schema.log EXCLUDE=statistics
      

      Directories & rights

      1SET LINES 200 PAGES 2000
      2SELECT * FROM dba_directories;   -- the paths defined for Oracle.
      
      1CREATE DIRECTORY my_dir AS '/backup/dump';
      2GRANT READ, WRITE ON DIRECTORY my_dir TO my_user;
      3DROP DIRECTORY my_dir;
      

      Then use it in an export: ... DIRECTORY=my_dir DUMPFILE=my_export.dmp.

    • ๐Ÿ”„ Data Guard

      Synchronisation mechanism between two databases in Active/Passive.

      Switchover

      1dgmgrl sys@orcl
      2DGMGRL> switchover to 'orcl';
      

      Check primary / standby

      1echo -e "set heading off;\n select database_role FROM v\$database;" | sqlplus -S / as sysdba
      2# PHYSICAL STANDBY   (or PRIMARY)
      3
      4echo -e "set heading off;\n select open_mode FROM v\$database;" | sqlplus -S / as sysdba
      5# MOUNTED             (a standby is mounted, not open)
      
      • PRIMARY + READ WRITE โ†’ primary.
      • PHYSICAL STANDBY + MOUNTED โ†’ standby.
    • ๐Ÿšš Move / Clone a Database

      Copy the source database oraprd into a target test database oratest (created beforehand). The copy stops oratest and replaces its files with oraprd’s, then makes them take effect.

      1. Generate the control-file script

      1ALTER DATABASE BACKUP CONTROLFILE TO TRACE;
      

      This writes a trace file into user_dump_dest. The relevant part looks like:

       1STARTUP NOMOUNT
       2CREATE CONTROLFILE REUSE DATABASE "oraprd" NORESETLOGS ARCHIVELOG
       3MAXLOGFILES 5
       4MAXLOGMEMBERS 3
       5MAXDATAFILES 100
       6MAXINSTANCES 1
       7MAXLOGHISTORY 908
       8LOGFILE
       9  GROUP 1 'G:\ORACLE\ORADATA\oraprd\REDO01.LOG' SIZE 10M,
      10  GROUP 1 'G:\ORACLE\ORADATA\oraprd\REDO02.LOG' SIZE 10M,
      11  GROUP 2 'F:\ORACLE\ORADATA\oraprd\REDO03.LOG' SIZE 10M,
      12  GROUP 2 'F:\ORACLE\ORADATA\oraprd\REDO04.LOG' SIZE 10M
      13DATAFILE
      14  'F:\ORACLE\ORADATA\oraprd\SYSTEM01.DBF',
      15  'F:\ORACLE\ORADATA\oraprd\CWMLITE01.DBF',
      16  'F:\ORACLE\ORADATA\oraprd\DATA\DATPRD.DBF',
      17  ... (the whole list of datafiles)
      18CHARACTER SET WE8MSWIN1252
      19;
      20
      21RECOVER DATABASE
      22ALTER SYSTEM ARCHIVE LOG ALL;
      23ALTER DATABASE OPEN;
      24ALTER TABLESPACE TEMP ADD TEMPFILE 'G:\ORACLE\ORADATA\oraprd\TEMP02.DBF' SIZE 2000M REUSE AUTOEXTEND OFF;
      

      2. Adapt the generated script

      Once oraprd’s files are copied over oratest, adapt the control-file script to the new paths (e.g. F:\ORACLE\ORADATA\oraprd and G:\... โ†’ D:\ORACLE\ORADATA\oratest), and change the database name:

    • ๐Ÿ‘ฅ Users, Roles & Privileges

      Managing users

      Four main concepts:

      • USERS โ€” with the granted PRIVILEGES.
      • ROLES โ€” a pack of privileges.
      • PROFILES โ€” a pack of limitations.

      Note: an unquoted SQL name is uppercase; a quoted name keeps its case as written.

      Creation / deletion:

      1-- all users, with account status, expiry, profile, etc.
      2SELECT username, profile, account_status, expiry_date, lock_date
      3FROM dba_users WHERE oracle_maintained = 'N';
      4
      5CREATE USER my_user IDENTIFIED BY my_password;   -- create a user.
      6DROP USER my_user;                              -- drop a user.
      7DROP USER my_user CASCADE;                      -- drop a user and all its tables.
      

      Privileges

      1SELECT * FROM dba_sys_privs;                               -- all possible privileges.
      2SELECT * FROM dba_sys_privs WHERE grantee = 'MY_USER';     -- one user's privileges.
      3
      4GRANT create session, alter session, drop any index TO my_user;
      5REVOKE alter session FROM my_user;
      

      Roles

       1CREATE ROLE my_role;      -- create a role.
       2GRANT create session, alter session, drop tablespace, delete any table TO my_role;  -- grant to a role.
       3GRANT my_role TO my_user, hr;   -- grant a role to users.
       4REVOKE alter session FROM my_role;
       5
       6SELECT * FROM dba_roles;
       7SELECT * FROM dba_role_privs WHERE grantee = 'MY_USER';   -- roles of one user.
       8SELECT grantee, granted_role, admin_option, default_role FROM dba_role_privs ORDER BY 1,2;
       9SELECT * FROM dba_sys_privs WHERE grantee = 'MY_ROLE';
      10SELECT * FROM dba_tab_privs WHERE grantee = 'MY_ROLE';
      

      Profiles

      1SELECT * FROM dba_profiles;                              -- all profiles.
      2SELECT * FROM dba_profiles WHERE profile = 'MY_PROFILE'; -- one profile's limits.
      3
      4CREATE PROFILE my_profile LIMIT idle_time 15 connect_time 20 failed_login_attempts 50;
      5ALTER USER my_user PROFILE my_profile;
      

      Account management

      1ALTER USER my_user IDENTIFIED BY new_password;   -- change the password.
      2ALTER USER my_user ACCOUNT UNLOCK;               -- unlock a user.
      

      sys / system

      1ALTER USER sys IDENTIFIED BY '<password>';
      2ALTER USER system IDENTIFIED BY '<password>';
      

      If the DB password is changed, you must also regenerate the password file (orapwd), which controls remote SYSDBA access:

    • ๐Ÿ•ต๏ธ Auditing

      Enable auditing

      1ALTER SYSTEM SET audit_trail = DB, EXTENDED SCOPE = SPFILE;   -- detailed user actions.
      2SHOW PARAMETER audit_trail;    -- default NONE โ†’ set it to EXTENDED where possible.
      3SHOW PARAMETER audit;          -- the full audit configuration.
      

      Audit users

      1AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE BY hr BY SESSION;
      2AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE BY hr BY SESSION WHENEVER SUCCESSFUL;
      3AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE BY hr BY SESSION WHENEVER NOT SUCCESSFUL;
      4AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE BY hr BY ACCESS;
      5AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE BY hr BY ACCESS WHENEVER SUCCESSFUL;
      6AUDIT SELECT TABLE, UPDATE TABLE, INSERT TABLE BY hr BY ACCESS WHENEVER NOT SUCCESSFUL;
      7
      8AUDIT ALL BY ACCESS;   -- alternatively, audit everything.
      

      Audit tables

      1AUDIT SELECT, INSERT, UPDATE ON hr.employees BY SESSION;
      2AUDIT SELECT, INSERT, UPDATE ON hr.employees BY SESSION WHENEVER SUCCESSFUL;
      3AUDIT SELECT, INSERT, UPDATE ON hr.employees BY SESSION WHENEVER NOT SUCCESSFUL;
      4AUDIT SELECT, INSERT, UPDATE ON hr.employees BY ACCESS;
      5AUDIT SELECT, INSERT, UPDATE ON hr.employees BY ACCESS WHENEVER SUCCESSFUL;
      6AUDIT SELECT, INSERT, UPDATE ON hr.employees BY ACCESS WHENEVER NOT SUCCESSFUL;
      

      View the audit trail

      1SELECT * FROM dba_audit_trail WHERE username = 'HR';   -- the audited actions of a user.
      2SELECT * FROM dba_stmt_audit_opts;                      -- the user-level audits enabled.
      3SELECT * FROM dba_obj_audit_opts;                       -- the object-level audits enabled.
      
    • ๐Ÿงช Invalid Objects

      Find invalid objects

      1COL owner FOR a20
      2COL object_name FOR a50
      3COL subobject_name FOR a30
      4
      5SELECT owner, object_name, subobject_name, object_type, created
      6FROM dba_objects WHERE status <> 'VALID' ORDER BY 2;
      

      Recompile โ€” good practice after an import

      1SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
      2-- 61
      3
      4@?/rdbms/admin/utlrp
      5
      6SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
      7-- 40
      

      Recompile with a PL/SQL cursor

       1SET TERMOUT ON
       2SET SERVEROUTPUT ON
       3DECLARE
       4    CURSOR cur_invalid_objects IS
       5      SELECT object_name, object_type FROM user_objects
       6      WHERE object_type IN ('PROCEDURE','FUNCTION','TRIGGER','SYNONYM','VIEW',
       7                            'MATERIALIZED VIEW','PACKAGE','PACKAGE BODY')
       8        AND status = 'INVALID';
       9    rec_columns cur_invalid_objects%ROWTYPE;
      10    err_status  NUMBER;
      11BEGIN
      12    dbms_output.enable(10000);
      13    OPEN cur_invalid_objects;
      14    LOOP
      15        FETCH cur_invalid_objects INTO rec_columns;
      16        EXIT WHEN cur_invalid_objects%NOTFOUND;
      17        BEGIN
      18            IF rec_columns.object_type IN ('VIEW','SYNONYM','MATERIALIZED VIEW','PACKAGE') THEN
      19                dbms_output.put_line('Recompiling ' || rec_columns.object_type || '  ' || rec_columns.object_name);
      20                EXECUTE IMMEDIATE 'ALTER ' || rec_columns.object_type || ' "' || rec_columns.object_name || '" COMPILE';
      21            ELSIF rec_columns.object_type = 'PACKAGE BODY' THEN
      22                dbms_output.put_line('Recompiling ' || rec_columns.object_type || '  ' || rec_columns.object_name);
      23                EXECUTE IMMEDIATE 'ALTER PACKAGE "' || rec_columns.object_name || '" COMPILE BODY';
      24            ELSE
      25                dbms_output.put_line('Recompiling ' || rec_columns.object_type || '  ' || rec_columns.object_name);
      26                dbms_ddl.alter_compile(rec_columns.object_type, NULL, rec_columns.object_name);
      27            END IF;
      28        EXCEPTION WHEN OTHERS THEN
      29            err_status := SQLCODE;
      30            dbms_output.put_line('Recompilation failed: ' || SQLERRM(err_status));
      31        END;
      32    END LOOP;
      33    CLOSE cur_invalid_objects;
      34END;
      35/
      

      Drop invalid objects

       1SET SERVEROUTPUT ON
       2DECLARE
       3    CURSOR cur_invalid_objects IS
       4      SELECT object_name, object_type FROM user_objects
       5      WHERE object_type IN ('PROCEDURE','FUNCTION','TRIGGER','SYNONYM','VIEW',
       6                            'MATERIALIZED VIEW','PACKAGE','PACKAGE BODY')
       7        AND status = 'INVALID';
       8    rec_columns cur_invalid_objects%ROWTYPE;
       9BEGIN
      10    dbms_output.enable(10000);
      11    OPEN cur_invalid_objects;
      12    LOOP
      13        FETCH cur_invalid_objects INTO rec_columns;
      14        EXIT WHEN cur_invalid_objects%NOTFOUND;
      15        dbms_output.put_line('DROP ' || rec_columns.object_type || ' ' || rec_columns.object_name);
      16        EXECUTE IMMEDIATE 'DROP ' || rec_columns.object_type || ' ' || rec_columns.object_name;
      17    END LOOP;
      18    CLOSE cur_invalid_objects;
      19END;
      20/
      
    • ๐Ÿ’ป Oracle Clients

      Listener / Tnsname.ora

       1# Check if listner is present
       2ps -edf | grep lsn
       3
       4# Prompt Listner
       5lsnrctl
       6LSNRCTL> help
       7The following operations are available
       8An asterisk (*) denotes a modifier or extended command:
       9
      10start           stop            status          services
      11version         reload          save_config     trace
      12spawn           quit            exit            set*
      13show*
      14
      15lsnrctl status
      16lsnrctl start
      17
      18# Logs
      19less /opt/oracle/product/12c/db/network/admin/listener.ora
      

      Local Listner

      1# in Oracle prompt
      2show parameter listener;
      3NAME                                 TYPE        VALUE
      4------------------------------------ ----------- ------------------------------
      5listener_networks                    string
      6local_listener                       string      LISTENER_TOTO
      7remote_listener                      string
      
      • First LISTENER_TOTO must be defined in the tnsnames.ora.
      1# in Oracle prompt
      2alter system set local_listener='LISTENER_TOTO' scope=both;
      3alter system register;
      
       1lsnrctl status
       2
       3LSNRCTL for Linux: Version 12.2.0.1.0 - Production on 29-APR-2021 18:58:48
       4Copyright (c) 1991, 2016, Oracle.  All rights reserved.
       5Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
       6STATUS of the LISTENER
       7------------------------
       8Alias                     LISTENER
       9Version                   TNSLSNR for Linux: Version 12.2.0.1.0 - Production
      10Start Date                29-APR-2021 18:11:13
      11Uptime                    0 days 0 hr. 47 min. 34 sec
      12Trace Level               off
      13Security                  ON: Local OS Authentication
      14SNMP                      OFF
      15Listener Log File         /u01/oracle/base/diag/tnslsnr/myhost/listener/alert/log.xml
      16Listening Endpoints Summary...
      17  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=myhost.example.com)(PORT=1521)))
      18Services Summary...
      19Service "+ASM" has 1 instance(s).
      20  Instance "+ASM", status READY, has 1 handler(s) for this service...
      21Service "+ASM_DATA" has 1 instance(s).
      22  Instance "+ASM", status READY, has 1 handler(s) for this service...
      23Service "+ASM_FRA" has 1 instance(s).
      24  Instance "+ASM", status READY, has 1 handler(s) for this service...
      25Service "ORCL" has 1 instance(s).
      26  Instance "ORCL", status READY, has 1 handler(s) for this service...
      27Service "ORCLXDB" has 1 instance(s).
      28  Instance "ORCL", status READY, has 1 handler(s) for this service...
      29The command completed successfully
      

      Static Listner: TNSnames.ORA

      Services have to be listed in tnsnames.ora of client hosts.

    • ๐Ÿ“‹ Procedures

      Basics

      • find a procedures
      1SELECT *
      2  FROM USER_OBJECTS
      3 WHERE object_type = 'PROCEDURE'
      4   AND object_name = 'grant_RW'
      
      • Example which give SELECT right on one schema to the role
       1CREATE OR REPLACE PROCEDURE grant_RO_to_schema(
       2    username VARCHAR2,
       3    grantee VARCHAR2)
       4AS
       5BEGIN
       6    FOR r IN (
       7        SELECT owner, table_name
       8        FROM all_tables
       9        WHERE owner = username
      10    )
      11    LOOP
      12        EXECUTE IMMEDIATE
      13            'GRANT SELECT ON '||r.owner||'.'||r.table_name||' to ' || grantee;
      14    END LOOP;
      15END;
      16/
      17
      18-- See if procedure is ok -- 
      19SHOW ERRORS 
      20
      21CREATE ROLE '${ROLE_NAME}' NOT IDENTIFIED;
      22GRANT CONNECT TO '${ROLE_NAME}';
      23GRANT SELECT ANY SEQUENCE TO '${ROLE_NAME}';
      24GRANT CREATE ANY TABLE TO '${ROLE_NAME}';
      25
      26-- Play the Procedure -- 
      27EXEC grant_RO_to_schema('${SCHEMA}','${ROLE_NAME}')
      
      • Procedure which give Read/Write right to one schema:
       1su - oracle -c '
       2export SQLPLUS="sqlplus -S / as sysdba"
       3export ORAENV_ASK=NO;
       4export ORACLE_SID='${SID}';
       5. oraenv | grep -v "remains";
       6
       7${SQLPLUS} <<EOF2
       8set lines 200 pages 2000;
       9CREATE OR REPLACE PROCEDURE grant_RW_to_schema(
      10    username VARCHAR2,
      11    grantee VARCHAR2)
      12AS
      13BEGIN
      14    FOR r IN (
      15        SELECT owner, table_name
      16        FROM all_tables
      17        WHERE owner = username
      18    )
      19    LOOP
      20        EXECUTE IMMEDIATE
      21            '\''GRANT SELECT,DELETE,UPDATE,INSERT,ALTER ON '\''||r.owner||'\''.'\''||r.table_name||'\'' to '\'' || grantee;
      22    END LOOP;
      23END;
      24/
      25CREATE ROLE '${ROLE_NAME}' NOT IDENTIFIED;
      26GRANT CONNECT TO '${ROLE_NAME}';
      27GRANT SELECT ANY SEQUENCE TO '${ROLE_NAME}';
      28GRANT CREATE ANY TABLE TO '${ROLE_NAME}';
      29GRANT CREATE ANY INDEX TO '${ROLE_NAME}';
      30EXEC grant_RW_to_schema('\'''${SCHEMA}''\'','\'''${ROLE_NAME}''\'')
      31exit;
      32EOF2
      33unset ORAENV_ASK;
      34'
      
       1-- This one is working better : 
       2CREATE OR REPLACE PROCEDURE grant_RW_to_schema(
       3myschema VARCHAR2,
       4myrole VARCHAR2)
       5AS
       6BEGIN
       7for t in (select owner,object_name,object_type from all_objects where owner=myschema and object_type in ('TABLE','VIEW','PROCEDURE','FUNCTION','PACKAGE')) loop
       8if t.object_type in ('TABLE','VIEW') then
       9EXECUTE immediate 'GRANT SELECT, UPDATE, INSERT, DELETE ON '||t.owner||'.'||t.object_name||' TO '|| myrole;
      10elsif t.object_type in ('PROCEDURE','FUNCTION','PACKAGE') then
      11EXECUTE immediate 'GRANT EXECUTE ON '||t.owner||'.'||t.object_name||' TO '|| myrole;
      12end if;
      13end loop;
      14end;
      15/
      
    • ๐Ÿ“ Scripting

      Inside a Shell script

      • One line command:
      1# Set the SID 
      2ORAENV_ASK=NO
      3export ORACLE_SID=orcl
      4. oraenv
      5
      6# Trigger oneline command
      7echo -e "select inst_id, instance_name, host_name, database_status from gv\$instance;" | sqlplus -S / as sysdba
      
      • In bash script:
       1su - oracle -c '
       2export SQLPLUS="sqlplus -S / as sysdba"
       3export ORAENV_ASK=NO;
       4export ORACLE_SID='${SID}';
       5. oraenv | grep -v "remains";
       6
       7${SQLPLUS} <<EOF2
       8set lines 200 pages 2000;
       9select inst_id, instance_name, host_name, database_status from gv\$instance;
      10exit;
      11EOF2
      12
      13unset ORAENV_ASK;
      14'
      

      Inside SQL Prompt

      1-- with an absolute path 
      2@C:\Users\Matthieu\test.sql 
      3
      4-- or trigger from director on which sqlplus was launched
      5@test.sql
      6
      7-- START syntax possible as well
      8START test.sql  
      

      Variables usages

      1-- User variable (if not define, oracle will prompt)
      2SELECT * FROM &my_table;
      3
      4-- Prompt user to set a variable
      5ACCEPT my_table PROMPT "Which table would you like to interrogate ? "
      6SELECT * FROM $my_table;
      

      Some Examples

      • Example of Shell script to launch sqlplus command:
       1export ORACLE_SID=SQM2DWH3
       2
       3echo "connect ODS/ODS
       4BEGIN
       5ODS.PURGE_ODS.PURGE_LOG();
       6ODS.PURGE_ODS.PURGE_DATA();
       7END;
       8/" | sqlplus /nolog
       9
      10echo "connect DSA/DSA
      11BEGIN
      12DSA.PURGE_DSA.PURGE_LOG();
      13DSA.PURGE_DSA.PURGE_DATA();
      14END;
      15/" | sqlplus /nolog
      
      • Example of script to check tablespaces.sh
       1#!/bin/ksh
       2
       3sqlplus -s system/manager <<!
       4SET HEADING off;
       5SET PAGESIZE 0;
       6SET TERMOUT OFF;
       7SET FEEDBACK OFF;
       8SELECT df.tablespace_name||','||
       9       df.bytes / (1024 * 1024)||','||
      10       SUM(fs.bytes) / (1024 * 1024)||','||
      11       Nvl(Round(SUM(fs.bytes) * 100 / df.bytes),1)||','||
      12       Round((df.bytes - SUM(fs.bytes)) * 100 / df.bytes)
      13  FROM dba_free_space fs,
      14       (SELECT tablespace_name,SUM(bytes) bytes FROM dba_data_files GROUP BY tablespace_name) df
      15 WHERE fs.tablespace_name (+)  = df.tablespace_name
      16 GROUP BY df.tablespace_name,df.bytes
      17 ORDER BY 1 ASC;
      18quit
      19!
      20
      21exit 0
      
       1#!/bin/ksh
       2
       3sqlplus -s system/manager <<!
       4
       5set pagesize 60 linesize 132 verify off
       6break on file_id skip 1
       7
       8column file_id heading "File|Id"
       9column tablespace_name for a15
      10column object          for a15
      11column owner           for a15
      12column MBytes          for 999,999
      13
      14select tablespace_name,
      15'free space' owner, /*"owner" of free space */
      16' ' object,         /*blank object name */
      17file_id, /*file id for the extent header*/
      18block_id, /*block id for the extent header*/
      19CEIL(blocks*4/1024) MBytes /*length of the extent, in Mega Bytes*/
      20from dba_free_space
      21where tablespace_name like '%TEMP%'
      22union
      23select tablespace_name,
      24substr(owner, 1, 20), /*owner name (first 20 chars)*/
      25substr(segment_name, 1, 32), /*segment name */
      26file_id, /*file id for extent header */
      27block_id, /*block id for extent header */
      28CEIL(blocks*4/1024) MBytes /*length of the extent, in Mega Bytes*/
      29from dba_extents
      30where tablespace_name like '%TEMP%'
      31order by 1, 4, 5
      32/
      33
      34quit
      35!
      36
      37exit 0
      

      SPOOL to write on system

      • from sqlplus:
      1SQL> SET TRIMSPOOL on
      2SQL> SET LINESIZE 1000
      3SQL> SPOOL /root/output.txt
      4SQL> select RULEID as RuleID, RULENAME as ruleName,to_char(DBMS_LOB.SUBSTR(EPLRULESTATEMENT,4000,1() as ruleStmt from gep_rules;
      5SQL> SPOOL OFF
      
      • from script.sql:
      1SET TRIMSPOOL on
      2SET LINESIZE 10000
      3SPOOL resultat.txt
      4ACCEPT var PROMPT "Which table do you want to get ? "
      5SELECT * FROM &var;
      6SPOOL OFF
      

      Generate DATA

      • Duplicate table to fill up tablespace or generate fake data:
      1SQL> Create table emp as select * from employees; 
      2SQL> UPDATE emp SET LAST_NAME='ABC';
      3SQL> commit;
      
Sunday, October 4, 2026 Monday, January 1, 1