Kevin Kempf's Blog

August 20, 2018


Filed under: Uncategorized — kkempf @ 2:42 pm

EBS Table Inventory

For a variety of reasons, I took inventory of the largest objects (in this particular case, tables) in my R12.2 EBS environment.  I strongly suggest you do the same, upon occasion, as it’s somewhat enlightening.

 ,bytes/1024/1024/1024 gb
  segment_type = 'TABLE'
order by
  bytes/1024/1024/1024 desc

At the very top of my list was APPLSYS.FND_LOG_MESSAGES, checking in at 29.4GB.  I now had a target.

Read the directions

This is EBS, we can’t just arbitrarily start shooting and hope we don’t break anything.  There’s a number of MOS notes on support describing various aspects of purging this table.  Number one on the list was the concurrent request, “Purge Logs and Closed System Alerts”.  There were also some notes about a bug which prevented this CR from performing correctly, but they didn’t seem relevant to EBS 12.2

Back to my problem child

SQL> select count(*) from applsys.fnd_log_messages;


This jumps out immediately.

SQL> select owner, segment_name, bytes/1024/1024/1024 gb 
from dba_segments where segment_type = 'TABLE' 
and segment_name = 'FND_LOG_MESSAGES';

OWNER                     SEGMENT_NAME              GB
------------------------- ------------------------- ----------
APPLSYS                   FND_LOG_MESSAGES          29.4005127

I run Concurrent Request “Purge Logs and Closed System Alerts” every week, and the log shows it’s completing normal.  Why are 308 rows consuming so much space on disk?  Let’s assume that this table has had no attention since it was first installed about 14 years ago.  There were times when debug was on, to be sure, filling FND_LOG_MESSAGES faster than normal.  But after a quick check of Profile Option Values I see that at present, nobody has debug enabled.

Proving out the solution

Is it possible that 14 years of inserts and deletes could cause this table to have developed a bad case of high water mark 29 GB deep?

SQL> alter table applsys.fnd_log_messages enable row movement;

Table altered.

Elapsed: 00:00:00.08
SQL> alter table applsys.fnd_log_messages shrink space;

Table altered.

Elapsed: 00:56:47.99
SQL> select owner, segment_name, 
bytes/1024/1024/1024 gb from dba_segments 
where segment_type = 'TABLE' 
and segment_name = 'FND_LOG_MESSAGES';

------------ ---------------- ---------
Elapsed: 00:00:00.31

Not bad; we’re down from 29.4GB to 14.5GB without much effort.  Let’s go in for the kill

SQL> alter table applsys.fnd_log_messages move;

Table altered.

Elapsed: 00:01:30.32

SQL> select owner, segment_name, 
bytes/1024/1024/1024 gb from dba_segments 
where segment_type = 'TABLE' 
and segment_name = 'FND_LOG_MESSAGES';

------- ---------------- ----------
Elapsed: 00:00:00.13

Sweet.  29GB down to .0003GB.

Don’t forget that alter table xyz move renders indexes invalid.

set pagesize 0
'alter index '
|| owner
|| '.'
|| index_name
|| ' rebuild;'
status = 'UNUSABLE'

SQL> alter index applsys.fnd_log_messages_n4 rebuild;

Index altered.

SQL> alter index applsys.fnd_log_messages_n5 rebuild;

Index altered.

SQL> alter index applsys.fnd_log_messages_n7 rebuild;

Index altered.

SQL> alter index applsys.fnd_log_messages_n8 rebuild;

Index altered.

June 5, 2017

The trouble with editions

Filed under: Online Patching, R12.2 — kkempf @ 10:27 am
(fake quote to grab your attention)

EBS 12.2 and Edition Based Redefinition

Unless you’ve been living under a rock for the past 5 years, you’re probably aware that EBS 12.2 online patching leverages Edition Based Redefinition (EBR).  In a nutshell, when you begin an online patch cycle, the adop phase=prepare command creates a new edition of the database which “contains” all current objects, but will also absorb database changes as you apply patches.  Simplified, it becomes your “on deck” database, ready to take effect (or step up to the plate, if you prefer the analogy) after you complete the adop phase=cutover.

Recognizing you have a problem

Left unattended, this system will continue to work for a long time without issue.  In my case, over 2.5 years, before I realized I had become an edition hoarder and needed help.  I realized that I had old editions hanging around, back to the day of our 11i to 12.2 go live.  Oracle very conveniently names the editions after the date/time they were created.  So you can see our first 12.2 edition was V_20141127_2225 (11/27/2014 at 10:25pm).

select edition_name from dba_editions order by edition_name;

35 rows selected.

