How oracle sequence works internally? - database

I wan to know how sequence for a table works internally in oracle database. Specially how they increment value of sequence.
Are they use trigger for incrementing value of sequence or anything else???

Oracle does not handle sequences as other objects, like tables.
If you insert 100 records using the NEXTVAL and issue a ROLLBACK,
this sequence does not get rolled back.
Instead, 100 records will have incremented the sequence.
The next insert will have the 101-st value of the sequence.
This will lead to "spaces" in the sequence. That allows for multiple people to
safely use sequences without the risk of duplicates.
If two users simultaneously grab the NEXTVAL, they will be
assigned unique numbers. Oracle caches sequences in memory.
The init.ora parameter SEQUENCE_CACHE_ENTRIES defines the cache size.

Related

There is a Sequence associated with the table. When i reset this sequence and inserting a data into a table data is not coming in ordered fashion

there is a Sequence associated with the table. When i reset this sequence and inserting a data into a table data is not coming in ordered fashion.
Please Do suggest what should I do for the same
The only way to guarantee ordering of a SELECT statement result set is by specifying an ORDER BY clause. This is regardless of the primary key and indexes as well as the order rows are inserted. If results are returned in the desired sequence without ORDER BY, it is by happenstance. See ORDER BY is Required for a demo of this behavior.
That being said, if SQL Server chooses to use a traditional b-tree index in a trivial query without parallelism in the READ COMMITTED isolation level, the storage engine will likely follow the forward page pointers and row offset array, resulting in a result ordered by the chosen index even without an ORDER BY clause. However, the same query may return results in a different order due to parallelism or if the storage engine uses an allocation order scan (e.g. in the READ UNCOMMITTED isolation level). I would expect other ANSI-SQL compliant DBMS products to similarly require ORDER BY.
With the ORDER BY clause, the semantics of data type comparison will dictate the ordering of results. Integer/numeric data types are ordered differently then character data.

Atomic retrieving sequential range from SEQUENCE

