I am quite familiar with the SYSMAN tables but this one required me some googling beyond the Oracle documentation.
The list of targets in your Oracle Enterprise Manager is in SYSMAN.MGMT_TARGETS. Each database target is monitored by a database user, typically DBSNMP.
To retrieve this information, you need some to hijack your database, read this : Gökhan Atil
- you copy your encryption key to your repository database, on the OMS server
- you decrypt the credentials for db monitoring
- remove the security leak
$ emctl config emkey -copy_to_repos Enter Enterprise Manager Root (SYSMAN) Password :
Now anyone with select any table on your repository will see all passwords. You don’t want to do this, but unfortunately you have to do this because even the username is encrpyted.
SELECT * FROM ( SELECT target_name, sysman.em_crypto.decrypt ( c.cred_attr_value, c.cred_salt) cred, cred_attr_name attr FROM SYSMAN.EM_TARGET_CREDS c JOIN SYSMAN.mgmt_targets t USING (target_guid) JOIN sysman.EM_NC_CRED_COLUMNS c USING (cred_guid) WHERE c.target_type = 'oracle_database' AND c.set_name = 'DBCredsMonitoring' ) PIVOT ( MAX (cred) FOR (attr) IN ( 'DBUserName' AS USERNAME, 'DBRole' AS "ROLE") )
TARGET_NAME USERNAME ROLE ----------- -------- ------ DB01 dbsnmp NORMAL DB02 dbsnmp NORMAL DB03 sys SYSDBA
$ emctl config emkey -remove_from_repos Enter Enterprise Manager Root (SYSMAN) Password :
Now the em_crypto won’t work any more
select sysman.em_crypto.decrypt('0','0') from dual * Error at line 2 ORA-28239: no key provided ORA-06512: at "SYS.DBMS_CRYPTO_FFI", line 67 ORA-06512: at "SYS.DBMS_CRYPTO", line 44 ORA-06512: at "SYSMAN.EM_CRYPTO", line 250 ORA-06512: at line 1
This information could be used to change the password dynamically accross all databases.
emcli login \ -username=sysman \ -password=sysmanpw emcli update_db_password \ -target_name=DB01 \ -user_name=dbsnmp \ -change_at_target=yes \ -old_password=oldpw \ -new_password=newpw \ -retype_new_password=newpw
The syntax that you are looking for is
DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ... [RESTRICT | CASCADE]
Wait, this does not work !
SQL> drop table if exists t; drop table if exists t * ERROR at line 1: ORA-00933: SQL command not properly ended
Okay. It was the Oracle MySQL book
In the Oracle database, I have created my own droptableifexists script.
I went for a SQL*Plus no-plsql approach. PL/SQL is also possible but it generated different error messages (ORA-06512: at line 1) and different feedback (PL/SQL procedure successfully completed.)
So I check the dictionary, put a command to drop in the sqlplus buffer if a table exists, then run that command first.
set feed off ver off pages 0 newp none def cmd="select 'OK: Table does not exist' from dual" col cmd new_v cmd nopri select 'drop table "'||table_name||'"' cmd from user_tables where table_name='&1'; 1 select del * 1 &cmd set feedb 6 head off / set head on del * undef cmd col cmd clear
Ok, let’s try
SQL> create table t(x number); Table created. SQL> @droptableifexists T Table dropped. SQL> @droptableifexists T OK: Table does not exist
A PL/SQL approach could be
for f in ( select 'drop table "'||table_name||'"' cmd from user_tables where table_name='T') loop execute immediate f.cmd; end loop;
Try it :
SQL> create table t(x number); Table created. SQL> exec for f in (select 'drop table "'||table_name||'"' cmd from user_tables where table_name='T')loop execute immediate f.cmd;end loop PL/SQL procedure successfully completed. SQL> exec for f in (select 'drop table "'||table_name||'"' cmd from user_tables where table_name='T')loop execute immediate f.cmd;end loop PL/SQL procedure successfully completed.
A bit easier to read. Same has to be done for USER, VIEW and so on.
PS: there are also other versions around catching for ORA-942, but ORA-942 may be ORA-943 in next release, try
drop table t;; in 11g and 12c to see those things really happen !
I wrote a while ago about my security concerns regarding
xhost + xterm -display mypc:0
Way back then, I suggested ssh tunnel. SSH is pretty easy to set up, by enabling the X11Forwarding option.
In OpenSSH 3.8 release note, 2004, there was a new default .
ssh(1) now uses untrusted cookies for X11-Forwarding
man ssh_config page, it’s still documented as being the default
ForwardX11Trusted The default is ‘no’
But it actually isn’t on most *ix derivates, e.g. RedHat /etc/ssh/ssh_config
# If this option is set to yes then
# remote X11 clients will have full access
# to the original X11 display. As virtually
# no X11 client supports the untrusted
# mode correctly we set this to yes.
Who is we?
Okay, let’s go back.
If you use the unsafest method,
xhost + and
xterm -display pc:0, then you grant everybody the right to manipulate X.
If you use trusted ssh, which is the _undocumented_ default in Linux, then you grant this right only to anyone with access to your authority, most probably located in the file $HOME/.Xauthority. So root and yourself, at least.
If you trust neither yourself nor root, you could restrict access to your resource, preventing one hacker from switching your mouse buttons or doing a screenshot. But this is probably going to prevent most of your applications from working. Also, it probably won’t work at all if you use putty, reflection and (virtually any?) other client tools.
If you want to force Trusted mode, use
If you want to force Untrusted mode, use
If you use only
-X, it may transparently defaults to the more convenient but less secure
-Y. Sometimes. At least on Linux OpenSSH. But if you use different Unix / SSH flavours, the
-X may ends with an error message like connection to “localhost:10.0″ refused by server. In that case, simply use
-Y. Actually, always use
-Y if you want Trusted.
We have backed up archivelog during a full and deleted them before the full completed.
RMAN> list backup of archivelog all; List of Backup Sets =================== BS Size Type Elapsed Completion -- ------ ---- -------- ---------- 15 4.00K DISK 00:00:00 13:31:08 BP Key: 15 Status: AVAILABLE Piece Name: /FULL/0fq7gc0s_1_1 List of Archived Logs in backup set 15 Seq LowSCN LowTime NextSCN NextTime --- ------- -------- ------- -------- 15 355533 13:29:55 355777 13:31:08 BS Size Type Elapsed Completion -- ------ ---- -------- ---------- 25 4.00K DISK 00:00:00 13:31:26 BP Key: 25 Status: AVAILABLE Piece Name: /ARCH/0pq7gc1e_1_1 List of Archived Logs in backup set 25 Seq LowSCN LowTime NextSCN NextTime --- ------- -------- ------- -------- 15 355533 13:29:55 355777 13:31:08 BS Size Type Elapsed Completion -- ------ ---- -------- ---------- 26 3.00K DISK 00:00:00 13:31:26 BP Key: 26 Status: AVAILABLE Piece Name: /ARCH/0qq7gc1e_1_1 List of Archived Logs in backup set 26 Seq LowSCN LowTime NextSCN NextTime --- ------- -------- ------- -------- 16 355777 13:31:08 355827 13:31:22 BS Size Type Elapsed Completion -- ------ ---- -------- ---------- 28 2.50K DISK 00:00:00 13:31:28 BP Key: 28 Status: AVAILABLE Piece Name: /FULL/0sq7gc1g_1_1 List of Archived Logs in backup set 28 Seq LowSCN LowTime NextSCN NextTime --- ------- -------- ------- -------- 17 355827 13:31:22 355863 13:31:28
Sequence 16 is missing in /FULL/ and is available in /ARCH/
Ok, let’s copy the missing pieces from ARCH to FULL
$ cd / $ cp -p ARCH/* FULL/
Now let’s try. I save my directory on an offline location (tape/usb/cdrom) and dropped my database including backups.
cd / tar cvf /tmp/FULL.tar FULL
Let’s drop (it’s just a test)
RMAN> startup force mount dba RMAN> drop database including backups; database dropped
Ok let’s get this USB stick back from the moon to my datacenter and see if I can restore …
cd / tar xvf /tmp/FULL.tar
Let’s do this !
RMAN> startup force nomount RMAN> restore controlfile from '/FULL/c-2414975447-20150521-01'; RMAN> alter database mount;
Now I want RMAN to look for other files in FULL and also marked expired stuff. The
start withdoes the magic.
RMAN> catalog start with '/FULL/' noprompt; RMAN> crosscheck backup; RMAN> crosscheck copy; RMAN> crosscheck archivelog all; RMAN> restore database; RMAN> recover database; RMAN> alter database open resetlogs;
As @dbastorage said on twitter:
“if it was easy, we would not need DBAs! ”
@laurentsch and have a job to backup the before backup redo, that includes the delete… if it was easy, we would not need DBAs! 2/2
— Peter Herdman-Grant (@DBAStorage) May 20, 2015
After my post Can you restore from a full online backup ?, I needed to come up with a report.
Assuming that each backup goes in a different directory, I just wrote two reports.
- Report gaps in v$backup_redolog (or rc_backup_redolog if you use the catalog)
DIR FIRST_CHANGE# NEXT_CHANGE# ------- ------------- ------------ /bck01/ 284891 285140 /bck01/ 285140 285178 /bck02/ 284891 285140 === GAP === /bck02/ 285178 285245 /bck03/ 285178 285245 /bck03/ 285245 286931 /bck03/ 286931 287803 /bck03/ 287803 288148
This could be done with analytics, by checking where the last next_change is not the current first_change, within a directory
SELECT dir, LAG missing_from_change#, first_change# missing_to_change# FROM ( SELECT REGEXP_REPLACE (handle, '[^/\]+$') dir, first_change#, next_change#, LAG(next_change#) OVER ( PARTITION BY REGEXP_REPLACE (handle, '[^/\]+$') ORDER BY first_change# ) LAG FROM v$backup_piece p JOIN v$backup_redolog l USING (set_stamp, set_count)) WHERE LAG != first_change#; DIR MISSING_FROM_CHANGE# MISSING_TO_CHANGE# ------- -------------------- ------------------ /bck02/ 285140 285178
- Reports directories where archivelogs don’t include changes (backup redolog) from the earliest to the latest checkpoint (backup datafile)
SELECT REGEXP_REPLACE (handle, '[^/\]+$') dir, MIN (checkpoint_change#), MAX (checkpoint_change#), MIN (first_change#), MAX (next_change#) FROM v$backup_piece p LEFT JOIN v$backup_datafile f USING (set_stamp, set_count) LEFT JOIN v$backup_redolog l USING (set_stamp, set_count) WHERE handle IS NOT NULL HAVING MIN (checkpoint_change#) < MIN (first_change#) OR MAX (checkpoint_change#) > MAX (next_change#) GROUP BY REGEXP_REPLACE (handle, '[^/\]+$'); DIR MINCHECKPT MAXCHECKPT MINFIRST MAXNEXT ------- ---------- ---------- ---------- ---------- /bck04/ 954292 954299 959487 1145473
the archives for the changes from 954292 to 959487 are missing.
If some archive backups are missing in one directory, it does not mean the database is irrecoverable, the archive backups could be in another directory. But it means that single directory would no longer permit you to restore or duplicate.
Another approach with RESTORE PREVIEW was provided by Franck in my previous post : List all RMAN backups that are needed to recover.
Usual disclaimer: there are plenty of other irrecoverabilty causes from hardware defect to backup “optimization” that are beyond the scope of this post.
The question is not HOW TO DO IT but WHETHER YOU CAN DO IT !
A typical backup script would contains something like
BACKUP DATABASE PLUS ARCHIVELOG:
backup database format '/u99/backup/DB01/20150518/full_0_%d_s%s_p%p' plus archivelog format '/u99/backup/DB01/20150518/arc_%d_s%s_p%p';
Starting backup at 2015-05-18_18:27:55 current log archived input archived log thread=1 sequence=469 ... piece handle= /u99/backup/DB01/20150518/arc_DB01_s86_p1 Finished backup at 2015-05-18_18:27:58 Starting backup at 2015-05-18_18:27:58 input datafile file number=00002 name= /u02/oradata/DB01/undots01.dbf ... including current control file in backup set including current SPFILE in backup set piece handle= /u99/backup/DB01/20150518/full_0_DB01_s88_p1 Finished backup at 2015-05-18_18:28:16
Starting backup at 2015-05-18_18:28:16 current log archived input archived log thread=1 sequence=20 piece handle= /u99/backup/DB01/20150518/arc_DB01_s89_p1 Finished backup at 2015-05-18_18:28:17
This sounds pretty safe, but what happened if you keep this full backup for ever ? do you have all what you need in it to restore ?
It depends. Chance exists that you can restore. To annoy the paranoiacs, here is a counter example.
you start your full backup at 6pm.
backuping sequence 21,22,23,24
at 7 pm one cronjob issue
backup archivelog all delete input;
backuping and deleting sequence 21,22,23,24,25,26,27,28,29,30
at 8pm your backup is about to finish
backuping sequence 31
Well, where is my sequence 27 ?
rm /tmp/arch_DB01* startup force mount; crosscheck backup;restore database;
Starting restore at 2015-05-18_18:47:45 channel ORA_DISK_1: restore complete, elapsed time: 00:02:05 Finished restore at 2015-05-18_18:49:51
Ok, the restore was fine. Now what?
RMAN> recover database;
Starting recover at 2015-05-18_18:50:35 using channel ORA_DISK_1 starting media recovery RMAN-00571: ================================================= RMAN-00569: ========== ERROR MESSAGE STACK FOLLOWS ========== RMAN-00571: ================================================= RMAN-03002: failure of recover command at 05/18/2015 18:50:36 RMAN-06053: unable to perform media recovery because of missing log RMAN-06025: no backup of archived log for thread 1 with sequence 30 RMAN-06025: no backup of archived log for thread 1 with sequence 29 RMAN-06025: no backup of archived log for thread 1 with sequence 27 RMAN> alter database open;
RMAN-00571: ================================================= RMAN-00569: ========== ERROR MESSAGE STACK FOLLOWS ========== RMAN-00571: ================================================= RMAN-03002: failure of alter db command at 05/18/2015 18:51:29 ORA-01113: file 1 needs media recovery ORA-01110: data file 1: '/u02/oradata/DB01/system01.dbf'
You have lost your database. Even if you did a full online backup plus archivelog, it did not contain all the archivelogs and RMAN did not tell you.
There is more than one way to reduce this annoyance :
1) don’t backup archivelogs during full backup
2) don’t delete archivelog backups done during a full backup
3) report any archivelog backups that run during a full. Either by looking in the RMAN dictionary or in your house logfiles
4) do offline backup for long term archives
5) don’t trust RMAN
And as well :
Test your backups
Some commands do not like non-interactive mode
$ passwd <<EOF > oldpassword > newpassword > newpassword > EOF Changing password for user lsc. Current password for email@example.com: passwd: Authentication token manipulation error $ echo oraclepassword | su - oracle standard in must be a tty $ echo sudopassword | sudo su - oracle [sudo] password for lsc: sudo: sorry, you must have a tty to run sudo
But ok, if you really want to run those in a script, you have plenty of clean (no hack there) ways of doing this.
For instance, let’s use a screen called BAR.
$ xterm -e "screen -S BAR" &  31732
Now we have an interactive terminal. It could be redirected to a frame buffer device if no x server is started.
Not really a human device, but an interactive terminal.
Now let’s send stuff
$ CR="$(echo '\r')" $ screen -S BAR -X stuff "sudo su - oracle$CR" $ screen -S BAR -X stuff "sudopassword$CR" $ screen -S BAR -X stuff "id > /tmp/xxx$CR" $ screen -S BAR -X stuff "exit$CR" $ screen -S BAR -X stuff "exit$CR"  + Done xterm -e "screen -S BAR" & $ cat /tmp/xxx uid=100(oracle) gid=100(dba) groups=100(dba)
Usual disclaimer: it is a bad security practice to hardcode your passwords in scripts. Use this only if you really understand security. Read man openssl about how to use openssl to encrypt your password. Ask your security friends before trying
When you really need to run one script, at all cost, an annoying error is
ORA-00020: maximum number of processes (40) exceeded, which can even occurs as sysdba.
Test case (21 is a not something to do in real life):
SQL> alter system set processes=21 scope=spfile; System altered. SQL> startup force quiet ORACLE instance started. Database mounted. Database opened. SQL> quit
From now on, sqlplus as sysdba is impossible.
$ sqlplus -s -L / as sysdba ERROR: ORA-00020: maximum number of processes (40) exceeded SP2-0751: Unable to connect to Oracle. Exiting SQL*Plus
Okay, if you really really need to run one script, you could connect with sqlplus -prelim and restart the database.
if :|sqlplus / as sysdba|grep ORA-00020 then echo shu abort|sqlplus -prelim / as sysdba echo startup quiet|sqlplus / as sysdba fi
If ORA-20 is detected, then the database will be restarted.
Almost a decade ago I wrote about su in sqlplus. This 10gR2 “new” feature allows delegation à la sudo.
By checking the DBA_USERS in 12c I found PROXY_ONLY_CONNECT. According to Miguel Anjo, there is a secret syntax for allowing only the proxy user.
SQL> ALTER USER app_user PROXY ONLY CONNECT; SQL> CONNECT app_user/xyz ERROR:ORA-28058: login is allowed only through a proxy
Depending the files, you may use different signs for comments, typically
# hash // slash slash /* slash-star star-slash */ : column -- dash dash
The latest is used in sql and pl/sql, but :
CREATE TABLE t (x NUMBER) ORGANIZATION EXTERNAL ( TYPE ORACLE_LOADER DEFAULT DIRECTORY data_pump_dir ACCESS PARAMETERS ( FIELDS TERMINATED BY ';' -- This is a comment (x)) LOCATION ('x')); SELECT * FROM t; SELECT * FROM t * ERROR at line 1: ORA-29913: error in executing ODCIEXTTABLEOPEN callout ORA-29400: data cartridge error KUP-00554: error encountered while parsing access parameters KUP-01005: syntax error: found "minussign": expecting one of: "column, enclosed, (, ltrim, lrtrim, ldrtrim, missing, notrim, optionally, rtrim, reject" KUP-01007: at line 2 column 38
not in external table access parameters.
No comment is allowed there!