THE WORLD DISCUSSES #PYTHIAN ON TWITTER. HAVE A QUESTION? USE OUR HASHTAG AND ASK AWAY.

Deferrable constraints in Oracle 11gR2 may lead to logically corrupted data

I’ve hit a bug in Oracle 11.2.0.1 when working with deferrable constraints which I think is worth sharing as it may have profound consequences under certain scenarios.

Let’s start by creating a simple table with a deferrable primary key:

SQL> create table def_bug(n number primary key deferrable initially deferred);

Table created

SQL> insert into def_bug values (1);

1 row inserted

SQL> insert into def_bug values (2);

1 row inserted

SQL> commit;

Commit complete

You can confirm that the primary key constraint is working fine by trying to insert a duplicate value:

SQL> insert into def_bug values (1);

1 row inserted

SQL> commit;

commit

ORA-02091: transaction rolled back
ORA-00001: unique constraint (SRC.SYS_C004070) violated

So far so good. Open a second session and execute the following update:

SQL> update def_bug set n=3 where n=2;

1 row updated

Do not commit yet and execute in your first session:

SQL> update def_bug set n=3 where n<=2;

The above update will block due to our second session holding a lock on the row where n=2. Now commit your second session…

SQL> update def_bug set n=3 where n=2;

1 row updated

SQL> commit;

Commit complete

…and then commit your first session:

SQL> update def_bug set n=3 where n<=2;

1 row updated

SQL> commit;

Commit complete

Take a look at the data now:

SQL> select * from def_bug;

         N
----------
         3
         3

Ouch! This was certainly unexpected. You can confirm that the primary key is still working by trying to insert a duplicate value again:

SQL> insert into def_bug values (3);

1 row inserted

SQL> commit;

commit

ORA-02091: transaction rolled back
ORA-00001: unique constraint (SRC.SYS_C004070) violated

It certainly looks like the update statement did not take into account deferrable constraint declared on the table during restart caused by the write consistency mechanism.

Oracle 11g SE Switch-Over

Recently, I tested a switchover on Oracle 11g SE1.

As you know, Oracle Database Standard Edition One—as well as Standard Edition—does not have the Data Guard feature. Therefore, I had to do everything manually.

The whole process took less than 15 minutes. This includes less than five minutes of full downtime to restart the database in READ-ONLY mode, and less than 10 minutes of READ-ONLY downtime.

Of course, it depends on the size of Redo logs and the network speed to move Redo logs from the primary server to standby.

Here is what I had. The primary database and one physical standby database:

  • OS – SUSE Linux ES10 (SP2) x86_64
  • Oracle – Release 11.1.0.7.0 64bit SE1

First of all, I switched the standby database to the primary role.

Read the rest of this entry . . .

Bug in DBD::Oracle’s execute_array with 11g

There seems to be a bug in DBD::Oracle’s execute_array when working with 11g.

If you tell DBD::Oracle to autocommit, it seems that in 11g this commit will not take place when an error occurs during the processing of one of the tuples that you passed into execute_array. So given this table:

CREATE TABLE test_array (
	    row_1 INTEGER NOT NULL,
	    row_2 INTEGER NOT NULL,
	    row_3 INTEGER NOT NULL)

the following code will result in no records being added to the db.

# create a database handle
my $dbh = DBI->connect('dbi:Oracle:','xxx@xxx','xx',{
	RaiseError			=> 1,
	PrintError			=> 0,
	ShowErrorStatement		=> 1,
	AutoCommit			=> 1

}) || die "Unable to establish connection with Oracle server: $DBI::errstr";

my $rv;
my @var1         = (1,1,1,1,1,1,1,1,1,1);
my @var2         = (2,2,2,2,'s',2,2,2,2,2);
my @var3         = (3,3,3,3,3,3,3,3,3,3);

my $tuple_status = [];
my $dumped ;
my $rows = [];

$sth->execute_array(
        {ArrayTupleStatus => $tuple_status},
          \@var1,
          \@var2,
          \@var2,
   );

The workaround is to set AutoCommit => 0 and then use $dbh-->commit() after the statement.

So far, the jury is out whether this is a bug only in 11g, but as this code works correctly in 9 and 10 (it adds the 9 rows), it seems likely. I have noted the bug here: http://forums.oracle.com/forums/thread.jspa?messageID=2663832#2663832.

Oracle 11G Result Cache in the Real World

As some of you probably already noticed, there was a thread on AskTom discussing the scalability tests I did back in 2007. You are welcome to read the entire thread, but in a nutshell, Tom Kyte claimed that my tests did not reflect how one would use the result cache in the real world.

