事务 60 秒的上限到点之后到底发生什么?是不是准点中止?事务外的写入会被它阻塞多久?这篇用 5 秒和 60 秒两个上限实测。
# 默认值
test> var r = db.adminCommand({getParameter: 1, transactionLifetimeLimitSeconds: 1, maxTransactionLockRequestTimeoutMillis: 1}); ({transactionLifetimeLimitSeconds: r.transactionLifetimeLimitSeconds, maxTransactionLockRequestTimeoutMillis: r.maxTransactionLockRequestTimeoutMillis})
{
transactionLifetimeLimitSeconds: 60,
maxTransactionLockRequestTimeoutMillis: 5
}事务最长存活 60 秒(transactionLifetimeLimitSeconds),currentOp 里的 expiryTime 就是开始时间加 60 秒。
currentOp 里事务的字段: ['expiryTime', 'parameters', 'readTimestamp', 'startWallClockTime', 'timeActiveMicros', 'timeInactiveMicros', 'timeOpenMicros']
timeOpenMicros = 672;timeActiveMicros = 126;expiryTime - startWallClockTime = 60.0 秒;parameters = {'txnNumber': 2, 'txnRetryCounter': 0, 'autocommit': False, 'readConcern': {'level': 'local', 'provenance': 'implicitDefault'}}事务被中止,修改回滚;继续操作或提交都报 251 NoSuchTransaction,带 TransientTransactionError,可以整个重试。
test> var r = db.adminCommand({setParameter: 1, transactionLifetimeLimitSeconds: 5}); ({was: r.was, ok: r.ok})
{ was: 60, ok: 1 }
事务外对 A 的 update 等了 5357 ms 才完成(上限 5 s;期间事务里一直没有再操作)
事务开始 5.4 s 后在事务里继续操作:code=251(NoSuchTransaction),errorLabels=['TransientTransactionError'];message: Transaction with { txnNumber: 1 } has been aborted., full error: {'errorLabels': ['TransientTransactionError'], 'ok': 0.
commit:code=251(NoSuchTransaction),errorLabels=['TransientTransactionError']
文档 A(_id 1)的 v = 0(事务里的 $inc 被回滚了),w = 1(事务外的写入生效)事务改了文档不提交,事务外对同一个文档的写入要等到事务被中止或提交才能完成(上限 5 秒时等了 5.4 秒)。
每 0.5 秒操作一次:成功了 15 次后在 7.6 s 时失败 code=251(NoSuchTransaction)——即使一直在用,到上限也会中止
生命周期从事务开始算起,即使一直在操作也会过期。
含 transaction + expired/abort 的日志行 4 条;不同的 msg: ["Aborting transaction because it has been running for longer than 'transactionLifetimeLimitSeconds'", 'transaction']
test> var r = db.adminCommand({setParameter: 1, transactionLifetimeLimitSeconds: 60}); ({was: r.was, ok: r.ok})
{ was: 5, ok: 1 }过期事务由后台任务周期性清理:默认 60 秒的事务在 70 秒时提交仍成功,89 秒才被中止。所以别指望“恰好 60 秒”,事务要尽量短。
事务 A:70 s 时 commit 成功;文档 _id 4 的 v = 1 事务 B(一直没动):在 89 s 时从 currentOp 里消失(被服务端中止),上限是 60 s B 的 commit:code=251(NoSuchTransaction),errorLabels=['TransientTransactionError'];文档 _id 3 的 v = 0(没有被修改) 日志里 "Aborting transaction because it has been running for longer than transactionLifetimeLimitSeconds" 的记录数 5
服务端会记一条 “Aborting transaction because it has been running for longer than transactionLifetimeLimitSeconds”。