久久久精品一区ed2k-女人被男人叉到高潮的视频-中文字幕乱码一区久久麻豆樱花-俄罗斯熟妇真实视频

mysql怎么用悲觀鎖 黨費(fèi)繳納主題黨日

mysql中的樂觀鎖和悲觀鎖怎么用

關(guān)于mysql中的樂觀鎖和悲觀鎖面試的時(shí)候被問到的概率還是比較大的。

創(chuàng)新互聯(lián)公司是一家以成都網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)、品牌設(shè)計(jì)、軟件運(yùn)維、seo優(yōu)化、小程序App開發(fā)等移動(dòng)開發(fā)為一體互聯(lián)網(wǎng)公司。已累計(jì)為護(hù)欄打樁機(jī)等眾行業(yè)中小客戶提供優(yōu)質(zhì)的互聯(lián)網(wǎng)建站和軟件開發(fā)服務(wù)。

mysql的悲觀鎖:

其實(shí)理解起來非常簡單,當(dāng)數(shù)據(jù)被外界修改持保守態(tài)度,包括自身系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理,因此,在整個(gè)數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制,但是也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在自身系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù)。

來點(diǎn)實(shí)際的,當(dāng)我們使用悲觀鎖的時(shí)候我們首先必須關(guān)閉mysql數(shù)據(jù)庫的自動(dòng)提交屬性,因?yàn)镸ySQL默認(rèn)使用autocommit模式,也就是說,當(dāng)你執(zhí)行一個(gè)更新操作后,MySQL會(huì)立刻將結(jié)果進(jìn)行提交。

關(guān)閉命令為:set autocommit=0;

悲觀鎖可以使用select…for update實(shí)現(xiàn),在執(zhí)行的時(shí)候會(huì)鎖定數(shù)據(jù),雖然會(huì)鎖定數(shù)據(jù),但是不影響其他事務(wù)的普通查詢使用。此處說普通查詢就是平時(shí)我們用的:select * from table 語句。在我們使用悲觀鎖的時(shí)候事務(wù)中的語句例如:

//開始事務(wù)

begin;/begin work;/start transaction; (三選一)

//查詢信息

select * from order where id=1 for update;

//修改信息

update order set name='names';

//提交事務(wù)

commit;/commit work;(二選一)

此處的查詢語句for update關(guān)鍵字,在事務(wù)中只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一條數(shù)據(jù)時(shí)會(huì)等待其它事務(wù)結(jié)束后才執(zhí)行,一般的SELECT查詢則不受影響。

執(zhí)行事務(wù)時(shí)關(guān)鍵字select…for update會(huì)鎖定數(shù)據(jù),防止其他事務(wù)更改數(shù)據(jù)。但是鎖定數(shù)據(jù)也是有規(guī)則的。

查詢條件與鎖定范圍:

1、具體的主鍵值為查詢條件

比如查詢條件為主鍵ID=1等等,如果此條數(shù)據(jù)存在,則鎖定當(dāng)前行數(shù)據(jù),如果不存在,則不鎖定。

2、不具體的主鍵值為查詢條件

比如查詢條件為主鍵ID1等等,此時(shí)會(huì)鎖定整張數(shù)據(jù)表。

3、查詢條件中無主鍵

會(huì)鎖定整張數(shù)據(jù)表。

4、如果查詢條件中使用了索引為查詢條件

明確指定索引并且查到,則鎖定整條數(shù)據(jù)。如果找不到指定索引數(shù)據(jù),則不加鎖。

悲觀鎖的確保了數(shù)據(jù)的安全性,在數(shù)據(jù)被操作的時(shí)候鎖定數(shù)據(jù)不被訪問,但是這樣會(huì)帶來很大的性能問題。因此悲觀鎖在實(shí)際開發(fā)中使用是相對(duì)比較少的。

mysql的樂觀鎖:

相對(duì)悲觀鎖而言,樂觀鎖假設(shè)數(shù)據(jù)一般情況下不會(huì)造成沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時(shí)候,才會(huì)對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測,如果發(fā)現(xiàn)沖突,則讓返回用戶錯(cuò)誤的信息,讓用戶決定如何去做。

一般來說,實(shí)現(xiàn)樂觀鎖的方法是在數(shù)據(jù)表中增加一個(gè)version字段,每當(dāng)數(shù)據(jù)更新的時(shí)候這個(gè)字段執(zhí)行加1操作。這樣當(dāng)數(shù)據(jù)更改的時(shí)候,另外一個(gè)事務(wù)訪問此條數(shù)據(jù)進(jìn)行更改的話就會(huì)操作失敗,從而避免了并發(fā)操作錯(cuò)誤。當(dāng)然,還可以將version字段改為時(shí)間戳,不過原理都是一樣的。

例如有表student,字段:

id,name,version

1 a 1

當(dāng)事務(wù)一進(jìn)行更新操作:update student set name='ygz' where id = #{id} and version = #{version};

此時(shí)操作完后數(shù)據(jù)會(huì)變?yōu)閕d = 1,name = ygz,version = 2,當(dāng)另外一個(gè)事務(wù)二同樣執(zhí)行更新操作的時(shí)候,卻發(fā)現(xiàn)version != 1,此時(shí)事務(wù)二就會(huì)操作失敗,從而保證了數(shù)據(jù)的正確性。

悲觀鎖和樂觀鎖都是要根據(jù)具體業(yè)務(wù)來選擇使用,本文僅作簡單介紹。

mysql的事務(wù)四個(gè)特性以及事務(wù)的四個(gè)隔離級(jí)別

分別是原子性、一致性、隔離性、持久性。

原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾,因此事務(wù)的操作如果成功就必須要完全應(yīng)用到數(shù)據(jù)庫,如果操作失敗則不能對(duì)數(shù)據(jù)庫有任何影響。

一致性是指事務(wù)必須使數(shù)據(jù)庫從一個(gè)一致性狀態(tài)變換到另一個(gè)一致性狀態(tài),也就是說一個(gè)事務(wù)執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。舉例來說,假設(shè)用戶A和用戶B兩者的錢加起來一共是1000,那么不管A和B之間如何轉(zhuǎn)賬、轉(zhuǎn)幾次賬,事務(wù)結(jié)束后兩個(gè)用戶的錢相加起來應(yīng)該還得是1000,這就是事務(wù)的一致性。

隔離性是當(dāng)多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫時(shí),比如同時(shí)操作同一張表時(shí),數(shù)據(jù)庫為每一個(gè)用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。關(guān)于事務(wù)的隔離性數(shù)據(jù)庫提供了多種隔離級(jí)別,稍后會(huì)介紹到。

持久性是指一個(gè)事務(wù)一旦被提交了,那么對(duì)數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會(huì)丟失提交事務(wù)的操作。例如我們?cè)谑褂肑DBC操作數(shù)據(jù)庫時(shí),在提交事務(wù)方法后,提示用戶事務(wù)操作完成,當(dāng)我們程序執(zhí)行完成直到看到提示后,就可以認(rèn)定事務(wù)已經(jīng)正確提交,即使這時(shí)候數(shù)據(jù)庫出現(xiàn)了問題,也必須要將我們的事務(wù)完全執(zhí)行完成。否則的話就會(huì)造成我們雖然看到提示事務(wù)處理完畢,但是數(shù)據(jù)庫因?yàn)楣收隙鴽]有執(zhí)行事務(wù)的重大錯(cuò)誤。這是不允許的。

在數(shù)據(jù)庫操作中,在并發(fā)的情況下可能出現(xiàn)如下問題:

正是為了解決以上情況,數(shù)據(jù)庫提供了幾種隔離級(jí)別。

數(shù)據(jù)庫事務(wù)的隔離級(jí)別有4個(gè),由低到高依次為Read uncommitted(未授權(quán)讀取、讀未提交)、Read committed(授權(quán)讀取、讀提交)、Repeatable read(可重復(fù)讀?。?、Serializable(序列化),這四個(gè)級(jí)別可以逐個(gè)解決臟讀、不可重復(fù)讀、幻象讀這幾類問題。

雖然數(shù)據(jù)庫的隔離級(jí)別可以解決大多數(shù)問題,但是靈活度較差,為此又提出了悲觀鎖和樂觀鎖的概念。

悲觀鎖,它指的是對(duì)數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度。因此,在整個(gè)數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制。也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)的數(shù)據(jù)訪問層中實(shí)現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù)。

商品t_items表中有一個(gè)字段status,status為1代表商品未被下單,status為2代表商品已經(jīng)被下單(此時(shí)該商品無法再次下單),那么我們對(duì)某個(gè)商品下單時(shí)必須確保該商品status為1。假設(shè)商品的id為1。

如果不采用鎖,那么操作方法如下:

