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

    • 8
    • 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

              backlog-server-storage-engines Backlog - Storage Engines Team
              mathias@mongodb.com Mathias Stearn
              Votes:
              0 Vote for this issue
              Watchers:
              17 Start watching this issue

              Dates

                Created:
                Updated: