Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Duplicate
-
None
-
None
-
Not for Release Notes
-
Description
Environment
- Product: MariaDB Server
- Observed affected versions: 10.3, 10.6, and 12.2.2
- Storage engine: InnoDB
- Clean comparison: MySQL 8.0.36 computes the expected generated value for the
same multi-table update.
Minimal reproduction
DROP DATABASE IF EXISTS mdev_multitable_generated; |
CREATE DATABASE mdev_multitable_generated; |
USE mdev_multitable_generated; |
|
|
CREATE TABLE p( |
id INT PRIMARY KEY, |
flag INT NOT NULL |
) ENGINE=InnoDB;
|
|
|
CREATE TABLE c( |
id INT PRIMARY KEY, |
pid INT NOT NULL, |
v INT NOT NULL, |
g INT GENERATED ALWAYS AS (v * 2) STORED, |
FOREIGN KEY (pid) REFERENCES p(id) |
) ENGINE=InnoDB;
|
|
|
DELIMITER //
|
CREATE TRIGGER c_bu BEFORE UPDATE ON c FOR EACH ROW |
BEGIN
|
SET NEW.v = NEW.v + 10; |
END// |
DELIMITER ;
|
|
|
INSERT INTO p VALUES (1, 0), (2, 1); |
INSERT INTO c(id, pid, v) VALUES (10, 1, 5), (20, 2, 7); |
|
|
UPDATE p JOIN c ON c.pid = p.id |
SET p.flag = p.flag + 1, |
c.v = c.v + 1
|
WHERE p.flag >= 0; |
|
|
SELECT id, pid, v, g, v * 2 AS expected_g, g = v * 2 AS invariant_holds |
FROM c |
ORDER BY id; |
Expected result
The UPDATE first proposes v=6 and v=8. The trigger adds 10, so the
persisted values should be v=16 and v=18 and the generated values must
be 32 and 36:
id pid v g expected_g invariant_holds
|
10 1 16 32 32 1
|
20 2 18 36 36 1
|
Actual result on MariaDB 10.3, 10.6, and 12.2.2
id pid v g expected_g invariant_holds
|
10 1 16 12 32 0
|
20 2 18 16 36 0
|
The persisted g values are 6 * 2 and 8 * 2: they reflect the
pre-trigger proposal rather than the final value stored in v.
Relevant controls
- On the same MariaDB schema, the single-table statement
UPDATE c SET v = v + 1 WHERE id IN (10, 20) invokes the same trigger and
persists g=32 and g=36. - MySQL 8.0.36 persists g=32 and g=36 for the multi-table statement.
- A transaction savepoint/rollback removes both the base-column change and the
generated value together; the observed problem is the successful
materialization before rollback, not rollback cleanup.
Constraint consequence (same mechanism)
Adding CHECK (g < 20) to c makes the consequence externally visible:
the multi-table update above is accepted by affected MariaDB versions with
v=16, g=12, although a correctly recomputed g=32 would violate the
constraint. MySQL 8.0.36 rejects the update. I regard this as an impact of
the same stale-materialization mechanism, not a separate issue report.
Repetition and nearby issues checked
The minimal multi-table signal reproduced three times on each of MariaDB 10.3,
10.6, and 12.2.2. The single-table control was clean. I checked nearby
reports MDEV-36026, MDEV-36191, MDEV-36717, and MDEV-39711; they concern other
INSERT ... SELECT, metadata, or system-versioning paths and do not describe
a successful UPDATE ... JOIN persisting a stored generated value computed
before a BEFORE UPDATE trigger mutation.
Attachments
Issue Links
- duplicates
-
MDEV-40480 LOAD DATA leaves a stale STORED generated column after a BEFORE INSERT trigger changes its base column
-
- Approved
-