Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: HowTo - create user defined sequence with proper serialization

Re: HowTo - create user defined sequence with proper serialization

From: <p.santos000_at_gmail.com>
Date: 29 Aug 2006 10:00:02 -0700
Message-ID: <1156870801.917784.310710@p79g2000cwp.googlegroups.com>

Steve Howard wrote:
> p.santos000_at_gmail.com wrote:
> > Folks,
> > Here is a difficult question that I'm hoping you can help me solve.
> >
> > Requirements:
> > - Create a user defined like "sequence" that increments by
> > power of 2.
> > - This defined "sequence" must distribute values like
> > 1,2,4,16,256 etc ..
> > - If a value is deleted, then the sequence must re-use that
> > value.
> > - acess to this "sequence" must be serialized so that no two
> > users can
> > grab the same value
> >
> > Example: (GROUPS table)
> >
> > ACCOUNT_ID NAME SEQ
> > ======= ===== =====
> > 347164311 GROUP1 1
> > 347164311 GROUP2 2
> > 347164311 GROUP2 4
> >
> > - So if account id " 347164311" wanted to create a new group in the
> > GROUPS
> > table, it would obtain a new sequence with the value of 16 and it
> > would insert it.
> >
> > - If at some point GROUP2 was removed from the table, the custom
> > sequence
> > would distribute 2 as the "NEXTVAL" ..
> >
> > The key thing here is serialization and I'm not sure how to achive
> > this.
> > Here is the sample function that delivers the next available sequence,
> > but
> > doesn't yet serialize access to it.
> >
> > CREATE OR REPLACE FUNCTION GET_SEQ (ACCTID NUMBER)
> > RETURN NUMBER IS
> > i NUMBER := 0;
> > two_power_i NUMBER := power(2,i);
> > curr_mask groups.seq%TYPE;
> >
> > CURSOR masksCursor IS SELECT seq FROM groups WHERE account_id = acctid
> > ORDER BY seq;
> >
> > BEGIN
> > OPEN masksCursor;
> > LOOP
> > FETCH masksCursor INTO curr_mask;
> > EXIT WHEN curr_mask != two_power_i OR masksCursor %NOTFOUND;
> > i := i + 1;
> > two_power_i := power(2,i);
> > END LOOP;
> > CLOSE masksCursor;
> > RETURN two_power_i;
> > END;
> > /
> >
> > Any idea on how to make the above function serial so that if 2
> > concurrent users execute the function, they don't both get the same
> > value?
> >
> > -peter

>

> If you absolutely need the sequence numbers to be unique/reuseable,
> etc., you'll have to change your SELECT to a SELECT FOR UPDATE. This
> locks the current row so that no one else can update, and you also know
> the value won't change between the time you read it and you update it.
>

> You can test this by opening two sessions. In the first one, issue
> something like...
>

> select c from my_sequence for update;
>

> ...and in the second session, issue something like...
>

> update my_sequence set c = 1;
>

> The second one will hang until you commit or rollback in the first
> session.
>

> I would try to use sequences if you can, because depending on your
> load, you'll see a *lot* of waits on "enq: TX - row lock contention",
> because, well, it's a queue :)
>

> Regards,
>

> Steve
>

> Regards,

>
> Steve

Steve,
  The need to reuse sequence values needs to exist. Therefore we have to do a linear search via a cursor to identify the lowest/next sequence value. I'm not sure where the select for update would go in the function I listed...

-peter Received on Tue Aug 29 2006 - 12:00:02 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US