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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

MySQL事务(transaction) (有这篇就足够了..)

發(fā)布時間:2024/3/12 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL事务(transaction) (有这篇就足够了..) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MySQL事務處理(TransAction)

大家好,我是胡亦,一名熱愛分享技術(shù)干貨的博主。

思考了很久,決定寫一篇關(guān)于mysql事務(transaction)的博客,一來嘛,因為最近在復習mysql的相關(guān)知識,幫自己回顧總結(jié)一下,其次就是想把這篇博客分享給大家,如果你才剛剛開始學習mysql,那么希望這篇博客對你有一點啟發(fā);亦或者你早已是一個mysql老油條,這篇博客也會使你對mysql事務有一個更深的印象。

話不多說,正文開始…

首先,什么是事務呢?

事務就是由單獨單元的一個或多個sql語句組成,在這個單元中,每個sql語句都是相互依賴的。而整個單獨單元是作為一個不可分割的整體存在,類似于物理當中的原子(一種不可分割的最小單位)。

往通俗的講就是,事務就是一個整體,里面的內(nèi)容要么都執(zhí)行成功,要么都不成功。不可能存在部分執(zhí)行成功而部分執(zhí)行不成功的情況。

就是說如果單元中某條sql語句一旦執(zhí)行失敗或者產(chǎn)生錯誤,那么整個單元將會回滾(返回最初狀態(tài))。所有受到影響的數(shù)據(jù)將返回到事務開始之前的狀態(tài),但是如果單元中的所有sql語句都執(zhí)行成功的話,那么該事務也就被順利執(zhí)行。

大家都知道,我們的數(shù)據(jù)都是通過各種不同技術(shù)的存儲引擎來引導存儲的,不同的存儲引擎,都有各自的特點。在mysql中,常見的存儲引擎有innodb、myisam,memory等。其中innodb支持事務(transaction),而myisam,memory等不支持事務。

可以通過show engines;語句來查看mysql支持的存儲引擎

一、事務的四個特性(ACID)【面試??柬棥?/h4>
  • 原子性(Atomicity):指事務是一個不可分割的最小工作單位,事務中的操作只有都發(fā)生和都不發(fā)生兩種情況
  • 一致性(Consistency):事務必須使數(shù)據(jù)庫從一個一致狀態(tài)變換到另外一個一致狀態(tài),舉一個栗子,李二給王五轉(zhuǎn)賬50元,其事務就是讓李二賬戶上減去50元,王五賬戶上加上50元;一致性是指其他事務看到的情況是要么李二還沒有給王五轉(zhuǎn)賬的狀態(tài),要么王五已經(jīng)成功接收到李二的50元轉(zhuǎn)賬。而對于李二少了50元,王五還沒加上50元這個中間狀態(tài)是不可見的。
  • 隔離性(Isolation):一個事務的執(zhí)行不能被其他事務干擾,即一個事務內(nèi)部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務是隔離的,并發(fā)執(zhí)行的各個事務之間不能互相干擾。
  • 持久性(Durability):一個事務一旦提交成功,它對數(shù)據(jù)庫中數(shù)據(jù)的改變將是永久性的,接下來的其他操作或故障不應對其有任何影響。

二、事務的分類

