日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

MySQL的事务与事务隔离

發(fā)布時(shí)間:2023/12/31 数据库 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL的事务与事务隔离 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?? MySQL中自從引入InnoDB引擎后,在MySQL中就支持事務(wù),事務(wù)就是一組原子性的查詢(xún)語(yǔ)句,也即將多個(gè)查詢(xún)當(dāng)作一個(gè)獨(dú)立的工作單元,平時(shí)通過(guò)提交工作單元來(lái)完成在事務(wù)中的相應(yīng)的查詢(xún)或修改,在能支持事務(wù)的數(shù)據(jù)庫(kù)中必須要滿(mǎn)足ACID測(cè)試,即事務(wù)的四個(gè)特性:

????A:Atomicity,原子性(都執(zhí)行或者都不執(zhí)行)

????C:Consistency,一致性(從一個(gè)一致性狀態(tài)轉(zhuǎn)到另外一個(gè)一致性狀態(tài))

????I:Isolaction,隔離性(一個(gè)事務(wù)的所有修改操作在提交前對(duì)其他事務(wù)時(shí)不可見(jiàn)的)

????D: Durability,持久性(旦事務(wù)得到提交,其所做的修改會(huì)永久有效)

而在早期默認(rèn)的引擎MyISAM是不支持事務(wù)的,所以如果是在MyISAM表中是不支持事物的,想要知道數(shù)據(jù)中具體支持哪些表引擎可以通過(guò)”SHOW ENGINES;”查看在所使用版本中MySQL所支持的所有引擎。在這里先創(chuàng)建一張表transaction_tbl用于測(cè)試:

CREATE?TABLE?transaction_tbl?(id?int(4))?ENGINE=InnoDB;? INSERT?INTO?transaction_tbl?VALUE?(1); INSERT?INTO?transaction_tbl?VALUE?(2); INSERT?INTO?transaction_tbl?VALUE?(3); INSERT?INTO?transaction_tbl?VALUE?(4); INSERT?INTO?transaction_tbl?VALUE?(5);

在正常的使用過(guò)程中需要關(guān)閉自動(dòng)提交的功能默認(rèn)系統(tǒng)下是開(kāi)啟的

mysql>?SHOW?GLOBAL?VARIABLES?LIKE?'autocommit';??????????????????????? +---------------+-------+ |?Variable_name?|?Value?| +---------------+-------+ |?autocommit????|?ON????| +---------------+-------+ 1?row?in?set?(0.00?sec)

在使用事務(wù)之前需要關(guān)閉,在平時(shí)使用事務(wù)之前需要先檢查是否有開(kāi)啟autocommit,當(dāng)然如果對(duì)事務(wù)的依賴(lài)比較大建議可以永久關(guān)閉全局的自動(dòng)提交,但是在平時(shí)使用的過(guò)程中只要在使用時(shí)關(guān)閉自動(dòng)提交,而使用手動(dòng)啟動(dòng)事務(wù),這樣在事務(wù)中需要回滾時(shí)才能根據(jù)相關(guān)的事務(wù)隔離級(jí)別得到想要的效果,可以在使用事務(wù)時(shí)關(guān)閉autocommit,在所有的事務(wù)結(jié)束后再開(kāi)啟autocommit

mysql>?SET?GLOBAL?AUTOCOMMIT=off;#當(dāng)然這里也可以使用布爾值的0和1 Query?OK,?0?rows?affected?(0.00?sec)

其中事務(wù)的控制語(yǔ)句也很簡(jiǎn)單,如下:

BEGIN;?或?START?TRANSACTION; 顯式地開(kāi)啟一個(gè)事務(wù)COMMIT; 提交事務(wù)即結(jié)束事務(wù),并使已對(duì)數(shù)據(jù)庫(kù)進(jìn)行的所有修改為持久性的ROLLBACK; 事務(wù)回滾,會(huì)結(jié)束用戶(hù)的事務(wù)并撤銷(xiāo)正在進(jìn)行的所有未提交的修改SAVEPOINT?identifier; 允許在事務(wù)中創(chuàng)建一個(gè)保存點(diǎn),一個(gè)事務(wù)中可以有多個(gè)SAVEPOINTRELEASE?SAVEPOINT?identifier; 刪除一個(gè)事務(wù)的保存點(diǎn),當(dāng)沒(méi)有指定的保存點(diǎn)時(shí),執(zhí)行該SQL語(yǔ)句會(huì)報(bào)異常ROLLBACK?TO?identifier; 把事務(wù)回滾到標(biāo)記點(diǎn)

而在事務(wù)中的隔離級(jí)別不同,則事物的安全性就不同,但是事物得安全性越高,并發(fā)性越低,當(dāng)然需要根據(jù)實(shí)際情況選擇,在MySQL中事務(wù)的隔離級(jí)別有四種,安全級(jí)分別由低至高:

????READ UNCOMMITTEND:讀未提交

????READ COMMITTEND:讀提交

????REPEATABLE READ :可重讀

????SERIALIZABLE:可串行化

查看當(dāng)前使用的默認(rèn)的事務(wù)隔離級(jí)別:

mysql>?SHOW?GLOBAL?VARIABLES?LIKE?'tx_isolation'; +---------------+-----------------+ |?Variable_name?|?Value???????????| +---------------+-----------------+ |?tx_isolation??|?REPEATABLE-READ?| +---------------+-----------------+ 1?row?in?set?(0.00?sec)

而在使用四個(gè)隔離級(jí)別中,所帶來(lái)效果都是不相同的,此時(shí)測(cè)試需要開(kāi)啟2個(gè)session更為直觀,在這里就用A、B來(lái)代表兩個(gè)session中開(kāi)啟事務(wù)A、B:

mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.01?sec)

??? 一、READ UNCOMMITTEND:讀未提交,顧名思義即所有的事務(wù)都可以讀取到其他事務(wù)中未提交的內(nèi)容,該隔離模式在平時(shí)一般都不使用,因?yàn)槭褂肦EAD UNCOMMITTEND會(huì)帶來(lái)臟讀問(wèn)題,下面就用transaction_tbl舉一個(gè)簡(jiǎn)單例子說(shuō)明下:

A、B中:

mysql>?SET?tx_isolation='READ-UNCOMMITTED'; Query?OK,?0?rows?affected?(0.00?sec) mysql>?SHOW?VARIABLES?LIKE?'tx_isolation'; +---------------+------------------+ |?Variable_name?|?Value????????????| +---------------+------------------+ |?tx_isolation??|?READ-UNCOMMITTED?| +---------------+------------------+ 1?row?in?set?(0.00?sec)

事務(wù)A中做了操作,但不提交:

mysql>?START?TRANSACTION; Query?OK,?0?rows?affected?(0.00?sec)mysql>?UPDATE?transaction_tbl?SET?id?=?'6'?WHERE?id='1'; Query?OK,?1?row?affected?(0.02?sec) Rows?matched:?1??Changed:?1??Warnings:?0mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)

但是此時(shí)事務(wù)B是可以看見(jiàn)事務(wù)A中數(shù)據(jù)

事務(wù)B:

mysql>?START?TRANSACTION; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.01?sec)

此時(shí)事務(wù)A回滾:

mysql>?ROLLBACK; Query?OK,?0?rows?affected?(0.01?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)

事務(wù)B中查出來(lái)的是事務(wù)A中未提交的數(shù)據(jù):

mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)

這樣就是由READ UNCOMMITTEND所帶來(lái)的臟讀,一般數(shù)據(jù)庫(kù)生產(chǎn)環(huán)境中都不用這種事務(wù)隔離級(jí)別。