What is “real world?”

Of course, the important question is whether I tested a feature in a way it was never designed to be used, or whether someone is just trying to make an excuse for poor scalability results by defining “real world” in a way that makes my tests inappropriate.

A new feature

What do you do, then, you first see a new feature? You read about it in the documentation, and then you test it in order to compare what you have read with what you have in reality.

What the documentation tells us

Open the Performance Tuning Guide and go to 7.3.1.4 Result Cache Concepts:

When these queries and functions are executed repeatedly, the results are retrieved directly from the cache memory. This results in a faster response time. The cached results stored become invalid when data in the dependent database objects is modified. The use of the result cache is a database-wide decision.

All it says is that you have to have repeatedly-executed functions and queries to get faster response time. It says nothing about what kind of queries or functions. It also suggests that the result cache should be used database-wide or shouldn’t be used at all (which is perfectly sound according to Jonathan Lewis’s Rules for Hinting).

Now skip up to 7.3.2.7 Use of Result Cache:

OLTP applications can benefit significantly from the use of the result cache. The benefits highly depend on the application. Consider the use of the PL/SQL function result cache and the SQL query result cache when evaluating whether your application can benefit from the result cache.

It clearly says that result cache is perfectly appropriate for OLTP applications. They leave a backdoor with the words, “depend on the application” but, yet again, they say nothing about what kind of OLTP applications.

Read the rest of this entry . . .

Installing Oracle 11g on Ubuntu 8.04 LTS (Hardy Heron)

Note: Installing Oracle 11gR1 on Ubuntu 8.10 Intrepid Ibex is now published.

After our last post about installing Oracle 11g on Ubuntu 7.10 (November, 6th), and considering Ubuntu 8.04 LTS was released on April 21st, I spent some time reviewing and putting together this new HOWTO for the installation.

Please note: I’ve used the x86 server version of Ubuntu 8.04, but the same steps should work without any problems for the Desktop version. Also notice that this whole procedure can easily take over six hours to complete, so don’t complain I didn’t warn you!

So, let’s get started, shall we?

Step One

Get the Ubuntu Linux 8.04 Hardy Heron (x86, 32-bit) image here, burn it, and install on any box you like. The only remark on the installation is that you should ask the installer to install an OpenSSH server at the end of the installation, since we’ll perform all the steps on this procedure remotely.

I’m not sure about the minimum requirements for the server, as, the last time I checked, running Oracle on Ubuntu is not officially supported by Oracle. In case you’re wondering, however, I’m using an x86 Pentium-like machine with 512M of RAM.

Step Two

Download Oracle 11g for Linux (x86, 32-bit).

Read the rest of this entry . . .

Another Tip on Using dg4odbc: Materialized Views

After setting up dg4odbc to connect to a SQL Server database (read ‘Tips on Using dg4odbc on 64-bit Linux’), I spent last week trying to get refreshes of materialized views to work in 11g, using the same DDL as in 8i. I was very frustrated to see the refreshes break in 11g.

The DDL gives no obvious clues. The remote table:

desc MYTABLE@SQLSERVER
Name                           Null?    Type
------------------------------ -------- ----------------------------
MY_ID                          NOT NULL NUMBER(5)
MY_DESC                        NOT NULL VARCHAR2(40)

SQL> create materialized view MV_MYTABLE
2 as select *
3 FROM   MYTABLE@SQLSERVER
4 WHERE  MY_ID IS NOT NULL
5 AND    MY_DESC IS NOT NULL;

Materialized view created.

SQL> begin
2  DBMS_SNAPSHOT.REFRESH( 'MV_MYTABLE','C');
3  end;
4  /
begin
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-01400: cannot insert NULL into (%s)
ORA-02063: preceding line from SQLSERVER
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2537
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2743
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2712
ORA-06512: at line 2

The reason, it turns out, is the ANSI-compliance of dg4odbc. The remote table has a row where the column MY_DESC is storing a '' (a zero-length string).

SQL Server treats the zero-length string as different from NULL. Oracle 11g treats zero-length strings as the same as NULL. Read the rest of this entry . . .

How To Set Up Oracle ASM on Ubuntu Gutsy Gibbon

I’ve recently moved to Ubuntu Linux, and this post describes my attempt to play around with Oracle ASM on Ubuntu. For this demonstration, I used Oracle 11.1.0.6 on Gutsy Gibbon. I hope it will be useful to somebody out there.

Important Notice: What I describe below is among the worst thing you can ever do with ASM. You can use it to play around but never use it with anything other than test data. If you lose something because of me, you’ll be the only one to blame !

Question #1: How do you simulate a disk from a file?

(See here for more details.)

If you have a free partition or disk to be used as an ASM disk, just skip this step. If you don’t, you can create a file with the dd command and create a device that actually loops to the file with the losetup command.

Let’s assume you’ve created a directory named /asmdisks (and you have write access to it). Run the command below to create a file named disk1 that is 3GB in size:

$ dd if=/dev/zero of=/asmdisks/disk1 bs=1024k count=3072
3072+0 records in
3072+0 records out
3221225472 bytes (3.2 GB) copied, 80.9113 seconds, 39.8 MB/s

Once you’ve created the file, map it to a device named loopN in /dev. You can list the used loop devices with the losetup -a command.

Once you’ve made sure the one you plan to used is free, e.g. /dev/loop1, you can map the device to the file with the following commands (you have to be root) :

# losetup /dev/loop1 /asmdisks/disk1
# losetup -a
/dev/loop1: [0802]:7438407 (/asmdisks/disk1)

Question #2: How do you create an interface to the disk that is usable by ASM?

Read the rest of this entry . . .

Oracle 11g: Another New SQL*Plus Command

I have been using this SQL*Plus command for a while now:

SQL> show spparameter service_names

SID      NAME          TYPE        VALUE
-------- ------------- ----------- ---------
*        service_names string      REDX

And guess what ?

  • The right syntax is actually show spparameters (with a “s” at the end of it).
  • It’s an 11g New Feature!

It doesn’t work with 10g:

SQL> show spparameters service_names

SP2-0735: unknown SHOW option beginning "spparamete..."
SP2-0735: unknown SHOW option beginning "service_na..."

I thought MySQL was trying to become as big as Oracle but it could be that Oracle is trying to become as cool as MySQL — it has had something like this for a long time! Now Oracle should add SHOW TABLES too.

Anyway, this is really 11g’s most useful feature so far, though.

Oracle Data Pump 11g: Little-Known New Feature

While perusing the Oracle 11g Data Pump documents recently, I noticed a new parameter that was introduced in Oracle 10g, but I had missed it there. The parameter is TABLE_EXISTS_ACTION, and it applies only to the Data Pump Import.

Basically, this feature allows you to decide how to handle importing data if a table already exists. The options are SKIP (defaut), APPEND, TRUNCATE, and REPLACE. Do these parameters look familiar? Possibly reminiscent of the SQL*Loader parameters (INTO TABLE x INSERT/REPLACE/TRUNCATE/APPEND)? They are very similar and they work the same way, with the exception of SKIP.

Here’s an explanation of each option.

  • SKIP: The default value for TABLE_EXISTS_ACTION. If the table exists, then SKIP will cause the table (and any related data) to not be loaded. The table will be skipped.
  • TRUNCATE: This will truncate the data in the table and load the data. If the table already exists, no metadata will be applied.
  • APPEND: This will append the data to the end of the table. Again, if the table already exists, no metadata will be applied.
  • REPLACE: This will drop the existing object, recreate the object with the information from the dumpfile, and then load the data.

Let’s create a simple test case to demonstrate. Read the rest of this entry . . .

Oracle 11g Result Cache Tested on Eight-Way Itanium

This will be the final post in my series on Result Caches. In my previous article, I had already got almost everything. Almost — four CPUs (cores) were still not enough to saturate the single latch. As you’ve probably already guessed, today we are going with an eight-way test.

Please note that today’s numbers are different since I’m using an entirely different hardware platform. While the four-way tests were done on a 2.4GHz Core 2 Quad box, today’s eight-way tests were done using four dual core Itanium 2 CPUs running at 1.1GHz.

Let’s take a look at the results:

# of processes Buffer Cache % linear Result Cache % linear
1 15085 100% 15451 100%
2 26745 88.65% 28881 93.46%
3 39144 86.5% 40628 87.65%
4 52342 86.75% 52625 85.15%
5 63922 84.75% 62767 81.25%
6 76336 84.34% 69549 75.02%
7 88844 84.14% 74208 68.61%
8 100959 83.66% 76768 62.11%

I made a nice-looking graph from this:

BC vs. RC

Read the rest of this entry . . .

Start NowWith Pythian - database design, management and emergency handling capabilities...

Live Updates

pythian: RT @sheeri: #confoo talk "Bending Queries to your Will with EXPLAIN" slides http://bit.ly/explainslides & handout
more



Testimonials

  • Serge Racine

    DBA, Brookfield Energy

    We are very satisfied by the service given to us by Andre and Shakir in support of our recent data quality and reorganization initiative.... more