事務分為隱式事務和顯式事務兩種。我們的DML語句(insert、update、delete)就是隱式事務。

  • 隱式事務:該事務沒有明顯的開啟和結(jié)束標記,它們都具有自動提交事務的功能;不妨思考一下,update語句修改數(shù)據(jù)時,是不是對表中數(shù)據(jù)進行改變了,它的本質(zhì)其實就相當于一個事務。
  • 舉一個栗子:張三同學買了一個csdn定制保溫杯花了99元,是不是就是update語句對字段name為張三的同學的余額balance進行減99元的處理呢?代碼如下:

  • 顯示事務:該事務具有明顯的開啟和結(jié)束標記;也是本文重點要講的東西。使用顯式事務的前提是你得先把自動提交事務的功能給禁用。禁用自動提交功能就是設(shè)置autocommit變量值為0(0:禁用 1:開啟)
  • 先查看一下當前的autocommit變量值,發(fā)現(xiàn)當前處于開啟自動提交事務的狀態(tài)

    禁用自動提交事務的功能并查看當前狀態(tài)

    三、開啟事務的步驟

    假設(shè)t_account表已經(jīng)存在

    #步驟一:開啟事務(可選) start transaction; #步驟二:編寫事務中的sql語句(insert、update、delete) #這里實現(xiàn)一下"李二給王五轉(zhuǎn)賬"的事務過程 update t_account set balance = 50 where vname = "李二"; update t_account set balance = 130 where vname = "王五"; #步驟三:結(jié)束事務 commit; #提交事務 # rollback; #回滾事務:就是事務不執(zhí)行,回滾到事務執(zhí)行前的狀態(tài)

    運行結(jié)果:

    四、事務并發(fā)時出現(xiàn)的問題

    但是呢,因為某一刻不可能總只有一個事務在運行,可能出現(xiàn)A在操作t_account表中的數(shù)據(jù),B也同樣在操作t_account表,那么就會出現(xiàn)并發(fā)問題,對于同時運行的多個事務,當這些事務訪問數(shù)據(jù)庫中相同的數(shù)據(jù)時,如果沒有采用必要的隔離機制,就會發(fā)生以下各種并發(fā)問題。

  • 🌴臟讀:對于兩個事務T1,T2,T1讀取了已經(jīng)被T2更新但還沒有被提交的字段之后,若T2回滾,T1讀取的內(nèi)容就是臨時且無效
  • 🌴不可重復讀 :對于兩個事務T1,T2,T1讀取了一個字段,然后T2更新了該字段之后,T1在讀取同一個字段,值就不同了
  • 🌴 幻讀:對于兩個事務T1,T2,T1在A表中讀取了一個字段,然后T2又在A表中插入了一些新的數(shù)據(jù)時,T1再讀取該表時,就會發(fā)現(xiàn)神不知鬼不覺的多出幾行了…
  • 所以,為了避免以上出現(xiàn)的各種并發(fā)問題,我們就必然要采取一些手段。mysql數(shù)據(jù)庫系統(tǒng)提供了四種事務的隔離級別,用來隔離并發(fā)運行各個事務,使得它們相互不受影響,這就是數(shù)據(jù)庫事務的隔離性。

    五、事務的隔離級別

    mysql中的四種事務隔離級別如下:

    1. read uncommitted(讀未提交數(shù)據(jù)):允許事務讀取未被其他事務提交的變更。(臟讀、不可重復讀和幻讀的問題都會出現(xiàn))。
    2. read committed(讀已提交數(shù)據(jù)):只允許事務讀取已經(jīng)被其他事務提交的變更。(可以避免臟讀,但不可重復讀和幻讀的問題仍然可能出現(xiàn))
    3.repeatable read(可重復讀):確保事務可以多次從一個字段中讀取相同的值,在這個事務持續(xù)期間,禁止其他事務對這個字段進行更新(update)。(可以避免臟讀和不可重復讀,但幻讀仍然存在)
    4. serializable(串行化):確保事務可以從一個表中讀取相同的行,在這個事務持續(xù)期間,禁止其他事務對該表執(zhí)行插入、更新和刪除操作,所有并發(fā)問題都可避免,但性能十分低下(因為你不完成就都不可以弄,效率太低)

    了解: oracle支持兩種事務隔離級別:read committed、serializable。

    oracle默認的事務隔離級別是:read committed。

    mysql的默認事務隔離級別是:repeatable read。

    一個事務與其他事務隔離的程度稱為隔離級別。數(shù)據(jù)庫規(guī)定了多種事務隔離級別,不同隔離級別對應不同的干擾程度,隔離級別越高,數(shù)據(jù)一致性就越好,但并發(fā)性就越差。

    這里通過一個例子向大家簡單介紹一下并發(fā):

    一個人🚶 在邊開車🚕 邊打電話📞,首先,人只有一個大腦(cpu),但是在同一時刻他卻在執(zhí)行2件事情,其實內(nèi)部就是靠他的大腦在不斷的切換執(zhí)行,之所以人民警察👮 不允許司機開車時打電話,就是怕人腦在那一瞬間切換不過來,從而導致交通事故的發(fā)生,并發(fā)和這個例子是差不多的意思。但在這里,電腦cpu可比人腦快多了,所以出錯的概率也相對來說小很多。

    接一下,演示一下在幾種不同的事務隔離級別下所發(fā)生的不同情況😶 。

    在演示之前呢,還需要知道如何查看和設(shè)置事務的隔離級別

    查看當前的事務隔離級別通過 tx_isolation變量或者transaction_isolation(版本8.0以上使用);

    語法:select @@tx_isolation;

    注意:在mysql8.0之后,就已經(jīng)拋棄了tx_isolation變量了,而是用 transaction_isolation變量代替了。

    語法:select @@transaction_isolation;

    #設(shè)置當前mysql連接的隔離級別: set session transaction isolation level read uncommitted; #設(shè)置數(shù)據(jù)庫系統(tǒng)的全局的隔離級別: set global transaction isolation level read uncommitted;

    注意:當前mysql連接的隔離級別和mysql全局的隔離級別的區(qū)別是什么?

    如果只設(shè)置當前的隔離級別,也就是session,那么另外一個并發(fā)的“mysqy程序”的隔離級別不會受到當前連接的影響,而是保持默認的repeatable read。

    但是如果是設(shè)置全局的事務隔離級別,則整個mysql數(shù)據(jù)庫(包括所有打開的mysql程序連接)的隔離級別都會隨之改變,除非服務器重啟,不然就不會恢復默認了。

    兩者僅僅一詞之差,其效果卻天差地別。

    好,了解完如何設(shè)置事務的隔離級別之后,下面將正式進入…

    呃呃呃… 等一下

    這里的講解主要是為了知道在并發(fā)的環(huán)境下,不同的事務隔離級別所表現(xiàn)出的不同特點,那么自然還是要先模擬一下并發(fā)環(huán)境

    這里打開兩個獨立的mysql數(shù)據(jù)庫連接(mysql程序1和mysql程序2),用來模擬并發(fā)環(huán)境

    咳咳咳… 正片開始

    同志們打起精神認真看啊!!

    • read uncommitted(讀未提交)

    首先,我們需要先將兩個會話的事務隔離級別都設(shè)置為read uncommitted;語句如下:

    read uncommitted可以讀到其他事務還沒提交的變更,這里舉例:程序2對t_account表中的數(shù)據(jù)進行更改,看程序1多次查詢的結(jié)果是否一致。

    可以看到程序2改變了t_account表中的vname字段,將李二改為了張三。但是程序1呢,連續(xù)2個select查詢語句的結(jié)果竟然不一致,估計現(xiàn)在程序1的表情和你手機里的第三個表情包一樣。這就是read uncommitted隔離級別的特點。
    不管你事務是否提交,只要數(shù)據(jù)發(fā)生改變我就可以察覺到…嘻嘻。是不是感覺它很強大。什么事情都逃不過它的法眼。

    接下來要看的是read committed(讀已提交)

    • read committed(讀已提交)

      測試前一定要記住設(shè)置事務的隔離級別為read committed;并且禁用自動提交事務【設(shè)置autocommit為0】(后面的每個測試都是一樣的)

      # 設(shè)置事務隔離級別為read committed set session transaction isolation level read committed; # 禁用自動提交事務功能 set autocommit = 0; #接下來的 repeatable read 隔離級別和 serializable 隔離級別也是同樣的操作

    以上例子實現(xiàn)了王五為張三轉(zhuǎn)賬的事務,可以看到程序2中事務提交前與提交后對程序1中的查詢語句產(chǎn)生的影響,前2個查詢是事務沒提交的結(jié)果,最后一個查詢是事務提交后的結(jié)果。 相信上面的例子已經(jīng)很充分的詮釋了read committed的特點。

    • repeatable read(可重復讀)

      該隔離級別為mysql的默認隔離級別;它對某字段進行操作時,其他事務禁止操作該字段。它總能保持你讀取的數(shù)據(jù)是一致的。

      以下代碼中,程序1模擬"王五向張三轉(zhuǎn)賬30元",程序2則在程序1在處理事務時,對張三的余額進行清空處理

    因為當前的事務隔離級別為repeatable read級別,所以在程序1操作t_account表時,程序2是無權(quán)對t_account表進行任何操作,如果強行操作的話,就會發(fā)生error (錯誤)

    “ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction”;

    其中文意思是:“超過鎖定等待超時;嘗試重新啟動事務”

    只有當程序1對t_account表操作完成后(結(jié)束事務后),程序2才可以對t_account表進行操作。

    • serializable(串行化)

    該隔離模式下執(zhí)行的事務在對某表進行操作期間,禁止其他所有事務對該表進行任何操作

    如果強行操作也會報錯(和上面那個錯誤一致),因為serializable用的相對比較少,這里就不做演示了。同學們理解了就好。

    • 事務的保存點(回滾點)

    回滾點表示的就是使事務回滾到指定回滾點

    語法: savepoint 節(jié)點名稱 ;

    注意:保存點只允許搭配rollback回滾來使用,不能和commit一起使用

    已知表t_stu存在,其數(shù)據(jù)如下:

    代碼舉例如下:

    #禁用自動提交事務 set autocommit = 0;#開啟事務 start transaction;#刪除id為2的記錄 delete from t_stu where id = 2;#設(shè)置保存點名為AA savepoint AA;#刪除id為3的記錄 delete from t_stu where id = 3;#回滾到AA保存點處 rollback to AA;

    運行結(jié)果如下:

    可以看到id為2的李四被刪除了,而王五卻還在,就是因為事務回滾到了AA處,所以id為3的那條記錄被回滾掉了。


    好了,以上就是本篇博客的全部內(nèi)容,喜歡的小伙伴們點贊收藏支持一下。

    我是lasting,一名熱衷于分享技術(shù)干貨的博主。我們下次見!

    總結(jié)

    以上是生活随笔為你收集整理的MySQL事务(transaction) (有这篇就足够了..)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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