索引下 update 只锁住符合条件的记录吗?


起步

我着手一个需要高并发 update 的功能,进行压测时,发现了大量锁超时。于是所有矛头就指向我了,认为我做任务分发时重复分发了两个或两个以上相同的子任务。

这一假设基于现有的子任务 update 范围,已知更新语句走索引 c,则有:子任务 A 更新 c=[1,10] ;子任务 B 更新 c=[11,20] ... 子任务 N 更新 c=[n-9, n]。所以同事认为,只有可能会出现相同的 A 任务(B、C ... N 都行),才可能引发锁超时。

假设同事是正确的,那就意味着 update 只锁主符合条件的记录。但果真如此吗?


如何获取 postgres 执行的 sql


起步

由于我在新项目里引入了 python 的 async 语法,在连接 pg 数据库时用到了 asyncpg 这个异步包。多日来,从线上得到了一些反馈。简单说来就是:数据库存在暂时无法修复的 bug,使得一些 sql 成为 “禁用 sql”,从应用层看没有执行过 “禁用 sql” ,但在监控器上发现执行了 “禁用 sql”。

我简单跟踪了 asyncpg 源码,没有发现 asyncpg 包内部执行了 “禁用 sql ”,但同事仍对这个第三方包质疑。因为不懂得,所以不仁慈,可我必须做点什么为 asyncpg 洗冤……


SQLAlchemy 奇怪的查数据库行为


起步

进行数十亿数据压测时,测试环境发生了一个很奇怪的现象:在对 SQLAlchemy 查出的结果做遍历操作时,随着集合越大,遍历的时间跟着变长,是肉眼可见的变长。

根据现象,一位腾讯的程序员向我提出了疑问:会不会遍历过程中 SQLAlchemy 又去查询了数据库?


databases 连接 pg 查询时返回的数据类型


使用 databases 做异步查询的时候,sqlite、mysql 查询结果返回的都是元组类型,但是连接 pg 数据库的时候返回的是 Record 对象实例。

database = Database(
    'postgresql://postgres:password@192.168.111.136:54321/postgres', 
    min_size=5, 
    max_size=20
)
await database.connect()
query = "SELECT score, name, id FROM HighScores"
rows = await database.fetch_all(query=query)  # 查询
print(rows)  # 打印结果
await database.disconnect()

输出:

[<databases.backends.postgres.Record object at 0x000001BADB1E2A08>]