[MDEV-31944] UPDATE creates new row in system-versioned tables even if there is no value to change Created: 2023-08-18  Updated: 2023-09-08  Resolved: 2023-09-05

Status: Closed
Project: MariaDB Server
Component/s: Versioned Tables
Affects Version/s: 10.6.15
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Federico Razzoli Assignee: Sergei Golubchik
Resolution: Not a Bug Votes: 1
Labels: None

Issue Links:
Duplicate
duplicates MDEV-26783 System-versioned table writes histori... Closed
is duplicated by MDEV-32124 System-Versioned Tables, extra rows w... Closed
Problem/Incident
is caused by MDEV-23446 UPDATE does not insert history row if... Closed

 Description   

UPDATE shouldn't do anything if the values I'm setting are identical to current values. But this is not the case with temporal tables.

I create my system-versioned table:

CREATE OR REPLACE TABLE kv (
    k VARCHAR(20) NOT NULL,
    v VARCHAR(20) NOT NULL,
    PRIMARY KEY (k)
);
 
ALTER TABLE kv
      ADD COLUMN valid_since TIMESTAMP(6) GENERATED ALWAYS AS ROW START INVISIBLE
    , ADD COLUMN valid_until TIMESTAMP(6) GENERATED ALWAYS AS ROW END INVISIBLE
    , ADD PERIOD FOR SYSTEM_TIME(valid_since, valid_until)
    , ADD SYSTEM VERSIONING
;

I run the same INSERT ... ON DUPLICATE KEY UPDATE twice, and I'll have 2 fows.

INSERT INTO kv (k, v) VALUES ('x', '1') ON DUPLICATE KEY UPDATE v = '1';
INSERT INTO kv (k, v) VALUES ('x', '1') ON DUPLICATE KEY UPDATE v = '1';
SELECT *, valid_since, valid_until
    FROM kv FOR SYSTEM_TIME ALL;
+---+---+----------------------------+----------------------------+
| k | v | valid_since                | valid_until                |
+---+---+----------------------------+----------------------------+
| x | 1 | 2023-08-18 01:35:12.193426 | 2023-08-18 01:35:13.245431 |
| x | 1 | 2023-08-18 01:35:13.245431 | 2038-01-19 03:14:07.999999 |
+---+---+----------------------------+----------------------------+

The same happens if I run an UPDATE:

UPDATE kv SET v = '1' WHERE k = 'x' LIMIT 1;
SELECT *, valid_since, valid_until
    FROM kv FOR SYSTEM_TIME ALL;
+---+---+----------------------------+----------------------------+
| k | v | valid_since                | valid_until                |
+---+---+----------------------------+----------------------------+
| x | 1 | 2023-08-18 01:35:12.193426 | 2023-08-18 01:35:13.245431 |
| x | 1 | 2023-08-18 01:35:13.245431 | 2023-08-18 01:41:57.249443 |
| x | 1 | 2023-08-18 01:41:57.249443 | 2038-01-19 03:14:07.999999 |
+---+---+----------------------------+----------------------------+

INSERT ... ON DUPLICATE KEY UPDATE is the logical way to implement a time-series-like workload. But the main advantage to do it in MariaDB with sysver tables is that storage is not supposed to grow until the values actually change, and avoid huge backups, frequent data rotation, etc. But this bug ruins the idea.



 Comments   
Comment by Sergei Golubchik [ 2023-09-05 ]

This is intentional. At first, such updates were not creating historical rows and in the course of MDEV-23446 it was changed.

Indeed, SQL Standard does not have the language "if the new row was equal to the old row, then it's not really an UPDATE". There's no concept of comparing and old and new rows there, it's an optimization inside MariaDB. We can use this optimization only when it doesn't cause any user visible effects. But, for example, triggers are still run even if the row is updated to itself. And a new historical row has to be created too.

Generated at Thu Feb 08 10:27:38 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.