mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
14cc7e7d6e
First UPDATE under START TRANSACTION does nothing (nstate= nstate), but anyway generates history. Since update vector is empty we get into (!uvect->n_fields) branch which only adds history row, but does not do update. After that we get current row with wrong (old) row_start value and because of that second UPDATE tries to insert history row again because it sees trx->id != row_start which is the guard to avoid inserting multiple trx_id-based history rows under same transaction (because we have same trx_id and we get duplicate error and this bug demostrates that). But this try anyway fails because PK is based on row_end which is constant under same transaction, so PK didn't change. The fix moves vers_make_update() to an earlier stage of calc_row_difference(). Therefore it prepares update vector before (!uvect->n_fields) check and never gets into that branch, hence no need to handle versioning inside that condition anymore. Now trx->id and row_start are equal after first UPDATE and we don't try to insert second history row. == Cleanups and improvements == ha_innobase::update_row(): vers_set_fields and vers_ins_row are cleaned up into direct condition check. SQLCOM_ALTER_TABLE check now is not used as this is dead code, assertion is done instead. upd_node->is_delete is set in calc_row_difference() just to keep versioning code as much in one place as possible. vers_make_delete() is still located in row_update_for_mysql() as this is required for ha_innodbase::delete_row() as well. row_ins_duplicate_error_in_clust(): Restrict DB_FOREIGN_DUPLICATE_KEY to the better conditions. VERSIONED_DELETE is used specifically to help lower stack to understand what caused current insert. Related to MDEV-29813.
24 lines
503 B
Text
24 lines
503 B
Text
--- update.result
|
|
+++ update.reject
|
|
@@ -84,12 +84,10 @@
|
|
commit;
|
|
select x, y, sys_trx_end = MAXVAL as current from t1 for system_time all order by sys_trx_end, x, y;
|
|
x y current
|
|
-3 1 0
|
|
2 1 0
|
|
-3 2 0
|
|
+3 1 0
|
|
4 1 0
|
|
5 1 0
|
|
-5 2 0
|
|
1 1 1
|
|
2 2 1
|
|
3 3 1
|
|
@@ -464,7 +462,6 @@
|
|
select nid, nstate, check_row(row_start, row_end) from t1 for system_time all order by row_start, row_end;
|
|
nid nstate check_row(row_start, row_end)
|
|
1 1 HISTORICAL ROW
|
|
-1 1 HISTORICAL ROW
|
|
1 3 CURRENT ROW
|
|
commit;
|
|
drop tables t1;
|