Reputation: 115
I have a persistent process which examines a row in a database table and spawns a child process on some interval, based on the last time the child process was spawned (basically, a pretty simple CRON replacement).
I had originally implemented it, simply subtracting the current timestamp from the value stored in the last_start column. CURRENT_TIMESTAMP - last_start
. This seemed to work, however, closer inspection revealed that the timestamp subtraction was acting rather strangely.
It seemed that as we crossed the minute barrier (so, the current time ticked over to a new minute), the "difference" that was calculated would jump up by 40 (eg. from 59 up to 100). This looks like "1:00" - sort of - until we get to a state like that shown below, where what would be the "seconds" part of it goes above 60 (it's 95 in the example below).
I solved the problem by using the TIMESTAMPDIFF
method to do the subtraction (thanks Stack Overflow!). But it's not clear to me why this fell short in the first place.
mysql db_name -e 'select CURRENT_TIMESTAMP, last_start, CURRENT_TIMESTAMP - last_start , TIMESTAMPDIFF(SECOND, last_start, CURRENT_TIMESTAMP) from tasks where id = 3' Thu Sep 11 09:49:17 2014
CURRENT_TIMESTAMP last_start CURRENT_TIMESTAMP - last_start TIMESTAMPDIFF(SECOND, last_start, CURRENT_TIMESTAMP)
2014-09-11 09:49:17 2014-09-11 09:37:22 1195 715
Can anyone explain to me what's happening when I just subtract timestamps, as I was doing?
Edit: The table schema is as follows:
CREATE TABLE `tasks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`task` char(128) NOT NULL,
`run_count` int(10) unsigned NOT NULL DEFAULT '0',
`domina` char(128) DEFAULT NULL,
`slave` char(128) DEFAULT NULL,
`last_start` timestamp NULL DEFAULT NULL,
`last_end` timestamp NULL DEFAULT NULL,
`avg_duration` int(10) unsigned NOT NULL DEFAULT '0',
`last_status` char(64) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
Upvotes: 3
Views: 73
Reputation: 1270993
Why is this going wrong? Well, you would expect that a database (or any other software product) that had a data type called TIMESTAMP
and a "constant" called CURRENT_TIMESTAMP
would represent the latter using the former.
But no. That is not MySQL. CURRENT_TIMESTAMP
is a synonym for now()
, whose type is context-dependent. Happily, the documentation explains this quite clearly:
Returns the current date and time as a value in 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS format, depending on whether the function is used in a string or numeric context.
Of course, you have to figure out what the different contexts are. A hint. The use of -
is a "numeric context".
What happens is the following. MySQL sees CURRENT_TIMESTAMP
and puts in the current time. But how? It sees the -
and determines that it goes in as a number. Then it comes across last_start
. Well, this now has to be converted to a number too. And, guess what? You get funky behavior.
Upvotes: 2