偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

MySQL/InnoDB樂(lè)觀鎖悲觀鎖共享鎖、排它鎖行鎖表鎖死鎖概念的理解

數(shù)據(jù)庫(kù) MySQL
MySQL/InnoDB的加鎖,一直是一個(gè)面試中常問(wèn)的話題。例如,數(shù)據(jù)庫(kù)如果有高并發(fā)請(qǐng)求,如何保證數(shù)據(jù)完整性?產(chǎn)生死鎖問(wèn)題如何排查并解決?我在工作過(guò)程中,也會(huì)經(jīng)常用到,樂(lè)觀鎖,排它鎖,等。于是今天就對(duì)這幾個(gè)概念進(jìn)行學(xué)習(xí),屢屢思路,記錄一下。

[[238415]]

MySQL/InnoDB的加鎖,一直是一個(gè)面試中常問(wèn)的話題。例如,數(shù)據(jù)庫(kù)如果有高并發(fā)請(qǐng)求,如何保證數(shù)據(jù)完整性?產(chǎn)生死鎖問(wèn)題如何排查并解決?我在工作過(guò)程中,也會(huì)經(jīng)常用到,樂(lè)觀鎖,排它鎖,等。于是今天就對(duì)這幾個(gè)概念進(jìn)行學(xué)習(xí),屢屢思路,記錄一下。

注:MySQL是一個(gè)支持插件式存儲(chǔ)引擎的數(shù)據(jù)庫(kù)系統(tǒng)。本文下面的所有介紹,都是基于InnoDB存儲(chǔ)引擎,其他引擎的表現(xiàn),會(huì)有較大的區(qū)別。

存儲(chǔ)引擎查看

MySQL給開(kāi)發(fā)者提供了查詢存儲(chǔ)引擎的功能,我這里使用的是MySQL5.6.4,可以使用:

SHOW ENGINES

樂(lè)觀鎖

用數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn),這是樂(lè)觀鎖最常用的一種實(shí)現(xiàn)方式。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),一般是通過(guò)為數(shù)據(jù)庫(kù)表增加一個(gè)數(shù)字類型的 “version” 字段來(lái)實(shí)現(xiàn)。當(dāng)讀取數(shù)據(jù)時(shí),將version字段的值一同讀出,數(shù)據(jù)每更新一次,對(duì)此version值加1。當(dāng)我們提交更新的時(shí)候,判斷數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息與***次取出來(lái)的version值進(jìn)行比對(duì),如果數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào)與***次取出來(lái)的version值相等,則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。

舉例

1、數(shù)據(jù)庫(kù)表設(shè)計(jì)

三個(gè)字段,分別是 id,value、version 

  1. select id,value,version from TABLE where id=#{id} 

2、每次更新表中的value字段時(shí),為了防止發(fā)生沖突,需要這樣操作 

  1. update TABLE  
  2. set value=2,version=version+1  
  3. where id=#{id} and version=#{version};  

悲觀鎖

與樂(lè)觀鎖相對(duì)應(yīng)的就是悲觀鎖了。悲觀鎖就是在操作數(shù)據(jù)時(shí),認(rèn)為此操作會(huì)出現(xiàn)數(shù)據(jù)沖突,所以在進(jìn)行每次操作時(shí)都要通過(guò)獲取鎖才能進(jìn)行對(duì)相同數(shù)據(jù)的操作,這點(diǎn)跟java中的synchronized很相似,所以悲觀鎖需要耗費(fèi)較多的時(shí)間。另外與樂(lè)觀鎖相對(duì)應(yīng)的,悲觀鎖是由數(shù)據(jù)庫(kù)自己實(shí)現(xiàn)了的,要用的時(shí)候,我們直接調(diào)用數(shù)據(jù)庫(kù)的相關(guān)語(yǔ)句就可以了。

說(shuō)到這里,由悲觀鎖涉及到的另外兩個(gè)鎖概念就出來(lái)了,它們就是共享鎖與排它鎖。 共享鎖和排它鎖是悲觀鎖的不同的實(shí)現(xiàn) ,它倆都屬于悲觀鎖的范疇。

使用,排它鎖 舉例

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

我們可以使用命令設(shè)置MySQL為非autocommit模式: 

  1. set autocommit=0;  
  2. # 設(shè)置完autocommit后,我們就可以執(zhí)行我們的正常業(yè)務(wù)了。具體如下:  
  3. # 1. 開(kāi)始事務(wù)  
  4. begin;/begin work;/start transaction; (三者選一就可以)  
  5. # 2. 查詢表信息  
  6. select status from TABLE where id=1 for update 
  7. # 3. 插入一條數(shù)據(jù)  
  8. insert into TABLE (id,value) values (2,2);  
  9. # 4. 修改數(shù)據(jù)為  
  10. update TABLE set value=2 where id=1;  
  11. # 5. 提交事務(wù)  
  12. commit;/commit work 

共享鎖

共享鎖又稱 讀鎖 read lock ,是讀取操作創(chuàng)建的鎖。其他用戶可以并發(fā)讀取數(shù)據(jù),但任何事務(wù)都不能對(duì)數(shù)據(jù)進(jìn)行修改(獲取數(shù)據(jù)上的排他鎖),直到已釋放所有共享鎖。

