MySQL存储过程之事务管理
生活随笔
收集整理的這篇文章主要介紹了
MySQL存储过程之事务管理
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
MySQL存儲(chǔ)過(guò)程之事務(wù)管理?
ACID:Atomic、Consistent、Isolated、Durable?
存儲(chǔ)程序提供了一個(gè)絕佳的機(jī)制來(lái)定義、封裝和管理事務(wù)。?
1,MySQL的事務(wù)支持?
MySQL的事務(wù)支持不是綁定在MySQL服務(wù)器本身,而是與存儲(chǔ)引擎相關(guān):?
Java代碼?MyISAM:不支持事務(wù),用于只讀程序提高性能?? InnoDB:支持ACID事務(wù)、行級(jí)鎖、并發(fā)?? Berkeley?DB:支持事務(wù)??
隔離級(jí)別:?
隔離級(jí)別決定了一個(gè)session中的事務(wù)可能對(duì)另一個(gè)session的影響、并發(fā)session對(duì)數(shù)據(jù)庫(kù)的操作、一個(gè)session中所見(jiàn)數(shù)據(jù)的一致性?
ANSI標(biāo)準(zhǔn)定義了4個(gè)隔離級(jí)別,MySQL的InnoDB都支持:?
Java代碼?READ?UNCOMMITTED:最低級(jí)別的隔離,通常又稱為dirty?read,它允許一個(gè)事務(wù)讀取還沒(méi)commit的數(shù)據(jù),這樣可能會(huì)提高性能,但是dirty?read可能不是我們想要的?? READ?COMMITTED:在一個(gè)事務(wù)中只允許已經(jīng)commit的記錄可見(jiàn),如果session中select還在查詢中,另一session此時(shí)insert一條記錄,則新添加的數(shù)據(jù)不可見(jiàn)?? REPEATABLE?READ:在一個(gè)事務(wù)開(kāi)始后,其他session對(duì)數(shù)據(jù)庫(kù)的修改在本事務(wù)中不可見(jiàn),直到本事務(wù)commit或rollback。在一個(gè)事務(wù)中重復(fù)select的結(jié)果一樣,除非本事務(wù)中update數(shù)據(jù)庫(kù)。?? SERIALIZABLE:最高級(jí)別的隔離,只允許事務(wù)串行執(zhí)行。為了達(dá)到此目的,數(shù)據(jù)庫(kù)會(huì)鎖住每行已經(jīng)讀取的記錄,其他session不能修改數(shù)據(jù)直到前一事務(wù)結(jié)束,事務(wù)commit或取消時(shí)才釋放鎖。??
可以使用如下語(yǔ)句設(shè)置MySQL的session隔離級(jí)別:?
Java代碼?SET?TRANSACTION?ISOLATION?LEVEL?{READ?UNCOMMITTED?|?READ?COMMITTED?|?REPEATABLE?READ?|?SERIALIZABLE}??
MySQL默認(rèn)的隔離級(jí)別是REPEATABLE READ,在設(shè)置隔離級(jí)別為READ UNCOMMITTED或SERIALIZABLE時(shí)要小心,READ UNCOMMITTED會(huì)導(dǎo)致數(shù)據(jù)完整性的嚴(yán)重問(wèn)題,而SERIALIZABLE會(huì)導(dǎo)致性能問(wèn)題并增加死鎖的機(jī)率?
事務(wù)管理語(yǔ)句:?
Java代碼?START?TRANSACTION:開(kāi)始事務(wù),autocommit設(shè)為0,如果已經(jīng)有一個(gè)事務(wù)在運(yùn)行,則會(huì)觸發(fā)一個(gè)隱藏的COMMIT?? COMMIT:提交事務(wù),保存更改,釋放鎖?? ROLLBACK:回滾本事務(wù)對(duì)數(shù)據(jù)庫(kù)的所有更改,然后結(jié)束事務(wù),釋放鎖?? SAVEPOINT?savepoint_name:創(chuàng)建一個(gè)savepoint識(shí)別符來(lái)ROLLBACK?TO?SAVEPOINT?? ROLLBACK?TO?SAVEPOINT?savepoint_name:回滾到從savepoint_name開(kāi)始對(duì)數(shù)據(jù)庫(kù)的所有更改,這樣就允許回滾事務(wù)中的一部分,保證更改的一個(gè)子集被提交?? SET?TRANSACTION:允許設(shè)置事務(wù)的隔離級(jí)別?? LOCK?TABLES:允許顯式的鎖住一個(gè)或多個(gè)table,會(huì)隱式的關(guān)閉當(dāng)前打開(kāi)的事務(wù),建議在執(zhí)行LOCK?TABLES語(yǔ)句之前顯式的commit或rollback。我們一般所以一般在事務(wù)代碼里不會(huì)使用LOCK?TABLES??
2,定義事務(wù)?
MySQL默認(rèn)的行為是在每條SQL語(yǔ)句執(zhí)行后執(zhí)行一個(gè)COMMIT語(yǔ)句,從而有效的將每條語(yǔ)句獨(dú)立為一個(gè)事務(wù)。?
在復(fù)雜的應(yīng)用場(chǎng)景下這種方式就不能滿足需求了。?
為了打開(kāi)事務(wù),允許在COMMIT和ROLLBACK之前多條語(yǔ)句被執(zhí)行,我們需要做以下兩步:?
1, 設(shè)置MySQL的autocommit屬性為0,默認(rèn)為1?
2,使用START TRANSACTION語(yǔ)句顯式的打開(kāi)一個(gè)事務(wù)?
如果已經(jīng)打開(kāi)一個(gè)事務(wù),則SET autocommit=0不會(huì)起作用,因?yàn)镾TART TRANSACTION會(huì)隱式的提交session中所有當(dāng)前的更改,結(jié)束已有的事務(wù),并打開(kāi)一個(gè)新的事務(wù)。?
使用SET AUTOCOMMIT語(yǔ)句的存儲(chǔ)過(guò)程例子:?
Java代碼?CREATE?PROCEDURE?tfer_funds?? ????(from_account?int,?to_account?int,?tfer_amount?numeric(10,2))?? BEGIN?? ????SET?autocommit=0;?? ?? ????UPDATE?account_balance?SET?balance=balance-tfer_amount?WHERE?account_id=from_account;?? ?? ????UPDATE?account_balance?SET?balance=balance+tfer_amount?WHERE?account_id=to_account;?? ?? ????COMMIT;?? END;??
使用START TRANSACITON打開(kāi)事務(wù)的例子:?
Java代碼?CREATE?PROCEDURE?tfer_funds?? ????(from_account?int,?to_account?int,?tfer_amount?numeric(10,2))?? BEGIN?? ????START?TRANSACTION;?? ?? ????UPDATE?account_balance?SET?balance=balance-tfer_amount?WHERE?account_id=from_account;?? ?? ????UPDATE?account_balance?SET?balance=balance+tfer_amount?WHERE?account_id=to_account;?? ?? ????COMMIT;?? END;??
通常COMMIT或ROLLBACK語(yǔ)句執(zhí)行時(shí)才完成一個(gè)事務(wù),但是有些DDL語(yǔ)句等會(huì)隱式觸發(fā)COMMIT,所以應(yīng)該在事務(wù)中盡可能少用或注意一下:?
Java代碼?ALTER?FUNCTION?? ALTER?PROCEDURE?? ALTER?TABLE?? BEGIN?? CREATE?DATABASE?? CREATE?FUNCTION?? CREATE?INDEX?? CREATE?PROCEDURE?? CREATE?TABLE?? DROP?DATABASE?? DROP?FUNCTION?? DROP?INDEX?? DROP?PROCEDURE?? DROP?TABLE?? UNLOCK?TABLES?? LOAD?MASTER?DATA?? LOCK?TABLES?? RENAME?TABLE?? TRUNCATE?TABLE?? SET?AUTOCOMMIT=1?? START?TRANSACTION??
3,使用Savepoint?
使用savepoint回滾難免有些性能消耗,一般可以用IF改寫?
savepoint的良好使用的場(chǎng)景之一是“嵌套事務(wù)”,你可能希望程序執(zhí)行一個(gè)小的事務(wù),但是不希望回滾外面更大的事務(wù):?
Java代碼?CREATE?PROCEDURE?nested_tfer_funds?? ????(in_from_acct???INTEGER,?? ?????in_to_acct?????INTEGER,?? ?????in_tfer_amount?DECIMAL(8,2))?? BEGIN?? ????DECLARE?txn_error?INTEGER?DEFAULT?0;?? ?? ????DECLARE?CONTINUE?HANDLER?FOR?SQLEXCEPTION?BEGIN?? ????????SET?txn_error=1;?? ????END?? ?? ????SAVEPINT?savepint_tfer;?? ?? ????UPDATE?account_balance?? ???????SET?balance=balance-in_tfer_amount?? ?????WHERE?account_id=in_from_acct;?? ?? ????IF?txn_error?THEN?? ????????ROLLBACK?TO?savepoint_tfer;?? ????????SELECT?'Transfer?aborted';?? ????ELSE?? ????????UPDATE?account_balance?? ???????????SET?balance=balance+in_tfer_amount?? ?????????WHERE?account_id=in_to_acct;?? ?? ????????IF?txn_error?THEN?? ????????????ROLLBACK?TO?savepoint_tfer;?? ????????????SELECT?'Transfer?aborted';?? ?? ????????END?IF:?? ????END?IF;?? END;??
4,事務(wù)和鎖?
事務(wù)的ACID屬性只能通過(guò)限制數(shù)據(jù)庫(kù)的同步更改來(lái)實(shí)現(xiàn),從而通過(guò)對(duì)修改數(shù)據(jù)加鎖來(lái)實(shí)現(xiàn)。?
直到事務(wù)觸發(fā)COMMIT或ROLLBACK語(yǔ)句時(shí)鎖才釋放。?
缺點(diǎn)是后面的事務(wù)必須等前面的事務(wù)完成才能開(kāi)始執(zhí)行,吞吐量隨著等待鎖釋放的時(shí)間增長(zhǎng)而遞減。?
MySQL/InnoDB通過(guò)行級(jí)鎖來(lái)最小化鎖競(jìng)爭(zhēng)。這樣修改同一table里其他行的數(shù)據(jù)沒(méi)有限制,而且讀數(shù)據(jù)可以始終沒(méi)有等待。?
可以在SELECT語(yǔ)句里使用FOR UPDATE或LOCK IN SHARE MODE語(yǔ)句來(lái)加上行級(jí)鎖?
Java代碼?SELECT?select_statement?options?[FOR?UPDATE|LOCK?IN?SHARE?MODE]??
FOR UPDATE會(huì)鎖住該SELECT語(yǔ)句返回的行,其他SELECT和DML語(yǔ)句必須等待該SELECT語(yǔ)句所在的事務(wù)完成?
LOCK IN SHARE MODE同F(xiàn)OR UPDATE,但是允許其他session的SELECT語(yǔ)句執(zhí)行并允許獲取SHARE MODE鎖?
死鎖:?
死鎖發(fā)生于兩個(gè)事務(wù)相互等待彼此釋放鎖的情景?
當(dāng)MySQL/InnoDB檢查到死鎖時(shí),它會(huì)強(qiáng)制一個(gè)事務(wù)rollback并觸發(fā)一條錯(cuò)誤消息?
對(duì)InnoDB而言,所選擇的rollback的事務(wù)是完成工作最少的事務(wù)(所修改的行最少)?
Java代碼?mysql?>?CALL?tfer_funds(1,2,300);?? ERROR?1213?(40001):?Deadlock?found?when?trying?to?get?lock;?try?restarting?transaction??
死鎖在任何數(shù)據(jù)庫(kù)系統(tǒng)里都可能發(fā)生,但是對(duì)MySQL/InnoDB這種行級(jí)鎖數(shù)據(jù)庫(kù)而言可能性相對(duì)較少。?
可以通過(guò)使用一致的順序來(lái)鎖row或table以及讓事務(wù)保持盡可能短來(lái)減少死鎖的頻率。?
如果死鎖不容易debug,你可以向你的程序中添加一些邏輯來(lái)處理死鎖并重試事務(wù),但這部分代碼多了以后很難維護(hù)?
所以,比較好的避免死鎖的方式是在做任何修改之前按一定的順序添加行級(jí)鎖,這樣就能避免死鎖:?
Java代碼?CREATE?PROCEDURE?tfer_funds3?? ????(from_account?INT,?to_account?INT,?tfer_amount?NUMERIC(10,2))?? BEGIN?? ????DECLARE?local_account_id?INT;?? ????DECLARE?lock_cursor?CURSOR?FOR?? ????????SELECT?account_id?? ??????????FROM?account_balance?? ?????????WHERE?account_id?IN?(from_account,?to_account)?? ?????????ORDER?BY?account_id?? ???????????FOR?UPDATE;?? ?? ????START?TRANSACTION;?? ?? ????OPEN?lock_cursor;?? ????FETCH?lock_cursor?INTO?local_account_id;?? ?? ????UPDATE?account_balance?? ???????SET?balance=balance-tfer_amount?? ?????WHERE?account_id=from_account;?? ?? ????UPDATE?account_balance?? ???????SET?balance=balance+tfer_amount?? ?????WHERE?account_id=to_account;?? ?? ????CLOSE?lock_cursor;?? ?? ????COMMIT;?? END;??
設(shè)置死鎖ttl: innodb_lock_wait_timeout,默認(rèn)為50秒?
如果你在一個(gè)事務(wù)中混合使用InnoDB和非InnoDB表,則MySQL不能檢測(cè)到死鎖,此時(shí)會(huì)拋出“l(fā)ock wait timeuot”1205錯(cuò)誤?
樂(lè)觀所和悲觀鎖策略:?
悲觀鎖:在讀取數(shù)據(jù)時(shí)鎖住那幾行,其他對(duì)這幾行的更新需要等到悲觀鎖結(jié)束時(shí)才能繼續(xù)?
樂(lè)觀所:讀取數(shù)據(jù)時(shí)不鎖,更新時(shí)檢查是否數(shù)據(jù)已經(jīng)被更新過(guò),如果是則取消當(dāng)前更新?
一般在悲觀鎖的等待時(shí)間過(guò)長(zhǎng)而不能接受時(shí)我們才會(huì)選擇樂(lè)觀鎖?
悲觀鎖的例子:?
Java代碼?CREATE?PROCEDURE?tfer_funds?? ???????(from_account?INT,?to_account?INT,tfer_amount?NUMERIC(10,2),?? ????????OUT?status?INT,?OUT?message?VARCHAR(30))?? BEGIN?? ????DECLARE?from_account_balance?NUMERIC(10,2);?? ?? ????START?TRANSACTION;?? ?? ?? ????SELECT?balance?? ??????INTO?from_account_balance?? ??????FROM?account_balance?? ?????WHERE?account_id=from_account?? ???????FOR?UPDATE;?? ?? ????IF?from_account_balance>=tfer_amount?THEN?? ?? ?????????UPDATE?account_balance?? ????????????SET?balance=balance-tfer_amount?? ??????????WHERE?account_id=from_account;?? ?? ?????????UPDATE?account_balance?? ????????????SET?balance=balance+tfer_amount?? ??????????WHERE?account_id=to_account;?? ?????????COMMIT;?? ?? ?????????SET?status=0;?? ?????????SET?message='OK';?? ????ELSE?? ?????????ROLLBACK;?? ?????????SET?status=-1;?? ?????????SET?message='Insufficient?funds';?? ????END?IF;?? END;??
樂(lè)觀鎖的例子:?
Java代碼?CREATE?PROCEDURE?tfer_funds?? ????(from_account?INT,?to_account?INT,?tfer_amount?NUMERIC(10,2),?? ????????OUT?status?INT,?OUT?message?VARCHAR(30)?)?? ?? BEGIN?? ?? ????DECLARE?from_account_balance????NUMERIC(8,2);?? ????DECLARE?from_account_balance2???NUMERIC(8,2);?? ????DECLARE?from_account_timestamp1?TIMESTAMP;?? ????DECLARE?from_account_timestamp2?TIMESTAMP;?? ?? ????SELECT?account_timestamp,balance?? ????????INTO?from_account_timestamp1,from_account_balance?? ????????????FROM?account_balance?? ????????????WHERE?account_id=from_account;?? ?? ????IF?(from_account_balance>=tfer_amount)?THEN?? ?? ????????--?Here?we?perform?some?long?running?validation?that?? ????????--?might?take?a?few?minutes?*/?? ????????CALL?long_running_validation(from_account);?? ?? ????????START?TRANSACTION;?? ?? ????????--?Make?sure?the?account?row?has?not?been?updated?since?? ????????--?our?initial?check?? ????????SELECT?account_timestamp,?balance?? ????????????INTO?from_account_timestamp2,from_account_balance2?? ????????????FROM?account_balance?? ????????????WHERE?account_id=from_account?? ????????????FOR?UPDATE;?? ?? ????????IF?(from_account_timestamp1?<>?from_account_timestamp2?OR?? ????????????from_account_balance????<>?from_account_balance2)??THEN?? ????????????ROLLBACK;?? ????????????SET?status=-1;?? ????????????SET?message=CONCAT("Transaction?cancelled?due?to?concurrent?update",?? ????????????????"?of?account"??,from_account);?? ????????ELSE?? ????????????UPDATE?account_balance?? ????????????????SET?balance=balance-tfer_amount?? ????????????????WHERE?account_id=from_account;?? ?? ????????????UPDATE?account_balance?? ????????????????SET?balance=balance+tfer_amount?? ????????????????WHERE?account_id=to_account;?? ?? ????????????COMMIT;?? ?? ????????????SET?status=0;?? ????????????SET?message="OK";?? ????????END?IF;?? ?? ????ELSE?? ????????ROLLBACK;?? ????????SET?status=-1;?? ????????SET?message="Insufficient?funds";?? ????END?IF;?? END$$??
5,事務(wù)設(shè)計(jì)指南?
Java代碼?1,保持事務(wù)短小?? 2,盡量避免事務(wù)中rollback?? 3,盡量避免savepoint?? 4,默認(rèn)情況下,依賴于悲觀鎖?? 5,為吞吐量要求苛刻的事務(wù)考慮樂(lè)觀鎖?? 6,顯示聲明打開(kāi)事務(wù)?? 7,鎖的行越少越好,鎖的時(shí)間越短越好 ?
ACID:Atomic、Consistent、Isolated、Durable?
存儲(chǔ)程序提供了一個(gè)絕佳的機(jī)制來(lái)定義、封裝和管理事務(wù)。?
1,MySQL的事務(wù)支持?
MySQL的事務(wù)支持不是綁定在MySQL服務(wù)器本身,而是與存儲(chǔ)引擎相關(guān):?
Java代碼?
隔離級(jí)別:?
隔離級(jí)別決定了一個(gè)session中的事務(wù)可能對(duì)另一個(gè)session的影響、并發(fā)session對(duì)數(shù)據(jù)庫(kù)的操作、一個(gè)session中所見(jiàn)數(shù)據(jù)的一致性?
ANSI標(biāo)準(zhǔn)定義了4個(gè)隔離級(jí)別,MySQL的InnoDB都支持:?
Java代碼?
可以使用如下語(yǔ)句設(shè)置MySQL的session隔離級(jí)別:?
Java代碼?
MySQL默認(rèn)的隔離級(jí)別是REPEATABLE READ,在設(shè)置隔離級(jí)別為READ UNCOMMITTED或SERIALIZABLE時(shí)要小心,READ UNCOMMITTED會(huì)導(dǎo)致數(shù)據(jù)完整性的嚴(yán)重問(wèn)題,而SERIALIZABLE會(huì)導(dǎo)致性能問(wèn)題并增加死鎖的機(jī)率?
事務(wù)管理語(yǔ)句:?
Java代碼?
2,定義事務(wù)?
MySQL默認(rèn)的行為是在每條SQL語(yǔ)句執(zhí)行后執(zhí)行一個(gè)COMMIT語(yǔ)句,從而有效的將每條語(yǔ)句獨(dú)立為一個(gè)事務(wù)。?
在復(fù)雜的應(yīng)用場(chǎng)景下這種方式就不能滿足需求了。?
為了打開(kāi)事務(wù),允許在COMMIT和ROLLBACK之前多條語(yǔ)句被執(zhí)行,我們需要做以下兩步:?
1, 設(shè)置MySQL的autocommit屬性為0,默認(rèn)為1?
2,使用START TRANSACTION語(yǔ)句顯式的打開(kāi)一個(gè)事務(wù)?
如果已經(jīng)打開(kāi)一個(gè)事務(wù),則SET autocommit=0不會(huì)起作用,因?yàn)镾TART TRANSACTION會(huì)隱式的提交session中所有當(dāng)前的更改,結(jié)束已有的事務(wù),并打開(kāi)一個(gè)新的事務(wù)。?
使用SET AUTOCOMMIT語(yǔ)句的存儲(chǔ)過(guò)程例子:?
Java代碼?
使用START TRANSACITON打開(kāi)事務(wù)的例子:?
Java代碼?
通常COMMIT或ROLLBACK語(yǔ)句執(zhí)行時(shí)才完成一個(gè)事務(wù),但是有些DDL語(yǔ)句等會(huì)隱式觸發(fā)COMMIT,所以應(yīng)該在事務(wù)中盡可能少用或注意一下:?
Java代碼?
3,使用Savepoint?
使用savepoint回滾難免有些性能消耗,一般可以用IF改寫?
savepoint的良好使用的場(chǎng)景之一是“嵌套事務(wù)”,你可能希望程序執(zhí)行一個(gè)小的事務(wù),但是不希望回滾外面更大的事務(wù):?
Java代碼?
4,事務(wù)和鎖?
事務(wù)的ACID屬性只能通過(guò)限制數(shù)據(jù)庫(kù)的同步更改來(lái)實(shí)現(xiàn),從而通過(guò)對(duì)修改數(shù)據(jù)加鎖來(lái)實(shí)現(xiàn)。?
直到事務(wù)觸發(fā)COMMIT或ROLLBACK語(yǔ)句時(shí)鎖才釋放。?
缺點(diǎn)是后面的事務(wù)必須等前面的事務(wù)完成才能開(kāi)始執(zhí)行,吞吐量隨著等待鎖釋放的時(shí)間增長(zhǎng)而遞減。?
MySQL/InnoDB通過(guò)行級(jí)鎖來(lái)最小化鎖競(jìng)爭(zhēng)。這樣修改同一table里其他行的數(shù)據(jù)沒(méi)有限制,而且讀數(shù)據(jù)可以始終沒(méi)有等待。?
可以在SELECT語(yǔ)句里使用FOR UPDATE或LOCK IN SHARE MODE語(yǔ)句來(lái)加上行級(jí)鎖?
Java代碼?
FOR UPDATE會(huì)鎖住該SELECT語(yǔ)句返回的行,其他SELECT和DML語(yǔ)句必須等待該SELECT語(yǔ)句所在的事務(wù)完成?
LOCK IN SHARE MODE同F(xiàn)OR UPDATE,但是允許其他session的SELECT語(yǔ)句執(zhí)行并允許獲取SHARE MODE鎖?
死鎖:?
死鎖發(fā)生于兩個(gè)事務(wù)相互等待彼此釋放鎖的情景?
當(dāng)MySQL/InnoDB檢查到死鎖時(shí),它會(huì)強(qiáng)制一個(gè)事務(wù)rollback并觸發(fā)一條錯(cuò)誤消息?
對(duì)InnoDB而言,所選擇的rollback的事務(wù)是完成工作最少的事務(wù)(所修改的行最少)?
Java代碼?
死鎖在任何數(shù)據(jù)庫(kù)系統(tǒng)里都可能發(fā)生,但是對(duì)MySQL/InnoDB這種行級(jí)鎖數(shù)據(jù)庫(kù)而言可能性相對(duì)較少。?
可以通過(guò)使用一致的順序來(lái)鎖row或table以及讓事務(wù)保持盡可能短來(lái)減少死鎖的頻率。?
如果死鎖不容易debug,你可以向你的程序中添加一些邏輯來(lái)處理死鎖并重試事務(wù),但這部分代碼多了以后很難維護(hù)?
所以,比較好的避免死鎖的方式是在做任何修改之前按一定的順序添加行級(jí)鎖,這樣就能避免死鎖:?
Java代碼?
設(shè)置死鎖ttl: innodb_lock_wait_timeout,默認(rèn)為50秒?
如果你在一個(gè)事務(wù)中混合使用InnoDB和非InnoDB表,則MySQL不能檢測(cè)到死鎖,此時(shí)會(huì)拋出“l(fā)ock wait timeuot”1205錯(cuò)誤?
樂(lè)觀所和悲觀鎖策略:?
悲觀鎖:在讀取數(shù)據(jù)時(shí)鎖住那幾行,其他對(duì)這幾行的更新需要等到悲觀鎖結(jié)束時(shí)才能繼續(xù)?
樂(lè)觀所:讀取數(shù)據(jù)時(shí)不鎖,更新時(shí)檢查是否數(shù)據(jù)已經(jīng)被更新過(guò),如果是則取消當(dāng)前更新?
一般在悲觀鎖的等待時(shí)間過(guò)長(zhǎng)而不能接受時(shí)我們才會(huì)選擇樂(lè)觀鎖?
悲觀鎖的例子:?
Java代碼?
樂(lè)觀鎖的例子:?
Java代碼?
5,事務(wù)設(shè)計(jì)指南?
Java代碼?
轉(zhuǎn)載于:https://www.cnblogs.com/sunwei2012/archive/2010/12/14/1905436.html
總結(jié)
以上是生活随笔為你收集整理的MySQL存储过程之事务管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。