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

Allow changing the "overwrite" setting on an existing WT cursor

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Works as Designed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      Right now it is only possible to set the "overwrite" setting at cursor creation time, which means that there are now two kinds of cursors that need to be kept separate. SERVER-55342 is an example of the issues this causes. Since mongo caches cursors in its glue layer, it needs to (but doesn't currently...) keep the cache partitioned based on both the table and the overwrite setting. As an alternative, if we could just set overwrite to the desired value on checkout, it would be both simpler to maintain the cache, and would result in fewer total cursors since we wouldn't need to create duplicate cursors. It is also somewhat unfortunate that cursors that are only used for reading, and therefore don't care about the overwrite setting, still need to pick a setting, which may prevent reuse of that cursor for writing.

      As an additional benefit, it would allow not using a separate cursor if you need to do some subset of operations with a different setting. This happens in mongo when we need to forcibly retry an operation that failed due to duplicate key error when we are in a state where we are supposed to ignore/allow those errors. For example, in a branch where I have pushed the usage of cursors for writing up to the higher mongodb layers there is logic like this where we need to bypass the cursor. If we were able to change the overwrite setting (and change it back after the special-case operation), we would be able to just use the cursor in the if block as well.

          auto cursor = _newInterface->newWriteCursor(
              opCtx, !unique /* dupsAllowed */, options.isForMultikeyMetadataKeys);
          // Add all new keys into the index. The RecordId for each is already encoded in the KeyString.
          for (const auto& keyString : keys) {
              Status status = cursor->insert(keyString);
       
              // When duplicates are encountered and allowed, retry with dupsAllowed. Call
              // onDuplicateKey() with the inserted duplicate key.
              if (ErrorCodes::DuplicateKey == status.code() && options.dupsAllowed) {
                  invariant(unique);
                  // Can't use cursor here since we need to use a different value of dupsAllowed.
                  status = _newInterface->insert(opCtx, keyString, true /* dupsAllowed */);
                  if (status.isOK() && onDuplicateKey)
                      status = onDuplicateKey(keyString);
              }
              uassertStatusOK(status);
          }
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              backlog-server-storage-engines Backlog - Storage Engines Team
              Reporter:
              redbeard0531 Mathias Stearn
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: