2013-02-02 18 views
1

我有一個簡單的Django網絡應用程序和一個Sqlite數據庫,用於收集用戶的電影評論,其中每部電影都應該得到2個評論者看它並提供一個審查它。用於Django網絡應用程序的Sqlite獨家閱讀/更新

要動態實現2條評論/電影需求,我必須確保我不會向2個以上的登錄用戶呈現給定的電影。否則,我會爲該電影獲得超過2條評論。

因此,在發送任何電影以供審閱之前,我需要檢查它尚未發送給2位審閱者。問題是:如果我將這些信息保存在數據庫中,我可能會有超過2個併發請求選擇某個電影,並將其發送出去以供審閱,因爲它們都同時執行了讀取/檢索操作。

希望我有像「SELECT FOR UPDATE」的東西,但不幸在SQLite中不支持。

有沒有人有任何想法?提前致謝。

回答

0

我認爲你可以使用transactions來解決你的問題。這裏是appropriate django documentationhere就是一個例子。

看起來你會得到「OperationalError:database is locked」,如果你試圖讓兩個併發事務寫入同一個sqlite數據庫。你可能會想使用Django ORM(請參閱鏈接),但這裏有一個黑客示例來演示這個想法。

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 

它會屏蔽你把廢話在你的數據庫,但即時寫入鎖是到達那裏的略微粗暴的方式。

相關問題