UPDATE是否會(huì)加鎖?
SQL語(yǔ)句為如下時(shí),是否會(huì)加鎖?
UPDATE table1 SET num = num + 1 WHERE id=1;
答案是不會(huì)
實(shí)際上MySQL是支持給數(shù)據(jù)行加鎖(InnoDB)的,并且在UPDATE/DELETE等操作時(shí)確實(shí)會(huì)自動(dòng)加上排它鎖。只是并非只要有UPDATE關(guān)鍵字就會(huì)全程加鎖,針對(duì)上面的MySQL語(yǔ)句而言,其實(shí)并不只是一條UPDATE語(yǔ)句,而應(yīng)該類(lèi)似于兩條SQL語(yǔ)句(偽代碼):
a = SELECT * FROM table1 WHERE id=1; UPDATE table1 SET num = a.num + 1 WHERE id=1;
其中執(zhí)行SELECT語(yǔ)句時(shí)沒(méi)有加鎖,只有在執(zhí)行UPDATE時(shí)才進(jìn)行加鎖的。所以才會(huì)出現(xiàn)并發(fā)操作時(shí)的更新數(shù)據(jù)不一致。原因找到了,解決問(wèn)題就不遠(yuǎn)了。而針對(duì)這類(lèi)問(wèn)題,解決的方法可以有2種:
SELECT顯式
加鎖對(duì)SELECT進(jìn)行加鎖的方式有兩種,如下:
SELECT ... LOCK IN SHARE MODE #共享鎖,其它事務(wù)可讀,不可更新 SELECT ... FOR UPDATE #排它鎖,其它事務(wù)不可讀寫(xiě)
如果你不使用這2種語(yǔ)句,默認(rèn)情況下SELECT語(yǔ)句是不會(huì)加鎖的。并且對(duì)于上面提到的場(chǎng)景,必須使用排它鎖。另外,上面的2種語(yǔ)句只有在事務(wù)之中才能生效,否則不會(huì)生效。在MySQL命令行使用事務(wù)的方式如下:
SET AUTOCOMMIT=0; BEGIN WORK; a = SELECT num FROM table1 WHERE id=2 FOR UPDATE; UPDATE table1 SET num = a.num + 1 WHERE id=2; COMMIT WORK;
這樣只要以后更新數(shù)據(jù)時(shí),都使用這樣事務(wù)來(lái)進(jìn)行操作;那么在并發(fā)的情況下,后執(zhí)行的事務(wù)就會(huì)被堵塞,直到當(dāng)前事務(wù)執(zhí)行完成。(通過(guò)鎖把并發(fā)改成了順序執(zhí)行)
使用樂(lè)觀(guān)鎖
樂(lè)觀(guān)鎖是鎖實(shí)現(xiàn)的一種機(jī)制,它總是會(huì)天真的認(rèn)為所有需要修改的數(shù)據(jù)都不會(huì)沖突。所以在更新之前它不會(huì)給數(shù)據(jù)加鎖,而只是查詢(xún)了數(shù)據(jù)行的版本號(hào)(這里的版本號(hào)屬于自定義的字段,需要在業(yè)務(wù)表的基礎(chǔ)上額外增加一個(gè)字段,每當(dāng)更新一次就會(huì)自增或者更新)。
在具體更新數(shù)據(jù)的時(shí)候更新條件中會(huì)添加版本號(hào)信息,
實(shí)踐
對(duì) for update上鎖進(jìn)行一次實(shí)踐一個(gè)student表,其中有一條數(shù)據(jù)
開(kāi)啟兩個(gè)client
第一個(gè)開(kāi)啟事務(wù)后執(zhí)行
select name from student where id = 1 for update;
第二個(gè)開(kāi)啟事務(wù)后執(zhí)行相同的語(yǔ)句,發(fā)現(xiàn)該條數(shù)據(jù)被第一個(gè)事務(wù)上鎖阻塞了
這時(shí)候第一個(gè)事務(wù)執(zhí)行修改并commit;
第二個(gè)事務(wù)的select執(zhí)行,發(fā)現(xiàn)阻塞了4秒多
小結(jié)
總的來(lái)說(shuō),這2種方式都可以支持?jǐn)?shù)據(jù)庫(kù)的并發(fā)更新操作。但具體使用哪一種就得看實(shí)際的應(yīng)用場(chǎng)景,應(yīng)用場(chǎng)景對(duì)哪種支持更好,并且對(duì)性能的影響最小。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
標(biāo)簽:陜西 北京 鄂爾多斯 黔西 昌都 駐馬店 荊門(mén) 梅河口
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《MySQL并發(fā)更新數(shù)據(jù)時(shí)的處理方法》,本文關(guān)鍵詞 MySQL,并發(fā),更新,數(shù)據(jù),時(shí),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。