在查询和插入之间锁定数据库表

时间:2014-03-15 10:17:26

标签: sql multithreading sqlite locking

请原谅我这是一个愚蠢的问题(我是数据库和SQL的新手),但是可以锁定一个表,类似于C#中的lock关键字,这样我就可以查询数据库了查看条件是否满足,然后插入一行,同时确保表的状态在两个动作之间没有变化?

在这种情况下,我有一个表transactions,它有两列:userproduct。这是多对一的关系;多个用户可以拥有相同的产品。但是,product的数量有限。

当用户将产品添加到他们的帐户时,我想首先检查具有相同product值的项目总数是否低于某个阈值,然后再添加该事务。但是,由于这是一个多线程应用程序,因此可以同时进行多个事务。我想确保其中一个被拒绝,并且一个成功,这样具有相同product值的事务数量永远不会高于限制。

我正在尝试做的粗略伪代码:

my_user, my_product = ....
my_product_count = 0
for each transaction in transactions:
    if product == my_product:
        my_product_count += 1
if my_product_count < LIMIT:
    insert my_user, my_product into transactions
    return SUCCESS
else:
    return FAILURE

如果重要的话,我正在使用SQLAlchemy和SQLite3。

2 个答案:

答案 0 :(得分:1)

如果您在事务中执行这两项操作(数据库支持),则不需要。数据库确实维护锁以保证事务完整性。事实上,这是数据库所做的四大支柱之一 - 它们被称为ACID保护(用于(原子性,一致性,隔离性,耐久性)。

因此,在您的情况下,为了确保一致性,您将在一个事务中进行两个操作,并以这样的方式放置事务参数,以阻止对已读取的行的读取。

SQL锁定比lock语句更强大,因为除其他外,每个定义的数据库都有多个线程(用户)命中相同的数据 - 这在编程中非常罕见(在多线程中避免了相同的数据访问)尽可能编程)。

我建议一本关于SQL的好书 - 因为你需要在某一点上简单地学习一些基本概念,否则你会犯错误而花钱。

答案 1 :(得分:0)

事务允许您以原子方式使用多个SQL语句。 (SQLite通过锁定整个数据库来实现事务,但确切的机制并不重要,您可能希望以后再使用其他数据库。)

但是,如果您可以使用单个SQL语句处理所需的算法,那么您甚至不需要打扰显式事务,如下所示:

INSERT INTO transactions(user, product)
SELECT @my_user, @my_product
WHERE (SELECT COUNT(*)
       FROM transactions
       WHERE product = @my_product) < @LIMIT;