本文目錄一覽:
- 1、看了一下,MYSQL在讀寫時會自動給表或者行加鎖,那為什麼還會出現所謂的並發問題?
- 2、如何處理資料庫並發問題
- 3、並發時,php操作mysql需要加鎖嗎?mysql在並發時讀寫數據表會加鎖,我覺得不用再手動加鎖,請問是這樣嗎?
- 4、mysql怎麼處理並發寫入
看了一下,MYSQL在讀寫時會自動給表或者行加鎖,那為什麼還會出現所謂的並發問題?
我理解的是:讀表的鎖表是指在讀的過程中上鎖,不允許中途還insert其他記錄,當讀表完畢,獲得select結果後,表就解鎖了,可以繼續新的select或insert等操作。
例子里:2人同時借錢,沒有業務鎖的話,兩個請求發到後端後可能同時去select,此時2次借款操作select餘額都是1000(在另一人借200後回寫餘額800之前),於是2個請求操作各自開始借錢,算出借錢後都剩下800,再分別update進表中,表裡餘額就是800
如果加業務鎖:2個請求到後端後,select餘額和借錢後Update按一個事務進行,那第1人select 1000元並借款後剩下800更新進表中,完成第1人借錢事務後,再進行第2人借錢select 剩下的800元並借款後剩下600更新進表中,就可以避免
如何處理資料庫並發問題
想要知道如何處理數據並發,自然需要先了解數據並發。
什麼是數據並發操作呢?
就是同一時間內,不同的線程同時對一條數據進行讀寫操作。
在互聯網時代,一個系統常常有很多人在使用,因此就可能出現高並發的現象,也就是不同的用戶同時對一條數據進行操作,如果沒有有效的處理,自然就會出現數據的異常。而最常見的一種數據並發的場景就是電商中的秒殺,成千上萬個用戶對在極端的時間內,搶購一個商品。針對這種場景,商品的庫存就是一個需要控制的數據,而多個用戶對在同一時間對庫存進行重寫,一個不小心就可能出現超賣的情況。
針對這種情況,我們如何有效的處理數據並發呢?
第一種方案、資料庫鎖
從鎖的基本屬性來說,可以分為兩種:一種是共享鎖(S),一種是排它鎖(X)。在MySQL的資料庫中,是有四種隔離級別的,會在讀寫的時候,自動的使用這兩種鎖,防止數據出現混亂。
這四種隔離級別分別是:
讀未提交(Read Uncommitted)
讀提交(Read Committed)
可重複讀(Repeated Read)
串列化(Serializable)
當然,不同的隔離級別,效率也是不同的,對於數據的一致性保證也就有不同的結果。而這些可能出現的又有哪些呢?
臟讀(dirty read)
當事務與事務之間沒有任何隔離的時候,就可能會出現臟讀。例如:商家想看看所有的訂單有哪些,這時,用戶A提交了一個訂單,但事務還沒提交,商家卻看到了這個訂單。而這時就會出現一種問題,當商家去操作這個訂單時,可能用戶A的訂單由於部分問題,導致數據回滾,事務沒有提交,這時商家的操作就會失去目標。
不可重複讀(unrepeatable read)
一個事務中,兩次讀操作出來的同一條數據值不同,就是不可重複讀。
例如:我們有一個事務A,需要去查詢一下商品庫存,然後做扣減,這時,事務B操作了這個商品,扣減了一部分庫存,當事務A再次去查詢商品庫存的時候,發現這一次的結果和上次不同了,這就是不可重複讀。
幻讀(phantom problem)
一個事務中,兩次讀操作出來的結果集不同,就是幻讀。
例如:一個事務A,去查詢現在已經支付的訂單有哪些,得到了一個結果集。這時,事務B新提交了一個訂單,當事務A再次去查詢時,就會出現,兩次得到的結果集不同的情況,也就是幻讀了。
那針對這些結果,不同的隔離級別可以幹什麼呢?
「讀未提(Read Uncommitted)」能預防啥?啥都預防不了。
「讀提交(Read Committed)」能預防啥?使用「快照讀(Snapshot Read)」方式,避免「臟讀」,但是可能出現「不可重複讀」和「幻讀」。
「可重複讀(Repeated Red)」能預防啥?使用「快照讀(Snapshot Read)」方式,鎖住被讀取記錄,避免出現「臟讀」、「不可重複讀」,但是可能出現「幻讀」。
「串列化(Serializable)」能預防啥?有效避免「臟讀」、「不可重複讀」、「幻讀」,不過運行效率奇差。
好了,鎖說完了,但是,我們的資料庫鎖,並不能有效的解決並發的問題,只是儘可能保證數據的一致性,當並發量特別大時,資料庫還是容易扛不住。那解決數據並發的另一個手段就是,儘可能的提高處理的速度。
因為數據的IO要提升難度比較大,那麼通過其他的方式,對數據進行處理,減少資料庫的IO,就是提高並發能力的有效手段了。
最有效的一種方式就是:緩存
想要減少並發出現的概率,那麼讀寫的效率越高,讀寫的執行時間越短,自然數據並發的可能性就變小了,並發性能也有提高了。
還是用剛才的秒殺舉例,我們為的就是保證庫存的數據不出錯,賣出一個商品,減一個庫存,那麼,我們就可以將庫存放在內存中進行處理。這樣,就能夠保證庫存有序的及時扣減,並且不出現問題。這樣,我們的資料庫的寫操作也變少了,執行效率也就大大提高了。
當然,常用的分散式緩存方式有:Redis和Memcache,Redis可以持久化到硬碟,而Memcache不行,應該怎麼選擇,就看具體的使用場景了。
當然,緩存畢竟使用的範圍有限,很多的數據我們還是必須持久化到硬碟中,那我們就需要提高資料庫的IO能力,這樣避免一個線程執行時間太長,造成線程的阻塞。
那麼,讀寫分離就是另一種有效的方式了
當我們的寫成為了瓶頸的時候,讀寫分離就是一種可以選擇的方式了。
我們的讀庫就只需要執行讀,寫庫就只需要執行寫,把讀的壓力從主庫中分離出去,讓主庫的資源只是用來保證寫的效率,從而提高寫操作的性能。
並發時,php操作mysql需要加鎖嗎?mysql在並發時讀寫數據表會加鎖,我覺得不用再手動加鎖,請問是這樣嗎?
如果要一次性做很多次插入,最好在每個循環的前後加上LOCK TABLES和UNLOCK TABLES,從而讓其他進程也能訪問數據表;這麼做性能依然不錯。
不然的話,會導致數據莫明其妙的插入不完整,或者沒插進去的情況。
mysql怎麼處理並發寫入
mysql的最大連接數默認是100, 這個數值對於並發連接很多的資料庫應用是遠遠不夠的,當連接請求大於默認連接數後,就會出現無法連接資料庫的錯誤,因此我們需要把它適當調大一些。 調節方法為: 1.linux伺服器中:改my.cnf中的值就行了
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/232090.html