❶ 資料庫事務隔離級別 一般用哪個
術式之後皆為邏輯,一切皆為需求和實現。希望此文能從需求、現狀和解決方式的角度幫大家理解隔離級別。
隔離級別的產生
在串型執行的條件下,數據修改的順序是固定的、可預期的結果,但是並發執行的情況下,數據的修改是不可預期的,也不固定,為了實現數據修改在並發執行的情況下得到一個固定、可預期的結果,由此產生了隔離級別。
所以隔離級別的作用是用來平衡資料庫並發訪問與數據一致性的方法。
事務的4種隔離級別
READ UNCOMMITTED 未提交讀,可以讀取未提交的數據。READ COMMITTED 已提交讀,對於鎖定讀(select with for update 或者 for share)、update 和 delete 語句, InnoDB 僅鎖定索引記錄,而不鎖定它們之間的間隙,因此允許在鎖定的記錄旁邊自由插入新記錄。 Gap locking 僅用於外鍵約束檢查和重復鍵檢查。REPEATABLE READ 可重復讀,事務中的一致性讀取讀取的是事務第一次讀取所建立的快照。SERIALIZABLE 序列化
在了解了 4 種隔離級別的需求後,在採用鎖控制隔離級別的基礎上,我們需要了解加鎖的對象(數據本身&間隙),以及了解整個數據范圍的全集組成。
數據范圍全集組成
SQL 語句根據條件判斷不需要掃描的數據范圍(不加鎖);
SQL 語句根據條件掃描到的可能需要加鎖的數據范圍;
以單個數據范圍為例,數據范圍全集包含:(數據范圍不一定是連續的值,也可能是間隔的值組成)
1. 數據已經填充了整個數據范圍:(被完全填充的數據范圍,不存在數據間隙)
整形,對值具有唯一約束條件的數據范圍 1~5 ,
已有數據1、2、3、4、5,此時數據范圍已被完全填充;
整形,對值具有唯一約束條件的數據范圍 1 和 5 ,
已有數據1、5,此時數據范圍已被完全填充;
整形的數據范圍 1~5 ,
已有數據 1、2、3、4、5,但是因為沒有唯一約束,
所以數據范圍可以繼續被 1~5 的數據重復填充;
整形,具有唯一約束條件的數據范圍 1~5 ,
已有數據 2,5,此時數據范圍未被完全填充,還可以填充 1、3、4 ;
整形的數據范圍 1~5 ,數據范圍內當前沒有任何數據。
更新丟失:當多個事務選擇了同一行,然後基於最初選定的值更新該行時,
由於每個事物不知道其他事務的存在,最後的更新就會覆蓋其他事務所做的更新;
臟讀: 一個事務正在對一條記錄做修改,這個事務完成並提交前,這條記錄就處於不一致狀態。
這時,另外一個事務也來讀取同一條記錄,如果不加控制,
第二個事務讀取了這些「臟」數據,並據此做了進一步的處理,就會產生提交的數據依賴關系。
這種現象就叫「臟讀」。
不可重復讀:一個事務在讀取某些數據後的某個時間,再次讀取以前讀過的數據,
卻發現其讀出的數據已經發生了改變,或者某些記錄已經被刪除了。
這種現象就叫「不可重復讀」。
幻讀:一個事務按相同的查詢條件重新讀取以前檢索過的數據,
卻發現其他事務插入了滿足其查詢條件的新數據,這種現象稱為「幻讀」。
可以簡單的認為滿足條件的數據量變化了。
Record Locks
索引記錄鎖,索引記錄鎖始終鎖定索引記錄,即使表中未定義索引,
這種情況下,InnoDB 創建一個隱藏的聚簇索引,並使用該索引進行記錄鎖定。
Gap Locks
間隙鎖是索引記錄之間的間隙上的鎖,或者對第一條記錄之前或者最後一條記錄之後的鎖。
間隙鎖是性能和並發之間權衡的一部分。
對於無間隙的數據范圍不需要間隙鎖,因為沒有間隙。
Next-Key Locks
索引記錄上的記錄鎖和索引記錄之前的 gap lock 的組合。
假設索引包含 10、11、13 和 20。
可能的next-key locks包括以下間隔,其中圓括弧表示不包含間隔端點,方括弧表示包含端點:
(負無窮大, 10] (10, 11] (11, 13] (13, 20] (20, 正無窮大) 對於最後一個間隔,next-key將會鎖定索引中最大值的上方,
2. 數據填充了部分數據范圍:(未被完全填充的數據范圍,是存在數據間隙)
3. 數據范圍內沒有任何數據(存在間隙)
如下:
在了解了數據全集的組成後,我們再來看看事務並發時,會帶來的問題。
無控制的並發所帶來的問題
並發事務如果不加以控制的話會帶來一些問題,主要包括以下幾種情況。
1. 范圍內已有數據更改導致的:
2. 范圍內數據量發生了變化導致:
因為無控制的並發會帶來一系列的問題,這些問題會導致無法滿足我們所需要的結果。因此我們需要控制並發,以實現我們所期望的結果(隔離級別)。
MySQL 隔離級別的實現
InnoDB 通過加鎖的策略來支持這些隔離級別。
行鎖包含:
左右滑動進行查看
"上確界"偽記錄的值高於索引中任何實際值。
上確界不是一個真正的索引記錄,因此,實際上,這個 next-key 只鎖定最大索引值之後的間隙。
基於此,當獲取的數據范圍中,數據已填充了所有的數據范圍,那麼此時是不存在間隙的,也就不需要 gap lock。
對於數據范圍內存在間隙的,需要根據隔離級別確認是否對間隙加鎖。
默認的 REPEATABLE READ 隔離級別,為了保證可重復讀,除了對數據本身加鎖以外,還需要對數據間隙加鎖。
READ COMMITTED 已提交讀,不匹配行的記錄鎖在 MySQL 評估了 where 條件後釋放。
對於 update 語句,InnoDB 執行 "semi-consistent" 讀取,這樣它會將最新提交的版本返回到 MySQL,
以便 MySQL 可以確定該行是否與 update 的 where 條件相匹配。
總結&延展:
唯一索引存在唯一約束,所以變更後的數據若違反了唯一約束的原則,則會失敗。
當 where 條件使用二級索引篩選數據時,會對二級索引命中的條目和對應的聚簇索引都加鎖;所以其他事務變更命中加鎖的聚簇索引時,都會等待鎖。
行鎖的增加是一行一行增加的,所以可能導致並發情況下死鎖的發生。
例如,
在 session A 對符合條件的某聚簇索引加鎖時,可能 session B 已持有該聚簇索引的 Record Locks,而 session B 正在等待 session A 已持有的某聚簇索引的 Record Locks。
session A 和 session B 是通過兩個不相乾的二級索引定位到的聚簇索引。
session A 通過索引 idA,session B通過索引 idB 。
當 where 條件獲取的數據無間隙時,無論隔離級別為 rc 或 rr,都不會存在間隙鎖。
比如通過唯一索引獲取到了已完全填充的數據范圍,此時不需要間隙鎖。
間隙鎖的目的在於阻止數據插入間隙,所以無論是通過 insert 或 update 變更導致的間隙內數據的存在,都會被阻止。
rc 隔離級別模式下,查詢和索引掃描將禁用 gap locking,此時 gap locking 僅用於外鍵約束檢查和重復鍵檢查(主要是唯一性檢查)。
rr 模式下,為了防止幻讀,會加上 Gap Locks。
事務中,SQL 開始則加鎖,事務結束才釋放鎖。
就鎖類型而言,應該有優化鎖,鎖升級等,例如rr模式未使用索引查詢的情況下,是否可以直接升級為表鎖。
就鎖的應用場景而言,在回放場景中,如果確定事務可並發,則可以考慮不加鎖,加快回放速度。
鎖只是並發控制的一種粒度,只是一個很小的部分:
從不同場景下是否需要控制並發,(已知無交集且有序的數據的變更,MySQL 的 MTS 相同前置事務的多事務並發回放)
並發控制的粒度,(鎖是一種邏輯粒度,可能還存在物理層和其他邏輯粒度或方式)
相同粒度下的優化,(鎖本身存在優化,如IX、IS類型的優化鎖)
粒度載入的安全&性能(如獲取行鎖前,先獲取頁鎖,頁鎖在執行獲取行鎖操作後即釋放,無論是否獲取成功)等多個層次去思考並發這玩意。
❷ SQL Server事務隔離級別和Oracle中的區別
SQL Server事務隔離級別和Oracle中的區別
設置一個事務的隔離級別
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ET TRANSACTION READ ONLY;
設置增個會話的隔離級別
ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
❸ 資料庫中姓名的數據格式請回答
REF CURSOR游標:
動態游標,在運行的時候才能確定游標使用的查詢。分類:
強類型(限制)REF CURSOR,規定返回類型
弱類型(非限制)REF CURSOR,不規定返回類型,可以獲取任何結果集。
TYPE ref_cursor_name IS REF CURSOR [RETURN return_type]
Oracle 的隔離級別
SQL92定義的隔離級別在理論上很完善,但是 Oracle 顯然認為在實際實現的時候並不應該完全照搬SQL92的模型。
- Oracle不支持 SQL92 標准中的「讀取未提交數據(read uncommitted)」隔離級別,想要臟讀都沒可能。
- Oracle 支持 SQL92 標准中的「讀取已提交數據(read committed)」隔離級別,(這也是Oracle默認的隔離級別)。
- Oracle不支持 SQL92 標准中的「可重現的讀取(repeatable read)」隔離級別,要想避免「不可重現的讀取(nonrepeatable read)」可以直接使用「序列化(serializable)」隔離級別。
- Oracle 支持 SQL92 標准中的「序列化(serializable)」隔離級別,但是並不真正阻塞事務的執行(這一點在後文還有詳述)。
- Oracle 還另外增加了一個非SQL92標準的「只讀(read-only)」隔離級別。
oracle startup的時候分為三個步驟:
1. Start an instance.
2. Mount the database.
3. Open the database.
三個步驟中所要做的工作主要如下:
1、start an instance
命令為 startup nomount
在這一步中主要工作有:
Reading the parameter file initsid.ora
Allocating the SGA
Starting the background processes
Opening the ALERT file and the trace files
讀參數文件是為了讀裡面的dbname,各個內存參數的大小,比如sga的大小,以便分配內存,還有控制文件的路徑等。在這一步並不打開控制文件,所以如果你要重建控制文件的時候,需要工作在這個狀態下。
2、Mount the database.
命令為 startup mount,如果在nomount狀態下命令為: alter database mount
在這一步中主要工作有:
Associating a database with a previously started instance
Locating and opening the control files specified in the parameter file
Reading the control files to obtain the names and status of the data files and redo log files
在這一步,主要用到的文件是控制文件.然後讀控制文件,得到各個數據文件和聯機日誌文件的名字和狀態(online or offline) ,但是並不去檢查各個文件是否存在.所以如果你要修改數據文件的名字和重建聯機日誌文件等操作,就需要工作在mount狀態下.因為下一步要打開各個數據文件和聯機日誌文件,所以如果數據文件不存在,你就需要在mount狀態下,恢復文件,才能使下一步不報錯誤.
3、Open the database.
命令為 startup,如果在mount狀態下命令為: alter database open.
在這一步中主要工作有:
Opening the online data files
Opening the online redo log files
在這一步中,資料庫主要的工作是打開第2步中在控制文件中讀到的在線的聯機日誌文件和數據文件.如果數據文件和聯機日誌文件不存在,oracle就會報錯.oracle打開數據文件和日誌文件之後,會對數據文件和日誌文件進行一致性檢查,如果發現不一致,會啟動SMON進程進行實例恢復.
另外,在整個過程中密碼文件都是必須的,因為要驗證操作的用戶是否具有適當的許可權。這個只是從宏觀上來看oracle啟動的整個過程。