【发布时间】:2018-12-20 19:01:41
【问题描述】:
假设我有以下伪代码:
SELECT count(*) FROM users WHERE email = 'bob@gmail.com'
>>>> MARKER A
if (count > 0) return;
else INSERT INTO users VALUES ('bob@gmail.com')
所以基本上只有在电子邮件不存在时才插入它。我知道我可以使用某种 INSERT IF NOT EXISTS 查询,但假设我们使用这个示例。
因此,如果上面的代码在线程 A 上运行,并且线程 B 实际上将 'bob@gmail.com' 插入到 MARKER A 的用户中,那么线程 A 具有“陈旧数据”并会尝试插入 'bob@gmail.com ',以为计数仍然是 0,但实际上它现在是 1。这将出错,因为我们在电子邮件上有一个唯一索引。
我应该使用什么工具来防止这个问题? 根据我对事务的阅读,它们基本上使一组操作原子化,因此上面的代码将完全执行或根本不执行。它不会确保用户表被锁定以防止更新正确吗?所以我不能只是将上面的代码包装在事务中并使其成为线程安全的吗?
我应该实现应用程序级锁定吗?我是否应该确保当这个操作发生时,它必须获得锁才能访问用户表,这样其他线程才能对其进行更改?我觉得锁定整个表是我想避免的性能损失。
【问题讨论】:
标签: sql multithreading postgresql transactions locks