yugabyte / yugabyte-db

YugabyteDB - the cloud native distributed SQL database for mission-critical applications.
https://www.yugabyte.com
Other
8.99k stars 1.07k forks source link

[DocDB] Incorrect conflict behavior between For Key Share / Update with packed rows #15970

Closed robertsami closed 1 year ago

robertsami commented 1 year ago

Jira Link: DB-5380

Description

bin/yb-ctl create --rf 1 --tserver_flags="ysql_enable_packed_row=true"

first setup the data:

yugabyte=#   CREATE TABLE foo (
yugabyte(#     key        int,
yugabyte(#     value    int,
yugabyte(#     PRIMARY KEY (key) INCLUDE (value)
yugabyte(#   );
CREATE TABLE
yugabyte=#
yugabyte=#   INSERT INTO foo VALUES (1, 1);
INSERT 0 1

yugabyte=#

then setup one session as follows:

yugabyte=# begin;
BEGIN
yugabyte=# UPDATE foo SET value = 2 WHERE key = 1;
UPDATE 1

In the second session, we should see the following output when running these commands:

yugabyte=# begin;
BEGIN
yugabyte=# select * from foo for key share;
 key | value
-----+-------
   1 |     1
(1 row)

Instead, the select in the second session will hang due to read committed internal retry, indicating that a conflict was incorrectly detected

robertsami commented 1 year ago

note that this behavior is no longer observed if the primary key def'n no longer has the include (value) clause

Huqicheng commented 1 year ago

The UPDATE stmt is packing full row update, so it only creates an intent with full row (just like an INSERT). So from conflict resolver's view, the full row is locked.

When resolving conflict with select-for-keyshare, it finds out the full row is locked, so waiting on the UPDATE to commit.

rthallamko3 commented 1 year ago

Created https://github.com/yugabyte/yugabyte-db/issues/16459 to track the longer term fix to fix this. For now, disabling the optimization unblocks PackedRow default behavior.