????二、READ COMMITTEND,讀提交,同理根據(jù)名字可知事物的隔離級(jí)別會(huì)比讀未提交高一個(gè)事務(wù)隔離級(jí)別更高,從而解決了臟讀的問(wèn)題,這也是大多數(shù)數(shù)據(jù)庫(kù)中所用的默認(rèn)事務(wù)隔離級(jí)別,但并不是MySQL的默認(rèn)事務(wù)隔離級(jí)別,該事務(wù)隔離級(jí)別雖然解決了臟讀問(wèn)題,但是帶來(lái)新的問(wèn)題是不可重讀,如果此時(shí)恰好有2個(gè)事務(wù)對(duì)相同的一張表做操作時(shí),在一個(gè)事務(wù)中執(zhí)行相同的查詢(xún)時(shí)會(huì)查出不同的結(jié)果:

A、B中:

mysql>?SET?tx_isolation='READ-COMMITTED'; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SHOW?VARIABLES?LIKE?'tx_isolation';??????? +---------------+----------------+ |?Variable_name?|?Value??????????| +---------------+----------------+ |?tx_isolation??|?READ-COMMITTED?| +---------------+----------------+ 1?row?in?set?(0.00?sec)

在事務(wù)A中:

mysql>?BEGIN; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)

此時(shí)事務(wù)B中也開(kāi)啟事務(wù)做了一個(gè)操作:

mysql>?BEGIN; Query?OK,?0?rows?affected?(0.00?sec)mysql>?UPDATE?transaction_tbl?SET?id?=?'6'?WHERE?id='1'; Query?OK,?1?row?affected?(0.00?sec) Rows?matched:?1??Changed:?1??Warnings:?0mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.01?sec)

此時(shí)看下事務(wù)A中的查詢(xún):

mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec) #但此時(shí)事務(wù)B中COMMIT提交后,事務(wù)A中 mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)

這樣就是由READ COMMITTEND所帶來(lái)的不可重讀問(wèn)題,所以在一般數(shù)據(jù)庫(kù)生產(chǎn)環(huán)境中也不建議采用這種事務(wù)隔離級(jí)別。

????三、REPEATABLE READ,可重讀,同理該事務(wù)隔離級(jí)別解決了不可重讀的問(wèn)題,在REPEATABLE READ中使用MVCC(多版本并發(fā)控制)在每個(gè)事務(wù)啟動(dòng)時(shí),InnoDB會(huì)為每個(gè)啟動(dòng)的事務(wù)提供一個(gè)當(dāng)下時(shí)刻的快照,為實(shí)現(xiàn)此功能,InnoDB會(huì)為每個(gè)表提供兩隱藏的字段,一個(gè)用于保存行的創(chuàng)建時(shí)間,一個(gè)用于保存行的失效時(shí)間,里面存儲(chǔ)的系統(tǒng)版本號(hào),MVCC旨在READ COMMITTEND和REPEATABLE READ兩個(gè)事務(wù)隔離中生效,但是在REPEATABLE READ同以上事務(wù)隔離級(jí)別一樣,在解決了不可重讀的問(wèn)題同時(shí)也帶來(lái)新的問(wèn)題幻讀,此時(shí)恰好有2個(gè)事務(wù)對(duì)相同的一張表做操作時(shí),在一個(gè)事務(wù)中提交之前其中一個(gè)事務(wù)在另一事務(wù)提交前后查詢(xún)的結(jié)果不一樣:

A、B中:

mysql>?SET?tx_isolation='REPEATABLE-READ';? Query?OK,?0?rows?affected?(0.01?sec)mysql>?SHOW?VARIABLES?LIKE?'tx_isolation'; +---------------+-----------------+ |?Variable_name?|?Value???????????| +---------------+-----------------+ |?tx_isolation??|?REPEATABLE-READ?| +---------------+-----------------+ 1?row?in?set?(0.01?sec)

事務(wù)A:

mysql>?BEGIN; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.02?sec)

事務(wù)B中做相關(guān)操作并提交:

mysql>?BEGIN; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)mysql>?UPDATE?transaction_tbl?SET?id?=?'1'?WHERE?id='6'; Query?OK,?1?row?affected?(0.00?sec) Rows?matched:?1??Changed:?1??Warnings:?0mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.01?sec)mysql>?COMMIT; Query?OK,?0?rows?affected?(0.02?sec)

此時(shí)再來(lái)看下事務(wù)A中:

mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.02?sec)mysql>?COMMIT; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??6?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)

這樣就是REPEATABLE READ帶來(lái)的幻讀問(wèn)題,當(dāng)然在實(shí)際生產(chǎn)中這么恰好的事比較少,所以一般都做為MySQL的默認(rèn)事務(wù)隔離級(jí)別。

????四、SERIALIZABLE,可串行化,強(qiáng)事務(wù)排序也是最高級(jí)別的事務(wù)隔離,所有的事務(wù)都有使用共享鎖,這樣就解決相應(yīng)的幻讀問(wèn)題,但是因?yàn)楣蚕礞i的原因從而使寫(xiě)入的性能降低,從而降低了MySQL的性能:

A、B中:

mysql>?SET?tx_isolation='SERIALIZABLE'; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SHOW?VARIABLES?LIKE?'tx_isolation'; +---------------+--------------+ |?Variable_name?|?Value????????| +---------------+--------------+ |?tx_isolation??|?SERIALIZABLE?| +---------------+--------------+ 1?row?in?set?(0.00?sec)

在事務(wù)A中插入一條數(shù)據(jù)不提交:

mysql>?BEGIN; Query?OK,?0?rows?affected?(0.00?sec)mysql>?INSERT?INTO?transaction_tbl?VALUE?('7'); Query?OK,?1?row?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| |??7?| +----+ 6?rows?in?set?(0.00?sec)

此時(shí)在事務(wù)B中,在事務(wù)A未提交前是無(wú)法寫(xiě)入提交的

mysql>?SHOW?GLOBAL?VARIABLES?LIKE?'tx_isolation'; +---------------+--------------+ |?Variable_name?|?Value????????| +---------------+--------------+ |?tx_isolation??|?SERIALIZABLE?| +---------------+--------------+ 1?row?in?set?(0.00?sec)mysql>?BEGIN; Query?OK,?0?rows?affected?(0.00?sec)mysql>?SELECT?*?FROM?transaction_tbl; +----+ |?id?| +----+ |??1?| |??2?| |??3?| |??4?| |??5?| +----+ 5?rows?in?set?(0.00?sec)mysql>?UPDATE?transaction_tbl?SET?id?=?'6'?WHERE?id='1'; ERROR?1205?(HY000):?Lock?wait?timeout?exceeded;?try?restarting?transaction

只有在事務(wù)A中COMMIT提交后才能在事務(wù)B中做相關(guān)的寫(xiě)入,但是在此需要注意的是在MySQL 中都是默認(rèn)都是使用REPEATABLE READ的事務(wù)隔離級(jí)別,而在平時(shí)利用事務(wù)時(shí)多用于存儲(chǔ)過(guò)程中大量使用,而不同數(shù)據(jù)庫(kù),語(yǔ)法差別很大,移植困難,換了數(shù)據(jù)庫(kù),需要重新編寫(xiě),所以把過(guò)多業(yè)務(wù)邏輯寫(xiě)在存儲(chǔ)過(guò)程不好維護(hù),不利于分層管理,容易混亂,一般存儲(chǔ)過(guò)程適用于個(gè)別對(duì)性能要求較高的業(yè)務(wù),其它的必要性不是很大,在平時(shí)使用需要根據(jù)實(shí)際情況而定。

轉(zhuǎn)載于:https://blog.51cto.com/jim123/1964004

總結(jié)

以上是生活随笔為你收集整理的MySQL的事务与事务隔离的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。