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

mysql在項(xiàng)目中怎么選事務(wù)隔離級(jí)別

 更新時(shí)間:2021年05月25日 09:08:12   作者:孤獨(dú)煙  
Mysql默認(rèn)的事務(wù)隔離級(jí)別是可重復(fù)讀,那互聯(lián)網(wǎng)項(xiàng)目中Mysql也是用默認(rèn)隔離級(jí)別,但在項(xiàng)目中呢,下面我們就一起來了解一下

引言

開始我們的內(nèi)容,相信大家一定遇到過下面的一個(gè)面試場(chǎng)景

面試官:“講講mysql有幾個(gè)事務(wù)隔離級(jí)別?”
你:“讀未提交,讀已提交,可重復(fù)讀,串行化四個(gè)!默認(rèn)是可重復(fù)讀”
面試官:“為什么mysql選可重復(fù)讀作為默認(rèn)的隔離級(jí)別?”
(你面露苦色,不知如何回答!)
面試官:"你們項(xiàng)目中選了哪個(gè)隔離級(jí)別?為什么?"
你:“當(dāng)然是默認(rèn)的可重復(fù)讀,至于原因。。呃。。?!?br /> (然后你就可以回去等通知了!)

為了避免上述尷尬的場(chǎng)景,請(qǐng)繼續(xù)往下閱讀!

Mysql默認(rèn)的事務(wù)隔離級(jí)別是可重復(fù)讀(Repeatable Read),那互聯(lián)網(wǎng)項(xiàng)目中Mysql也是用默認(rèn)隔離級(jí)別,不做修改么?
OK,不是的,我們?cè)陧?xiàng)目中一般用讀已提交(Read Commited)這個(gè)隔離級(jí)別!

what!居然是讀已提交,網(wǎng)上不是說這個(gè)隔離級(jí)別存在不可重復(fù)讀幻讀問題么?不用管么?好,帶著我們的疑問開始本文!

正文

我們先來思考一個(gè)問題,在Oracle,SqlServer中都是選擇讀已提交(Read Commited)作為默認(rèn)的隔離級(jí)別,為什么Mysql不選擇讀已提交(Read Commited)作為默認(rèn)隔離級(jí)別,而選擇可重復(fù)讀(Repeatable Read)作為默認(rèn)的隔離級(jí)別呢?

Why?Why?Why?

這個(gè)是有歷史原因的,當(dāng)然要從我們的主從復(fù)制開始講起了!
主從復(fù)制,是基于什么復(fù)制的?

是基于binlog復(fù)制的!這里不想去搬binlog的概念了,就簡單理解為binlog是一個(gè)記錄數(shù)據(jù)庫更改的文件吧~

binlog有幾種格式?

OK,三種,分別是

  • statement:記錄的是修改SQL語句
  • row:記錄的是每行實(shí)際數(shù)據(jù)的變更
  • mixed:statement和row模式的混合

那Mysql在5.0這個(gè)版本以前,binlog只支持STATEMENT這種格式!而這種格式在讀已提交(Read Commited)這個(gè)隔離級(jí)別下主從復(fù)制是有bug的,因此Mysql將可重復(fù)讀(Repeatable Read)作為默認(rèn)的隔離級(jí)別!
接下來,就要說說當(dāng)binlog為STATEMENT格式,且隔離級(jí)別為讀已提交(Read Commited)時(shí),有什么bug呢?如下圖所示,在主(master)上執(zhí)行如下事務(wù)


此時(shí)在主(master)上執(zhí)行下列語句

select * from test;

輸出如下

+---+
| b |
+---+
| 3 |
+---+
1 row in set

但是,你在此時(shí)在從(slave)上執(zhí)行該語句,得出輸出如下

Empty set

這樣,你就出現(xiàn)了主從不一致性的問題!原因其實(shí)很簡單,就是在master上執(zhí)行的順序?yàn)橄葎h后插!而此時(shí)binlog為STATEMENT格式,它記錄的順序?yàn)橄炔搴髣h!從(slave)同步的是binglog,因此從機(jī)執(zhí)行的順序和主機(jī)不一致!就會(huì)出現(xiàn)主從

不一致!

如何解決?

解決方案有兩種!
(1)隔離級(jí)別設(shè)為可重復(fù)讀(Repeatable Read),在該隔離級(jí)別下引入間隙鎖。當(dāng)Session 1執(zhí)行delete語句時(shí),會(huì)鎖住間隙。那么,Ssession 2執(zhí)行插入語句就會(huì)阻塞??!
(2)將binglog的格式修改為row格式,此時(shí)是基于行的復(fù)制,自然就不會(huì)出現(xiàn)sql執(zhí)行順序不一樣的問題!奈何這個(gè)格式在mysql5.1版本開始才引入。因此由于歷史原因,mysql將默認(rèn)的隔離級(jí)別設(shè)為可重復(fù)讀(Repeatable Read),保證主從復(fù)制不出問題!

