商務邏輯是這樣的:
統計某一文章每一天的獲贊次數:
tb(id,time,num)
id:文章ID
time:2016-1-31
id,time是複合主鍵
商務程序:
sql_1:select * from tb where id=$id and time=$tif (sql_1) sql_2:updata from tb set num = num + 1 where id=$id and time=$telse sql_2_:INSERT INTO tb (id,time,num) values ($id,$t,1)
就是這樣的很簡單邏輯,本來沒有什麼問題,可是最近老是出錯,原因是因為插入重複的複合主鍵,我才知道這樣設計有並發的問題(兩個進程同時判斷通過,就會導致sql_2_執行兩次而出錯);
網上有很多講這樣的知識的,樂觀鎖,悲觀鎖等,但是都是將一些理論知識,一遇到實際問題,就沒人理你了,書本上也基本是理論知識,沒有實際問題的解決方案,我沒有經驗,不知道怎麼解決這個問題,不想用樂觀鎖,需要要建一個version欄位覺得不爽,程式多個地方用到時還不好控制。
意識到這個問題之後,我發現我之前所有的代碼其實都會有這個問題,我相信上面這個邏輯是個非常基本的邏輯,我沒想到會有這樣的問題,好恐怖;
如果需要用到事務,我就把表全改為innodb的;
希望高人指點,就我上面的例子說實際的解決辦法,不要找一些理論知識我看了。
謝謝大家了。
回複內容:
商務邏輯是這樣的:
統計某一文章每一天的獲贊次數:
tb(id,time,num)
id:文章ID
time:2016-1-31
id,time是複合主鍵
商務程序:
sql_1:select * from tb where id=$id and time=$tif (sql_1) sql_2:updata from tb set num = num + 1 where id=$id and time=$telse sql_2_:INSERT INTO tb (id,time,num) values ($id,$t,1)
就是這樣的很簡單邏輯,本來沒有什麼問題,可是最近老是出錯,原因是因為插入重複的複合主鍵,我才知道這樣設計有並發的問題(兩個進程同時判斷通過,就會導致sql_2_執行兩次而出錯);
網上有很多講這樣的知識的,樂觀鎖,悲觀鎖等,但是都是將一些理論知識,一遇到實際問題,就沒人理你了,書本上也基本是理論知識,沒有實際問題的解決方案,我沒有經驗,不知道怎麼解決這個問題,不想用樂觀鎖,需要要建一個version欄位覺得不爽,程式多個地方用到時還不好控制。
意識到這個問題之後,我發現我之前所有的代碼其實都會有這個問題,我相信上面這個邏輯是個非常基本的邏輯,我沒想到會有這樣的問題,好恐怖;
如果需要用到事務,我就把表全改為innodb的;
希望高人指點,就我上面的例子說實際的解決辦法,不要找一些理論知識我看了。
謝謝大家了。
實名反對以上答案!!!
mysql:
1.ON DUPLICATE KEY UPDATE語句
ID,time複合主鍵
INSERT INTO tb (id,time,num) values ($id,$t,1) ON DUPLICATE KEY UPDATE num=num+1;
2.悲觀鎖for update
select * from tb where id=$id and time=$t for updateif (sql_1) sql_2:updata from tb set num = num + 1 where id=$id and time=$telse sql_2_:INSERT INTO tb (id,time,num) values ($id,$t,1)
沒人回答嗎?
這個可以在轉寄mysql請求,使用memcache獨佔鎖,
最簡單的辦法是將任務全部放到隊列中去,然後使用單線程不斷處理這個任務隊列中的任務,這樣解決了並發問題,但是效率就變低了。
我在用多線程寫檔案的時候也遇到過多線程同時寫檔案的問題,這個時候用線程鎖(Python):
import threadinglock = threading.Lock()with lock: # done something
使用redis實現分布式鎖,鎖的位置如下
lock
sql_1:select * from tb where id=$id and time=$t
if (sql_1)
sql_2:updata from tb set num = num + 1 where id=$id and time=$t
else
sql_2_:INSERT INTO tb (id,time,num) values ($id,$t,1)
unlock
我說過 我去年看過的一解決辦法,我舉個不切實際(ps:但是我覺得這個解決辦法還是蠻好的,你可以去看一下《redis實戰》這本書)的個例子,你建立100條資料,關聯一篇新的文章,然後如果有更新,隨機的更新1-100的資料 +1
。等到了一個合適的時候,把這100條合并成1條