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

Mysql案例刨析事務(wù)隔離級(jí)別

 更新時(shí)間:2021年09月23日 11:49:05   作者:_江南一點(diǎn)雨  
隔離性其實(shí)比想象要復(fù)雜。在SQL中定義了四種隔離的級(jí)別,每一種隔離級(jí)別都規(guī)定了一個(gè)事務(wù)中的修改,哪些是在事務(wù)內(nèi)和事務(wù)間是可見(jiàn)的,哪些是不可見(jiàn)的。較低級(jí)別的隔離通常來(lái)說(shuō)能承受更高的并發(fā),系統(tǒng)的開(kāi)銷(xiāo)也會(huì)更小

很多小伙伴對(duì) MySQL 的隔離級(jí)別一直心存疑惑,其實(shí)這個(gè)問(wèn)題一點(diǎn)都不難,關(guān)鍵看怎么講!單純的看理論,絕對(duì)讓你暈頭轉(zhuǎn)向,但是,如果我們通過(guò)幾個(gè)實(shí)際的 SQL 來(lái)演示一些,大家就會(huì)發(fā)現(xiàn)這玩意原來(lái)這么簡(jiǎn)單!

今天松哥想通過(guò)幾個(gè)簡(jiǎn)單的案例,來(lái)和大家演示一下 MySQL 中的事務(wù)隔離級(jí)別問(wèn)題。

1. 理論

MySQL 中事務(wù)的隔離級(jí)別一共分為四種,分別如下:

  • 序列化(SERIALIZABLE)
  • 可重復(fù)讀(REPEATABLE READ)
  • 提交讀(READ COMMITTED)
  • 未提交讀(READ UNCOMMITTED)

四種不同的隔離級(jí)別含義分別如下:

SERIALIZABLE

如果隔離級(jí)別為序列化,則用戶之間通過(guò)一個(gè)接一個(gè)順序地執(zhí)行當(dāng)前的事務(wù),這種隔離級(jí)別提供了事務(wù)之間最大限度的隔離。

REPEATABLE READ

在可重復(fù)讀在這一隔離級(jí)別上,事務(wù)不會(huì)被看成是一個(gè)序列。不過(guò),當(dāng)前正在執(zhí)行事務(wù)的變化仍然不能被外部看到,也就是說(shuō),如果用戶在另外一個(gè)事務(wù)中執(zhí)行同條 SELECT 語(yǔ)句數(shù)次,結(jié)果總是相同的。(因?yàn)檎趫?zhí)行的事務(wù)所產(chǎn)生的數(shù)據(jù)變化不能被外部看到)。

READ COMMITTED

READ COMMITTED 隔離級(jí)別的安全性比 REPEATABLE READ 隔離級(jí)別的安全性要差。處于 READ COMMITTED 級(jí)別的事務(wù)可以看到其他事務(wù)對(duì)數(shù)據(jù)的修改。也就是說(shuō),在事務(wù)處理期間,如果其他事務(wù)修改了相應(yīng)的表,那么同一個(gè)事務(wù)的多個(gè) SELECT 語(yǔ)句可能返回不同的結(jié)果。

READ UNCOMMITTED

READ UNCOMMITTED 提供了事務(wù)之間最小限度的隔離。除了容易產(chǎn)生虛幻的讀操作和不能重復(fù)的讀操作外,處于這個(gè)隔離級(jí)的事務(wù)可以讀到其他事務(wù)還沒(méi)有提交的數(shù)據(jù),如果這個(gè)事務(wù)使用其他事務(wù)不提交的變化作為計(jì)算的基礎(chǔ),然后那些未提交的變化被它們的父事務(wù)撤銷(xiāo),這就導(dǎo)致了大量的數(shù)據(jù)變化。

在 MySQL 數(shù)據(jù)庫(kù)種,默認(rèn)的事務(wù)隔離級(jí)別是 REPEATABLE READ

2. SQL 實(shí)踐

接下來(lái)通過(guò)幾條簡(jiǎn)單的 SQL 向讀者驗(yàn)證上面的理論。

2.1 查看隔離級(jí)別

通過(guò)如下 SQL 可以查看數(shù)據(jù)庫(kù)實(shí)例默認(rèn)的全局隔離級(jí)別和當(dāng)前 session 的隔離級(jí)別:

MySQL8 之前使用如下命令查看 MySQL 隔離級(jí)別:

SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

查詢結(jié)果如圖:

可以看到,默認(rèn)的隔離級(jí)別為 REPEATABLE-READ,全局隔離級(jí)別和當(dāng)前會(huì)話隔離級(jí)別皆是如此。

MySQL8 開(kāi)始,通過(guò)如下命令查看 MySQL 默認(rèn)隔離級(jí)別:

SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation;

就是關(guān)鍵字變了,其他都一樣。

通過(guò)如下命令可以修改隔離級(jí)別(建議開(kāi)發(fā)者在修改時(shí)修改當(dāng)前 session 隔離級(jí)別即可,不用修改全局的隔離級(jí)別):

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

上面這條 SQL 表示將當(dāng)前 session 的數(shù)據(jù)庫(kù)隔離級(jí)別設(shè)置為 READ UNCOMMITTED,設(shè)置成功后,再次查詢隔離級(jí)別,發(fā)現(xiàn)當(dāng)前 session 的隔離級(jí)別已經(jīng)變了,如圖1-2:

注意,如果只是修改了當(dāng)前 session 的隔離級(jí)別,則換一個(gè) session 之后,隔離級(jí)別又會(huì)恢復(fù)到默認(rèn)的隔離級(jí)別,所以我們測(cè)試時(shí),修改當(dāng)前 session 的隔離級(jí)別即可。

2.2 READ UNCOMMITTED

2.2.1 準(zhǔn)備測(cè)試數(shù)據(jù)

READ UNCOMMITTED 是最低隔離級(jí)別,這種隔離級(jí)別中存在臟讀、不可重復(fù)讀以及幻象讀問(wèn)題,所以這里我們先來(lái)看這個(gè)隔離級(jí)別,借此大家可以搞懂這三個(gè)問(wèn)題到底是怎么回事。

下面分別予以介紹。

首先創(chuàng)建一個(gè)簡(jiǎn)單的表,預(yù)設(shè)兩條數(shù)據(jù),如下:

表的數(shù)據(jù)很簡(jiǎn)單,有 javaboy 和 itboyhub 兩個(gè)用戶,兩個(gè)人的賬戶各有 1000 人民幣。現(xiàn)在模擬這兩個(gè)用戶之間的一個(gè)轉(zhuǎn)賬操作。

注意,如果讀者使用的是 Navicat 的話,不同的查詢窗口就對(duì)應(yīng)了不同的 session,如果讀者使用了 SQLyog 的話,不同查詢窗口對(duì)應(yīng)同一個(gè) session,因此如果使用 SQLyog,需要讀者再開(kāi)啟一個(gè)新的連接,在新的連接中進(jìn)行查詢操作。

2.2.2 臟讀

一個(gè)事務(wù)讀到另外一個(gè)事務(wù)還沒(méi)有提交的數(shù)據(jù),稱(chēng)之為臟讀。具體操作如下:

首先打開(kāi)兩個(gè)SQL操作窗口,假設(shè)分別為 A 和 B,在 A 窗口中輸入如下幾條 SQL (輸入完成后不用執(zhí)行):

START TRANSACTION;
UPDATE account set balance=balance+100 where name='javaboy';
UPDATE account set balance=balance-100 where name='itboyhub';
COMMIT;

在 B 窗口執(zhí)行如下 SQL,修改默認(rèn)的事務(wù)隔離級(jí)別為 READ UNCOMMITTED,如下:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

接下來(lái)在 B 窗口中輸入如下 SQL,輸入完成后,首先執(zhí)行第一行開(kāi)啟事務(wù)(注意只需要執(zhí)行一行即可):

START TRANSACTION;
SELECT * from account;
COMMIT;

接下來(lái)執(zhí)行 A 窗口中的前兩條 SQL,即開(kāi)啟事務(wù),給 javaboy 這個(gè)賬戶添加 100 元。

