when the -linearizable flag is set, the coordinator receiving the
EndTransaction request will make a note of the local wall time
before dispatching the request further, reexamining the local
clock and txn commit timestamp when the call completes successfully.
if either MaxOffset ns were spent between those two events, or
the transaction's commit timestamp is MaxOffset behind the
local clock after the EndTransaction call has been carried
out successfully, control is returned to the client immediately.
Otherwise, the smaller of the two durations described above
is waited before returning control.
This ensures that at the point of returning control, all nodes
in the system are ahead of the commit timestamp in the transaction.
git pull https://github.com/tschottdorf/cockroach linflag
Or view, comment on, or merge it at:
https://github.com/cockroachdb/cockroach/pull/244
—
Reply to this email directly or view it on GitHub.
@spencerkimball I've added taking into account the commit timestamp which is something we didn't discuss. Please scrutinize :)
> @@ -32,6 +33,10 @@ import ( > "github.com/cockroachdb/cockroach/util/log" > ) > > +var linearizable = flag.Bool("linearizable", false, "enables linearizable behaviour "+ > + "of operations on this node by making sure that no commit timestamp is "+ > + "reported back to the client until all other node's clocks have passed it.")
s/node's clocks have/node clocks have necessarily/
> @@ -313,6 +322,25 @@ func (tc *TxnCoordSender) sendOne(call *client.Call) { > var txn *proto.Transaction > if call.Method == proto.EndTransaction { > txn = call.Reply.Header().Txn > + // If the -linearizable flag is set, we want to make sure that > + // all the clocks in the system are past the commit timestamp > + // of the transaction. This is guaranteed if either > + // - the commit timestamp is MaxOffset behind startNS > + // - MaxOffset ns were spent in this function > + // when returning to the client. Below we chose the option
s/chose/choose/
> + // If the -linearizable flag is set, we want to make sure that > + // all the clocks in the system are past the commit timestamp > + // of the transaction. This is guaranteed if either > + // - the commit timestamp is MaxOffset behind startNS > + // - MaxOffset ns were spent in this function > + // when returning to the client. Below we chose the option > + // that involves less waiting, which is likely the first one > + // unless a transaction commits with an odd timestamp. > + if tsNS := txn.Timestamp.WallTime; startNS > tsNS { > + startNS = tsNS > + } > + sleepNS := tc.clock.MaxOffset() - > + time.Duration(tc.clock.PhysicalNow()-startNS) > + if *linearizable && sleepNS > 0 { > + defer func() { > + log.Infof("%v: waiting %dms on EndTransaction for linearizability", txn.ID, sleepNS/1000000)
log.V(1).Infof would be better.
LGTM. Nice
> @@ -32,6 +33,10 @@ import ( > "github.com/cockroachdb/cockroach/util/log" > ) > > +var linearizable = flag.Bool("linearizable", false, "enables linearizable behaviour "+ > + "of operations on this node by making sure that no commit timestamp is "+ > + "reported back to the client until all other node's clocks have passed it.")
done.
> @@ -313,6 +322,25 @@ func (tc *TxnCoordSender) sendOne(call *client.Call) { > var txn *proto.Transaction > if call.Method == proto.EndTransaction { > txn = call.Reply.Header().Txn > + // If the -linearizable flag is set, we want to make sure that > + // all the clocks in the system are past the commit timestamp > + // of the transaction. This is guaranteed if either > + // - the commit timestamp is MaxOffset behind startNS > + // - MaxOffset ns were spent in this function > + // when returning to the client. Below we chose the option
done.
> + // If the -linearizable flag is set, we want to make sure that > + // all the clocks in the system are past the commit timestamp > + // of the transaction. This is guaranteed if either > + // - the commit timestamp is MaxOffset behind startNS > + // - MaxOffset ns were spent in this function > + // when returning to the client. Below we chose the option > + // that involves less waiting, which is likely the first one > + // unless a transaction commits with an odd timestamp. > + if tsNS := txn.Timestamp.WallTime; startNS > tsNS { > + startNS = tsNS > + } > + sleepNS := tc.clock.MaxOffset() - > + time.Duration(tc.clock.PhysicalNow()-startNS) > + if *linearizable && sleepNS > 0 { > + defer func() { > + log.Infof("%v: waiting %dms on EndTransaction for linearizability", txn.ID, sleepNS/1000000)
done.
Merged #244.