[MDEV-10139] Support for SEQUENCE objects Created: 2016-05-27  Updated: 2023-11-13  Resolved: 2018-02-13

Status: Closed
Project: MariaDB Server
Component/s: Sequences
Fix Version/s: 10.3.1

Type: Task Priority: Critical
Reporter: Michael Widenius Assignee: Michael Widenius
Resolution: Fixed Votes: 12
Labels: 10.3-beta

Issue Links:
Duplicate
is duplicated by MDEV-13075 AliSQL: [Feature] Issue #41 Sequence ... Closed
PartOf
includes MDEV-12930 Testing SEQUENCE object Closed
includes MDEV-12941 First release of SEQUENCEs Closed
includes MDEV-13005 Fixing bugs in SEQUENCE, part 3 Closed
includes MDEV-13679 crash when using SEQUENCE as column d... Closed
includes MDEV-13711 Assertion `is_temporary_table(tables)... Closed
includes MDEV-13714 Value of SEQUENCE table option is ign... Closed
includes MDEV-13720 Server crashes in SEQUENCE::write_loc... Closed
includes MDEV-13732 User with SELECT privilege can ALTER ... Closed
includes MDEV-14824 Assertion `!trx_is_started(trx)' fail... Closed
is part of MDEV-10137 Providing compatibility to other data... Open
Problem/Incident
causes MDEV-14824 Assertion `!trx_is_started(trx)' fail... Closed
causes MDEV-22491 Support mariadb-check and CHECK TABL... Open
causes MDEV-32795 ALTER SEQUENCE IF NOT EXISTS non_exis... Closed
Relates
relates to MDEV-12883 CREATE SEQUENCE with huge MAXVALUE Closed
relates to MDEV-13006 update_time column of on i_s.tables r... Open
relates to MDEV-13008 Documentation improvements for Sequen... Closed
relates to MDEV-13010 NEXTVAL should increment only once fo... Open
relates to MDEV-13497 concurrently used sequence hangs in S... Closed
relates to MDEV-32350 Can't selectively restore sequences u... Confirmed
relates to MDEV-12168 AUTO_INCREMENT with CYCLE support Closed
relates to MDEV-12533 sql_mode=ORACLE: Add support for data... Closed
relates to MDEV-13393 SEQUENCE related crash when running c... Closed
relates to MDEV-13497 concurrently used sequence hangs in S... Closed
relates to MDEV-20111 (CREATE|ALTER) SEQUENCE / SETVAL: onl... Closed
Sub-Tasks:
Key
Summary
Type
Status
Assignee
MDEV-13717 Document permissions required to work... Technical task Closed Ian Gilfillan  
Epic Link: Compatibility

 Description   

Add support for SEQUENCES, like in PostgreSQL or Oracle:

CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
    [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]

See https://www.postgresql.org/docs/8.1/static/sql-createsequence.html
for details.

The main part of the task is to add support for sequence tables in the storage engine interface. The main difference between transactional tables are only that they don't roll back when issuing a ROLLBACK statement.

Example:

CREATE SEQUENCE s1;
SELECT s1.NEXTVAL FROM DUAL;

Supported statements:

  • CREATE SEQUENCE
  • DROP SEQUENCE
  • ALTER SEQUENCE
  • NEXT VALUE FOR sequence_name and NEXTVAL(sequence_name)
  • PREVIOUS VALUE FOR sequence_name and LASTVAL(sequence_name)
  • SETVAL(sequence_name, next_value, is_used, round)
  • SHOW CREATE SEQUENCE


 Comments   
Comment by Alvin Richards (Inactive) [ 2016-12-08 ]

Additional examples, combining sequences with expressions / functions

SELECT TO_CHAR(SYSDATE,'YYYYMMDDHHMMSS')||MY_SEQ.Nextval INTO Bar FROM DUAL;
 
SELECT LPAD(MY_SEQ.NEXTVAL,10,'0') INTO Bar FROM DUAL;

Comment by Michael Widenius [ 2017-01-17 ]

The idea I have, from the interface point of view, is to implement

CREATE SEQUENCE foo;

As internally do:

CREATE TABLE foo (seq longlong) ROLLBACK=OFF;
INSERT INTO foo (seq) values (minvalue);

(The user will never see this syntax: The handler will get one new flag
ROLLBACK=OFF to take care of, it supports sequences).

And implement all value handling in the SQL level, including value caching.

What the engine needs to do is:

  • No rollback
  • It doesn't matter if a middle transaction is lost by being overwritten by a later one.
  • When reading and writing, no row locks.
  • Upper level will cache values and ensure that we don't do conflicting updates.
  • When reading, return latest entry as if read uncommitted.
Comment by Marko Mäkelä [ 2017-01-18 ]

This is almost aligned with my thinking. I would prefer to omit the INSERT, and I would prefer to some other methods than handler::write_row() or handler::read*() to access the seqeuence object. I would like to see the proposed API.

I think that the minimum that we need is a table entry (both a .frm file and InnoDB data dictionary records, with a flag identifying the table as a sequence pseudo-table. On disk, the data would look like an empty InnoDB table consisting of an empty clustered index root page where PAGE_ROOT_AUTO_INC (introduced in MDEV-6076) stores the sequence value.

Comment by Anders Karlsson [ 2017-01-31 ]

If we want to be Oracle compatible, note that nextval is incremented at most once per row processed. This is rather odd and this isn't something used much I guess but it is worth noting and should possibly go into the documentation. See this example:

CREATE SEQUENCE seq1;
CREATE TABLE ta(c1 NUMBER);
CREATE TABLE tb(c1 NUMBER, c2 NUMBER);
INSERT INTO ta VALUES(1);
INSERT INTO ta VALUES(2);
INSERT INTO tb SELECT seq1.nextval, seq1.nextval FROM ta;
SELECT * FROM tb;

This will result in:

        C1         C2
---------- ----------
         1          1
         2          2

And not:

        C1         C2
---------- ----------
         1          2
         3          4

As you might be expecting.

Comment by Peter Gulutzan [ 2017-02-19 ]

Regarding the comment from Mr Karlsson: Oracle's behaviour – incrementing once per row – is standard and I believe is what other DBMSs do – except PostgreSQL. PostgreSQL exposes a function so its behaviour is "once per invocation".

Comment by Anders Karlsson [ 2017-02-20 ]

Peter is absolutely right that this is standard, and that is my mistake of not checking this first. SQL-2003 says this "If there are multiple instances of <next value expression>s specifying the same sequence generator within a single SQL-statement, all those instances return the same value for a given row processed by that SQL-statement.", also this is the behavior exposed by Oracle and SQL Server, as far as I can see. That said, I still think it is somewhat odd but makes some sense. My initial reaction to this was that if you wanted this behavior you really should use currval (which is the Oracle way of asking for the current value from a sequence, in SQL-2003 there is no such construct), but actually that would actually introduce a few issues. For example it would assume a particular execution order inside a particular SQL statement, so there is a reason why the SQL standard actually omits currval completely. Thanks Peter for catching this!

Comment by Marko Mäkelä [ 2017-03-24 ]

alvinr, I do not know who will do the design review. I implemented the InnoDB part of this yesterday and slightly revised today. The InnoDB changes are almost trivial; the real work takes place above the storage engine layer. As far as I understood, the code by monty is still somewhat incomplete.

Comment by Michael Widenius [ 2017-03-26 ]

First version of sequences is pushed to bb-10.2-sequence. It should be merged to bb-10.2-compatilbity and then to 10.3 shortly (1-2 weeks).

What is working for the moment:

CREATE OR REPLACE [TEMPORARY] SEQUENCE [IF NOT EXISTS] name
[ INCREMENT [ BY | = ] increment ]
[ MINVALUE [=] minvalue | NO MINVALUE ]
[ MAXVALUE [=] maxvalue | NO MAXVALUE ]
[ START [ WITH | = ] start ] [ CACHE [=] cache ] [ [ NO ] CYCLE ]
ENGINE=xxx COMMENT=".."
SELECT NEXT VALUE FOR sequence_name;
SELECT NEXTVAL(sequence_name);
SELECT PREVIOUS VALUE FOR sequence_name;
SELECT LASTVAL(sequence_name);

SHOW CREATE SEQUENCE sequence_name;
SHOW CREATE TABLE sequence_name;
CREATE TABLE sequence-structure ... SEQUENCE=1
ALTER TABLE sequence RENAME TO sequence2;
RENAME TABLE sequence RENAME TO sequence2;
DROP [TEMPORARY] SEQUENCE sequence_name [IF EXISTS]

CREATE SEQUENCE is documented at:
https://mariadb.com/kb/en/mariadb/create-sequence/

Comment by Alexander Barkov [ 2017-04-09 ]

Pushed into bb-10.2-ext.
Pushed to 10.3.

Comment by Jérôme Brauge [ 2017-05-10 ]

Hi,
Can I suggest two improvement :
first : support the command "grant select on sequence sequence_name to .."
second : support "alter sequence " on an attribute with the current value.

Example:
create sequence seq1 start with 1;
alter sequence seq1 cache 1;
alter sequence seq1 cache 1;

ERROR 1030 (HY000): Got error 169 "Record was not update. Original values was same as new values" from storage engine InnoDB

Regards.

Comment by Michael Widenius [ 2017-05-24 ]

Still some work to be done. Current state is:

  • Everything coded in server, all 'base' tests are done. Now it's up to QA to test the code thoroughly.
  • mysqldump will need a small change to dump sequence tables last. (This is worked upon)
Comment by Michaël de groot [ 2017-05-30 ]

Cool!!

I have a question about this, does auto_increment_increment and _offset change anything to sequence behaviour? I guess it could otherwise lead to conflicts in a multi-master cluster.

Comment by Michael Widenius [ 2017-06-06 ]

Yes, auto_increment_increment and _offset will work for sequences defined with INCREMENT=0.
This is documented at:
https://mariadb.com/kb/en/mariadb/sequence-overview/#replication

Comment by Michael Widenius [ 2017-06-06 ]

About GRANT.

Sequences uses normal table grants. To read from state of a sequence, one needs SELECT privilege,
to update the sequence one needs INSERT privilege. To use ALTER SEQUENCE one will need the ALTER privilege.

Comment by Alexander Bienemann (Inactive) [ 2017-10-11 ]

For migrations from Oracle: Access to SEQUENCE objects through migrated SYNONYM constructs should be checked, e.g. through FederatedX and VIEWs.

Comment by Michael Widenius [ 2018-02-13 ]

Pushed into 10.3 tree a long time ago

Generated at Thu Feb 08 07:39:58 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.