PHP高並發下的數據同步的解決方法?

資料庫有個表tb_add

程序的要求是如果tb_add這個表的數據超過1W行,就不允許在插入數據。

程序的處理流程如下:

第一步:先查詢tb_add現在有多少行

第二步:如果不超過1W行,則可以寫入數據

那麼問題來了,如果並發量大的情況下,如果數據剛好差1行就滿1W,是否會出現以下情況:

例如有2個用戶,A和B,他們同時在瀏覽器執行了提交,導致這個用戶同時執行第一步,所以他們的都符合插入數據的條件,然後都被指定了第二步,最終的結果就是資料庫變成了10001行。

問1:是否會出現以上的情況?

問2:在不鎖表的情況下(因為會拖慢速度),如何解決這這樣的問題?

ps:目前本人自己的解決方法就是,插入數據後,反查一下資料庫是否超過1W行,超過則刪除本次添加的數據,但是問題又來了,如果2個用戶同時執行了反查的操作,那麼又會同時刪除2條數據,變為9999。。。

謝謝熱心人解答。


啊,這個需求好奇怪。

問一:很可能會出現,取決於你的網站的請數量。

問二:首先考慮能不能不解決,在發現以後把多出來的數據刪掉。其次難道不能提前建好1w條數據,然後每次都去update么?


隊列也是鎖……

默默的說……


用一個計數器

我最近在做一個項目 高並發選課系統

每次insert之前先計數器+1然後判斷他的值是否大於max

如果大於max計數器自減1 類似回滾

如果小於max 執行insert語句

ps:計數器自增和自減需要保證其原子性

推薦Redis來做計數器 max也可以用redis來存.

我昨天做了一個並發1000的測試

數據錯誤率為0


在不修改業務的情況下,必須上鎖。如果後期性能遇到瓶頸,在不提升硬體性能的條件下,優化方式只有降低鎖層次,或修改業務。

有人說排隊,其實排隊也是一種鎖。

扯幾句題外話:

現在網上的誤導文章太多了,各種高並發情況下的不鎖、無鎖。有時候真想問候作者的各種親朋好友。

同時,很多連資料庫手冊都沒耐心看完的小屁孩,看到那種無鎖的文章,連原理都沒去理解,就屁顛屁顛地照搬過來。不出問題才怪。而且以後遇到高並發情況,還趾高氣揚地來一句:必須無鎖。想到那場面老夫就想一巴掌拍過去。


共享一個鎖,或者隊列


首先,我們從邏輯上去看你的問題的前置條件:超過1w行則不寫數據。

那麼我大概想了這些幾個情況:

1.加鎖

缺點:降低性能

優點:減少代碼邏輯複雜度(題主現在這樣超過1w條就刪數據的邏輯,感覺看起來就點糟糕啊,如果整個系統一複雜,這樣的來回寫數據,你確定你的邏輯還維護得下去?建議題主梳理一下代碼的邏輯流)

2.隊列(redis/各類mq等)

缺點:引入其他組件,增加系統複雜度,降低穩定性。

優點:能夠將web的並行邏輯串列,其實和加鎖差不多,不過更優雅,並且性能上面也更可控。如果題主的系統的邏輯複雜,推薦採用這種。

建議:php寫多你會發現,它的邏輯就是一波流的。在它的邏輯層實現過多的重試,等待,以及回寫,會導致php很臃腫。建議要麼在資料庫層上鎖,要麼引入隊列等待,要麼就直接報錯,讓用戶F5重試,如果用ajax重試,幾乎沒有用戶體驗上的問題。那麼來說一下直接報錯的方案。

3.建一個計數器表

舉例:

create table store_count (total int(11) NOT NULL) ENGINE=InnoDB

搶計數器:

如果我查出來現在總數是2,那麼我 update store_count set total = 3 where total = 2

如果更新成功,說明現在的總行數是3,可以去插表,如果未更新,說明這時已經有其他用戶插入了,直接給用戶報錯,讓他下次請求再來過。

缺點:這種方式其實比前兩個更粗暴,前2種方式還是等待的,這種方式直接丟棄了部分用戶流量,帶來的是一個有緩存特性的計數器來實現題主提的邏輯。

這個計數器在內存中效果更佳。

建議題主根據自身的系統狀況,和代碼邏輯,進行性能、開發效率、邏輯成本、維護成本上的取捨。


上鎖,commit。backroll


用隊列唄


應用層加個計數器


感覺拋開業務目標,抽離出來看實現方法,看得人渾身彆扭。

比如,業務本身的目標是什麼?為什麼選擇了通過一個錶行數來控制數量的技術方案?肯定沒有別的方案了么?不是什麼樣的奇怪問題,都非要硬著頭皮解決啊……


加鎖就行,要麼鎖表,要麼鎖程序,加了鎖就相當於變成隊列執行,一次只能一個人拿到鎖,只能一個人通過,去插入數據。

php里可以使用文件鎖,或memcached鎖也行,文件鎖會導致阻塞。

可以搜索:php鎖,php文件鎖


推薦閱讀:

用MySQL WHERE進行過濾
pandas數據保存至Mysql資料庫
MySQL訓練——Self join@sqlzoo.net
為何Redis用樂觀鎖,而MySQL資料庫卻沒有?
為什麼我不再看好MariaDB

TAG:PHP | MySQL | PHP開發 | PHP學習 |