Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-35483

rollback makes config.transactions fastcount inaccurate

    XMLWordPrintableJSON

Details

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: Major - P3 Major - P3
    • None
    • None
    • Replication
    • Replication
    • ALL
    • Hide

      (function() {
          "use strict";
       
          load("jstests/replsets/libs/rollback_test.js");
       
          const testName = "rollback_transactions_count";
          const dbName = testName;
       
          let replSet = new ReplSetTest({name: testName, nodes: 3, useBridge: true});
          replSet.startSet();
       
          const nodes = replSet.nodeList();
          replSet.initiate({
              _id: testName,
              members: [
                  {_id: 0, host: nodes[0]},
                  {_id: 1, host: nodes[1]},
                  {_id: 2, host: nodes[2], arbiterOnly: true}
              ]
          });
       
          // Set up Rollback Test.
          let rollbackTest = new RollbackTest(testName, replSet);
          let primary = rollbackTest.getPrimary();
          assert.commandWorked(primary.setLogLevel(3, 'storage.recovery'));
          let testDb = primary.getDB(dbName);
       
          const txnName = "txnCollName";
       
          const session1 = primary.startSession();
          const sessionDb1 = session1.getDatabase(dbName);
          const sessionColl1 = sessionDb1[txnName];
          assert.commandWorked(sessionColl1.insert({a: 1}));
          session1.startTransaction();
          assert.commandWorked(sessionColl1.insert({b: 1}));
          session1.commitTransaction();
       
          replSet.awaitLastOpCommitted();
          assert.commandWorked(
              primary.adminCommand({configureFailPoint: 'disableSnapshotting', mode: 'alwaysOn'}));
       
          const session2 = primary.startSession();
          const sessionDb2 = session2.getDatabase(dbName);
          const sessionColl2 = sessionDb2[txnName];
          session2.startTransaction();
          assert.commandWorked(sessionColl2.insert({c: 1}));
          session2.commitTransaction();
       
          rollbackTest.transitionToRollbackOperations();
       
          session2.startTransaction();
          assert.commandWorked(sessionColl2.insert({d: 1}));
          session2.commitTransaction();
       
          const session3 = primary.startSession();
          const sessionDb3 = session3.getDatabase(dbName);
          const sessionColl3 = sessionDb3[txnName];
          session3.startTransaction();
          assert.commandWorked(sessionColl3.insert({e: 1}));
          session3.commitTransaction();
       
          rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
          rollbackTest.transitionToSyncSourceOperationsDuringRollback();
          try {
              rollbackTest.transitionToSteadyStateOperations();
          } finally {
              assert.commandWorked(
                  primary.adminCommand({configureFailPoint: 'disableSnapshotting', mode: 'off'}));
          }
       
          rollbackTest.stop();
      })();
      

      Show
      (function() { "use strict";   load("jstests/replsets/libs/rollback_test.js");   const testName = "rollback_transactions_count"; const dbName = testName;   let replSet = new ReplSetTest({name: testName, nodes: 3, useBridge: true}); replSet.startSet();   const nodes = replSet.nodeList(); replSet.initiate({ _id: testName, members: [ {_id: 0, host: nodes[0]}, {_id: 1, host: nodes[1]}, {_id: 2, host: nodes[2], arbiterOnly: true} ] });   // Set up Rollback Test. let rollbackTest = new RollbackTest(testName, replSet); let primary = rollbackTest.getPrimary(); assert.commandWorked(primary.setLogLevel(3, 'storage.recovery')); let testDb = primary.getDB(dbName);   const txnName = "txnCollName";   const session1 = primary.startSession(); const sessionDb1 = session1.getDatabase(dbName); const sessionColl1 = sessionDb1[txnName]; assert.commandWorked(sessionColl1.insert({a: 1})); session1.startTransaction(); assert.commandWorked(sessionColl1.insert({b: 1})); session1.commitTransaction();   replSet.awaitLastOpCommitted(); assert.commandWorked( primary.adminCommand({configureFailPoint: 'disableSnapshotting', mode: 'alwaysOn'}));   const session2 = primary.startSession(); const sessionDb2 = session2.getDatabase(dbName); const sessionColl2 = sessionDb2[txnName]; session2.startTransaction(); assert.commandWorked(sessionColl2.insert({c: 1})); session2.commitTransaction();   rollbackTest.transitionToRollbackOperations();   session2.startTransaction(); assert.commandWorked(sessionColl2.insert({d: 1})); session2.commitTransaction();   const session3 = primary.startSession(); const sessionDb3 = session3.getDatabase(dbName); const sessionColl3 = sessionDb3[txnName]; session3.startTransaction(); assert.commandWorked(sessionColl3.insert({e: 1})); session3.commitTransaction();   rollbackTest.transitionToSyncSourceOperationsBeforeRollback(); rollbackTest.transitionToSyncSourceOperationsDuringRollback(); try { rollbackTest.transitionToSteadyStateOperations(); } finally { assert.commandWorked( primary.adminCommand({configureFailPoint: 'disableSnapshotting', mode: 'off'})); }   rollbackTest.stop(); })();

    Description

      When an applyOps entry causes a record to be upserted into the config.transactions table, it's impossible to know whether the entry changed the count of the collection or not. If it's a new session it will change the count, but if it's an existing session it won't. We would need to actually inspect the table for the existence of the session to correct this.

      Attachments

        Activity

          People

            backlog-server-repl Backlog - Replication Team
            judah.schvimer@mongodb.com Judah Schvimer
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: