Uploaded image for project: 'WiredTiger'
  1. WiredTiger
  2. WT-7310

dupekey error on uncommited write should return WT_ROLLBACK not WT_DUPLICATE_KEY

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Blocked
    • Priority: Major - P3
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: Backlog
    • Component/s: None
    • Labels:
      None
    • Story Points:
      8
    • Sprint:
      Storage - Ra 2021-05-31, Storage - Ra 2021-06-14

      Description

      When getting back a WT_DUPLICATE_KEY, a caller of a cursor write operation should be able to assume that a record with that key already exists. However, if the transaction that wrote the conflicting entry is uncommitted, it doesn't have that guarantee, because that write could always roll back.

      repro in mongo unit test:

      TEST(WiredTigerUtilTest, DupeKeyInTxnRollsBack) {
          WiredTigerUtilHarnessHelper harnessHelper("statistics=(all)");
          auto conn = harnessHelper.getConnection()->getConnection();
       
          WT_SESSION* session1;
          invariantWTOK(conn->open_session(conn, nullptr, nullptr, &session1));
       
          auto uri = "table:mytable";
          invariantWTOK(session1->create(session1, uri, "key_format=i,value_format=i"));
       
          // Open a transaction on session1 and insert key=1, and leave transaction open.
          invariantWTOK(session1->begin_transaction(session1, "isolation=snapshot"));
          {
              WT_CURSOR* cursor;
              invariantWTOK(session1->open_cursor(session1, uri, nullptr, "overwrite=false", &cursor));
              ON_BLOCK_EXIT([&] { cursor->close(cursor); });
              cursor->set_key(cursor, 1);
              cursor->set_value(cursor, 1);
              invariantWTOK(cursor->insert(cursor));
          }
       
          WT_SESSION* session2;
          invariantWTOK(conn->open_session(conn, nullptr, nullptr, &session2));
       
          // Open a transaction on session2 and try to insert key=1.
          {
              invariantWTOK(session2->begin_transaction(session2, "isolation=snapshot"));
              WT_CURSOR* cursor;
              invariantWTOK(session2->open_cursor(session1, uri, nullptr, "overwrite=false", &cursor));
              ON_BLOCK_EXIT([&] { cursor->close(cursor); });
              cursor->set_key(cursor, 1);
              cursor->set_value(cursor, 1);
              auto ret = cursor->insert(cursor);
              // Should not return dupe key for something not inserted as of my snapshot.
              ASSERT_NE(ret, WT_DUPLICATE_KEY); // <--- fails
              ASSERT_EQ(ret, WT_ROLLBACK);
          }
       
          // Let transactions auto-abort when their sessions are closed.
      }
      
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              haseeb.bokhari Haseeb Bokhari
              Reporter:
              redbeard0531 Mathias Stearn
              Votes:
              0 Vote for this issue
              Watchers:
              16 Start watching this issue

                Dates

                Created:
                Updated: