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

rollback makes config.transactions fastcount inaccurate

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major - P3
    • Resolution: Won't Fix
    • 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

        Issue Links

          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: