欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL學(xué)習(xí)之事務(wù)與并發(fā)控制

 更新時(shí)間:2023年03月30日 16:15:15   作者:摳腳的大灰狼  
這篇文章主要介紹了MySQL中的事務(wù)與并發(fā)控制,一個(gè)事務(wù)可以理解為一組操作,這一組操作要么全部執(zhí)行,要么全部不執(zhí)行,想了解更多的小伙伴,可以參考閱讀本文

事務(wù)

  1. 概念

    一個(gè)事務(wù)可以理解為一組操作,這一組操作要么全部執(zhí)行,要么全部不執(zhí)行。

  2. 特性

    1. 原子性

      一個(gè)事務(wù)是一個(gè)獨(dú)立的原子單元,一個(gè)事務(wù)內(nèi)所有的操作,要么全部執(zhí)行,要么全部不執(zhí)行。關(guān)注的是一組操作的執(zhí)行結(jié)果(全部成功or全部失敗)。是通過(guò)undo log實(shí)現(xiàn)的。

    2. 一致性

      看了網(wǎng)上很多博客對(duì)一致性的講解,總覺(jué)得沒(méi)有說(shuō)到點(diǎn)子上,我就從我的個(gè)人角度來(lái)說(shuō)說(shuō)對(duì)一致性的理解:

      一個(gè)事務(wù)使得數(shù)據(jù)庫(kù)從一個(gè)狀態(tài)A0,轉(zhuǎn)換到另一個(gè)狀態(tài)A1。相鄰的兩個(gè)狀態(tài)轉(zhuǎn)換之間,只能有一個(gè)事務(wù)起作用。如果當(dāng)前狀態(tài)A0轉(zhuǎn)換到下一個(gè)狀態(tài)A1,之間包括了2個(gè)事務(wù),則說(shuō)明有一個(gè)事務(wù)的effect被覆蓋了。如事務(wù)并發(fā)問(wèn)題中的丟失更新,典型的例子是轉(zhuǎn)賬問(wèn)題,A向B轉(zhuǎn)賬,同時(shí)C也向B轉(zhuǎn)賬,最后會(huì)發(fā)現(xiàn)A或者C轉(zhuǎn)過(guò)去的錢(qián)不見(jiàn)了,這種例子隨便一搜就有,不贅述。用轉(zhuǎn)賬問(wèn)題來(lái)解釋一致性,比較好理解,因?yàn)殄X(qián)的總數(shù)應(yīng)該是確定的,比如B本來(lái)有1000,A向B轉(zhuǎn)100,C向B轉(zhuǎn)200,那么B賬戶(hù)上最后應(yīng)該有1300,然而最終我們可能看到是1100或1200,因?yàn)橛幸粋€(gè)人的操作被覆蓋掉了。其實(shí)這也就是說(shuō),B賬戶(hù)的錢(qián),從一個(gè)狀態(tài),到另一個(gè)狀態(tài),中間有2個(gè)事務(wù)起了effect,這樣是不對(duì)的。事務(wù)具有隔離性,數(shù)據(jù)庫(kù)的每一個(gè)狀態(tài),應(yīng)該都有且僅有一個(gè)與之對(duì)應(yīng)的事務(wù)在take effect。

    3. 隔離性

      不同的事務(wù)之間,應(yīng)該是不能互相影響的。

      4種隔離級(jí)別

      1. Read Uncommit
      2. Read Commit
      3. Repetable Read
      4. Serializable

      RU相當(dāng)于沒(méi)有隔離,RC和RR是用MVCC實(shí)現(xiàn)(具體是通過(guò)undo log 和 read view),Serializable是用鎖實(shí)現(xiàn),事務(wù)串行執(zhí)行。

      查看當(dāng)前的隔離級(jí)別

select @@tx_isolation;
-- mysql 8的變量名變?yōu)槿缦碌男问?
select @@transaction_isolation;

-- 設(shè)置隔離級(jí)別
set transacation_isolation = '隔離級(jí)別名'

數(shù)據(jù)庫(kù)隔離級(jí)別是一種需求,不同的隔離級(jí)別有對(duì)應(yīng)的實(shí)現(xiàn)方式。

  1. 持久性

    事務(wù)執(zhí)行成功后(提交后),對(duì)數(shù)據(jù)庫(kù)的更改是永久性的(即寫(xiě)到磁盤(pán))。是通過(guò)redo log + Force Log at Commit機(jī)制實(shí)現(xiàn)的

  2. 事務(wù)并發(fā)問(wèn)題

    1. 丟失更新

      1. 第一類(lèi)丟失更新

        針對(duì)同一行數(shù)據(jù),事務(wù)A先開(kāi)始,事務(wù)B后開(kāi)始,事務(wù)B提交,隨后事務(wù)A回滾,則回滾會(huì)導(dǎo)致將事務(wù)B已提交的修改給覆蓋掉。這個(gè)問(wèn)題在現(xiàn)在的數(shù)據(jù)庫(kù)軟件中已不會(huì)產(chǎn)生

      2. 第二類(lèi)丟失更新

        針對(duì)同一行數(shù)據(jù),事務(wù)A先開(kāi)始,事務(wù)B后開(kāi)始,事務(wù)A提交,隨后事務(wù)B提交,則事務(wù)B將事務(wù)A的修改給覆蓋掉了

    2. 臟讀

      事務(wù)A讀到了事務(wù)B未提交的數(shù)據(jù),事務(wù)B后回滾,則事務(wù)A讀到的是臟數(shù)據(jù)

    3. 不可重復(fù)讀

      事務(wù)A連續(xù)2次讀一行記錄,讀取到的是不一樣的。這是由于A連續(xù)2次讀的中間,事務(wù)B對(duì)這行記錄做了更新。

    4. 幻讀

      表現(xiàn)為兩次讀取的數(shù)據(jù)數(shù)量不一致,發(fā)現(xiàn)變多了,或者變少了。

      比如我讀取age > 10 的學(xué)生數(shù)據(jù),第一次讀發(fā)現(xiàn)有10個(gè)學(xué)生,第二次讀發(fā)現(xiàn)有20個(gè)學(xué)生,就好像出現(xiàn)了幻覺(jué)一樣,同樣的查詢(xún)條件,兩次讀取發(fā)現(xiàn)有學(xué)生增加或減少。

  3. 事務(wù)命令

    MySQL命令行下默認(rèn)是autocommit的,即事務(wù)會(huì)自動(dòng)提交。要顯示開(kāi)啟一個(gè)事務(wù),需使用命令BEGINSTART TRANSACTION

    • BEGIN 或 START TRANSACTION 開(kāi)啟事務(wù)
    • COMMIT 提交事務(wù)
    • ROLLBACK 回滾事務(wù)

并發(fā)控制

兩種并發(fā)控制策略

  1. MVCC

    Multi-Version Concurrency Control

    核心理念是快照,InnoDB主要通過(guò)undo log 和 read view來(lái)實(shí)現(xiàn)MVCC。

    **讀不加鎖,讀寫(xiě)不互斥。**讀會(huì)從多個(gè)版本的數(shù)據(jù)中挑選一個(gè)合適的版本返回。寫(xiě)操作會(huì)產(chǎn)生一個(gè)新的版本。

    每一行的記錄,會(huì)包含3個(gè)隱藏字段:row_id,tx_id,roll_ptr

    其中tx_id表示最近操作該行記錄的事務(wù)id,roll_ptr則是回滾指針,指向一條undo log記錄,即指向該次改動(dòng)之前的數(shù)據(jù)

undo log

  • insert undo log

    由insert操作產(chǎn)生,可在事務(wù)提交后直接刪除。因?yàn)閕nsert操作只對(duì)當(dāng)前事務(wù)本身可見(jiàn),其他事務(wù)不可見(jiàn)

  • update undo log

    由update/delete產(chǎn)生。是對(duì)已有記錄的修改,為了提供MVCC機(jī)制,該undo log不能在事務(wù)提交后就刪除,而需要等待purge線(xiàn)程來(lái)進(jìn)行最后的刪除

    使用update修改當(dāng)前行時(shí),首先用X鎖鎖定,然后將該行當(dāng)前值復(fù)制到undo log,然后再執(zhí)行修改,最后填寫(xiě)事務(wù)id,并使回滾指針指向undo log中修改前的行

read view

用于判斷數(shù)據(jù)可見(jiàn)性的一個(gè)數(shù)據(jù)結(jié)構(gòu),里面存儲(chǔ)了

  • 當(dāng)前活躍事務(wù)的最小id:min_id
  • 當(dāng)前活躍事務(wù)的最大id:max_id
  • 當(dāng)前活躍事務(wù)id list:ids

若讀取到的某一行的某個(gè)版本tx_id < min_id,則說(shuō)明此行的該版本在本次事務(wù)開(kāi)啟之前就已經(jīng)提交,故這個(gè)數(shù)據(jù)對(duì)本次事務(wù)可見(jiàn)。

若讀取到的某一行的某個(gè)版本tx_id >= max_id,說(shuō)明此行的該版本在本次事務(wù)開(kāi)啟之后才開(kāi)始進(jìn)行修改,故這個(gè)數(shù)據(jù)對(duì)本次事務(wù)不可見(jiàn)。

若讀取到的某一行的某個(gè)版本tx_id在min_id和max_id之間,則判斷此行的tx_id是否在ids內(nèi),若是,表明此行的事務(wù)還在活躍中,此行數(shù)據(jù)不可見(jiàn),否則,說(shuō)明此行的事務(wù)已經(jīng)提交,此行數(shù)據(jù)可見(jiàn)

簡(jiǎn)單來(lái)說(shuō),若在某一時(shí)刻開(kāi)啟了一個(gè)事務(wù)A,則會(huì)記錄下事務(wù)A開(kāi)啟時(shí),還活躍著的其他事務(wù)(記下這些活躍事務(wù)的id,保存為一個(gè)set,比如叫ids),這些事務(wù)按照開(kāi)始的時(shí)間先后,會(huì)有從小到大的事務(wù)id(tx_id),tx_id小的事務(wù),說(shuō)明是先開(kāi)啟的,tx_id大的事務(wù),說(shuō)明是后開(kāi)啟的。若在事務(wù)A中,讀取到某一行數(shù)據(jù),這一行數(shù)據(jù)的tx_id小于ids中最小的id(min_id),說(shuō)明這一行數(shù)據(jù)對(duì)應(yīng)的事務(wù),已提交過(guò)了(已不活躍了),這一行數(shù)據(jù)的修改已經(jīng)持久化,故該行數(shù)據(jù)對(duì)事務(wù)A來(lái)說(shuō)是可見(jiàn)的。若這一行數(shù)據(jù)的tx_id大于或等于ids中的最大id,說(shuō)明有一個(gè)事務(wù),在事務(wù)A開(kāi)始之后,才開(kāi)始對(duì)這一行數(shù)據(jù)進(jìn)行修改,故該行數(shù)據(jù)對(duì)事務(wù)A不可見(jiàn)。若這一行數(shù)據(jù)的tx_id,在min_id和max_id之間,那么就判斷這個(gè)tx_id是不是在ids中,即對(duì)這行數(shù)據(jù)進(jìn)行修改的那個(gè)事務(wù),還在不在活躍的事務(wù)列表中,若在,說(shuō)明修改這行數(shù)據(jù)的事務(wù)還沒(méi)提交,這行數(shù)據(jù)還沒(méi)持久化,故不可見(jiàn),反之,說(shuō)明這行數(shù)據(jù)的修改已經(jīng)持久化,故可見(jiàn)。

RC隔離級(jí)別下,在一個(gè)事務(wù)中,每次讀取數(shù)據(jù)都會(huì)新建一個(gè)ReadView。所以可能會(huì)產(chǎn)生不可重復(fù)讀的問(wèn)題,因?yàn)樵趦纱巫x之間,有其他事務(wù)對(duì)數(shù)據(jù)進(jìn)行了修改,而兩次讀時(shí)都新建了ReadView,故第二次讀的時(shí)候,修改后的數(shù)據(jù)是可見(jiàn)的。

RR隔離級(jí)別下,在一個(gè)事務(wù)中,第一次讀取時(shí)會(huì)新建一個(gè)ReadView,后序讀取都使用這個(gè)ReadView。所以哪怕在兩次讀之間,有其他事務(wù)修改了數(shù)據(jù),也不會(huì)產(chǎn)生不可重復(fù)讀的問(wèn)題。因?yàn)榈诙巫x,并沒(méi)有新建ReadView,而是使用了一開(kāi)始創(chuàng)建的那個(gè)ReadView,所以數(shù)據(jù)可見(jiàn)性和第一次是一樣的。

MVCC中,讀操作分為兩類(lèi):快照讀,當(dāng)前讀

  • 快照讀(一致性非鎖定讀)
    讀取的時(shí)記錄的可見(jiàn)版本(可能是歷史版本),不加鎖。
    當(dāng)某一行被一個(gè)事務(wù)A加了X鎖時(shí),另一個(gè)事務(wù)B仍然可以讀取該行,只不過(guò)讀取的是歷史版本。
-- 簡(jiǎn)單select
SELECT * FROM product;
  • 當(dāng)前讀

讀取的是記錄的最新版本,當(dāng)前讀返回的記錄,會(huì)加鎖,保證了其他并發(fā)事務(wù)不能修改當(dāng)前記錄

SELECT * FROM product lock in share mode;
SELECT * FROM product for update;
insert ....
update ....
delete ....

LBCC

  1. LCC

    Lock-Based Concurrency Control

    讀加讀鎖,寫(xiě)加寫(xiě)鎖。讀讀不互斥,讀寫(xiě),寫(xiě)寫(xiě)互斥。Serilizable的隔離級(jí)別是通過(guò)LBCC實(shí)現(xiàn)的

 以上就是MySQL學(xué)習(xí)之事務(wù)與并發(fā)控制的詳細(xì)內(nèi)容,更多關(guān)于MySQL事務(wù)與并發(fā)控制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論