1

我有一个简单的 Django 网络应用程序,带有一个 Sqlite DB,用于从用户那里收集电影评论,每部电影都应该有 2 个评论者来查看它并为其提供评论。

要动态实现 2 条评论/电影要求,我必须确保我不会向超过 2 个登录用户展示给定电影。否则,我将获得超过 2 条对该电影的评论。

因此,在发送任何电影进行审核之前,我需要检查它尚未发送给 2 位评论者。问题是:如果我将这些信息保存在数据库中,我可能会有超过 2 个并发请求选择某部电影并将其发送出去以供审查,因为它们都同时执行了读取/检索操作。

希望我有类似“SELECT FOR UPDATE”的东西,但不幸的是,SQLite 不支持。

有没有人有任何想法?提前致谢。

4

1 回答 1

0

我认为您可以使用事务来解决您的问题。这是适当的 django 文档是一个示例。

如果您尝试让两个并发事务写入同一个 sqlite DB,看起来您会得到“OperationalError:database is locked”。您可能想要使用 Django ORM(请参阅链接),但这里有一个 hacky 示例来演示这个想法。

import sqlite3
# 2 connections, 2 cursors
con = sqlite3.connect('test.db', isolation_level=None)
con2 = sqlite3.connect('test.db', isolation_level=None)
cur = con.cursor()
cur2 = con2.cursor()

# create really simple table
try:
    cur.execute("CREATE TABLE MOVIES(id INTEGER PRIMARY KEY, r1 INTEGER, r2 INTEGER)")
    cur.execute("INSERT INTO MOVIES(id,r1, r2) VALUES (1,0,0)")
    cur.execute("INSERT INTO MOVIES(id,r1, r2) VALUES (2,0,0)")
except:
    pass

# awkward read/write split mid-transaction is purely for demonstration purposes..
def read(cursor):
    cursor.execute("BEGIN IMMEDIATE TRANSACTION")  # get write lock straight away
    data = cursor.execute("SELECT * FROM MOVIES WHERE r1 == 0 OR r2 == 0")
    return data.fetchall()

def write(cursor, movie_id, reviewer_column, new_reviewer_id):
    cursor.execute("UPDATE MOVIES SET %s=%d WHERE id == %d AND %s ==0" % (
        reviewer_column, new_reviewer_id, movie_id, reviewer_column))
    cursor.execute("COMMIT")

# works fine
data1 = read(cur) # [(1, 0, 0), (2, 0, 0)]
write(cur, data1[0][0], "r1", 123)

# now we have concurrent access..
data1 = read(cur) # [(1, 123, 0), (2, 0, 0)]
data2 = read(cur2) # throws OperationalError: database is locked.
# the second thread should probably wait a bit before retrying.

# in the mean time..
write(cur, data1[0][0], "r2", 456) #works

# now it's safe for the second thread to retry
data2 = read(cur2) # [(2, 0, 0)]
write(cur2, data2[0][0], "r1", 457) #works

以上之后的数据:

# MOVIES
# id |  r1 |  r2
#  1 | 123 | 456
#  2 | 457 |   0

它会保护你避免在你的数据库中胡说八道,但是立即写锁是一种稍微粗略的到达那里的方式。

于 2013-02-03T01:27:45.773 回答