Monday, January 28, 2013

Big BLOBs being greedy in TEMP tablespace


I work in a small team. There are just five of us at the 'coalface' for the application, responsible for both development and production. One of the five acts as the 'DBA/Sysadmin' (as well as doing programming and acting team as leader when the actual team leader is on leave and filling in a couple of other roles). And he was on leave on Friday when we got the plaintive email with the subject "The application is broken".

We could log in and out, so it wasn't 'catastrophic'. The application is mostly APEX, so my next step was to check the Apex activity log where I saw "ORA-01652: unable to extend temp segment by 128 in tablespace TEMP". The error was at least 'extreme'. 

Yes, a DBA probably would have gone to the alert.log first. I am not a DBA :)

Prompted by that message, I ran a query across V$TEMPSEG_USAGE to find several inactive sessions under APEX_PUBLIC_USER holding hundreds of MBs of temporary LOB segments. With a temp tablespace around 2GB, this level of usage isn't sustainable. The quick solution was just to shoot the sessions. 

APEX lies on top of HTTP, a stateless protocol and the session state is actually preserved in tables (check out Scott Wesley's post on viewing Apex session state). It generally isn't a problem if you kill one of the database sessions forming the connection pool and it isn't active.

On further investigation, we have identified one trouble spot, which is an application component that allows users to upload and download files. It seems that recently they have been doing large files (hundreds of MB). When the files are uploaded or download it allocates a temporary LOG segment and it holds onto the segment even after a commit or a DBMS_LOB.FREETEMPORARY or a reset package state. 

Those end users aren't getting the same database session each time oo if they do several file transfers, multiple sessions can be hanging onto these hundreds of MB of temporary segments. With around 20 sessions at peak, that was locking up our 2GB temp file.

As a stop-gap, we've introduced a scheduled job every three hours to kill off greedy sessions. It is an ugly solution though, and we'll be discussing options when we're all back at work after the long weekend. These include


  • A support note that points to event 60025 to free up the stray LOB segments
  • Tying the file upload/download component to one or two database sessions
  • File size limits on uploads and downloads
  • Is Apex the appropriate security gate-keeper to those fils
  • Can we avoid dealing with the 'entire' file, and just have a few MBs at a time

If you have any other suggestions, feel free to add a comment.

Sunday, January 27, 2013

Engaging with Google+

In the pub after the Sydney Oracle Meetup ('SQL Developer for DBAs, featuring a guest recorded appearance by the one and only +Jeff Smith ), Google+ got a mention. Okay, it was me who mentioned it, and it was closely followed by a remark by another attendee that he didn't know anyone else who used it.

It is getting some traction, apparently overtaking Twitter in active members ( I don't know how the figures are calculated. Twitter is more high profile still, possibly because practically every tweet is public).

Google+... grew in terms of active usage by 27% to 343m users to become the number 2 social platform. Interestingly for Google, YouTube (not previously tracked by us as a social platform) comes in at number 3....

But it is still a geeky place. The most popular communities are Space, Android and Photography. Photography is big in G+. Sport less so, with the Minecraft community being bigger than the 'F1 Racing' group (which is the biggest of any sport).

Google+ Tips and Suggestions

If you do want to get active in G+, finding appropriate communities is a good start.

Try Science Sunday or IT Professionals for active groups, or find something aligned to your non-work interests. There's no busy Oracle community yet. If you are an Oracle person, feel free to join the Sydney Oracle community (even if you don't live around here).

If you want a selected set of individuals to start with, I've shared a circle here. Some of them (Laurence Pegard and Artsaholic) are 'visual' posters with lots of imagery. Wired, The Economist and the Daily WTF will be known to anyone reading this. Frankly the comments on the Economist posts often fall into the drivel category.Tim Hall and Jeff Smith are included because they are the bigger Oracle 'identities'. David Brin is the sci-fi author, and the others represent good originators or curators of content.

I have one circle that is empty. I share articles to that if I want to read them later.

I have a circle for 'local' content (where it will be active during the daytime in Australia) and another for 'Following' a group of people who post stuff that I don't want to miss. I catch up on that group in the mornings (mostly) simply reading back to the last post I remember.

I have a 'Background' circle of stuff that I can read if I have time, but I can skip when bust. And I sometimes have 'potential' circles where I've imported a bunch of people and want to filter them into a better circle, or remove them altogether,

I generally remove (uncircle) people for posting lots of cat pictures or memes, or if they have a very high noise to signal ratio. I block people who irritate me. It makes life more pleasant.

If you comment on an article, you get notifications for subsequent comments (unless you mute the post). If you follow interesting people, you can often find other interesting people when they comment on interesting posts.

I don't expect people I follow to follow me back. I don't expect to find people I know in real-life.
Lots of people don't post publically. Mostly women, and mostly because of creeps. Because of this, you might need to wait until you are circled by them before you actually see any content from them.

Also, stick enough information in your profile so that people know 'what you are about'.

Thursday, January 10, 2013

Greatest, Least and NULLs

The functions greatest and least are amongst the special ones which can take lots of arguments. They are a bit similar to min and max for columns rather than rows. But they have one difference to the aggregate functions that meant I avoided them for a long time.

Unlike aggregate functions, which ignore null values,  greatest and least will return a null if any of the supplied columns (or expressions) are null. If that isn't what you want (and it often isn't) it means putting NVLs around everything and with substitution values that don't break the logic.

For example, 


create table state_sum
  (style varchar2(10), 
  nsw number, vic number, wa number, qld number, 
  sa number, tas number, nt number, act number);
  
begin
  insert into state_sum values
    ('Red',5,3,9,null,1,7,8,null);
  insert into state_sum values
    ('Blue',null,null,null,null,null,null,null,null);
  insert into state_sum values
    ('Green',10,9,8,7,6,5,4,3);
  commit;
end;
/

If I try a 
SELECT least(nsw,vic,wa,qld) 
FROM state_sum 
WHERE style  = 'Red';
It will return a null (because there's a null value for the QLD column);

I could try
SELECT least(nvl(nsw,0),nvl(vic,0),nvl(wa,0),nvl(qld,0)
FROM state_sum 
WHERE style  = 'Red';

But that returns a 0 because that has been substituted for the QLD null. To get the lowest 'real' value, I'd need to NVL with a value so high that it could never be the lowest. A similar problem occurs for greatest except you can probably get away with a zero....up until you get a set of negative numbers. And don't even get me started on character and date values.

In short, I never found these functions to be as useful as intended.

But once in a while this apparent drawback in their management of null values does make them useful.

Coalesce, greatest/least and null tests

I have become a fan of coalesce as NVL on steroids. 
I never liked NVL2. It might be useful, but if you can't actually give it a decent name, then you shouldn't have bothered. Or maybe just wait till you invent the concept of overloading and simply have the existing two-parameter NVL and an additional three-parameter NVL instead of NVL2.

If you haven't used it, it returns the first no-null value in the list. And, like greatest/least, it can take lots of arguments.

SQL> select style from state_sum
  2  where coalesce(nsw,vic,wa,qld,sa,tas,nt,act) is null;

STYLE
----------
Blue

SQL> select style from state_sum
  2  where coalesce(nsw,vic,wa,qld,sa,tas,nt,act) is not null;

STYLE
----------
Red
Green

But what if you want to know if any of the values are null. That is, you want Red and Blue, but not Green (or vice versa).
Yep, you guessed it. That's where you can use  greatest/least.


SQL> select style from state_sum
  2  where least(nsw,vic,wa,qld,sa,tas,nt,act) is null;

STYLE
----------
Red
Blue

SQL> select style from state_sum
  2  where least(nsw,vic,wa,qld,sa,tas,nt,act) is not null;

STYLE
----------
Green

And it is easy enough to combine them 

SQL> select style,
  2         case when least(nsw,vic,wa,qld,sa,tas,nt,act) is null 
                 then 'Y' else 'N' end nulls_present,
  3         case when coalesce(nsw,vic,wa,qld,sa,tas,nt,act) is null 
                 then 'Y' else 'N' end all_null
  4  from state_sum;

STYLE      N A
---------- - -
Red        Y N
Blue       Y Y
Green      N N


Saturday, January 05, 2013

Inskipp the uncatchable exception

The world is full of exceptions. And exception handlers.

And sometimes, just sometimes, it actually makes sense to have a WHEN OTHERS. For example, if a program fails, under any circumstances, maybe you want it to log the exception or send an email to a support account.

But then, just sometimes, you want a program to FAIL, and to fail in such a way that even the most resilient of exception handlers won't catch it. Maybe you're working on a function that gets called way down the bottom of a deep call stack, and right there at the top is a WHEN OTHERS exception handler you can't afford to trigger.

PL/SQL doesn't support classes or sets or exception handlers. But there's one exception that is superspecial. Okay, NO_DATA_FOUND is special, as I've discussed before, but this one is special in a different way.

This is exception -0028, licenced to die. (Actually, the double-zero prefix is unnecessary, but it is still Christmas holidays for me, so I'm sneaking in a Bond reference).

This is a regular exception.


SQL> declare
  2    e_suicide exception;
  3    pragma exception_init(e_suicide,-27);
  4  begin
  5    raise e_suicide;
  6  exception
  7    when others then
  8      dbms_output.put_line('Caught:'||sqlcode);
  9  end;
 10  /
Caught:-27

PL/SQL procedure successfully completed.

And this is the uncatchable exception (oh, and Inskipp the uncatchable was a character from the Stainless Steel Rat)

SQL> declare
  2    e_suicide exception;
  3    pragma exception_init(e_suicide,-28);
  4  begin
  5    raise e_suicide;
  6  exception
  7    when others then
  8      dbms_output.put_line('Caught:'||sqlcode);
  9  end;
 10  /
declare
*
ERROR at line 1:
ORA-00028: your session has been killed
ORA-06512: at line 5

When it says the session has been killed, it means it. It is dead. An ex-session. Not pining for a PGA, but deceased and bereft of state.

SQL> select 1 from dual;
select 1 from dual
*
ERROR at line 1:
ORA-01012: not logged on

This one will return control to the calling program and a new connection will need to be established to the database if desired.