但是上面這種場景在高并發(fā)訪問的情況下很可能會(huì)出現(xiàn)問題。例如當(dāng)?shù)谝徊讲僮髦?,查詢出來的商品status為1。但是當(dāng)我們執(zhí)行第三步Update操作的時(shí)候,有可能出現(xiàn)其他人先一步對(duì)商品下單把t_items中的status修改為2了,但是我們并不知道數(shù)據(jù)已經(jīng)被修改了,這樣就可能造成同一個(gè)商品被下單2次,使得數(shù)據(jù)不一致。所以說這種方式是不安全的。

在上面的場景中,商品信息從查詢出來到修改,中間有一個(gè)處理訂單的過程,使用悲觀鎖的原理就是,當(dāng)我們?cè)诓樵兂鰐_items信息后就把當(dāng)前的數(shù)據(jù)鎖定,直到我們修改完畢后再解鎖。那么在這個(gè)過程中,因?yàn)閠_items被鎖定了,就不會(huì)出現(xiàn)有第三者來對(duì)其進(jìn)行修改了。需要注意的是,要使用悲觀鎖,我們必須關(guān)閉mysql數(shù)據(jù)庫的自動(dòng)提交屬性,因?yàn)镸ySQL默認(rèn)使用autocommit模式,也就是說,當(dāng)你執(zhí)行一個(gè)更新操作后,MySQL會(huì)立刻將結(jié)果進(jìn)行提交。我們可以使用命令設(shè)置MySQL為非autocommit模式: set autocommit=0;

設(shè)置完autocommit后,我們就可以執(zhí)行我們的正常業(yè)務(wù)了。具體如下:

上面的begin/commit為事務(wù)的開始和結(jié)束,因?yàn)樵谇耙徊轿覀冴P(guān)閉了mysql的autocommit,所以需要手動(dòng)控制事務(wù)的提交。

上面的第一步我們執(zhí)行了一次查詢操作: select status from t_items where id=1 for update; 與普通查詢不一樣的是,我們使用了 select…for update 的方式,這樣就通過數(shù)據(jù)庫實(shí)現(xiàn)了悲觀鎖。此時(shí)在t_items表中,id為1的那條數(shù)據(jù)就被我們鎖定了,其它的事務(wù)必須等本次事務(wù)提交之后才能執(zhí)行。這樣我們可以保證當(dāng)前的數(shù)據(jù)不會(huì)被其它事務(wù)修改。需要注意的是,在事務(wù)中,只有 SELECT ... FOR UPDATE 或 LOCK IN SHARE MODE 操作同一個(gè)數(shù)據(jù)時(shí)才會(huì)等待其它事務(wù)結(jié)束后才執(zhí)行,一般 SELECT ... 則不受此影響。拿上面的實(shí)例來說,當(dāng)我執(zhí)行 select status from t_items where id=1 for update; 后。我在另外的事務(wù)中如果再次執(zhí)行 select status from t_items where id=1 for update; 則第二個(gè)事務(wù)會(huì)一直等待第一個(gè)事務(wù)的提交,此時(shí)第二個(gè)查詢處于阻塞的狀態(tài),但是如果我是在第二個(gè)事務(wù)中執(zhí)行 select status from t_items where id=1; 則能正常查詢出數(shù)據(jù),不會(huì)受第一個(gè)事務(wù)的影響。

使用 select…for update 會(huì)把數(shù)據(jù)給鎖住,不過我們需要注意一些鎖的級(jí)別,MySQL InnoDB默認(rèn)Row-Level Lock,所以只有「明確」地指定主鍵或者索引,MySQL 才會(huì)執(zhí)行Row lock (只鎖住被選取的數(shù)據(jù)) ,否則MySQL 將會(huì)執(zhí)行Table Lock (將整個(gè)數(shù)據(jù)表單給鎖住)。舉例如下:

1、 select * from t_items where id=1 for update;

這條語句明確指定主鍵(id=1),并且有此數(shù)據(jù)(id=1的數(shù)據(jù)存在),則采用row lock。只鎖定當(dāng)前這條數(shù)據(jù)。

2、 select * from t_items where id=3 for update;

這條語句明確指定主鍵,但是卻查無此數(shù)據(jù),此時(shí)不會(huì)產(chǎn)生lock(沒有元數(shù)據(jù),又去lock誰呢?)。

3、 select * from t_items where name='手機(jī)' for update;

這條語句沒有指定數(shù)據(jù)的主鍵,那么此時(shí)產(chǎn)生table lock,即在當(dāng)前事務(wù)提交前整張數(shù)據(jù)表的所有字段將無法被查詢。