I have a sequence and I want to atomically retrieve several sequential values from it.
As far as I know, sequences do not support transactions.
Standard NEXT VALUE FOR syntax can not help, while in other databases it can be done like that.
I found sp_sequence_get_range function, but I'm not sure if it is atomic. Testing such cases is quite tricky.
Is it possible?
In short, yes, sequences have the property you're looking for.
Now a little bit as to why. At their base, a sequence is just a row in a system table that has (among other things) a column that represents the current value in the sequence. Normally, when you call NEXT VALUE FOR, SQL Server fetches that current value, increments that value by 1, and finally returns the fetched value. When you use the sp_sequence_get_range, it does the same thing except it increments the value by the size of the range you asked for (e.g. if you called it with #range_size = 10, it increments the value by 10).
One thing that I was curious about was whether or not a rollback of a transaction that contained the sp_sequence_get_range procedure call also rolled back the allocation of that range. I'm happy to report that it does not. So, you needn't worry about two calls to that procedure getting the same value.
Lastly, I caution you against the fallacy of a gapless sequence. If you get a range and that thread dies for whatever reason (e.g. your application terminates, the SQL Server shuts down expectedly or unexpectedly), that sequence is lost forever. That is, there's no putting an "unused" range back in the queue so that the next call for a range gets that range.

Multiple TSQL sequences in one sequence

I need to run sequence number for all of my customers in my SQL Server database.
I have about 1000 customers, I need each and one of them have their own sequence?
How can that be done in TSQL?
Is it possible to make one sequence to serve all purposes?
It doesn't sounds reasonable to created 1000 sequences.
Sequence will give you only one number series. To have one per each customer, and I would assume new customers can also appear, the only way I can think of is to create a table for the sequences. You could just have a column for the customer code and int column for the sequence.
If your database needs these sequences really often (in scale of several per second), this could easily become a bottleneck, but I assume here that's not the case.

What happens when DB engine runs out of numbers to use for primary keys?

Since DBs do not reuse numbers of deleted records it is possible to run out of numbers, especially if you pick not really a big integer type for this column.
What would happen and how to prevent it if it's bad?
// SQL Server, MySQL //
You end up with a 3+ Hour Downtime, like Slashdot did on their Comments-Function.
I think exactly what happens will be dependent on which database engine you're using (there may even be differences between INNODB and MyISAM in MySQL).
Whatever happens, it's not going to be pretty.
You'd simply have to change the column type to a larger integer.
For MySQL, it is documented that:
The behavior of the auto-increment mechanism is not defined if a user assigns a negative value to the column or if the value becomes bigger than the maximum integer that can be stored in the specified integer type.
Most database systems have a numeric datatype that can be wider than 32 bits. If you anticipate more than 2^32 records you should use an appropriate key width.
Yes it is possible: if you only allow for 2 digit numbers you can only have IDs up to 99, and so on. Inserts would fail once the limit was reached. It is a matter of common sense to choose an appropriate size.
In Postgres, the "serial" type is equivalent to the creation of a SEQUENCE with the NO CYCLE option, and setting the default of the field to nextval. Exhausting such a sequence produces an error:
http://www.postgresql.org/docs/8.3/interactive/sql-createsequence.html
It depends on your database, I believe in MS SqlServer, you simply cannot insert any new rows until you fix the problem. The last time I encountered it, we fixed the problem by reseeding the identity column to 1. That's obviously not a universal fix, but it was ok with our situation.
I tried this in SQL 2000 some time ago. After Integer.MaxValue the next identity value is Integer.MinValue. It then keeps counting up as you would expect. As long as the records that used to exist at 1,2,3 etc have gone by the time it gets there nothing bad will happen. If it runs into a duplicate (and the field is the primary key) then the insert fails with a key violation. I haven't tried an identity column that isn't constrained to unique values though. I would guess it would be happy with the duplicates.
Oracle doesn't support autoincrementing ID columns and standard practice is to use a sequence generator. A sequence generates integers of up to 28 digits, so if you run out of those then ... I guess you have a pretty big table. But behaviour would then be dependent on the configuration of the sequence generator -- either an error or it would cycle back to the start value and you'd get a PK constraint violation on the next insert.
Generally you'll get an error. Use a BIGINT if you are paranoid.

Is it ok to set the sequence of a table to very large value like 10 million?

Is there any performance impact or any kind of issues?
The reason I am doing this is that we are doing some synchronization between two set of DBs with similar tables and we want to avoid duplicate PK errors when synchronizing data.
Yes, it's okay.
Note: If you have perfomance concerns you could use the "CACHE" option on "CREATE SEQUENCE":
"Specify how many values of the sequence the database preallocates and keeps in memory for faster access. This integer value can have 28 or fewer digits. The minimum value for this parameter is 2. For sequences that cycle, this value must be less than the number of values in the cycle. You cannot cache more values than will fit in a given cycle of sequence numbers. Therefore, the maximum value allowed for CACHE must be less than the value determined by the following formula:"
(CEIL (MAXVALUE - MINVALUE)) / ABS (INCREMENT)
"If a system failure occurs, all cached sequence values that have not been used in committed DML statements are lost. The potential number of lost values is equal to the value of the CACHE parameter."
Sure. What you plan on doing is actually a rather common practice. Just make sure the variables in your client code which you use to hold IDs are big enough (i.e., use longs instead of ints)
The only problem we recently had with creating tables with really large seeds was when we tried to interface with a system we did not control. That system was apparently reading our IDs as a char(6) field, so when we sent row 10000000 it would fail to write.
Performance-wise we have seen no issues on our side with using large ID numbers.
No performance impact that we've seen. I routinely bump sequences up by a large amount. The gaps come in handy if you need to "backfill" data into the table.
The only time we had a problem was when a really large sequence exceeded MAXINT on a particular client program. The sequence was fine, but the conversion to an integer in the client app started failing! In our case it was easy to refactor the ID column in the table and get things running again, but in retrospect this could have been a messy situation if the tables had been arranged differently!
If you are synching two tables why not change the PK seed/increment amount so that everything takes care of itself when a new PK is added?
Let's say you had to synch the data from 10 patient tables in 10 different databases.
Let's also say that eventually all databases had to be synched into a Patient table at headquarters.
Increment the PK by ten for each row but ensure the last digit was different for each database.
DB0 10,20,30..
DB1 11,21,31..
.....
DB9 19,29,39..
When everything is merged there is guaranteed to be no conflicts.
This is easily scaled to n database tables. Just make sure your PK key type will not overflow. I think BigInt could be big enough for you...

Resources