術式之后皆為邏輯,一切皆為需求和實現(xiàn)。希望此文能從需求、現(xiàn)狀和解決方式的角度幫大家理解隔離級別。
創(chuàng)新互聯(lián)專注于洛浦企業(yè)網(wǎng)站建設,響應式網(wǎng)站設計,商城開發(fā)。洛浦網(wǎng)站建設公司,為洛浦等地區(qū)提供建站服務。全流程按需搭建網(wǎng)站,專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務
隔離級別的產(chǎn)生
在串型執(zhí)行的條件下,數(shù)據(jù)修改的順序是固定的、可預期的結果,但是并發(fā)執(zhí)行的情況下,數(shù)據(jù)的修改是不可預期的,也不固定,為了實現(xiàn)數(shù)據(jù)修改在并發(fā)執(zhí)行的情況下得到一個固定、可預期的結果,由此產(chǎn)生了隔離級別。
所以隔離級別的作用是用來平衡數(shù)據(jù)庫并發(fā)訪問與數(shù)據(jù)一致性的方法。
事務的4種隔離級別
READ UNCOMMITTED ? ? ? 未提交讀,可以讀取未提交的數(shù)據(jù)。READ COMMITTED ? ? ? ? 已提交讀,對于鎖定讀(select with for update 或者 for share)、update 和 delete 語句, ? ? ? ? ? ? ? ? ? ? ? InnoDB 僅鎖定索引記錄,而不鎖定它們之間的間隙,因此允許在鎖定的記錄旁邊自由插入新記錄。 ? ? ? ? ? ? ? ? ? ? ? Gap locking 僅用于外鍵約束檢查和重復鍵檢查。REPEATABLE READ ? ? ? ?可重復讀,事務中的一致性讀取讀取的是事務第一次讀取所建立的快照。SERIALIZABLE ? ? ? ? ? 序列化
在了解了 4 種隔離級別的需求后,在采用鎖控制隔離級別的基礎上,我們需要了解加鎖的對象(數(shù)據(jù)本身間隙),以及了解整個數(shù)據(jù)范圍的全集組成。
數(shù)據(jù)范圍全集組成
SQL 語句根據(jù)條件判斷不需要掃描的數(shù)據(jù)范圍(不加鎖);
SQL 語句根據(jù)條件掃描到的可能需要加鎖的數(shù)據(jù)范圍;
以單個數(shù)據(jù)范圍為例,數(shù)據(jù)范圍全集包含:(數(shù)據(jù)范圍不一定是連續(xù)的值,也可能是間隔的值組成)
1. 數(shù)據(jù)已經(jīng)填充了整個數(shù)據(jù)范圍:(被完全填充的數(shù)據(jù)范圍,不存在數(shù)據(jù)間隙)
整形,對值具有唯一約束條件的數(shù)據(jù)范圍 1~5 ,
已有數(shù)據(jù)1、2、3、4、5,此時數(shù)據(jù)范圍已被完全填充;
整形,對值具有唯一約束條件的數(shù)據(jù)范圍 1 和 5 ,
已有數(shù)據(jù)1、5,此時數(shù)據(jù)范圍已被完全填充;
2. 數(shù)據(jù)填充了部分數(shù)據(jù)范圍:(未被完全填充的數(shù)據(jù)范圍,是存在數(shù)據(jù)間隙)
整形的數(shù)據(jù)范圍 1~5 ,
已有數(shù)據(jù) 1、2、3、4、5,但是因為沒有唯一約束,
所以數(shù)據(jù)范圍可以繼續(xù)被 1~5 的數(shù)據(jù)重復填充;
整形,具有唯一約束條件的數(shù)據(jù)范圍 1~5 ,
已有數(shù)據(jù) 2,5,此時數(shù)據(jù)范圍未被完全填充,還可以填充 1、3、4 ;
3. 數(shù)據(jù)范圍內(nèi)沒有任何數(shù)據(jù)(存在間隙)
如下:
整形的數(shù)據(jù)范圍 1~5 ,數(shù)據(jù)范圍內(nèi)當前沒有任何數(shù)據(jù)。
在了解了數(shù)據(jù)全集的組成后,我們再來看看事務并發(fā)時,會帶來的問題。
無控制的并發(fā)所帶來的問題
并發(fā)事務如果不加以控制的話會帶來一些問題,主要包括以下幾種情況。
1. 范圍內(nèi)已有數(shù)據(jù)更改導致的:
更新丟失:當多個事務選擇了同一行,然后基于最初選定的值更新該行時,
由于每個事物不知道其他事務的存在,最后的更新就會覆蓋其他事務所做的更新;
臟讀: 一個事務正在對一條記錄做修改,這個事務完成并提交前,這條記錄就處于不一致狀態(tài)。
這時,另外一個事務也來讀取同一條記錄,如果不加控制,
第二個事務讀取了這些“臟”數(shù)據(jù),并據(jù)此做了進一步的處理,就會產(chǎn)生提交的數(shù)據(jù)依賴關系。
這種現(xiàn)象就叫“臟讀”。
2. 范圍內(nèi)數(shù)據(jù)量發(fā)生了變化導致:
不可重復讀:一個事務在讀取某些數(shù)據(jù)后的某個時間,再次讀取以前讀過的數(shù)據(jù),
卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變,或者某些記錄已經(jīng)被刪除了。
這種現(xiàn)象就叫“不可重復讀”。
幻讀:一個事務按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),
卻發(fā)現(xiàn)其他事務插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象稱為“幻讀”。
可以簡單的認為滿足條件的數(shù)據(jù)量變化了。
因為無控制的并發(fā)會帶來一系列的問題,這些問題會導致無法滿足我們所需要的結果。因此我們需要控制并發(fā),以實現(xiàn)我們所期望的結果(隔離級別)。
MySQL 隔離級別的實現(xiàn)
InnoDB 通過加鎖的策略來支持這些隔離級別。
行鎖包含:
Record Locks
索引記錄鎖,索引記錄鎖始終鎖定索引記錄,即使表中未定義索引,
這種情況下,InnoDB 創(chuàng)建一個隱藏的聚簇索引,并使用該索引進行記錄鎖定。
Gap Locks
間隙鎖是索引記錄之間的間隙上的鎖,或者對第一條記錄之前或者最后一條記錄之后的鎖。
間隙鎖是性能和并發(fā)之間權衡的一部分。
對于無間隙的數(shù)據(jù)范圍不需要間隙鎖,因為沒有間隙。
Next-Key Locks
索引記錄上的記錄鎖和索引記錄之前的 gap lock 的組合。
假設索引包含 10、11、13 和 20。
可能的next-key locks包括以下間隔,其中圓括號表示不包含間隔端點,方括號表示包含端點:
(負無窮大, 10] ? ?(10, 11] ? ?(11, 13] ? ?(13, 20] ? ?(20, 正無窮大) ? ? ? ?對于最后一個間隔,next-key將會鎖定索引中最大值的上方,
左右滑動進行查看
"上確界"偽記錄的值高于索引中任何實際值。
上確界不是一個真正的索引記錄,因此,實際上,這個 next-key 只鎖定最大索引值之后的間隙。
基于此,當獲取的數(shù)據(jù)范圍中,數(shù)據(jù)已填充了所有的數(shù)據(jù)范圍,那么此時是不存在間隙的,也就不需要 gap lock。
對于數(shù)據(jù)范圍內(nèi)存在間隙的,需要根據(jù)隔離級別確認是否對間隙加鎖。
默認的 REPEATABLE READ 隔離級別,為了保證可重復讀,除了對數(shù)據(jù)本身加鎖以外,還需要對數(shù)據(jù)間隙加鎖。
READ COMMITTED 已提交讀,不匹配行的記錄鎖在 MySQL 評估了 where 條件后釋放。
對于 update 語句,InnoDB 執(zhí)行 "semi-consistent" 讀取,這樣它會將最新提交的版本返回到 MySQL,
以便 MySQL 可以確定該行是否與 update 的 where 條件相匹配。
總結延展:
唯一索引存在唯一約束,所以變更后的數(shù)據(jù)若違反了唯一約束的原則,則會失敗。
當 where 條件使用二級索引篩選數(shù)據(jù)時,會對二級索引命中的條目和對應的聚簇索引都加鎖;所以其他事務變更命中加鎖的聚簇索引時,都會等待鎖。
行鎖的增加是一行一行增加的,所以可能導致并發(fā)情況下死鎖的發(fā)生。
例如,
在 session A 對符合條件的某聚簇索引加鎖時,可能 session B 已持有該聚簇索引的 Record Locks,而 session B 正在等待 session A 已持有的某聚簇索引的 Record Locks。
session A 和 session B 是通過兩個不相干的二級索引定位到的聚簇索引。
session A 通過索引 idA,session B通過索引 idB 。
當 where 條件獲取的數(shù)據(jù)無間隙時,無論隔離級別為 rc 或 rr,都不會存在間隙鎖。
比如通過唯一索引獲取到了已完全填充的數(shù)據(jù)范圍,此時不需要間隙鎖。
間隙鎖的目的在于阻止數(shù)據(jù)插入間隙,所以無論是通過 insert 或 update 變更導致的間隙內(nèi)數(shù)據(jù)的存在,都會被阻止。
rc 隔離級別模式下,查詢和索引掃描將禁用 gap locking,此時 gap locking 僅用于外鍵約束檢查和重復鍵檢查(主要是唯一性檢查)。
rr 模式下,為了防止幻讀,會加上 Gap Locks。
事務中,SQL 開始則加鎖,事務結束才釋放鎖。
就鎖類型而言,應該有優(yōu)化鎖,鎖升級等,例如rr模式未使用索引查詢的情況下,是否可以直接升級為表鎖。
就鎖的應用場景而言,在回放場景中,如果確定事務可并發(fā),則可以考慮不加鎖,加快回放速度。
鎖只是并發(fā)控制的一種粒度,只是一個很小的部分:
從不同場景下是否需要控制并發(fā),(已知無交集且有序的數(shù)據(jù)的變更,MySQL 的 MTS 相同前置事務的多事務并發(fā)回放)
并發(fā)控制的粒度,(鎖是一種邏輯粒度,可能還存在物理層和其他邏輯粒度或方式)
相同粒度下的優(yōu)化,(鎖本身存在優(yōu)化,如IX、IS類型的優(yōu)化鎖)
粒度加載的安全性能(如獲取行鎖前,先獲取頁鎖,頁鎖在執(zhí)行獲取行鎖操作后即釋放,無論是否獲取成功)等多個層次去思考并發(fā)這玩意。
1. 打開Mysql的數(shù)據(jù)庫服務
2.啟動MySQL后,我們找到需要用到的腳本文件,也就是數(shù)據(jù)庫文件,當然,我們首先得建立一個數(shù)據(jù)庫,這樣才可以導入腳本
3.我們在將腳本拷到本地磁盤的根目錄,這樣方便進入找到腳本,這里以D盤來說明,使用test.sql:接著我們來到命令行,使用SOURCE d:/test.sql;來導入數(shù)據(jù)庫,先進入mysql
4.首先要在數(shù)據(jù)庫中建立好數(shù)據(jù)庫,然后導入腳本,所以先建立一個數(shù)據(jù)庫哦,不要腳本是不知道你要往哪個數(shù)據(jù)庫中導入腳本的
5.
然后就可以輸入導入.sql文件命令:
mysql USE 數(shù)據(jù)庫名;
mysql SOURCE d:/test.sql;
參考自
有兩種辦法。
1、在B機器上裝mysql。
將A機器上的mysql/data下的你的數(shù)據(jù)庫目錄整個拷貝下來。
將B機器上的mysql服務停止。
找到B機器上的mysql/data目錄,將你拷貝的目錄粘貼進去,然后啟動mysql服務就可以了。
2、使用SQL語句備份和恢復
你可以使用SELECT INTO OUTFILE語句備份數(shù)據(jù),并用LOAD DATA INFILE語句恢復數(shù)據(jù)。這種方法只能導出數(shù)據(jù)的內(nèi)容,不包括表的結構,如果表的結構文件損壞,你必須要先恢復原來的表的結構。
語法:
SELECT * INTO {OUTFILE | DUMPFILE} ’file_name’ FROM tbl_name
LOAD DATA [LOW_PRIORITY] [LOCAL] INFILE ’file_name.txt’ [REPLACE | IGNORE]
INTO TABLE tbl_name
SELECT ... INTO OUTFILE ’file_name’
在dos命令提示符下使用mysqldump命令進行備份
mysql的4種事務隔離級別,如下所示:
1、未提交讀(Read Uncommitted):允許臟讀,也就是可能讀取到其他會話中未提交事務修改的數(shù)據(jù)。
2、提交讀(Read Committed):只能讀取到已經(jīng)提交的數(shù)據(jù)。Oracle等多數(shù)數(shù)據(jù)庫默認都是該級別 (不重復讀)。
3、可重復讀(Repeated Read):可重復讀。在同一個事務內(nèi)的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重復讀,但是還存在幻象讀,但是innoDB解決了幻讀。
4、串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞。
相關簡介
MySQL是一個關系型數(shù)據(jù)庫管理系統(tǒng),由瑞典MySQL AB?公司開發(fā),屬于?Oracle?旗下產(chǎn)品。MySQL 是最流行的關系型數(shù)據(jù)庫管理系統(tǒng)之一,在?WEB?應用方面,MySQL是最好的?RDBMS?(Relational Database Management System,關系數(shù)據(jù)庫管理系統(tǒng)) 應用軟件之一。
MySQL是一種關系型數(shù)據(jù)庫管理系統(tǒng),關系數(shù)據(jù)庫將數(shù)據(jù)保存在不同的表中,而不是將所有數(shù)據(jù)放在一個大倉庫內(nèi),這樣就增加了速度并提高了靈活性。
MySQL所使用的 SQL 語言是用于訪問數(shù)據(jù)庫的最常用標準化語言。MySQL 軟件采用了雙授權政策,分為社區(qū)版和商業(yè)版,由于其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,一般中小型網(wǎng)站的開發(fā)都選擇 MySQL 作為網(wǎng)站數(shù)據(jù)庫。
先來總體說一下我對這個問題的理解,用一句話概括:
數(shù)據(jù)庫是可以控制事務的傳播和隔離級別的,Spring在之上又進一步進行了封裝,可以在不同的項目、不同的操作中再次對事務的傳播行為和隔離級別進行策略控制。
注意:Spring不僅可以控制事務傳播行為(PROPAGATION_REQUIRED等),還可以控制事務隔離級別(ISOLATION_READ_UNCOMMITTED等)。
(以下是個人理解,如果有瑕疵請及時指正)
下面我具體解釋一下:
為了大家能夠更好的理解,先來明確幾個知識點:
事務的傳播行為:簡單來說就是事務是手動提交還是自動提交,事務什么時候開始,什么時候提交。
事務的隔離級別:簡單來說,就四個,提交讀,提交讀,重復讀,序列化讀。
首先我來描述一下,數(shù)據(jù)庫(mysql)層面上對于事務傳播行為和隔離級別的配置和實驗方法:
數(shù)據(jù)庫層面(采用命令行):其實mySql命令行很簡單,希望實驗操作一下:
//連接數(shù)據(jù)庫,我這里是本地,后面是用戶名密碼,不要打分號,如果指令不行,配置下環(huán)境變量,網(wǎng)上有很多。
1. cmd中執(zhí)行:mysql -hlocalhost -uroot -pmysql
//查看本地數(shù)據(jù)庫事務傳播行為是手動提交(0),還是自動提交(1)。
2.select @@autocommit;
//如果是0,希望設置為手動提交,這里其實是設置本對話的autocommit,因為如果你再開一個cmd,發(fā)現(xiàn)還是沒改回來,如果想修改全局的,網(wǎng)上有global方法。
3.set @@autocommit=0;
//然后查詢本地數(shù)據(jù)庫中的一條記錄,我本地數(shù)據(jù)庫為test1;
4.use test1;
5.select * from task where taskid=1;
//同時新開一個窗口cmd,連接數(shù)據(jù)庫,并且修改這條記錄,update語句我就不寫了,或者直接修改數(shù)據(jù)庫本條記錄。
//再次執(zhí)行select * from task where taskid=1;發(fā)現(xiàn)值沒變。OK因為此時數(shù)據(jù)庫隔離級別為repeatable read 重復讀,因為mysql默認的隔離級別是重復讀。
//修改數(shù)據(jù)庫隔離級別
6.set global transaction isolation level read committed;
//查看一下,可能需要重新連接一下
7.select @@tx_isolation;
//這時在執(zhí)行一下4,5操作,發(fā)現(xiàn)值變了,ok。因為已經(jīng)改變了數(shù)據(jù)庫隔離級別,發(fā)生了重復讀出不同數(shù)據(jù)的現(xiàn)象。
(以上操作希望有不明白的上網(wǎng)自學一下,很有用,先把數(shù)據(jù)庫隔離級別弄明白了)
然后再來講一下,Spring對事務傳播行為和隔離級別的二次封裝。
因為不同項目可能在一個mysql的不同數(shù)據(jù)庫上,所以可以在項目中配置數(shù)據(jù)庫的傳播行為和隔離級別:
關于spring的傳播行為(PROPAGATION_REQUIRED、PROPAGATION_REQUIRED等),我《數(shù)據(jù)庫隔離級別(mysql+Spring)與性能分析 》文章中有講,網(wǎng)上也有很多相關資料,我就不說了。
關于spring的事務隔離級別與數(shù)據(jù)庫的一樣,也是那四個,多了一個default,我也不仔細講了。
下面主要講一下spring的配置方法:
property name="transactionAttributes"
props
prop key="save*"PROPAGATION_REQUIRED/prop
prop key="update*"PROPAGATION_REQUIRED/prop
prop key="delete*"PROPAGATION_REQUIRED/prop
prop key="get*"PROPAGATION_REQUIRED,readOnly/prop
prop key="find*"PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED/prop
/props
就以find為例,可以配置這么配置,前面是控制傳播行為,后面是控制事務隔離級別的。那么這時哪怕數(shù)據(jù)庫層面上是重復讀,但是還是以這里為準,你會發(fā)現(xiàn)在同一個事務中兩次查詢的結果是不一樣的。
最后掃除一個盲區(qū),readonly這個屬性,是放在傳播行為中的,一般書都這么歸類,我也嘗試了一下,readonly并不能影響數(shù)據(jù)庫隔離級別,只是配置之后,不允許在事務中對數(shù)據(jù)庫進行修改操作,僅此而已。
分享標題:關于mysql怎么把tx_的信息
文章地址:http://jinyejixie.com/article28/dssiojp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、靜態(tài)網(wǎng)站、品牌網(wǎng)站設計、App開發(fā)、網(wǎng)站排名、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)