EXPERIMENT 04 / BUSINESS INVARIANT
两边都提交了,却无人值班。
两名医生各自在“还有别人值班”时才撤岗。事务成功提交,仍可能共同破坏业务规则。
这里展示真实 MySQL 8.4 运行记录;浏览器不执行 SQL。实验限于固定成员,不对范围插入、任意已有快照或性能作出保证。
不变量:SUM(on_call) ≥ 1。初始状态 (1,1),各有一次撤岗请求。独立 Python 模型枚举两种串行请求顺序,只允许 (0,1) 或 (1,0)。两方提交后,另一个自动提交观察者独立读取 MySQL 终值。
实测首跑 JSON · 停止重启后复跑 JSON · 生命周期与反例验收 · 可修改 SQL
先预测,再阅读结果
- 双方先完成计数,再开始写入。单行 AND on_call=1 能否保护跨行规则?
- 双方先建立 RR 快照,再竞争独占守卫锁。之后的普通计数会更新吗?
- 在首次一致性读之前获取守卫锁,或直接 FOR UPDATE 读取名单。什么证据能证明 B 真正等待?
首轮实测结果
| 隔离级别 | strategy | A 计数 | B 计数 | 剩余值班 | 串行可达 |
|---|---|---|---|---|---|
| READ COMMITTED | unguarded | 2 | 2 | 0 | 否 |
| READ COMMITTED | late_guard | 2 | 1 | 1 | 是 |
| READ COMMITTED | guard_first | 2 | 1 | 1 | 是 |
| READ COMMITTED | locking_roster | 2 | 1 | 1 | 是 |
| REPEATABLE READ | unguarded | 2 | 2 | 0 | 否 |
| REPEATABLE READ | late_guard | 2 | 2 | 0 | 否 |
| REPEATABLE READ | guard_first | 2 | 1 | 1 | 是 |
| REPEATABLE READ | locking_roster | 2 | 1 | 1 | 是 |
上表每行都有两次成功提交;是否批准撤岗是另一个决策。每份记录重复三轮,第二轮交换医生 ID;第二份记录来自停止、重启后的复跑。时间只用于检查执行顺序,不作性能基准。
差异来自哪里
- unguarded:双方在写入前都读到 2,更新不同的行并提交。RC 和 RR 都出现 (0,0) 反例。
- late_guard:锁确实串行化了访问,但不会替换已有的 RR 读视图。RR 下后来的计数仍为 2;RC 下新的语句在这个调度中读到 1。
- guard_first:守卫锁之前没有一致性读。B 等待 A 提交,之后首次计数读到 1。所有写入者都必须遵守协议。
- locking_roster:当前锁定读取保护决策使用的行。B 等待后只返回一名值班医生。这里验证固定成员,不推广到所有范围或谓词场景。
运行、修改 SQL、复跑
python lab.py doctor
python lab.py start
python lab.py oncall --output .local/oncall-first.json
python lab.py stop
python lab.py start
python lab.py oncall --output .local/oncall-repeat.json
python scripts/validate_oncall.py .local/oncall-first.json .local/oncall-repeat.json
cp sql/oncall.json .local/oncall-sql.json
# Edit .local/oncall-sql.json, preserve the baseline
python lab.py oncall --sql-file .local/oncall-sql.json --output .local/oncall-edited.json
python lab.py stop- 基线:修改前解释失败场景为何不在模型允许的串行终值内。检查参数绑定,确认每个会话实际修改了哪名医生。
- 等价改写:将 count 改为 SELECT COALESCE(SUM(on_call),0) AS n FROM oncall_roster WHERE shift_id=1。复跑完整矩阵,固定名单下应保留相同语义。
- 负对照:从 guard 查询中删除 FOR UPDATE。所需 B→A 等待边消失,运行器必须在期限内失败,且不能产生成功 JSON。这是在拒绝失效的调度前提,并非新的终值证明。
- 解释把普通读取提前到 guard_first 之前,为何就变成 late_guard。用已有 late_guard RR 记录作为反例,再对比 RC。
检查实际证据
READ COMMITTED / unguarded / 剩余 0
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 0
}
],
"oracle": {
"on_call_count": 0,
"invariant_holds": false,
"serially_reachable": false,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"B": {
"doctor_id": 2,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
}
}
}这里不声称观测到锁等待,屏障依据是双方已完成的读取。
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 18.576,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 2,
"elapsed_ms": 19.559,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 3,
"elapsed_ms": 19.568,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 20.126,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 20.131,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 6,
"elapsed_ms": 21.032,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 7,
"elapsed_ms": 21.035,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 21.464,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 21.471,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 10,
"elapsed_ms": 22.647,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 11,
"elapsed_ms": 22.651,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 12,
"elapsed_ms": 23.208,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 13,
"elapsed_ms": 23.211,
"actor": "coordinator",
"action": "barrier: both initial counts completed before writes"
},
{
"step": 14,
"elapsed_ms": 23.303,
"actor": "B",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
2
]
},
{
"step": 15,
"elapsed_ms": 23.328,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 16,
"elapsed_ms": 24.057,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 17,
"elapsed_ms": 24.06,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 18,
"elapsed_ms": 24.084,
"actor": "B",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
2
]
},
{
"step": 19,
"elapsed_ms": 24.087,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 20,
"elapsed_ms": 25.498,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 21,
"elapsed_ms": 25.822,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]READ COMMITTED / late_guard / 剩余 1
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 1
}
],
"oracle": {
"on_call_count": 1,
"invariant_holds": true,
"serially_reachable": true,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 1,
"approved": false,
"outcome": "committed"
}
}
}| actor | table | index | mode | status |
|---|---|---|---|---|
| A | oncall_guard | PRIMARY | X,REC_NOT_GAP | GRANTED |
| A | oncall_guard | None | IX | GRANTED |
| B | oncall_guard | PRIMARY | X,REC_NOT_GAP | WAITING |
| B | oncall_guard | None | IX | GRANTED |
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 7.396,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 2,
"elapsed_ms": 8.127,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 3,
"elapsed_ms": 8.132,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 8.746,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 8.748,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 6,
"elapsed_ms": 9.344,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 7,
"elapsed_ms": 9.346,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 9.865,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 9.872,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 10,
"elapsed_ms": 10.602,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 11,
"elapsed_ms": 10.606,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 12,
"elapsed_ms": 11.234,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 13,
"elapsed_ms": 11.237,
"actor": "coordinator",
"action": "barrier: both initial counts completed before writes"
},
{
"step": 14,
"elapsed_ms": 11.238,
"actor": "A",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 15,
"elapsed_ms": 11.903,
"actor": "A",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 16,
"elapsed_ms": 11.996,
"actor": "B",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 17,
"elapsed_ms": 25.861,
"actor": "observer",
"action": "barrier: observed lock wait",
"waiting": "B",
"blocking": "A"
},
{
"step": 18,
"elapsed_ms": 25.872,
"actor": "coordinator",
"action": "barrier: release A only after observed B→A wait"
},
{
"step": 19,
"elapsed_ms": 25.876,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 20,
"elapsed_ms": 26.724,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 21,
"elapsed_ms": 26.729,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 22,
"elapsed_ms": 27.703,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 23,
"elapsed_ms": 27.706,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 24,
"elapsed_ms": 29.426,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 25,
"elapsed_ms": 29.495,
"actor": "B",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 26,
"elapsed_ms": 29.501,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 27,
"elapsed_ms": 30.322,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 1
}
]
},
{
"step": 28,
"elapsed_ms": 30.325,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 29,
"elapsed_ms": 31.188,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]READ COMMITTED / guard_first / 剩余 1
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 1
}
],
"oracle": {
"on_call_count": 1,
"invariant_holds": true,
"serially_reachable": true,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 1,
"approved": false,
"outcome": "committed"
}
}
}| actor | table | index | mode | status |
|---|---|---|---|---|
| A | oncall_guard | PRIMARY | X,REC_NOT_GAP | GRANTED |
| A | oncall_guard | None | IX | GRANTED |
| B | oncall_guard | PRIMARY | X,REC_NOT_GAP | WAITING |
| B | oncall_guard | None | IX | GRANTED |
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 9.927,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 2,
"elapsed_ms": 11.009,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 3,
"elapsed_ms": 11.013,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 11.621,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 11.63,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 6,
"elapsed_ms": 12.229,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 7,
"elapsed_ms": 12.232,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 12.835,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 12.84,
"actor": "A",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 10,
"elapsed_ms": 13.554,
"actor": "A",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 11,
"elapsed_ms": 13.663,
"actor": "B",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 12,
"elapsed_ms": 15.733,
"actor": "observer",
"action": "barrier: observed lock wait",
"waiting": "B",
"blocking": "A"
},
{
"step": 13,
"elapsed_ms": 15.737,
"actor": "coordinator",
"action": "barrier: release A only after observed B→A wait"
},
{
"step": 14,
"elapsed_ms": 15.74,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 15,
"elapsed_ms": 16.691,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 16,
"elapsed_ms": 16.696,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 17,
"elapsed_ms": 17.423,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 18,
"elapsed_ms": 17.428,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 19,
"elapsed_ms": 18.986,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 20,
"elapsed_ms": 19.068,
"actor": "B",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 21,
"elapsed_ms": 19.091,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 22,
"elapsed_ms": 19.963,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 1
}
]
},
{
"step": 23,
"elapsed_ms": 19.967,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 24,
"elapsed_ms": 20.487,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]READ COMMITTED / locking_roster / 剩余 1
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 1
}
],
"oracle": {
"on_call_count": 1,
"invariant_holds": true,
"serially_reachable": true,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 1,
"approved": false,
"outcome": "committed"
}
}
}| actor | table | index | mode | status |
|---|---|---|---|---|
| A | oncall_roster | PRIMARY | X,REC_NOT_GAP | GRANTED |
| A | oncall_roster | PRIMARY | X,REC_NOT_GAP | GRANTED |
| A | oncall_roster | None | IX | GRANTED |
| B | oncall_roster | PRIMARY | X,REC_NOT_GAP | WAITING |
| B | oncall_roster | None | IX | GRANTED |
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 10.083,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 2,
"elapsed_ms": 10.702,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 3,
"elapsed_ms": 10.71,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 11.24,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 11.244,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
},
{
"step": 6,
"elapsed_ms": 11.721,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED",
"rows": []
},
{
"step": 7,
"elapsed_ms": 11.725,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 12.125,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 12.129,
"actor": "A",
"action": "submit",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE"
},
{
"step": 10,
"elapsed_ms": 12.897,
"actor": "A",
"action": "returned",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE",
"rows": [
{
"doctor_id": 1
},
{
"doctor_id": 2
}
]
},
{
"step": 11,
"elapsed_ms": 12.996,
"actor": "B",
"action": "submit",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE"
},
{
"step": 12,
"elapsed_ms": 15.375,
"actor": "observer",
"action": "barrier: observed lock wait",
"waiting": "B",
"blocking": "A"
},
{
"step": 13,
"elapsed_ms": 15.381,
"actor": "coordinator",
"action": "barrier: release A only after observed B→A wait"
},
{
"step": 14,
"elapsed_ms": 15.386,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 15,
"elapsed_ms": 15.947,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 16,
"elapsed_ms": 15.95,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 17,
"elapsed_ms": 17.832,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 18,
"elapsed_ms": 17.877,
"actor": "B",
"action": "returned",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE",
"rows": [
{
"doctor_id": 2
}
]
},
{
"step": 19,
"elapsed_ms": 17.88,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 20,
"elapsed_ms": 18.419,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]REPEATABLE READ / unguarded / 剩余 0
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 0
}
],
"oracle": {
"on_call_count": 0,
"invariant_holds": false,
"serially_reachable": false,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 2,
"approved": true,
"outcome": "committed"
}
}
}这里不声称观测到锁等待,屏障依据是双方已完成的读取。
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 10.685,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 2,
"elapsed_ms": 11.194,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 3,
"elapsed_ms": 11.198,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 11.938,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 11.94,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 6,
"elapsed_ms": 12.602,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 7,
"elapsed_ms": 12.605,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 13.091,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 13.095,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 10,
"elapsed_ms": 13.815,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 11,
"elapsed_ms": 13.818,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 12,
"elapsed_ms": 14.337,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 13,
"elapsed_ms": 14.339,
"actor": "coordinator",
"action": "barrier: both initial counts completed before writes"
},
{
"step": 14,
"elapsed_ms": 14.434,
"actor": "B",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
2
]
},
{
"step": 15,
"elapsed_ms": 14.466,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 16,
"elapsed_ms": 15.365,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 17,
"elapsed_ms": 15.368,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 18,
"elapsed_ms": 15.414,
"actor": "B",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
2
]
},
{
"step": 19,
"elapsed_ms": 15.424,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 20,
"elapsed_ms": 17.547,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 21,
"elapsed_ms": 18.433,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]REPEATABLE READ / late_guard / 剩余 0
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 0
}
],
"oracle": {
"on_call_count": 0,
"invariant_holds": false,
"serially_reachable": false,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 2,
"approved": true,
"outcome": "committed"
}
}
}| actor | table | index | mode | status |
|---|---|---|---|---|
| A | oncall_guard | PRIMARY | X,REC_NOT_GAP | GRANTED |
| A | oncall_guard | None | IX | GRANTED |
| B | oncall_guard | PRIMARY | X,REC_NOT_GAP | WAITING |
| B | oncall_guard | None | IX | GRANTED |
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 6.902,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 2,
"elapsed_ms": 7.487,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 3,
"elapsed_ms": 7.49,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 8.008,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 8.01,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 6,
"elapsed_ms": 8.545,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 7,
"elapsed_ms": 8.547,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 9.054,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 9.058,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 10,
"elapsed_ms": 9.794,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 11,
"elapsed_ms": 9.796,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 12,
"elapsed_ms": 10.817,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 13,
"elapsed_ms": 10.82,
"actor": "coordinator",
"action": "barrier: both initial counts completed before writes"
},
{
"step": 14,
"elapsed_ms": 10.822,
"actor": "A",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 15,
"elapsed_ms": 11.438,
"actor": "A",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 16,
"elapsed_ms": 11.53,
"actor": "B",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 17,
"elapsed_ms": 14.814,
"actor": "observer",
"action": "barrier: observed lock wait",
"waiting": "B",
"blocking": "A"
},
{
"step": 18,
"elapsed_ms": 14.819,
"actor": "coordinator",
"action": "barrier: release A only after observed B→A wait"
},
{
"step": 19,
"elapsed_ms": 14.821,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 20,
"elapsed_ms": 16.029,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 21,
"elapsed_ms": 16.034,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 22,
"elapsed_ms": 17.838,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 23,
"elapsed_ms": 17.842,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 24,
"elapsed_ms": 19.769,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 25,
"elapsed_ms": 19.83,
"actor": "B",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 26,
"elapsed_ms": 19.837,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 27,
"elapsed_ms": 20.487,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 28,
"elapsed_ms": 20.49,
"actor": "B",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
2
]
},
{
"step": 29,
"elapsed_ms": 21.136,
"actor": "B",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
2
]
},
{
"step": 30,
"elapsed_ms": 21.138,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 31,
"elapsed_ms": 22.756,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]REPEATABLE READ / guard_first / 剩余 1
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 1
}
],
"oracle": {
"on_call_count": 1,
"invariant_holds": true,
"serially_reachable": true,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 1,
"approved": false,
"outcome": "committed"
}
}
}| actor | table | index | mode | status |
|---|---|---|---|---|
| A | oncall_guard | PRIMARY | X,REC_NOT_GAP | GRANTED |
| A | oncall_guard | None | IX | GRANTED |
| B | oncall_guard | PRIMARY | X,REC_NOT_GAP | WAITING |
| B | oncall_guard | None | IX | GRANTED |
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 7.752,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 2,
"elapsed_ms": 8.148,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 3,
"elapsed_ms": 8.15,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 8.564,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 8.566,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 6,
"elapsed_ms": 9.101,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 7,
"elapsed_ms": 9.104,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 9.499,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 9.502,
"actor": "A",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 10,
"elapsed_ms": 10.003,
"actor": "A",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 11,
"elapsed_ms": 10.101,
"actor": "B",
"action": "submit",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE"
},
{
"step": 12,
"elapsed_ms": 11.833,
"actor": "observer",
"action": "barrier: observed lock wait",
"waiting": "B",
"blocking": "A"
},
{
"step": 13,
"elapsed_ms": 11.836,
"actor": "coordinator",
"action": "barrier: release A only after observed B→A wait"
},
{
"step": 14,
"elapsed_ms": 11.838,
"actor": "A",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 15,
"elapsed_ms": 12.365,
"actor": "A",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 2
}
]
},
{
"step": 16,
"elapsed_ms": 12.369,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 17,
"elapsed_ms": 12.953,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 18,
"elapsed_ms": 12.956,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 19,
"elapsed_ms": 14.716,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 20,
"elapsed_ms": 14.802,
"actor": "B",
"action": "returned",
"sql": "SELECT shift_id FROM oncall_guard WHERE shift_id=1 FOR UPDATE",
"rows": [
{
"shift_id": 1
}
]
},
{
"step": 21,
"elapsed_ms": 14.81,
"actor": "B",
"action": "submit",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1"
},
{
"step": 22,
"elapsed_ms": 15.634,
"actor": "B",
"action": "returned",
"sql": "SELECT COUNT(*) AS n FROM oncall_roster WHERE shift_id=1 AND on_call=1",
"rows": [
{
"n": 1
}
]
},
{
"step": 23,
"elapsed_ms": 15.639,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 24,
"elapsed_ms": 16.269,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]REPEATABLE READ / locking_roster / 剩余 1
独立终值与模型判断
{
"final_rows": [
{
"doctor_id": 1,
"on_call": 0
},
{
"doctor_id": 2,
"on_call": 1
}
],
"oracle": {
"on_call_count": 1,
"invariant_holds": true,
"serially_reachable": true,
"allowed_serial_states": [
[
0,
1
],
[
1,
0
]
]
},
"decisions": {
"A": {
"doctor_id": 1,
"observed_count": 2,
"approved": true,
"outcome": "committed"
},
"B": {
"doctor_id": 2,
"observed_count": 1,
"approved": false,
"outcome": "committed"
}
}
}| actor | table | index | mode | status |
|---|---|---|---|---|
| A | oncall_roster | PRIMARY | X | GRANTED |
| A | oncall_roster | PRIMARY | X | GRANTED |
| A | oncall_roster | PRIMARY | X | GRANTED |
| A | oncall_roster | None | IX | GRANTED |
| B | oncall_roster | PRIMARY | X | WAITING |
| B | oncall_roster | None | IX | GRANTED |
实际执行时间线,含 SQL 参数
[
{
"step": 1,
"elapsed_ms": 6.286,
"actor": "A",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 2,
"elapsed_ms": 6.803,
"actor": "A",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 3,
"elapsed_ms": 6.807,
"actor": "A",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 4,
"elapsed_ms": 7.317,
"actor": "A",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 5,
"elapsed_ms": 7.323,
"actor": "B",
"action": "submit",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"
},
{
"step": 6,
"elapsed_ms": 7.828,
"actor": "B",
"action": "returned",
"sql": "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ",
"rows": []
},
{
"step": 7,
"elapsed_ms": 7.831,
"actor": "B",
"action": "submit",
"sql": "START TRANSACTION"
},
{
"step": 8,
"elapsed_ms": 8.385,
"actor": "B",
"action": "returned",
"sql": "START TRANSACTION",
"rows": []
},
{
"step": 9,
"elapsed_ms": 8.389,
"actor": "A",
"action": "submit",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE"
},
{
"step": 10,
"elapsed_ms": 9.232,
"actor": "A",
"action": "returned",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE",
"rows": [
{
"doctor_id": 1
},
{
"doctor_id": 2
}
]
},
{
"step": 11,
"elapsed_ms": 9.334,
"actor": "B",
"action": "submit",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE"
},
{
"step": 12,
"elapsed_ms": 11.487,
"actor": "observer",
"action": "barrier: observed lock wait",
"waiting": "B",
"blocking": "A"
},
{
"step": 13,
"elapsed_ms": 11.491,
"actor": "coordinator",
"action": "barrier: release A only after observed B→A wait"
},
{
"step": 14,
"elapsed_ms": 11.494,
"actor": "A",
"action": "submit",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"parameters": [
1
]
},
{
"step": 15,
"elapsed_ms": 12.197,
"actor": "A",
"action": "returned",
"sql": "UPDATE oncall_roster SET on_call=0 WHERE shift_id=1 AND doctor_id=%s AND on_call=1",
"rows": [],
"parameters": [
1
]
},
{
"step": 16,
"elapsed_ms": 12.201,
"actor": "A",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 17,
"elapsed_ms": 14.238,
"actor": "A",
"action": "returned",
"sql": "COMMIT",
"rows": []
},
{
"step": 18,
"elapsed_ms": 14.292,
"actor": "B",
"action": "returned",
"sql": "SELECT doctor_id FROM oncall_roster WHERE shift_id=1 AND on_call=1 ORDER BY doctor_id FOR UPDATE",
"rows": [
{
"doctor_id": 2
}
]
},
{
"step": 19,
"elapsed_ms": 14.296,
"actor": "B",
"action": "submit",
"sql": "COMMIT"
},
{
"step": 20,
"elapsed_ms": 14.759,
"actor": "B",
"action": "returned",
"sql": "COMMIT",
"rows": []
}
]理论与实现边界
CMU/MIT 用于理解调度、2PL 与多版本。本实验验证显式 START TRANSACTION 内的具体 MySQL 8.4 语句,不代表全部 InnoDB 读取都遵循严格 2PL,也不代表所有 RR 历史都可串行化。不需要 API key、模型、向量插件或外部数据库。
具体讲次与阅读映射 → · MySQL 8.4 consistent reads · MySQL 8.4 locking reads