[MDEV-26096] Make the Unique index ONLY evaluate immediately before the commit (NOT after each UPDATE) Created: 2021-07-06  Updated: 2023-11-30

Status: Stalled
Project: MariaDB Server
Component/s: Storage Engine - InnoDB
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Nilnandan Joshi Assignee: Marko Mäkelä
Resolution: Unresolved Votes: 1
Labels: None

Issue Links:
Duplicate
duplicates MDEV-26097 Constraints: support deferred constra... Open
Relates
relates to MDEV-15250 UPSERT during ALTER-TABLE results in ... Closed
relates to MDEV-24608 Failing assertion: error == DB_SUCCES... Open

 Description   

Make the Unique index ONLY evaluate immediately before the commit and NOT after each UPDATE ("Deferred Constraints Check" )

MariaDB [test]> CREATE TABLE `node` (
    -> `id` int(11) NOT NULL AUTO_INCREMENT,
    -> `parentId` int(11) NULL DEFAULT NULL,
    -> `orderIndex` int(5) NOT NULL,
    -> `label` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
    -> PRIMARY KEY (`id`) USING BTREE,
    -> INDEX `FKparent`(`parentId`) USING BTREE,
    -> CONSTRAINT `FKparent` FOREIGN KEY (`parentId`) REFERENCES `node` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
    -> ) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
Query OK, 0 rows affected (0.038 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (1, NULL, 0, 'root1');
Query OK, 1 row affected (0.014 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (2, 1, 0, 'child1a');
Query OK, 1 row affected (0.008 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (3, 1, 1, 'child1b');
Query OK, 1 row affected (0.013 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (4, 1, 2, 'child1c');
Query OK, 1 row affected (0.004 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (5, NULL, 0, 'root2');
Query OK, 1 row affected (0.006 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (6, 2, 0, 'child2a');
Query OK, 1 row affected (0.003 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (7, 2, 1, 'child2b');
Query OK, 1 row affected (0.005 sec)
 
MariaDB [test]> INSERT INTO `node` VALUES (8, 2, 2, 'child2c');
Query OK, 1 row affected (0.004 sec)
 
MariaDB [test]> 
MariaDB [test]> START TRANSACTION;
Query OK, 0 rows affected (0.000 sec)
 
MariaDB [test]> update node set orderindex=2 where id = 3;
Query OK, 1 row affected (0.000 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
MariaDB [test]> update node set orderindex=1 where id = 4;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
MariaDB [test]> COMMIT;
Query OK, 0 rows affected (0.004 sec)
 
MariaDB [test]> ALTER TABLE `node`
    -> ADD UNIQUE INDEX `UXorderIndex`(`parentId`, `orderIndex`);
Query OK, 0 rows affected (0.025 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
MariaDB [test]> START TRANSACTION;
Query OK, 0 rows affected (0.000 sec)
 
MariaDB [test]> update node set orderindex=1 where id = 3;
ERROR 1062 (23000): Duplicate entry '1-1' for key 'UXorderIndex'
MariaDB [test]> update node set orderindex=2 where id = 4;
ERROR 1062 (23000): Duplicate entry '1-2' for key 'UXorderIndex'
MariaDB [test]> COMMIT;
Query OK, 0 rows affected (0.004 sec)

upstream feature request: https://bugs.mysql.com/bug.php?id=68360

Also this feature should be implemented as a optional and not by default so if anyone wants to use the old way, they can.



 Comments   
Comment by Hartmut Holzgraefe [ 2021-07-07 ]

Looking at other SQL products, e.g. PostgreSQL allows to declare a CONSTRAINT as either IMMEDIATE or DEFERRED, with DEFERRED meaning "check at COMMIT time":

https://www.postgresql.org/docs/13/sql-set-constraints.htm

IMMEDIATE checks still being the default behavior so there, DEFERRED checks need to be declared explicitly.

Comment by Hartmut Holzgraefe [ 2021-07-07 ]

IMMEDIATE/DEFERRED constraint checks seem to be defined in

ISO/IEC 9075-2:2008 subclauses 10.8 and 17.4 if I read this correctly:

https://docs.microsoft.com/en-us/openspecs/sql_standards/ms-tsqliso02/70d6050a-28c7-4fae-a205-200ccb363522

Comment by Julien Fritsch [ 2021-09-23 ]

Duplicated by MDEV-26097

Comment by Marko Mäkelä [ 2022-01-25 ]

I do not think that this exactly duplicates MDEV-26097. It is related to or part of that task, but not duplicating it.

Comment by Marko Mäkelä [ 2022-01-25 ]

My idea for fixing MDEV-15250 (which is about deferred unique checks during online ALTER TABLE) is to traverse the transaction’s undo log at the time a concurrent DML transaction is being committed.

I think that deferred unique key checks could be implemented inside InnoDB by simply traversing the undo log at XA PREPARE or COMMIT time. This would require some storage engine API changes, because there currently is no such call. Such API change might also be needed for fixing MDEV-24608.

Generated at Thu Feb 08 09:42:42 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.