如果事務(wù)T對(duì)數(shù)據(jù)A加上共享鎖后,則其他事務(wù)只能對(duì)A再加共享鎖,不能加排他鎖。獲得共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)

打開(kāi)***個(gè)查詢窗口 

  1. begin;/begin work;/start transaction; (三者選一就可以)  
  2. SELECT * from TABLE where id = 1 lock in share mode;  

然后在另一個(gè)查詢窗口中,對(duì)id為1的數(shù)據(jù)進(jìn)行更新 

  1. update TABLE set name="www.souyunku.com" where id =1; 

此時(shí),操作界面進(jìn)入了卡頓狀態(tài),過(guò)了超時(shí)間,提示錯(cuò)誤信息

如果在超時(shí)前,執(zhí)行 commit ,此更新語(yǔ)句就會(huì)成功。 

  1. [SQL]update test_one set name="www.souyunku.com" where id =1;  
  2. [Err] 1205 - Lock wait timeout exceeded; try restarting transaction  

加上共享鎖后,也提示錯(cuò)誤信息 

  1. update test_one set name="www.souyunku.com" where id =1 lock in share mode;  
  2. [SQL]update test_one set name="www.souyunku.com" where id =1 lock in share mode;  
  3. [Err] 1064 - 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 'lock in share mode' at line 1  

在查詢語(yǔ)句后面增加 LOCK IN SHARE MODE ,Mysql會(huì)對(duì)查詢結(jié)果中的每行都加共享鎖,當(dāng)沒(méi)有其他線程對(duì)查詢結(jié)果集中的任何一行使用排他鎖時(shí),可以成功申請(qǐng)共享鎖,否則會(huì)被阻塞。其他線程也可以讀取使用了共享鎖的表,而且這些線程讀取的是同一個(gè)版本的數(shù)據(jù)。

加上共享鎖后,對(duì)于 update,insert,delete 語(yǔ)句會(huì)自動(dòng)加排它鎖。

排它鎖

排他鎖 exclusive lock(也叫writer lock)又稱 寫(xiě)鎖 。

排它鎖是悲觀鎖的一種實(shí)現(xiàn),在上面悲觀鎖也介紹過(guò)。

若事務(wù) 1 對(duì)數(shù)據(jù)對(duì)象A加上X鎖,事務(wù) 1 可以讀A也可以修改A,其他事務(wù)不能再對(duì)A加任何鎖,直到事物 1 釋放A上的鎖。這保證了其他事務(wù)在事物 1 釋放A上的鎖之前不能再讀取和修改A。排它鎖會(huì)阻塞所有的排它鎖和共享鎖

讀取為什么要加讀鎖呢:防止數(shù)據(jù)在被讀取的時(shí)候被別的線程加上寫(xiě)鎖,

使用方式:在需要執(zhí)行的語(yǔ)句后面加上 for update 就可以了

行鎖

行鎖又分 共享鎖排他鎖 ,由字面意思理解,就是給某一行加上鎖,也就是一條記錄加上鎖。

注意:行級(jí)鎖都是基于索引的,如果一條SQL語(yǔ)句用不到索引是不會(huì)使用行級(jí)鎖的,會(huì)使用表級(jí)鎖。

共享鎖:

名詞解釋:共享鎖又叫做讀鎖,所有的事務(wù)只能對(duì)其進(jìn)行讀操作不能寫(xiě)操作,加上共享鎖后在事務(wù)結(jié)束之前其他事務(wù)只能再加共享鎖,除此之外其他任何類型的鎖都不能再加了。 

  1. SELECT * from TABLE where id = "1" lock in share mode; 

結(jié)果集的數(shù)據(jù)都會(huì)加共享鎖

排他鎖:

名詞解釋:若某個(gè)事物對(duì)某一行加上了排他鎖,只能這個(gè)事務(wù)對(duì)其進(jìn)行讀寫(xiě),在此事務(wù)結(jié)束之前,其他事務(wù)不能對(duì)其進(jìn)行加任何鎖,其他進(jìn)程可以讀取,不能進(jìn)行寫(xiě)操作,需等待其釋放。 

  1. select status from TABLE where id=1 for update

可以參考之前演示的共享鎖,排它鎖語(yǔ)句

由于對(duì)于表中,id字段為主鍵,就也相當(dāng)于索引。執(zhí)行加鎖時(shí),會(huì)將id這個(gè)索引為1的記錄加上鎖,那么這個(gè)鎖就是行鎖。

表鎖

如何加表鎖

innodb 的行鎖是在有索引的情況下,沒(méi)有索引的表是鎖定全表的.

Innodb中的行鎖與表鎖

前面提到過(guò),在Innodb引擎中既支持行鎖也支持表鎖,那么什么時(shí)候會(huì)鎖住整張表,什么時(shí)候或只鎖住一行呢? 只有通過(guò)索引條件檢索數(shù)據(jù),InnoDB才使用行級(jí)鎖,否則,InnoDB將使用表鎖!

在實(shí)際應(yīng)用中,要特別注意InnoDB行鎖的這一特性,不然的話,可能導(dǎo)致大量的鎖沖突,從而影響并發(fā)性能。

行級(jí)鎖都是基于索引的,如果一條SQL語(yǔ)句用不到索引是不會(huì)使用行級(jí)鎖的,會(huì)使用表級(jí)鎖。行級(jí)鎖的缺點(diǎn)是:由于需要請(qǐng)求大量的鎖資源,所以速度慢,內(nèi)存消耗大。

死鎖

死鎖(Deadlock) 所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。由于資源占用是互斥的,當(dāng)某個(gè)進(jìn)程提出申請(qǐng)資源后,使得有關(guān)進(jìn)程在無(wú)外力協(xié)助下,永遠(yuǎn)分配不到必需的資源而無(wú)法繼續(xù)運(yùn)行,這就產(chǎn)生了一種特殊現(xiàn)象死鎖。

解除正在死鎖的狀態(tài)有兩種方法:

***種:

1.查詢是否鎖表 

  1. show OPEN TABLES where In_use > 0; 

2.查詢進(jìn)程(如果您有SUPER權(quán)限,您可以看到所有線程。否則,您只能看到您自己的線程) 

  1. show processlist 

3.殺死進(jìn)程id(就是上面命令的id列)

kill id

第二種:

1:查看當(dāng)前的事務(wù) 

  1. SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; 

2:查看當(dāng)前鎖定的事務(wù) 

  1. SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 

3:查看當(dāng)前等鎖的事務(wù) 

  1. SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 

殺死進(jìn)程

kill 線程ID

如果系統(tǒng)資源充足,進(jìn)程的資源請(qǐng)求都能夠得到滿足,死鎖出現(xiàn)的可能性就很低,否則就會(huì)因爭(zhēng)奪有限的資源而陷入死鎖。其次,進(jìn)程運(yùn)行推進(jìn)順序與速度不同,也可能產(chǎn)生死鎖。 產(chǎn)生死鎖的四個(gè)必要條件:

(1) 互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。 (2) 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。 (3) 不剝奪條件:進(jìn)程已獲得的資源,在末使用完之前,不能強(qiáng)行剝奪。 (4) 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

雖然不能完全避免死鎖,但可以使死鎖的數(shù)量減至最少。將死鎖減至最少可以增加事務(wù)的吞吐量并減少系統(tǒng)開(kāi)銷,因?yàn)橹挥泻苌俚氖聞?wù)回滾,而回滾會(huì)取消事務(wù)執(zhí)行的所有工作。由于死鎖時(shí)回滾而由應(yīng)用程序重新提交。

下列方法有助于***限度地降低死鎖:

(1)按同一順序訪問(wèn)對(duì)象。 (2)避免事務(wù)中的用戶交互。 (3)保持事務(wù)簡(jiǎn)短并在一個(gè)批處理中。 (4)使用低隔離級(jí)別。 (5)使用綁定連接。

參考 :

  • https://blog.csdn.net/puhaiyang/article/details/72284702
  • https://www.jb51.net/article/78088.htm

原文鏈接:https://www.souyunku.com/2018/07/30/mysql 如果侵犯您的權(quán)益請(qǐng)告知?jiǎng)h除 

 

責(zé)任編輯:龐桂玉 來(lái)源: 今天頭條
相關(guān)推薦

2019-01-04 11:18:35

獨(dú)享鎖共享鎖非公平鎖

2024-01-29 01:08:01

悲觀鎖遞歸鎖讀寫(xiě)鎖

2024-05-17 09:33:22

樂(lè)觀鎖CASversion

2019-11-28 16:00:06

重入鎖讀寫(xiě)鎖樂(lè)觀鎖

2024-07-25 09:01:22

2025-04-23 08:45:00

悲觀鎖樂(lè)觀鎖并發(fā)控制機(jī)制

2024-09-03 15:14:42

2023-02-23 10:32:52

樂(lè)觀鎖

2021-03-30 09:45:11

悲觀鎖樂(lè)觀鎖Optimistic

2020-09-16 07:56:28

多線程讀寫(xiě)鎖悲觀鎖

2024-11-29 07:38:12

MySQL數(shù)據(jù)庫(kù)

2019-05-05 10:15:42

悲觀鎖樂(lè)觀鎖數(shù)據(jù)安全

2009-09-25 16:43:44

Hibernate悲觀Hibernate樂(lè)觀

2023-11-06 08:35:08

表鎖行鎖間隙鎖

2011-08-18 13:44:42

Oracle悲觀鎖樂(lè)觀鎖

2020-07-06 08:03:32

Java悲觀鎖樂(lè)觀鎖

2020-10-20 13:50:47

MySQL數(shù)據(jù)庫(kù)

2010-05-24 12:50:59

MySQL表級(jí)鎖

2023-07-05 08:18:54

Atomic類樂(lè)觀鎖悲觀鎖

2025-06-04 02:55:00

MySQL意向鎖記錄鎖
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)