對於軟件開發人員來講,有時候咱們須要面對瞬時海量的併發請求,例如阿里雙十一等活動,當處理併發流程時須要咱們經過各類機制保持數據一致性,其中,最有效的一種機制就是鎖機制。而對於數據庫管理人員來講,併發問題一樣存在。併發問題的本質在於一條邏輯代碼在機器層面可能須要幾條指令來完成,也就是說這條邏輯代碼可能在多個機器週期內完成,若是在順時執行時這樣執行是不會存在問題的,而在併發執行時就會出現數據不一致的狀況。這種最小的邏輯指令對應到數據庫中就是事務,事務包含原子性(Atomicity)、一致性(Consistency)、一致性(Consistency)和持久性(Durability)。而因爲一個事務在機器層面可能須要幾條指令完成,這也意味着它在併發時會出現以下問題:髒讀、不可重複讀和幻讀,下面以MySQL爲例詳細介紹在什麼狀況下可能會出現上述問題。java
此事務隔離級別會出現髒讀現象*(事務的修改,即便沒有提交,其餘事務也能看的到),不建議在生產環境中去使用。mysql
show variables like 'tx_iso%';
mysql> set tx_isolation='READ-UNCOMMITTED';
注意:READ-UNCOMMITTED是字符串,若是不使用雙引號,就會報錯,錯誤信息以下:sql
set tx_isolation=READ-UNCOMMITTED; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'READ-UNCOMMITTED' at line 1
create table test(int id);//典型的錯誤,能夠和java 類比 create table test(id int);//正確寫法
注意:咱們須要手動開啓事務(begin)和提交事務(commit),否則MySQL會自動提交事務數據庫
針對當前讀,RC隔離級別保證對讀取到的記錄加鎖(記錄鎖),存在不可重複讀現象(在一個事務內,屢次讀取,會讀取到不一樣的數據)。session
truncate table test;
咱們發現session2中執行兩次select * from test
會出現不一樣的結果,這就是不可重複讀現象。併發
這是MySQL默認隔離級別,解決不可重複讀,可是還會出現存在幻讀現象。幻讀現象就是說當某個會話對某個數據進行修改並提交,而其餘會話讀取這個數據並非最新的值。code
session1 session2 begin; begin; select ;//得到一個時間點快照,在表記錄中的每個行都會有trx_id,之後每次查詢,都會查詢比這個trx_id小於等於的值 insert; commit; select;
MySQL經過MVCC(解決讀寫併發問題)和間隙鎖(解決寫寫併發問題)來解決幻讀,Repetable Read違反了隔離性,ACID中對隔離性的定義以下:server
The isolation property ensures that the concurrent execution of transactions results in a system state that would be obtained if transactions were executed sequentially, i.e., one after the other. Providing isolation is the main goal of concurrency control. Depending on the concurrency control method (i.e., if it uses strict - as opposed to relaxed - serializability), the effects of an incomplete transaction might not even be visible to another transaction
大概意思:一個沒有提交的事務對其餘事務是不可見的,而提交過的事務對其餘事務是可見的。可是Repeatable Read中提交的事務對其餘事務是不可見的,顯然違反了隔離性。blog
串行化解決了髒讀、不可重複讀、幻讀現象,可是效率會比較低下。從MVCC併發控制退化爲基於鎖的併發控制。不區分快照讀與當前讀,全部的讀操做均爲當前讀。事務
更多文章請訂閱公衆號"木可大大"。