[MDEV-31365] Not following of the definition of the TIMESTAMP in the table. Created: 2023-05-30  Updated: 2023-06-05  Resolved: 2023-06-05

Status: Closed
Project: MariaDB Server
Component/s: Data Manipulation - Update
Affects Version/s: 10.6.13
Fix Version/s: N/A

Type: Bug Priority: Critical
Reporter: Linkang, Zhang Assignee: Sergei Golubchik
Resolution: Not a Bug Votes: 0
Labels: None


 Description   

When we use ON DUPLICATE UPDATE syntax to insert data, CURRENT_TIMESTAMP in primary key, we get wrong answer.

How to repeat:
we can repeat this by mysql-test.

create one file named 'test_update.test' in directory mysql-test/main

The content of 'test_update.test' is:

CREATE TABLE `test_up`(
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `data` int,
    PRIMARY KEY(`ts`) 
);
 
INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 1);
 
INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 2) ON DUPLICATE KEY UPDATE data=2;
INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 3) ON DUPLICATE KEY UPDATE data=3;
INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 4) ON DUPLICATE KEY UPDATE data=4;

now, we can use this command in directory mysql-test:

./mtr main.test_update

now, the wrong answer is:

mysqltest: At line 11: Query 'INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 4) ON DUPLICATE KEY UPDATE data=4' failed.
ERROR 1062 (23000): Duplicate entry '2023-05-29 12:42:03' for key 'test_up.PRIMARY'



 Comments   
Comment by Elena Stepanova [ 2023-06-04 ]

It looks confusing at first, as it often happens with TIMESTAMP, but if we take it step by step, it doesn't appear to do anything it shouldn't do.

Let's say, just for specifics in the example, that's current time is 2023-06-05 00:00:00.

Your first INSERT inserts the row 2023-05-29 17:34:55,1 into the empty table:

INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 1);
select * from test_up;
ts	data
2023-05-29 17:34:55	1

The second INSERT attempts to insert the row 2023-05-29 17:34:55.01, 2; because it hits the duplicate key in ts, it performs an update instead, updating data to 2, but since now it is UPDATE, it also updates ts to CURRENT_TIMESTAMP, just as the table definition specifies. So, now we have

INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 2) ON DUPLICATE KEY UPDATE data=2;
select * from test_up;
ts	data
2023-06-05 00:00:00	2

The third INSERT inserts the row 2023-05-29 17:34:55.01, 3. Since we no longer have this timestamp in the table, it inserts successfully, and we have two rows now:

INSERT INTO test_up VALUES("2023-05-29 17:34:55.01", 3) ON DUPLICATE KEY UPDATE data=3;
select * from test_up;
ts	data
2023-06-05 00:00:00	2
2023-05-29 17:34:55	3

Finally, the fourth INSERT attempts to insert the row 2023-05-29 17:34:55.01, 4. Like the 2nd one, it hits the duplicate key (conflicting with the row (2023-05-29 17:34:55,3)) and attempts to convert it into update, updating data column to 4, and – again – ts column to CURRENT_TIMESTAMP, which is still 2023-06-05 00:00:00 because the test is fast. However unlike the 2nd INSERT, this UPDATE hits a duplicate key too, because we already have 2023-06-05 00:00:00 in the table, so you get the error.

The only TIMESTAMP specifics here is that the ts column is updated – or attempted to get updated – automatically, according to ON UPDATE CURRENT_TIMESTAMP clause. Otherwise, you would observe the same behavior with a regular numeric primary key, if you tried to update it to a value which already exists, something like

create table t (a int, b int, primary key (a));
 
insert into t values (1,10);
insert into t values (1,20) on duplicate key update a = 2, b = 20;
insert into t values (1,30) on duplicate key update a = 2, b = 30;
insert into t values (1,40) on duplicate key update a = 2, b = 40;

will also hit a duplicate key error on the 4th insert.

Does it explain the behavior you are getting, or do you still think that it's incorrect?

Comment by Linkang, Zhang [ 2023-06-05 ]

I think the MariaDB syntax "on duplicate key update" should know the case,and do something to avoid this.
Because when we use "ON DUPLICATE KEY UPDATE" we want the mariadbd server to solve the case that may cause duplicate key.
You can see the bug I provided to MySQL at the same time , and they verified it:https://bugs.mysql.com/bug.php?id=111183

Comment by Elena Stepanova [ 2023-06-05 ]

I'll leave it to serg as an architect to decide.

In my opinion it currently works exactly according to the table definition, and any change, while possible, would be a deviation from it; neither do I expect that MySQL will actually change the behavior, despite the verification team confirmation.
But since the timestamp magic is such a gray area, there is a room for arbitrary decisions and no clear right or wrong answers.

Comment by Sergei Golubchik [ 2023-06-05 ]

Yes, elenst is right, this is expected behavior. Her comment explains why MariaDB behaves that way.

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