Get Help

The fix is pretty simple, but I’ll add a real-world “gotcha” to Oracle’s documentation.  You can look  at EBS 12.2 Maintenance guide( Pg 3-27 to see the official verbiage, but here’s the gist of how to drop the old editions:

  • adop phase=prepare
  • adop phase=apply patches=(whatever patches you want to do, or none)
  • adop phase=actualize_all
  • adop phase=finalize finalize_mode=full
  • adop phase=cutover
  • adop phase=cleanup cleanup_mode=full

I’ll point out that Oracle’s document does not include the apply phase, however you can indeed apply patches during an edition cleanup.  Not only have we done it, but Oracle said it was fine to do in an SR.

The other thing the document doesn’t tell you is that this is not necessarily an impact-free operation.  We had a long maintenance window on a Sunday afternoon and decided to defer the phase=cleanup cleanup_mode=full until Monday morning when users were in the system.  Within 10 minutes, we had calls to the help desk because of massive object contention and locks, to the point where nobody could log into EBS.  I look at Enterprise Manager and it’s bright red, with hundreds of blocking locks in the system.  I don’t know if this is a result of the fact that we were dropping 30+ editions, or if it will happen just doing 1 edition.  Regardless, we ended up stopping the front end during the next maintenance cycle, then running the cleanup, and it was done in 45 mins or less.

SQL> select edition_name from dba_editions order by edition_name;


November 18, 2016

EBS R12.2 Security

Filed under: Oracle, R12.2, Security — kkempf @ 10:27 am


That light at the end of the tunnel might be a freight train

If you’re running 12.2 and considering 12.2.6 any time in the near future, you need to be aware of significant changes coming to the security requirements of EBS.  At the East Coast Oracle conference in Raleigh a few weeks back, I sat in a session by Elke Phelps (Oracle) entitled “Ready or Not: Applying Secure  Configuration to Oracle  E – Business Suite“.   Oracle EBS is getting serious, if not belligerent, about security.

Bottom line: If you don’t comply with their security recommendations, your users will not be able to log into EBS.  That’s right.  This is probably the most concerning thing about the changes: they’re not suggested.  Don’t believe me?  Check out Doc 2174164.1 section 3.1:

The Secure Configuration Console automates the security configuration process by consolidating the security configuration process onto one user interface and creating a single checkpoint entry into the system. It checks your system against 16 high-priority security configuration guidelines and makes recommendations to the system administrator to either fix or suppress the failure. Until the system administrator acknowledges these checks, users will be denied entry into the system.

Do I have you attention now?

Here’s the thing: most of the things it appears to be concerned with are either simple fixes or common sense.  While I haven’t seen it myself, I’ve been assured there is a page somewhere (in OAM?) where the apps DBA can go in and check boxes saying “I understand I’ve broken security rules, now please let me use my ERP”. Think: DEV environments.

One problem with all of this is it’s implemented in Oracle’s typical unwieldy and disparate manner.  Start by grinding your way through the 468 page Oracle Ebusiness Suite R12.2 security guide.  Let me just say it’s not a real page turner and I’ve had less reading in graduate level courses.


So we move on to 2069190.1 where you can find a nifty set of scripts called  This is run against your database, and comes back with somewhat actionable results.  I will admit, it found some things I wasn’t aware of, but it’s not perfect.  By the numbers:

  • Check: Security Profiles: Configuration ERRORS
    • This checks POVs to see if you’re doing anything wrong.  In my case, it didn’t like a site level POV called Framework Validation Level (value was set to none).  The problem with this assessment, is that this isn’t a POV I can find in any way.  As in, I can’t query it up in forms, and when I try to use to change it, it errors.  First check and I have to open an SR.  Great start!
  • Check: Security Profiles: Configuration WARNINGS
    • This appears to check and see who has the ability to run diagnostics in EBS, as well as who can attach files and personalize self service bits.  The problem is, it doesn’t bother to check and see if the EBS user with these privs is end dated.  So I wound up with a list of end-dated consultants from our R12.2 upgrade, none of which can log in, and a list of IT super users.
  • Check: Security Profiles: Configuration MISSING
    • No idea, I “passed” this one
  • Check: Application Users with Default Passwords
    • I’ll give Oracle credit on this one, it found some interesting things here.  I had to change my guest password, and disable autoinstall.  Hint: try to find that user.. when you get tired of that game, run FND_USER_PKG.DISABLEUSER(‘AUTOINSTALL’);
    • It also found some schemas which had the default password.  As in, all the new schemas presumably introduced by the 12.2 upgrade, so kudos to Oracle there.  Mine were ddr, dna, dpp, gmo, ibw, inl, ipm, jmp, mth, qpr and rrs.  Obviously I hadn’t run FNDCPASS against “ALL” since the upgrade, and so these were just hanging around.
  • Check: DB Users With Default Passwords
    • Again, a handful out there, but if the script would exclude “EXPIRED & LOCKED” that’d be great.  Most significant was applsyspub.  I swear it used to be you were told not to change this, but it’s easy enough to fix with FNDCPASS
  • Check: For excessive privs in APPLSYSPUB
    • Passed this one
  • Check: Oracle Applications User Passwords Migrated to Non-Reversible Hash Password
    • Yeah, I hadn’t done this.  It’s an easy fix see 457166.1
  • Check: Server Security Status
    • Passed this one
  • Check: SSL Status
    • You need to be using TLS 1.2.  See 2143101.1.  If you’re not familiar with the process, welcome to a lot of work.  And now you get to keep up with an external signing authority!  Yay work!
  • Check: Credit Card Encryption Status
    • Beats me, I failed this, but we don’t store this in the database, so perhaps that would be helpful to note.
  • Check Status of 12.2 Security Features
    • I had a recommendations here, because I allowed unrestricted JSP access,  unrestricted redirects and a setting it didn’t like for Cookie Domain.  This is probably legitimate, but it’s going to cause havoc with our Oracle APEX implementation and will likely take time to fix.  There’s a script called in $FND_TOP/patch/115/bin which may help you (“Oracle E-Business Suite Release 12.2.6 delivers a configuration script which can assist in configuring the products in your Allowed JSP lists. Products will be turned off in the Allowed JSP family configuration files based on whether recent transactions are detected for the product. Customers are strongly recommended to configure the Allowed JSPs using this script.”).  Check out the Oracle EBS Security Guide
  • Check: Users with Access to Sensitive Pages
    • Disabled by default.  I guess I pass?

Where this falls apart for me

They’re going to hold your EBS hostage until you address security gaps?  Unacceptable.  While it’s true, you’re not going to wake up one morning to users unable to log into production, it’s still a rather arrogant shift.  I happen to know my company paid a fortune for their software, but now I’m not so confident we own it.  This feels like some back room legal department at Oracle decided to get a record that “so and so” at XYZ company deliberately agreed to ignore our security recommendations, and we have it on the record because they checked boxes acknowledging they assume the risk.  Except the reciprocal is not true.  If I get hacked despite having complied with Oracle recommendations, I’m pretty sure Oracle isn’t going to write me a check to help me fix it.

Oracle is making assumptions about my environment and punishing me if I don’t comply.  What if I have no internet exposure?  What if this is a DEV environment where I don’t care or can’t afford to keep up with TLS 1.2?

Instead, a warning message (old school nag screen) at login to any user stating something like “Your corporate EBS may be at risk to security vulnerabilities, please contact your system administrator” would have been equally effective.  I’m not going to let that screen be up there for the world to see, and I will get phone calls.  But if something happens beyond my control, my users can still get into EBS.

October 11, 2016

Determining your EBS Code Level and Family Pack

Filed under: Online Patching, Oracle, R12.2 — kkempf @ 10:29 am

Quick and Dirty

There’s lots of posts out there telling you how to determine your EBS patch levels, code levels, etc.  But whenever I google them, I can’t find the one that actually tells me what I want in a simplified way.

Here’s what matters most often to me as the Apps DBA:

  abbreviation in( 'ad','txk','fnd','fwk','atg_pf','icx' )
order by


ABBREVIATION                   CODELEVEL                                                                                                                                            
------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------
ad                             C.7                                                                                                                                                   
atg_pf                         C.4                                                                                                                                                   
fnd                            C.4                                                                                                                                                   
fwk                            C.4                                                                                                                                                   
icx                            D.3                                                                                                                                                   
txk                            C.7                                                                                                                                                   

 6 rows selected

August 9, 2016

How to Migrate an Oracle database host in R12.2 using LVM

Filed under: Oracle, Oracle Linux — kkempf @ 9:40 am

Painting the backdrop

I realize this post is somewhat specific to your setup, but I believe it may hold value to some folks out there so I thought I’d formalize it.  In my case, I have a rather large (1TB+) database residing on Oracle Linux (RHEL) 5 which serves as the back end for my EBS 12.2 environment.  We do not use ASM nor RAC, but do use Linux LVM (logical volume manager) to make growing disks easier.  The disk itself is on a SAN in the data center, so in my case this process involves some assistance from the systems/network folks.

I’m moving from OL5 to OL6 because support for OL5 is running down.  Let’s face it: the database works great on OL5, and I have no compelling reason to migrate it, but this is part of our lives: upgrades for the sake of upgrading.

For the purposes of this post, I’ll simply use oldhost as the OL5 hostname, and newhost as the OL6 hostname for the database, and appshost as the hostname for the applications tier.

In the olden days

Oracle used to have a bonafide methodology for migrating the database tier, in 11i it’s spelled out under DOC 338003.1.  It made sense; it said to use the tech stack on the front end to tell the application tier that there’s a new host for the database.

The R12.2 solution

I opened an SR to get the equivalent document for 12.2 and the analyst basically said “Follow Doc ID 1968231.1 to use logical hostnames, you can sort of use autoconfig but we don’t support it”.  I don’t know if that’s really the best answer, but it was all I had to go with.  I had been planning to use DNS as a safety net, not the primary vehicle of changing the database hostname.  But apparently it’s the only vehicle now, despite the fact that I enter hostname on the front end in the context file.  While I think this is a terrible answer, that’s not the point of my post so I’ll let it go.

LVM Setup (oldhost)

In my environment, I set up my lvm volume groups like this:

Data1 - product datafiles for EBS
Data2 - more product datafiles for EBS
Archivelogs - archivelog destination
Redo - online redo
System - system/sysaux datafiles
RDBMS - Oracle database installation (binaries)
As you can imagine, the files contained in these groups are pretty large; well over a terabyte.  In an ideal situation, I’d take the database down cold and simply rsync the files to the new host in the same location, then crank everything up.  But that would take hours I don’t have, so I went a different route.  It’s worth noting, that on OL5, my disks on oldhost are ext3, and OL6 delivers ext4.  Since I’m moving the disks “as is”, I’m getting ext3 filesystems on newhost, the OL6 server.  It’s compatible, and something I just have to live with.
I feel like I should mention at this point that probably the very first step was to build newhost as an OL6 environment with appropriate cpu and memory.

LVM Prep (oldhost)

  • The first step is to shut everything down, obviously, front and back end on oldhost and appshost.
  • Next, I unmount all the volumes pertaining to the environment (in this case, dev).  For my environment, each of these corresponds to an LVM volume group
    • umount /u01/appdev
    • umount /u03/appdev
    • umount /u04/appdev
    • umount /u05/appdev
    • umount /u06/appdev
    • umount /usr/local/oracle/archive
  • Set all the volume groups to inactive
    • vgchange -an Data2
    • vgchange -an Data1
    • vgchange -an Archivelogs
    • vgchange -an Redo
    • vgchange -an System
    • vgchange -an RDBMS
  • Export the volume groups
    • vgexport Data2
    • vgexport Data1
    • vgexport Archivelogs
    • vgexport Redo
    • vgexport System
    • vgexport RDBMS

Disk manipulation

At this point, the volumes can be safely manipulated by the disk admins.  What this entails will vary greatly based on  your datacenter, and is outside the scope of linux so I’m not going to detail it here.  The gist of it is that your admin needs to remove the disks/virtual disks from the old host and install them on the new one by whatever means is appropriate.  I apologize in advance if I’m not saying this part correctly.

Adding the disks (newhost)

The first thing to try (assuming your new host received the disks “hot”) is simply


They may just show up.  If not, you can try rescanning the scsi host:

ls /sys/class/scsi_host/ | whileread host ; do echo "- - -"> /sys/class/scsi_host/$host/scan ; done
-or this-
echo "- - -"> /sys/class/scsi_host/(host#, hit tab or guess)/scan
-for example this may turn into:

 echo “- – -” > /sys/class/scsi_host/host0/scan

echo “- – -” > /sys/class/scsi_host/host1/scan

echo “- – -” > /sys/class/scsi_host/host2/scan

Then issue
fdisk -l
and it’s worth noting you can watch /var/log/messages for the system to recognize new disks being added.  When all else fails, a reboot has never failed to get all disks recognized.
At this point, pvscan should show all your volume groups

Final steps (newhost)

It’s kind of the opposite of the prep steps:

  • Import the volume groups
    • vgimport Data2
    • vgimport Data1
    • vgimort Archivelogs
    • vgimport Redo
    • vgimport System
    • vgimport RDBMS
  • Active the volume groups
    • vgchange -ay Data2
    • vgchange -ay Data1
    • vgchange -ay Archivelogs
    • vgchange -ay Redo
    • vgchange -ay System
    • vgchange -ay RDBMS
  • Mount the disks (and put them in /etc/fstab so they survive a reboot!)
    • mount /dev/mapper/RDBMS-Dev /u01/appdev
    • mount /dev/mapper/System-Dev /u03/appdev
    • mount /dev/mapper/Redo-Dev /u04/appdev
    • mount /dev/mapper/Data1-Dev /u05/appdev
    • mount /dev/mapper/Data2-Dev /u06/appdev
    • mount /dev/mapper/Archivelogs-Logs /usr/local/oracle/archive

Final Steps

In my case, I had to do 3 final steps to comply with Oracle’s document and make everything work:

  • change /etc/hosts on appshost to explicitly refer to the newhost as oldhost… just in case
  • change listener.ora on newhost to be the new hostname on the database ($TNS_ADMIN)
  • add DNS record to change calls to old host to new one
  • Start up the database (newhost)

Parting Shots

This method took me about 30 minutes.  If the database were smaller, I’d simply rsync the ext3 filesytems to new disks built as ext4 on newhost.



May 25, 2016

When ADOP breaks because of the magic of checkfile

Filed under: Online Patching, Oracle, R12.2 — kkempf @ 3:57 pm

As usual, it’s been some time since I’ve thrown anything out here.  What’s been keeping me busy has been largely to do with ADOP.  I have a real love/hate relationship with this new addition to the EBS family, and lately it’s been more hate.

Oracle defines nocheckfile as an unsupported option which isn’t to be used unless explicitly stated in the readme for a patch.  Intriguing, wonder what that’s all about, why would it be there at all?  Let’s start from the beginning, defining default adop behavior and what checkfile does.  In theory, during the adop apply phase, the default option “checkfile” says “go see if I already know I have a more advanced or equal version of this code before I apply it”.  If it thinks it already has ingested this particular bit of code, don’t process it in an effort to save time during the patch.  Couple of key things here to note.  First, it’s trying to save me time.  Second, is it ever wrong about whether it’s already ingested an advanced version of the code?

First, let’s talk about saving time.  That’s a good thing.  If I only have to ingest 30% of a large patch, even using adop with the EBS available, that’s a good thing.  Now the second part.  It’s only good if it’s accurate.  100% accurate.  Because if it skips code I actually need, it turns out you wind up with a big, stinking mess to sort through.  There’s a little foreshadowing there.

Take this scenario, which you’ve probably guessed by now happened to me.  Some bug surfaced as a result of some aborted patch cycles which made my EBS adop cycle think it could safely skip pieces of a patch which it had thought were applied.  Only they weren’t, that patch cycle was aborted.

Here’s your first hint that you may be experiencing this: you get a warning during the apply phase that the patch already exists in your system, but you know that not to be the case.  At this point, Oracle thinks the patch is in, but you know it’s not.  So you innocently go on and use forceapply, per the adop “HINT”.  Now you also think the patch is in your system.  But it’s not.  Because of the magic of checkfile, and the fact that the patch was previously aborted and adop thinks it’s in there, you’re in a world of hurt now.

It’s a really insidious state to find yourself in, and the fix is to reapply the patches, using nocheckfile and forceapply.  This basically says “apply the patch despite the fact that you already think it’s installed, and force every bit of code into the system regardless of whether you think you already have it”.

I can tell you this: never run an adop abort without a full cleanup, as well as an fsclone to reset your patch environment.  That should keep you in good shape.  Officially Oracle now advertises this in Oracle E-Business Suite Maintenance Guide, Release 12.2 (Part Number E22954-20).  I strongly recommend reading that from cover to cover.  Because early on in 12.2, this wasn’t how adop abort was explained even by Oracle University.

March 10, 2016

My EBS R12.2 adop patch failed, now what?

Filed under: Oracle, R12.2 — kkempf @ 3:55 pm

adop fails a lot, especially when you’re building a regression test environment.  Remember the old DOS days when you yanked out the floppy disk but still had a: on the screen and DOS said (a)bort, (r)etry, (f)ail?  And abort and fail always seemed like the same thing, but somehow they weren’t?  Same thing with adop, only it calls them abandon and restart.

adop defaults to abandon=no restart=yes if not specified, but to me, that’s still a bit unclear.  For example, what the heck would abandon=yes restart=no do?  Here’s what I came up with

(1) abandon and cleanup (I strongly urge you to do a full cleanup, or you may be asking for trouble)

adop phase=abort,cleanup cleanup_mode=full
adop phase=fs_clone

(2) fix the problem via whatever means (adctrl in the patch environment, drop the index the patch is trying to re-create, etc) and retry from where it failed

adop phase=apply patches=17020683 restart=yes [abandon=no is implied and not required]

(3) fix what’s wrong but retry from the beginning of the patch, or try a new patch (why you would do the latter, I have no idea)

adop phase=apply patches=17020683 abandon=yes [restart=yes is implied and not required]   (same patch)
adop phase=apply patches=17893964,18497540 abandon=yes          (new patch)


December 9, 2015

FND_LOBS and Securefiles (Part II)

Filed under: 11g, 12c, R12, R12.2 — kkempf @ 3:03 pm

An Actionable Plan

Last post, I talked about how I was playing with securefiles, fnd_lobs, deduplication and advanced compression.  It took a bit of tweaking, but I think I can safely share my success at reigning in FND_LOBS.  I’m going to outline the process of an online conversion from FND_LOBS defined as a basicfile (the default) to securefiles.

Jumping off a Bridge

Ever see Oracle do a presentation and the first slide is legalese called a Safe Harbor which basically says everything you are about to see and hear is subject to change and no business plans should be made on assumptions or potential future releases?  I feel like I should make a similar warning, let’s call it a bridge jumper.  Remember the old saying, “If all your friends jumped off a bridge, would you do it too?”.  Here’s what I’ll say: This works in DEV on EBS version R12.2, and I’ve done some minimal functional testing.  Don’t do it in PROD until you prove that it doesn’t impact something I forgot about or can’t foresee.  I recommend a regression pass.  Also don’t use products you’re not licensed for, such as advanced compression, even in non-production environments.


Just the Highlights

You can convert your FND_LOBS table via online redefintion from basicfiles to securefiles.  In doing so, you will define the new lob table as securefile storage, and if you use deduplication and compression clauses, you will probably save a lot of space.  I did, dropping from 150GB to about 50GB.

select a.owner, a.table_name, a.column_name, a.segment_name , b.bytes/1024/1024
    from dba_lobs a, dba_segments b
    where a.segment_name = b.segment_name
    and a.owner = b.owner
    and a.table_name like 'FND_LOBS%'
   order by b.bytes/1024/1024 desc
SQL> /
OWNER                   TABLE_NAME              COLUMN_NAME                     SEGMENT_NAME            B.BYTES/1024/1024
------------------------------ ------------------------------ --------------------------------------------------
APPLSYS                FND_LOBS               FILE_DATA                      SYS_LOB0000034032C00004$$        149115.25

By the Numbers

I really wish WordPress would let me paste code in better, as I could make this a lot easier on the eyes.  Well you get what you get.

1. Increase the size of your APPS_TS_MEDIA tablespace until you can hold at least another table some percentage of the size of your FND_LOBs lob segment.  See my prior post to figure out how to determine this.

2. Create FND_LOBS_NEW (yeah, creative name right?) using the same syntax as your old table.  Note deduplicate, compress high clauses.

  table applsys.fnd_lobs_new
    file_id          number
  ,file_name         varchar2( 256)
  ,file_content_type varchar2( 256) not null
  ,file_data blob
  ,upload_date     date
  ,expiration_date date
  ,program_name    varchar2( 32)
  ,program_tag     varchar2( 32)
  ,language        varchar2( 4) default( userenv( 'LANG') )
  ,oracle_charset  varchar2( 30) default( substr( userenv( 'LANGUAGE'),instr( userenv( 'LANGUAGE'),'.') + 1) )
  ,file_format     varchar2( 10) not null
  ,primary key( file_id ) validate
  tablespace apps_ts_media pctfree 10initrans 10maxtrans 255storage
    initial 128k buffer_pool default
  logging nocompress lob
  store as securefile
    deduplicate compress high tablespace apps_ts_media chunk 8192storage( initial 128k buffer_pool default) pctversion 0nocache logging
  ) ;

3. Take your new table out of logging and enable parallel dml in an effort to save time:

  • alter table applsys.fnd_lobs_new nologging;
  • alter session force parallel dml parallel 4;
  • set timing on

4. Map the columns to the new table (this ran about 12 hours for me)

  l_col_mapping varchar2(1000);
  l_col_mapping :=
     'file_id file_id, '
   ||'file_name file_name, '
   ||'file_content_type file_content_type, '
   ||'file_data file_data, '
   ||'upload_date upload_date, '
   ||'expiration_date expiration_date, '
   ||'program_name program_name, '
   ||'program_tag program_tag, '
   ||'language language, '
   ||'oracle_charset oracle_charset, '
   ||'file_format file_format'
   dbms_redefinition.start_redef_table ('APPLSYS', 'FND_LOBS', 'FND_LOBS_NEW', l_col_mapping)

5. Drop the existing index on APPLSYS.FND_LOBS_CTX (intermedia index). At this point, you may experience adverse performance on FND_LOBS for some users, but this index is of the insides of the LOBs as I understand it, so I doubt anyone will notice (your primary key remains available).  If you don’t do this, the next step fails spectacularly

drop index applsys.fnd_lobs_ctx;

6. Begin the redefinition process.  This ran really fast for me.

   l_error_count pls_integer := 0;
   dbms_redefinition.copy_table_dependents('APPLSYS', 'FND_LOBS', 'FND_LOBS_NEW', 1, TRUE, TRUE, TRUE, FALSE, l_error_count)
   dbms_output.put_line('Errors Occurred := '|| to_char(l_error_count))

7. Finish the redefinition process.  Also very fast.

       ('ARUP', 'FND_LOBS', 'FND_LOBS_NEW');

8. Confirm it worked

select securefile
from dba_lobs
where table_name = 'FND_LOBS'

9. Space check

select a.owner, a.table_name, a.column_name, a.segment_name , b.bytes/1024/1024
    from dba_lobs a, dba_segments b
    where a.segment_name = b.segment_name
    and a.owner = b.owner
    and a.table_name like 'FND_LOBS%'
   order by b.bytes/1024/1024 desc
OWNER                   TABLE_NAME              COLUMN_NAME             SEGMENT_NAME            B.BYTES/1024/1024
------------------------------ ------------------------------ ------------------------------ ------------------------------
APPLSYS                FND_LOBS               FILE_DATA              SYS_LOB0008283556C00004$$            46987

Elapsed: 00:00:11.64

10. Drop the temp table

drop table fnd_lobs_new;

11. Recreate the index APPLSYS.FND_LOBS_CTX from the EBS script.  This ran about 5 hours for me.

cd $FND_TOP/sql
sqlplus apps
SQL> @aflobbld.sql APPLSYS APPS

12. Gather statistics


Parting Shot

It occurs to me during cleanup, that if you create your “temporary” FND_LOBS table (in my case, FND_LOBS_NEW) in a new tablespace instead of apps_ts_media, once you’re done you could probably reclaim all the disk allocated for this one-time project. The alternative is that your apps_ts_media is now 3x (or more) what you need, as you eliminated your large, basicfiles FND_LOBS table, and now have a compressed and deduplicated version on securefiles which will presumably take a long, long time to fill up your apps_ts_media tablespace now that you’ve expanded it for the project. Because of high water marks, I was unable to shrink my tablespace in any significant way after I was done.

That’s It Folks

I tested this a few ways from the functional standpoint.  I ran a report which printed a LOB (Invoice) which was part of a requisition.  I opened an attachment in Quality.  I saved an attachment in Quality.  Everything checked out.  On to a full regression cycle!  Thanks for tuning in, let me know if you find this useful.

December 4, 2015

FND_LOBS and Securefiles (Part I)

Filed under: 11g, R12.2 — kkempf @ 11:05 am

FND_LOBS, how I hate thee

In our EBS environment, users have filled up FND_LOBS with attachments for the past 10 years.  From a functional standpoint, this is mostly quotes (.pdf’s) attached to purchase orders, and M$ Office documents attached to customer orders.  It grows without bounds, and in most cases there’s no expiration date included in the table or means to purge it with any reassurance that I’m not breaking something.  During a database 12c class last summer in Chicago, I learned some of the benefits of securefiles and it seemed like something to look into.  Then I was at a conference in Raleigh in September and it came up again.  Seeing a trend, I decided to start playing around with it (finally, yes, I know this is not new technology!).


Securefiles are like lobs 2.0 in Oracle.  It’s their attempt to better manage unstructured data within Oracle, and it’s a core database feature, having nothing directly to do with EBS.  The best document I found on it was here.  Here’s what caught my attention: it can leverage deduplication and advanced compression.  I didn’t see any easy way to see what % of my FND_LOBS content was duplicate, but let’s be honest, users don’t care if they upload the same thing 10 times, it’s not their problem.


As usual, check with your sales rep before you do this stuff in production.  Some of what I’m doing requires a license for Advanced Compression on your core database, and that’s not cheap.

Sizing up the Problem

A quick query shows that the fnd_lobs table (really, it’s associated lob segment) is consuming 150 GB.  That may not seem staggering, except multiply it by all EBS instances, add dataguard, and account for increased backup times and sizes, and it gets my attention.  Also take into account that this one object accounts for ~15% of my database size.  It’s been on my radar for a long time.

select a.owner, a.table_name, a.column_name, a.segment_name , b.bytes/1024/1024
from dba_lobs a, dba_segments b
where a.segment_name = b.segment_name
and a.owner = b.owner
and a.table_name like ‘FND_LOBS%’
order by b.bytes/1024/1024 desc

APPLSYS    FND_LOBS    FILE_DATA    SYS_LOB0000034032C00004$$    149115.25
APPLSYS    FND_LOBS_DOCUMENT    CONTENT    SYS_LOB0000034093C00008$$    0.125

A Quick and Dirty Test Case

I wanted to see what my space savings was going to be if I converted this table to securefiles.  Thus I added a little space to apps_ts_media (well, a lot!) and created a table called fnd_lobs_new to look just like fnd_lobs, except it used securefiles as it’s lob storage choice, and high compression.

  table applsys.fnd_lobs_new
 (file_id          number
 ,file_name         varchar2( 256)
 ,file_content_type varchar2( 256) not null
 ,file_data blob
 ,upload_date     date
 ,expiration_date date
 ,program_name    varchar2( 32)
 ,program_tag     varchar2( 32)
 ,language        varchar2( 4) default( userenv( 'LANG') )
 ,oracle_charset  varchar2( 30) default( substr( userenv( 'LANGUAGE'),instr( userenv( 'LANGUAGE'),'.') + 1) )
 ,file_format     varchar2( 10) not null
 ,primary key( file_id ) validate
 tablespace apps_ts_media pctfree 10 initrans 10 maxtrans 255 storage
 initial 128k buffer_pool default
 logging nocompress lob
 store as securefile
 deduplicate compress high tablespace apps_ts_media chunk 8192 storage( initial 128k buffer_pool default) pctversion 0 nocache logging
alter table applsys.fnd_lobs_new nologging;
insert into applsys.fnd_lobs_new select * from applsys.fnd_lobs;  (this takes a LONG time.  As in 12+ hours for me)
select a.owner, a.table_name, a.column_name, a.segment_name , b.bytes/1024/1024
    from dba_lobs a, dba_segments b
    where a.segment_name = b.segment_name
    and a.owner = b.owner
    and a.table_name like 'FND_LOBS%'
   order by b.bytes/1024/1024 desc
SQL> /
OWNER                   TABLE_NAME              COLUMN_NAME                     SEGMENT_NAME            B.BYTES/1024/1024
------------------------------ ------------------------------ -------------------------------------------------- ------------------------------ -----------------
APPLSYS                FND_LOBS               FILE_DATA                      SYS_LOB0000034032C00004$$        149115.25
APPLSYS                FND_LOBS_NEW              FILE_DATA                      SYS_LOB0008283485C00004$$        46989.875
APPLSYS                FND_LOBS_DOCUMENT          BLOB_CONTENT                     SYS_LOB0000034093C00007$$               25
APPLSYS                FND_LOBS_DOCUMENT          CONTENT                         SYS_LOB0000034093C00008$$             .125

Bottom Line

I reduced fnd_lobs from 150GB to 47GB.  That’s a win!

Next Steps

My test isn’t practical.  I simply wanted to see if there was enough gain to continue with an online conversion.  There is.  Next post I hope to show you exactly how to convert FND_LOBS to securefiles without any downtime.

October 29, 2015

Fun with adop

Filed under: 11g, R12.2 — kkempf @ 1:58 pm

Sphincter said what?

I was doing some core ETCC database patching against a 12.2 DEV instance today.  I was hoping to get to AD/TXK Delta 7 and see how that worked.  But after a big opatch session, when I restarted services, adop phase=prepare threw this error:

Validating system setup…
[ERROR]     Failed to execute SQL statement :
select AD_ZD_ADOP.GET_INVALID_NODES() from dual
[ERROR]     Error Message :
[ERROR]     Failed to execute SQL statement :
select AD_ZD_ADOP.GET_INVALID_NODES() from dual
[ERROR]     Error Message :
[UNEXPECTED]Nodes “-1” are listed in ADOP_VALID_NODES table but not in FND_NODES table.
[UNEXPECTED]To correct this, run AutoConfig on nodes “-1”
[UNEXPECTED]Error while checking if this is a multi node instance

MOS had a direct hit on this (1988581.1):  “Nodes “-1″ are listed in ADOP_VALID_NODES table but not in FND_NODES table.”, but it didn’t fix the issue.  In fact in accordance with this note I was fine.

The Fix

On the database tier, go to $ORACLE_HOME/appsutil/admin and re-run adgrants, then recompile the package:

sqlplus / as sysdba

@adgrants apps

alter package apps.AD_ZD_ADOP compile body;

After this, adop phase=prepare ran happily enough, and included an explicit autoconfig.  I can’t promise this will work for you, but since the error message is rather vague and unhelpful I thought I’d post this.

Older Posts »

Create a free website or blog at