[MDEV-16546] System versioning setting to allow history modification Created: 2018-06-21  Updated: 2023-08-07  Resolved: 2022-10-26

Status: Closed
Project: MariaDB Server
Component/s: Versioned Tables
Fix Version/s: 10.11.1

Type: Task Priority: Critical
Reporter: Aleksey Midenkov Assignee: Sergei Golubchik
Resolution: Fixed Votes: 8
Labels: Preview_10.11

Issue Links:
Blocks
blocks MDEV-16029 mysqldump: dump and restore historica... Closed
is blocked by MDEV-18727 System Versioning: optimize DML opera... Closed
is blocked by MDEV-29833 CREATE ... SELECT system_versioned_ta... Closed
Duplicate
duplicates MDEV-16734 LOAD DATA and system_versioning_modif... Closed
PartOf
includes MDEV-16587 Vers: SQL sysvers_show SELECT fix Closed
is part of MDEV-29547 prepare 10.11.0 preview releases Closed
Problem/Incident
causes MDEV-29674 History modification inserts records ... Stalled
causes MDEV-29721 Inconsistency upon inserting history ... Closed
causes MDEV-29722 History modification requires specify... Closed
causes MDEV-29732 mysqlbinlog produces syntactically in... Closed
causes MDEV-29738 REPLACE under system_versioning_inser... Closed
causes MDEV-29741 SHOW BINLOG EVENTS shows garbage with... Closed
causes MDEV-29750 Triggers can modify history Closed
causes MDEV-29805 Attempt to insert into system version... Closed
causes MDEV-29812 Confusing behavior upon ODKU trying t... Closed
causes MDEV-29813 REPLACE/IGNORE does not work with his... Closed
causes MDEV-29830 Assertion `table->versioned()' in THD... Closed
causes MDEV-29837 Column privileges prevent from direct... Open
Relates
relates to MDEV-22413 Server hangs upon UPDATE/DELETE on a ... Closed
relates to MDEV-29730 mysqldump --dump-history creates brok... Closed
relates to MDEV-29736 mysqldump sets system_versioning_inse... Closed
relates to MDEV-29737 mysqldump doesn't check for --tz-utc ... Closed

 Description   

Add a session server variable @@system_versioning_insert_history which allows to use ROW_START and ROW_END columns in the INSERT (unless they are normal visible (in SELECT *) fields, they have to be explicitly specified in INSERT as any invisible fields are). And if @@secure_timestamp allows the current user to modify @@timestamp then he should be able to insert directly into ROW_START/ROW_END columns.

The use case of this is to be able to dump the history with mysqldump and to load it back later (MDEV-16029). It provides a convenient way to have a row in the system versioned table with row_start=A and row_end=B. Without @@system_versioning_insert_history it can be achieved with

set @@timestamp=A;
insert t1 values (...);
set @@timestamp=B;
delete from t1 where ... -- a condition to match the row that was just inserted

So this new feature does not provide any new functionality, but allows to load the history dump much faster than with timestamp manipulations as above. In particular it does not allow to do anything that wasn't possible to do before, it requires exactly the same set of privileges as the snippet above, and is subject to the same set of restrictions.



 Comments   
Comment by Sergei Golubchik [ 2018-06-21 ]

no sql mode please. make it a separate sysvar.

Comment by Michael McClennen [ 2020-05-10 ]

I am very anxious to use system versioning, but I cannot make the changeover until this feature is available. This is due to the fact that I have existing history data that needs to be moved over to the new system. I am glad to see that it is In Review, and hope to see it in the next MariaDB release.

Comment by Nayuta Yanagisawa (Inactive) [ 2020-10-24 ]

I also interested in the system versioning. If I could get logical backup by mysqldump, it would be great for me.

The ticket for such a feature seems to be blocked by this ticket. There are several PRs for this JIRA issue, while they are not merged. Could anyone let me know how things are going?

Comment by Federico Razzoli [ 2021-06-12 ]

If anyone can do this, I see a security risk.
Will this require the SUPER privilege?

Comment by Sergei Golubchik [ 2021-06-12 ]

f_razzoli, it's just a convenience feature. It doesn't allow to do anything that one wasn't allowed to do before. Say, you want to have a fake history record that tells that a row with the value V existed from timestamp A to timestamp B. You can do it as

set @@timestamp=A;
insert into t1 values (V);
set @@timestamp=B;
delete from t1 where value=V;

Note, that this is only allowed for certain values of @@secure_timestamp variable. For example, with @@secure_timestamp=YES no one can fake history.

In this issue we want to simplify the above to

set @@system_versioning_insert_history=1;
insert t1 values (V, A, B);

This is primarily to be able to use multi-row inserts in mysqldump. This convenience feature won't do any additional privilege checks, it will work for everyone who can change @@timestamp as above, so it'll obey @@secure_timestamp setting.

Comment by Aleksey Midenkov [ 2022-08-02 ]

Please review bb-10.6-midenok

Comment by Aleksey Midenkov [ 2022-08-28 ]

Please review bb-10.11-midenok-MDEV-16546

Comment by Sergei Golubchik [ 2022-09-07 ]

I've interrupted the review, as I stumbled on a bug, try this test case:

create table t1(y int primary key,
  row_start timestamp(6) as row start,
  row_end timestamp(6) as row end,
  period for system_time (row_start, row_end))
with system versioning;
 
insert into t1 values (1, NULL, NULL);
--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN
insert into t1 values (2, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
set @@system_versioning_insert_history= 1;
insert into t1 values (3, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
select * from t1 for system_time all;
drop table t1;

This INSERT uses a different fill_record() function and does not go into Item_field::fix_fields().

Comment by Aleksey Midenkov [ 2022-09-13 ]

Fixed. It should not go into Item_field::fix_fields() because there is no explicit field list (so no Item_field). It uses different fill_record() for implicit field list, that's normal.

Comment by Aleksey Midenkov [ 2022-09-13 ]

I wanted to split THD::vers_insert_history(Field *) into Field::vers_insert_history(THD *) and THD::vers_insert_history(). But they both cannot be inline (or it sort of hard to rule out without inline files) because Field::vers_insert_history(THD *) must call THD::vers_insert_history() but sql_class.h is not included into field.h. serg, I remember about your inline request.

Comment by Sergei Golubchik [ 2022-09-15 ]

midenok, you haven't fixed the issue yet. You don't have the test case for it. If you do

-insert into t3(z, row_start, row_end) values (5, '1980-01-01 00:00:00', '1980-01-01 00:00:01');
+insert into t3 values (5, '1980-01-01 00:00:00', '1980-01-01 00:00:01');

you'll see that values are ignored

Comment by Sergei Golubchik [ 2022-09-17 ]

pushed into bb-10.11-MDEV-16546

Comment by Elena Stepanova [ 2022-10-20 ]

I have no objections against pushing bb-10.11-MDEV-16546 as of 87fca0525 into 10.11 branch and releasing it with 10.11.1.

Some notes in no particular order (greenman FYI):

  • the final implementation allows INSERT, CREATE .. INSERT, and LOAD; does not allow REPLACE, LOAD .. REPLACE, UPDATE, INSERT .. ON DUPLICATE KEY UPDATE
  • in addition to sufficient permissions to change the timestamp, the user performing the operation naturally also needs standard grants for inserting into the table;
  • the variable is already in the KB, but the description needs to indicate that it only applies to timestamp-based versioning;
  • while inserting history into a versioned table with limit-based partitioning, the user must be aware of MDEV-29674, all injected historical rows are inserted into the first partition. It may be fixed in future;
  • in general, functionality is mainly aimed for re-loading the real history by the means of mysqldump / restoration. While arbitrary history inserting also works, the effect may be not quite what the user expects to achieve.
  • see also notes in MDEV-16029.
Generated at Thu Feb 08 08:29:43 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.