严一档,不可重复读也没了

👁️ 0 人浏览 💬 0 人评论 ❤️ 添加收藏

甲开着事务读两次,中间乙想改。不放松的时候乙改不进去,放松之后乙改得进去。下面这段打出不放松时乙那次写的结果放松时甲两次读到的值(三段,用 / 隔开)。

acct 表:3 行,一开始每人 100,总额 300
id    1 / 2 / 3
name  甲 / 乙 / 丙
bal   100 / 100 / 100

四个现成的工具函数(题面里已经写好)
bank(ru_a, ru_b) → 铺一份新库,给你两个连到**同一份数据**的连接 a、b
bal(c, i)        → 某个账户的余额;读不到(被锁着)就返回"锁住"
total(c)         → 三个账户加起来多少钱;读不到就返回"锁住"
try_write(c, sql)→ 写一下:写得进去返回"成功",被锁住返回"写不进"
import sqlite3

_KEEP = []          # 保管连接:只要它活着,这份内存库就不会被回收
_SEQ = [0]

def bank(ru_a=False, ru_b=False):
    """铺一份新的三账户库,返回两个连到同一份数据的连接 (a, b)。
    ru_a / ru_b:把那一边放松成"可以读到别人还没提交的改动"。"""
    _SEQ[0] += 1
    uri = "file:bank" + str(_SEQ[0]) + "?mode=memory&cache=shared"
    keep = sqlite3.connect(uri, uri=True)
    _KEEP.append(keep)
    keep.execute("CREATE TABLE acct (id INTEGER PRIMARY KEY, name TEXT, bal INTEGER)")
    keep.executemany("INSERT INTO acct VALUES (?,?,?)",
                     [(1, "甲", 100), (2, "乙", 100), (3, "丙", 100)])
    keep.commit()
    a = sqlite3.connect(uri, uri=True)
    b = sqlite3.connect(uri, uri=True)
    if ru_a:
        a.execute("PRAGMA read_uncommitted = 1")
    if ru_b:
        b.execute("PRAGMA read_uncommitted = 1")
    return a, b

def bal(c, i):
    """某个账户的余额。读不到(表被别人锁着)就返回"锁住"。"""
    try:
        return c.execute("SELECT bal FROM acct WHERE id = ?", (i,)).fetchone()[0]
    except sqlite3.OperationalError:
        return "锁住"

def total(c):
    """三个账户加起来一共多少钱。读不到就返回"锁住"。"""
    try:
        return c.execute("SELECT SUM(bal) FROM acct").fetchone()[0]
    except sqlite3.OperationalError:
        return "锁住"

def try_write(c, sql):
    """让这个连接写一下,写得进去返回"成功",被锁住返回"写不进"。"""
    try:
        c.execute(sql)
        return "成功"
    except sqlite3.OperationalError:
        return "写不进"
a, b = bank()                       # 不放松
a.execute("BEGIN")
bal(a, 3)
w = try_write(b, "UPDATE acct SET bal = 555 WHERE id = 3")
a.rollback()

c, d = bank(ru_a=True)              # 放松
c.execute("BEGIN")
x = bal(c, 3)
d.execute("UPDATE acct SET bal = 555 WHERE id = 3")
d.commit()
y = bal(c, 3)
c.rollback()
print(w + "/" + str(x) + "/" + str(y))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论