進(jìn)入到 B 窗口,執(zhí)行 B 窗口的第二條查詢 SQL(SELECT * from user;),結(jié)果如下:

可以看到,A 窗口中的事務(wù),雖然還未提交,但是 B 窗口中已經(jīng)可以查詢到數(shù)據(jù)的相關(guān)變化了。

這就是臟讀問(wèn)題。

2.2.3 不可重復(fù)讀

不可重復(fù)讀是指一個(gè)事務(wù)先后讀取同一條記錄,但兩次讀取的數(shù)據(jù)不同,稱(chēng)之為不可重復(fù)讀。具體操作步驟如下(操作之前先將兩個(gè)賬戶的錢(qián)都恢復(fù)為1000):

  1. 首先打開(kāi)兩個(gè)查詢窗口 A 和 B ,并且將 B 的數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別設(shè)置為 READ UNCOMMITTED。具體 SQL 參考上文,這里不贅述。
  2. 在 B 窗口中輸入如下 SQL,然后只執(zhí)行前兩條 SQL 開(kāi)啟事務(wù)并查詢 javaboy 的賬戶:
START TRANSACTION;
SELECT * from account where name='javaboy';
COMMIT;

前兩條 SQL 執(zhí)行結(jié)果如下:

在 A 窗口中執(zhí)行如下 SQL,給 javaboy 這個(gè)賬戶添加 100 塊錢(qián),如下:

START TRANSACTION;
UPDATE account set balance=balance+100 where name='javaboy';
COMMIT;

4.再次回到 B 窗口,執(zhí)行 B 窗口的第二條 SQL 查看 javaboy 的賬戶,結(jié)果如下:

javaboy 的賬戶已經(jīng)發(fā)生了變化,即前后兩次查看 javaboy 賬戶,結(jié)果不一致,這就是不可重復(fù)讀。

和臟讀的區(qū)別在于,臟讀是看到了其他事務(wù)未提交的數(shù)據(jù),而不可重復(fù)讀是看到了其他事務(wù)已經(jīng)提交的數(shù)據(jù)(由于當(dāng)前 SQL 也是在事務(wù)中,因此有可能并不想看到其他事務(wù)已經(jīng)提交的數(shù)據(jù))。

2.2.4 幻象讀

幻象讀和不可重復(fù)讀非常像,看名字就是產(chǎn)生幻覺(jué)了。

我舉一個(gè)簡(jiǎn)單例子。

在 A 窗口中輸入如下 SQL:

START TRANSACTION;
insert into account(name,balance) values('zhangsan',1000);
COMMIT;

然后在 B 窗口輸入如下 SQL:

START TRANSACTION;
SELECT * from account;
delete from account where name='zhangsan';
COMMIT;

我們執(zhí)行步驟如下:

  • 首先執(zhí)行 B 窗口的前兩行,開(kāi)啟一個(gè)事務(wù),同時(shí)查詢數(shù)據(jù)庫(kù)中的數(shù)據(jù),此時(shí)查詢到的數(shù)據(jù)只有 javaboy 和 itboyhub。
  • 執(zhí)行 A 窗口的前兩行,向數(shù)據(jù)庫(kù)中添加一個(gè)名為 zhangsan 的用戶,注意不用提交事務(wù)。
  • 執(zhí)行 B 窗口的第二行,由于臟讀問(wèn)題,此時(shí)可以查詢到 zhangsan 這個(gè)用戶。
  • 執(zhí)行 B 窗口的第三行,去刪除 name 為 zhangsan 的記錄,這個(gè)時(shí)候刪除就會(huì)出問(wèn)題,雖然在 B 窗口中可以查詢到 zhangsan,但是這條記錄還沒(méi)有提交,是因?yàn)榕K讀的原因才看到了,所以是沒(méi)法刪除的。此時(shí)就產(chǎn)生了幻覺(jué),明明有個(gè) zhangsan,卻無(wú)法刪除。

這就是幻讀。

看了上面的案例,大家應(yīng)該明白了臟讀、不可重復(fù)讀以及幻讀各自是什么含義了。

2.3 READ COMMITTED

和 READ UNCOMMITTED 相比,READ COMMITTED 主要解決了臟讀的問(wèn)題,對(duì)于不可重復(fù)讀和幻象讀則未解決。

將事務(wù)的隔離級(jí)別改為 READ COMMITTED 之后,重復(fù)上面關(guān)于臟讀案例的測(cè)試,發(fā)現(xiàn)已經(jīng)不存在臟讀問(wèn)題了;重復(fù)上面關(guān)于不可重復(fù)讀案例的測(cè)試,發(fā)現(xiàn)不可重復(fù)讀問(wèn)題依然存在。

上面那個(gè)案例不適用于幻讀的測(cè)試,我們換一個(gè)幻讀的測(cè)試案例。

還是兩個(gè)窗口 A 和 B,將 B 窗口的隔離級(jí)別改為 READ COMMITTED,

然后在 A 窗口輸入如下測(cè)試 SQL:

START TRANSACTION;
insert into account(name,balance) values('zhangsan',1000);
COMMIT;

在 B 窗口輸入如下測(cè)試 SQL:

START TRANSACTION;
SELECT * from account;
insert into account(name,balance) values('zhangsan',1000);
COMMIT;

測(cè)試方式如下:

  • 首先執(zhí)行 B 窗口的前兩行 SQL,開(kāi)啟事務(wù)并查詢數(shù)據(jù),此時(shí)查到的只有 javaboy 和 itboyhub 兩個(gè)用戶。
  • 執(zhí)行 A 窗口的前兩行 SQL,插入一條記錄,但是并不提交事務(wù)。
  • 執(zhí)行 B 窗口的第二行 SQL,由于現(xiàn)在已經(jīng)沒(méi)有了臟讀問(wèn)題,所以此時(shí)查不到 A 窗口中添加的數(shù)據(jù)。
  • 執(zhí)行 B 窗口的第三行 SQL,由于 name 字段唯一,因此這里會(huì)無(wú)法插入。此時(shí)就產(chǎn)生幻覺(jué)了,明明沒(méi)有 zhangsan 這個(gè)用戶,卻無(wú)法插入 zhangsan。

2.4 REPEATABLE READ

和 READ COMMITTED 相比,REPEATABLE READ 進(jìn)一步解決了不可重復(fù)讀的問(wèn)題,但是幻象讀則未解決。

REPEATABLE READ 中關(guān)于幻讀的測(cè)試和上一小節(jié)基本一致,不同的是第二步中執(zhí)行完插入 SQL 后記得提交事務(wù)。

由于 REPEATABLE READ 已經(jīng)解決了不可重復(fù)讀,因此第二步即使提交了事務(wù),第三步也查不到已經(jīng)提交的數(shù)據(jù),第四步繼續(xù)插入就會(huì)出錯(cuò)。

注意,REPEATABLE READ 也是 InnoDB 引擎的默認(rèn)數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別

2.5 SERIALIZABLE

SERIALIZABLE 提供了事務(wù)之間最大限度的隔離,在這種隔離級(jí)別中,事務(wù)一個(gè)接一個(gè)順序的執(zhí)行,不會(huì)發(fā)生臟讀、不可重復(fù)讀以及幻象讀問(wèn)題,最安全。

如果設(shè)置當(dāng)前事務(wù)隔離級(jí)別為 SERIALIZABLE,那么此時(shí)開(kāi)啟其他事務(wù)時(shí),就會(huì)阻塞,必須等當(dāng)前事務(wù)提交了,其他事務(wù)才能開(kāi)啟成功,因此前面的臟讀、不可重復(fù)讀以及幻象讀問(wèn)題這里都不會(huì)發(fā)生。

3. 總結(jié)

總的來(lái)說(shuō),隔離級(jí)別和臟讀、不可重復(fù)讀以及幻象讀的對(duì)應(yīng)關(guān)系如下:

隔離級(jí)別 臟讀 不可重復(fù)讀 幻象讀
READ UNCOMMITTED 允許 允許 允許
READ COMMITED 不允許 允許 允許
REPEATABLE READ 不允許 不允許 允許
SERIALIZABLE 不允許 不允許 不允許

性能關(guān)系如圖:

好了,這篇文章就和小伙伴們先說(shuō)這么多,大家不妨寫(xiě)幾行 SQL 試一試。

到此這篇關(guān)于Mysql案例刨析事務(wù)隔離級(jí)別的文章就介紹到這了,更多相關(guān)Mysql 事務(wù)隔離級(jí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SQLyog錯(cuò)誤號(hào)碼2058最新解決辦法

    SQLyog錯(cuò)誤號(hào)碼2058最新解決辦法

    這篇文章主要給大家介紹了關(guān)于SQLyog錯(cuò)誤號(hào)碼2058的最新解決辦法,使用sqlyog連接數(shù)據(jù)庫(kù)過(guò)程中可能會(huì)出現(xiàn)2058錯(cuò)誤,出現(xiàn)的原因是因?yàn)镸YSQL8.0對(duì)密碼的加密方式進(jìn)行了改變,需要的朋友可以參考下
    2023-08-08
  • MySQL分區(qū)表的使用

    MySQL分區(qū)表的使用

    本文詳細(xì)介紹了在MySQL中創(chuàng)建分區(qū)表的方法和注意事項(xiàng),包括Range和List兩種常見(jiàn)分區(qū)類(lèi)型的具體操作流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • 阿里云云服務(wù)器mysql密碼找回的方法

    阿里云云服務(wù)器mysql密碼找回的方法

    這篇文章主要介紹了阿里云云服務(wù)器mysql密碼找回的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • 淺析MySQL 鎖和事務(wù)

    淺析MySQL 鎖和事務(wù)

    這篇文章主要介紹了MySQL 鎖和事務(wù)的相關(guān)資料,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫(kù),感興趣的朋友可以了解下
    2020-09-09
  • MySQL定期整理磁盤(pán)碎片的方法實(shí)現(xiàn)

    MySQL定期整理磁盤(pán)碎片的方法實(shí)現(xiàn)

    磁盤(pán)碎片是指文件在磁盤(pán)上分散存儲(chǔ)的情況,這可能導(dǎo)致磁盤(pán)讀寫(xiě)速度下降、空間浪費(fèi)等問(wèn)題,本文主要介紹了MySQL定期整理磁盤(pán)碎片的方法實(shí)現(xiàn),感興趣的可以了解一下
    2024-02-02
  • mysql enum字段類(lèi)型的謹(jǐn)慎使用

    mysql enum字段類(lèi)型的謹(jǐn)慎使用

    本文主要介紹了mysql enum字段類(lèi)型使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • MySQL表的增刪改查(CRUD)

    MySQL表的增刪改查(CRUD)

    這篇文章主要介紹了如何對(duì)數(shù)據(jù)庫(kù)增刪改查,想要更全面了解的小伙伴,可以詳細(xì)閱讀本文
    2023-03-03
  • MySQL數(shù)據(jù)庫(kù)命令

    MySQL數(shù)據(jù)庫(kù)命令

    這篇文章主要介紹了數(shù)據(jù)庫(kù)的常用命令,數(shù)據(jù)庫(kù)中對(duì)表的命令以及一些常用的數(shù)據(jù)庫(kù)查詢和常用函數(shù),感興趣的小伙伴可以借鑒一下
    2023-03-03
  • mysql 8.0 錯(cuò)誤The server requested authentication method unknown to the client解決方法

    mysql 8.0 錯(cuò)誤The server requested authentication method unkno

    在本篇文章里小編給大家整理的是關(guān)于mysql 8.0 錯(cuò)誤The server requested authentication method unknown to the client解決方法,有此需要的朋友們可以學(xué)習(xí)下。
    2019-08-08
  • mysql 5.7.18 Installer安裝下載圖文教程

    mysql 5.7.18 Installer安裝下載圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 5.7.18 Installer安裝下載圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09

最新評(píng)論