4、 select * from t_items where id0 for update; 或者 select * from t_items where id1 for update; (注:在SQL中表示不等于)

上述兩條語句的主鍵都不明確,也會(huì)產(chǎn)生table lock。

5、 select * from t_items where status=1 for update; (假設(shè)為status字段添加了索引)

這條語句明確指定了索引,并且有此數(shù)據(jù),則產(chǎn)生row lock。

6、 select * from t_items where status=3 for update; (假設(shè)為status字段添加了索引)

這條語句明確指定索引,但是根據(jù)索引查無此數(shù)據(jù),也就不會(huì)產(chǎn)生lock。

樂觀鎖( Optimistic Locking ) 相對(duì)悲觀鎖而言,樂觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會(huì)造成沖突,所以只會(huì)在數(shù)據(jù)進(jìn)行提交更新的時(shí)候,才會(huì)正式對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測,如果發(fā)現(xiàn)沖突了,則返回用戶錯(cuò)誤的信息,讓用戶決定如何去做。實(shí)現(xiàn)樂觀鎖一般來說有以下2種方式:

mysql事務(wù)隔離級(jí)別 以及 悲觀鎖-樂觀鎖

以上不是重點(diǎn),重點(diǎn)是 對(duì)事務(wù)控制語句不熟悉。

SAVEPOINT identifier : 在事務(wù)中 創(chuàng)建保存點(diǎn)。一個(gè)事務(wù)中 允許有多個(gè)保存點(diǎn)。

RELEASE SAVEPOINT identifier : 刪除保存點(diǎn)。當(dāng)事務(wù)中 沒有指定的 保存點(diǎn),執(zhí)行該語句 會(huì)拋異常。

ROLLBACK TO identifier : 把事務(wù)回滾到 保存點(diǎn)。

Say you have a table T with a column C with one row in it, say it has the value '1'. And consider you have a simple task like following:

That is a simple task that issue two reads from table T, with a delay of 1 minute between them.

If you follow the logic above you can quickly realize that SERIALIZABLE transactions, while they may make life easy for you, are always completely blocking every possible concurrent operation, since they require that nobody can modify, delete nor insert any row. The default transaction isolation level of the .Net System.Transactions scope is serializable, and this usually explains the abysmal performance that results.

在Repeatable Read隔離級(jí)別下,一個(gè)事務(wù)可能會(huì)遇到幻讀(Phantom Read)的問題。

幻讀是指,在一個(gè)事務(wù)中,第一次查詢某條記錄,發(fā)現(xiàn)沒有,但是,當(dāng)試圖更新這條不存在的記錄時(shí),竟然能成功,并且,再次讀取同一條記錄,它就神奇地出現(xiàn)了。

我們?nèi)匀幌葴?zhǔn)備好students表的數(shù)據(jù):

然后,分別開啟兩個(gè)MySQL客戶端連接,按順序依次執(zhí)行事務(wù)A和事務(wù)B:

事務(wù)B在第3步第一次讀取id=99的記錄時(shí),讀到的記錄為空,說明不存在id=99的記錄。隨后,事務(wù)A在第4步插入了一條id=99的記錄并提交。事務(wù)B在第6步再次讀取id=99的記錄時(shí),讀到的記錄仍然為空,但是,事務(wù)B在第7步試圖更新這條不存在的記錄時(shí),竟然成功了,并且,事務(wù)B在第8步再次讀取id=99的記錄時(shí),記錄出現(xiàn)了。

可見,幻讀就是沒有讀到的記錄,以為不存在,但其實(shí)是可以更新成功的,并且,更新成功后,再次讀取,就出現(xiàn)了。

在沖突較少的情況下,使用樂觀鎖。樂觀鎖 因?yàn)闆]有 加鎖 釋放鎖,也減少了 加鎖 釋放鎖的開銷。

沖突較多時(shí),如果使用樂觀鎖 需要不停地嘗試,所以 使用悲觀鎖。

如果樂觀鎖 進(jìn)行嘗試時(shí) 的花銷較大,也是使用悲觀鎖。

分享名稱:mysql怎么用悲觀鎖 黨費(fèi)繳納主題黨日
新聞來源:http://sd-ha.com/article34/doijjpe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化、網(wǎng)頁設(shè)計(jì)公司小程序開發(fā)、動(dòng)態(tài)網(wǎng)站、軟件開發(fā)虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司