| Bug #119595 | UPDATE with OR condition updates the same row twice, resulting in duplicated expression evaluation | ||
|---|---|---|---|
| Submitted: | 25 Dec 2025 3:52 | Modified: | 25 Dec 2025 4:42 |
| Reporter: | Siyang Weng | Email Updates: | |
| Status: | Can't repeat | Impact on me: | |
| Category: | MySQL Server | Severity: | S3 (Non-critical) |
| Version: | 8.0.22 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[25 Dec 2025 4:42]
MySQL Verification Team
Thanks for the report. I could reproduce this on 8.0.22, but not on 8.0.44. mysql> SELECT version_2 FROM tbl_2; +-----------+ | version_2 | +-----------+ | | | | | T2T2 | +-----------+ 3 rows in set (0.00 sec) mysql> select version(); +-------------------+ | version() | +-------------------+ | 8.0.22-commercial | +-------------------+ 1 row in set (0.00 sec) ========= mysql> SELECT version_2 FROM tbl_2; +-----------+ | version_2 | +-----------+ | | | | | T2 | +-----------+ 3 rows in set (0.00 sec) mysql> select version(); +-------------------+ | version() | +-------------------+ | 8.0.44-commercial | +-------------------+ 1 row in set (0.00 sec)

Description: A single-row UPDATE statement may update the same row multiple times when the WHERE clause contains an OR condition whose predicates are evaluated through different access paths. As a result, expressions in the SET clause are applied more than once to the same row, violating standard SQL semantics. This issue only reproduces when both predicates in the OR condition are present. Removing either predicate prevents the bug. ### Expected Behavior For a single UPDATE statement: Each qualifying row should be updated at most once. Expressions in the SET clause should be evaluated using the row’s original value. For the test case below, version_2 should become T2. ### Actual Behavior The same row is matched twice during the execution of a single UPDATE. The SET expression is applied twice. The final value becomes T2T2. How to repeat: run the following case ```sql DROP TABLE IF EXISTS tbl_2; CREATE TABLE tbl_2 ( col_2_1 INT, col_2_7 INT, col_2_9 FLOAT, pkid_2 INT, version_2 VARCHAR(200), PRIMARY KEY (col_2_1, col_2_7, pkid_2), INDEX idx_2_1 (col_2_7, col_2_9) ); INSERT INTO tbl_2 (col_2_7, pkid_2, col_2_9, col_2_1, version_2) VALUES (4, 0, 1, 2, ''); INSERT INTO tbl_2 (col_2_7, pkid_2, col_2_9, col_2_1, version_2) VALUES (5, 4, 1, 1, ''); INSERT INTO tbl_2 (col_2_7, pkid_2, col_2_9, col_2_1, version_2) VALUES (4, 7, 1, 3, ''); SELECT version_2 FROM tbl_2; --- returns three rows, each one is '' UPDATE tbl_2 SET col_2_9 = 2, version_2 = CONCAT(version_2, 'T2') WHERE col_2_7 = 6 OR col_2_1 >= 3; SELECT version_2 FROM tbl_2; -- returns three rows, the last one is 'T2T2' instead of 'T2' ```