portable sequence

D

Drazen Gemic

Hi !

I need to have a portable global sequence generator that works
regardless of database engine used. For example, Postgres have
sequence, mssql doesn't, but I need sequence for both. I tried to
create one, uzing SERIALIZABLE transactions, but under the increased
load it started to generate deadlocks.

The sequence table, 'uniseq' in this example, contains just one row
with one column ('next_id'), and that column is a sequence value, a
globaly unique number (BIGINT).

If the table is empty, new row is inserted, with sequence number = 1.
Otherwise sequence number is increased and stored.

What should I do to avoid deadlocks ?

Here is the code:

public static Long getUniqId(AdbWrapper dbx)
{
boolean flag=true;
dbx.startTran("SERIALIZABLE"); // transaction start
Long num=(Long) dbx.getField("select next_id from uniseq");
if(num == null)
{
num=new Long(1);
flag=(dbx.update("insert into uniseq values (1)") > 0);
}
else
{
num=new Long(1+num.longValue());
flag=(dbx.update("update uniseq set next_id="+num) > 0);
}
dbx.endTran(flag); // transaction end
//
return num;
}
 
A

Arne Vajhøj

Drazen said:
I need to have a portable global sequence generator that works
regardless of database engine used. For example, Postgres have
sequence, mssql doesn't, but I need sequence for both. I tried to
create one, uzing SERIALIZABLE transactions, but under the increased
load it started to generate deadlocks.

The sequence table, 'uniseq' in this example, contains just one row
with one column ('next_id'), and that column is a sequence value, a
globaly unique number (BIGINT).

If the table is empty, new row is inserted, with sequence number = 1.
Otherwise sequence number is increased and stored.

What should I do to avoid deadlocks ?

Here is the code:

public static Long getUniqId(AdbWrapper dbx)
{
boolean flag=true;
dbx.startTran("SERIALIZABLE"); // transaction start
Long num=(Long) dbx.getField("select next_id from uniseq");
if(num == null)
{
num=new Long(1);
flag=(dbx.update("insert into uniseq values (1)") > 0);
}
else
{
num=new Long(1+num.longValue());
flag=(dbx.update("update uniseq set next_id="+num) > 0);
}
dbx.endTran(flag); // transaction end
//
return num;
}

With a high transaction isolation level you need to be prepared to
retry in case of deadlocks/timeouts.

If you switch to Scott Ambler high-low approach, then:
- performance will be much better
- deadlocks/timeouts will me rare
(but you can get holes in your sequence though)

Arne
 
L

Lew

Arne said:
With a high transaction isolation level you need to be prepared to
retry in case of deadlocks/timeouts.

If you switch to Scott Ambler high-low approach, then:
- performance will be much better
- deadlocks/timeouts will me rare
(but you can get holes in your sequence though)

I prefer to use the built-in sequence mechanism, and just translate to the
appropriate dialect if I need to port to a new RDBMS.
 
D

Drazen Gemic

I prefer to use the built-in sequence mechanism, and just translate to the
appropriate dialect if I need to port to a new RDBMS.
If there is one. MS SQL 2000 does not have it.

I am thinking about asking my clients to standardize on Postgres.
Majority of them don't have true DBA anyway, and there are problems
because
of that

DG
 
L

Lew

Drazen said:
I am thinking about asking my clients to standardize on Postgres.
Majority of them don't have true DBA anyway, and there are problems
because of that

Those problems will not go away by using Postgres.

You can't cure lack of a DBA by switching DBMSes.
 
A

Arne Vajhøj

Lew said:
I prefer to use the built-in sequence mechanism, and just translate to
the appropriate dialect if I need to port to a new RDBMS.

You will be more portable and get better performance by going the
other route.

You will also need to write some code and have to live with holes
in the sequence.

Arne
 
D

Drazen Gemic

You will be more portable and get better performance by going the
other route.

You will also need to write some code and have to live with holes
in the sequence.

I haven't been able to find an article or example you were referring
to.


What do you mean by holes ? Do you mean increment greater than 1 or
possibility
to get duplicate ID ?

DG
 
D

Drazen Gemic

I've taken a look, it is elegant, but I don't think I am going to
use it, because there is something more simple. I know how many
keys I need per session, so I coud request a continuous block of 10 or
20 keys
in single operation.

That will significantly decrease the load, and I can still check for
deadlocks.

ID is used to match response to requests sent to another, remote
application. Looking at the logs I suspect that load is generated
when impatient users repeatedly click while waiting for the response
from remote host, so I am going to add Thread.sleep() call to the
operation.

DG
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top