An automatically updated timestamp is useful until one particular maintenance statement should leave it alone. A counter may need correction, for example, without pretending that the underlying content changed. MySQL has a statement-level solution for this case: assign the timestamp column its current value.
The Automatic Timestamp
Consider a table that records when a tag last changed:
CREATE TABLE tag (
id BIGINT UNSIGNED NOT NULL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
relation_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
updated_at TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
); When an UPDATE changes another column, MySQL normally writes the current time to updated_at:
UPDATE tag
SET relation_count = relation_count + 1
WHERE id = 7; The automatic update is skipped when all other assigned values remain unchanged. Once a value really changes, however, ON UPDATE CURRENT_TIMESTAMP takes effect.
Preserve the Existing Value
To correct the counter without changing the timestamp, explicitly assign updated_at to itself:
UPDATE tag
SET relation_count = 42,
updated_at = updated_at
WHERE id = 7; The right-hand updated_at is the value from the row before the assignment. Because the statement supplies an explicit value for the column, that value takes precedence over its automatic update property. The same pattern works for a multi-row update; each row retains its own timestamp:
UPDATE tag
SET relation_count = 0,
updated_at = updated_at
WHERE relation_count < 0; This is substantially safer than temporarily altering the column definition. It requires no metadata lock for an ALTER TABLE, creates no interval in which concurrent statements see different schema semantics, and can remain inside the transaction that performs the correction.
Force an Update Instead
The inverse operation is explicit as well. Assign CURRENT_TIMESTAMP when the timestamp should advance even if no other value changes:
UPDATE tag
SET updated_at = CURRENT_TIMESTAMP
WHERE id = 7; For events that can occur more than once per second, declare matching fractional precision throughout the column definition:
updated_at TIMESTAMP(6)
DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6) Know What the Timestamp Means
Preserving updated_at is correct only when the maintenance change is deliberately outside the event the column represents. If consumers use it for cache invalidation, replication decisions, or optimistic locking, hiding a real change can violate that contract. Separate columns such as content_updated_at and aggregate_refreshed_at are clearer when both events matter.
The self-assignment controls MySQL's automatic timestamp property. A BEFORE UPDATE trigger can still assign a different value to NEW.updated_at, so inspect explicit triggers when the timestamp changes despite this pattern.