Including a "txnNumber" field on a command using "linearizable" read concern will bypass post-execution read concern wait

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Duplicate
    • Priority: Major - P3
    • None
    • Affects Version/s: 4.1.10
    • Component/s: Replication
    • None
    • ALL
    • Hide
      
      const name = "linearizable_read_txnNum";
      const replTest = new ReplSetTest({
          name: name,
          nodes: 1,
      });
      replTest.startSet();
      replTest.initiate();
      
      const dbName = name;
      const collName = "coll";
      
      let primary = replTest.getPrimary();
      const session = primary.startSession({causalConsistency: false});
      const sessionDb = session.getDatabase(dbName);
      const sessionColl = sessionDb[collName];
      
      // Insert a doc.
      assert.commandWorked(sessionColl.insert({x:1}));
      
      jsTestLog("Running find command.");
      let res = sessionDb.runCommand({
          find: collName,
          readConcern: {level: 'linearizable'},
      });
      counters = primary.adminCommand({serverStatus: 1}).opReadConcernCounters;
      assert.eq(counters.linearizable, 1);
      
      res = sessionDb.runCommand({
          find: collName,
          readConcern: {level: 'linearizable'},
          txnNumber: NumberLong(1)
      });
      counters = primary.adminCommand({serverStatus: 1}).opReadConcernCounters;
      // This assertion will fail if we don't do a proper 'linearizable' read above.
      assert.eq(counters.linearizable, 2);
      
      
      replTest.stopSet();
      
      Show
      const name = "linearizable_read_txnNum" ; const replTest = new ReplSetTest({ name: name, nodes: 1, }); replTest.startSet(); replTest.initiate(); const dbName = name; const collName = "coll" ; let primary = replTest.getPrimary(); const session = primary.startSession({causalConsistency: false }); const sessionDb = session.getDatabase(dbName); const sessionColl = sessionDb[collName]; // Insert a doc. assert.commandWorked(sessionColl.insert({x:1})); jsTestLog( "Running find command." ); let res = sessionDb.runCommand({ find: collName, readConcern: {level: 'linearizable' }, }); counters = primary.adminCommand({serverStatus: 1}).opReadConcernCounters; assert.eq(counters.linearizable, 1); res = sessionDb.runCommand({ find: collName, readConcern: {level: 'linearizable' }, txnNumber: NumberLong(1) }); counters = primary.adminCommand({serverStatus: 1}).opReadConcernCounters; // This assertion will fail if we don 't do a proper ' linearizable' read above. assert.eq(counters.linearizable, 2); replTest.stopSet();
    • Repl 2019-05-20
    • 10
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      If you run a read command on a session (e.g. 'find') at "linearizable" read concern and include a "txnNumber" field, the server will do no waiting to satisfy the linearizable read concern i.e. it will bypass the call to waitForLinearizableReadConcern. This is due to the fact that when we check out a session, which we will do when a command includes a txnNumber, we read from the transactions table inside a DBDirectClient query. The DBDirectClient overrides the original read concern on the OperationContext and so at the end of command execution, we will not wait on any read concern.

            Assignee:
            Tess Avitabile (Inactive)
            Reporter:
            Will Schultz
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: