數(shù)據(jù)庫(kù)高并發(fā)請(qǐng)求怎么保證數(shù)據(jù)完整性

小編給大家分享一下數(shù)據(jù)庫(kù)高并發(fā)請(qǐng)求怎么保證數(shù)據(jù)完整性,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

目前創(chuàng)新互聯(lián)已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、千陽(yáng)網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

存儲(chǔ)引擎查看

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

SHOW ENGINES

begin!

樂(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

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

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

update TABLE
set value=2,version=version+1
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模式:

set autocommit=0;

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

# 1. 開(kāi)始事務(wù)

begin;/begin work;/start transaction; (三者選一就可以)

# 2. 查詢表信息

select status from TABLE where id=1 for update;

# 3. 插入一條數(shù)據(jù)

insert into TABLE (id,value) values (2,2);

# 4. 修改數(shù)據(jù)為

update TABLE set value=2 where id=1;

# 5. 提交事務(wù)

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è)查詢窗口

begin;/begin work;/start transaction;  (三者選一就可以)

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

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

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

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

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

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

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

update  test_one set name="www.souyunku.com" where id =1 lock in share mode;
[SQL]update  test_one set name="www.souyunku.com" where id =1 lock in share mode;
[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ù)只能再加共享鎖,除此之外其他任何類型的鎖都不能再加了。

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ě)操作,需等待其釋放。

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.查詢是否鎖表

show OPEN TABLES where In_use > 0;

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

show processlist

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

kill id

第二種

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

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

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

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

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

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)使用綁定連接。

end!

看完了這篇文章,相信你對(duì)數(shù)據(jù)庫(kù)高并發(fā)請(qǐng)求怎么保證數(shù)據(jù)完整性有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

本文名稱:數(shù)據(jù)庫(kù)高并發(fā)請(qǐng)求怎么保證數(shù)據(jù)完整性
標(biāo)題路徑:http://muchs.cn/article10/jcgpgo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、定制網(wǎng)站網(wǎng)站設(shè)計(jì)、網(wǎng)站維護(hù)網(wǎng)站排名、商城網(wǎng)站

廣告

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

成都網(wǎng)頁(yè)設(shè)計(jì)公司