那么,當(dāng)我們了解完mysql選可重復(fù)讀(Repeatable Read)作為默認(rèn)隔離級(jí)別的原因后,接下來我們將其和讀已提交(Read Commited)進(jìn)行對(duì)比,來說明為什么在互聯(lián)網(wǎng)項(xiàng)目為什么將隔離級(jí)別設(shè)為讀已提交(Read Commited)!

對(duì)比

ok,我們先明白一點(diǎn)!項(xiàng)目中是不用讀未提交(Read UnCommitted)和串行化(Serializable)兩個(gè)隔離級(jí)別,原因有二

  • 采用讀未提交(Read UnCommitted),一個(gè)事務(wù)讀到另一個(gè)事務(wù)未提交讀數(shù)據(jù),這個(gè)不用多說吧,從邏輯上都說不過去!
  • 采用串行化(Serializable),每個(gè)次讀操作都會(huì)加鎖,快照讀失效,一般是使用mysql自帶分布式事務(wù)功能時(shí)才使用該隔離級(jí)別!(筆者從未用過mysql自帶的這個(gè)功能,因?yàn)檫@是XA事務(wù),是強(qiáng)一致性事務(wù),性能不佳!互聯(lián)網(wǎng)的分布式方案,多采用最終一致性的事務(wù)解決方案!)

也就是說,我們?cè)摷m結(jié)都只有一個(gè)問題,究竟隔離級(jí)別是用讀已經(jīng)提交呢還是可重復(fù)讀?
接下來對(duì)這兩種級(jí)別進(jìn)行對(duì)比,講講我們?yōu)槭裁催x讀已提交(Read Commited)作為事務(wù)隔離級(jí)別!
假設(shè)表結(jié)構(gòu)如下

 CREATE TABLE `test` (
`id` int(11) NOT NULL,
`color` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB

數(shù)據(jù)如下

+----+-------+
| id | color |
+----+-------+
|  1 |  red  |
|  2 | white |
|  5 |  red  |
|  7 | white |
+----+-------+

為了便于描述,下面將

  • 可重復(fù)讀(Repeatable Read),簡稱為RR;
  • 讀已提交(Read Commited),簡稱為RC;

緣由一:在RR隔離級(jí)別下,存在間隙鎖,導(dǎo)致出現(xiàn)死鎖的幾率比RC大的多!
此時(shí)執(zhí)行語句

select * from test where id <3 for update;

在RR隔離級(jí)別下,存在間隙鎖,可以鎖住(2,5)這個(gè)間隙,防止其他事務(wù)插入數(shù)據(jù)!
而在RC隔離級(jí)別下,不存在間隙鎖,其他事務(wù)是可以插入數(shù)據(jù)!

ps:在RC隔離級(jí)別下并不是不會(huì)出現(xiàn)死鎖,只是出現(xiàn)幾率比RR低而已!

緣由二:在RR隔離級(jí)別下,條件列未命中索引會(huì)鎖表!而在RC隔離級(jí)別下,只鎖行
此時(shí)執(zhí)行語句

update test set color = 'blue' where color = 'white'; 

在RC隔離級(jí)別下,其先走聚簇索引,進(jìn)行全部掃描。加鎖如下:


但在實(shí)際中,MySQL做了優(yōu)化,在MySQL Server過濾條件,發(fā)現(xiàn)不滿足后,會(huì)調(diào)用unlock_row方法,把不滿足條件的記錄放鎖。

實(shí)際加鎖如下


然而,在RR隔離級(jí)別下,走聚簇索引,進(jìn)行全部掃描,最后會(huì)將整個(gè)表鎖上,如下所示

緣由三:在RC隔離級(jí)別下,半一致性讀(semi-consistent)特性增加了update操作的并發(fā)性!

在5.1.15的時(shí)候,innodb引入了一個(gè)概念叫做“semi-consistent”,減少了更新同一行記錄時(shí)的沖突,減少鎖等待。
所謂半一致性讀就是,一個(gè)update語句,如果讀到一行已經(jīng)加鎖的記錄,此時(shí)InnoDB返回記錄最近提交的版本,由MySQL上層判斷此版本是否滿足update的where條件。若滿足(需要更新),則MySQL會(huì)重新發(fā)起一次讀操作,此時(shí)會(huì)讀取行的最新版本(并加鎖)!
具體表現(xiàn)如下:
此時(shí)有兩個(gè)Session,Session1和Session2!
Session1執(zhí)行

update test set color = 'blue' where color = 'red'; 

先不Commit事務(wù)!
與此同時(shí)Ssession2執(zhí)行

update test set color = 'blue' where color = 'white'; 

session 2嘗試加鎖的時(shí)候,發(fā)現(xiàn)行上已經(jīng)存在鎖,InnoDB會(huì)開啟semi-consistent read,返回最新的committed版本(1,red),(2,white),(5,red),(7,white)。MySQL會(huì)重新發(fā)起一次讀操作,此時(shí)會(huì)讀取行的最新版本(并加鎖)!
而在RR隔離級(jí)別下,Session2只能等待!

兩個(gè)疑問

在RC級(jí)別下,不可重復(fù)讀問題需要解決么?
不用解決,這個(gè)問題是可以接受的!畢竟你數(shù)據(jù)都已經(jīng)提交了,讀出來本身就沒有太大問題!Oracle的默認(rèn)隔離級(jí)別就是RC,你們改過Oracle的默認(rèn)隔離級(jí)別么?

在RC級(jí)別下,主從復(fù)制用什么binlog格式?
OK,在該隔離級(jí)別下,用的binlog為row格式,是基于行的復(fù)制!Innodb的創(chuàng)始人也是建議binlog使用該格式!

總結(jié)

本文啰里八嗦了一篇文章只是為了說明一件事,互聯(lián)網(wǎng)項(xiàng)目請(qǐng)用:讀已提交(Read Commited)這個(gè)隔離級(jí)別!

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

相關(guān)文章

  • Mysql查詢表字段結(jié)構(gòu)注釋的方式

    Mysql查詢表字段結(jié)構(gòu)注釋的方式

    這篇文章主要介紹了Mysql查詢表字段結(jié)構(gòu)注釋的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Windows10下MySQL5.7.31解壓版安裝與卸載方法

    Windows10下MySQL5.7.31解壓版安裝與卸載方法

    這篇文章主要介紹了Windows10下MySQL5.7.31解壓版安裝與卸載,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-12-12
  • mysql的json處理實(shí)現(xiàn)

    mysql的json處理實(shí)現(xiàn)

    本文主要介紹了mysql的json處理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • mysql數(shù)據(jù)庫從服務(wù)器移植到個(gè)人PC的方法

    mysql數(shù)據(jù)庫從服務(wù)器移植到個(gè)人PC的方法

    有時(shí)候本地也需要數(shù)據(jù)庫進(jìn)行測(cè)試,那么就需要將服務(wù)器的東西移植到本地,如果有服務(wù)器控制權(quán)限,可以直接復(fù)制mysql的目錄(windows下),如果是別的那么就需要下面的方法了。
    2011-08-08
  • Centos7.5安裝mysql5.7.24二進(jìn)制包方式部署

    Centos7.5安裝mysql5.7.24二進(jìn)制包方式部署

    這篇文章主要介紹了Centos7.5安裝mysql5.7.24二進(jìn)制包方式部署,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-12-12
  • mysql 8.0.12 安裝配置圖文教程

    mysql 8.0.12 安裝配置圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.12 安裝配置圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • linux下mysql 5.1 和 5.7的安裝教程

    linux下mysql 5.1 和 5.7的安裝教程

    下面小編就為大家分享一篇linux下mysql 5.1 和 5.7的安裝教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • MySQL多實(shí)例的配置應(yīng)用實(shí)例場(chǎng)景

    MySQL多實(shí)例的配置應(yīng)用實(shí)例場(chǎng)景

    在一臺(tái)服務(wù)器上,運(yùn)行多個(gè)數(shù)據(jù)庫服務(wù),這些服務(wù)進(jìn)程通過不同的socket監(jiān)聽不同的服務(wù)端口來提供各自的服務(wù),這篇文章主要介紹了MySQL多實(shí)例的配置場(chǎng)景分析,需要的朋友可以參考下
    2021-12-12
  • 淺談mysql explain中key_len的計(jì)算方法

    淺談mysql explain中key_len的計(jì)算方法

    下面小編就為大家?guī)硪黄獪\談mysql explain中key_len的計(jì)算方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • Mysql數(shù)據(jù)庫的日志管理、備份與回復(fù)詳細(xì)圖文教程

    Mysql數(shù)據(jù)庫的日志管理、備份與回復(fù)詳細(xì)圖文教程

    備份的主要目的是災(zāi)難恢復(fù),備份還可以測(cè)試應(yīng)用、回滾數(shù)據(jù)修改、查詢歷史數(shù)據(jù)、審計(jì)等,這篇文章主要給大家介紹了關(guān)于Mysql數(shù)據(jù)庫的日志管理、備份與回復(fù)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08

最新評(píng)論