成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官上來就問MySQL事務,瑟瑟發抖...

原創
數據庫 MySQL
關于學習這件事情寧可花點時間系統學習,也不要東一榔頭西一棒槌,都說學習最好的方式就是系統的學習,希望看完本文會讓你對 MySQL 事物有一定的理解,數據庫版本為 8.0。

【51CTO.com原創稿件】關于學習這件事情寧可花點時間系統學習,也不要東一榔頭西一棒槌,都說學習最好的方式就是系統的學習,希望看完本文會讓你對 MySQL 事物有一定的理解,數據庫版本為 8.0。

[[389472]]

圖片來自 Pexels

什么是事物

事物是獨立的工作單元,在這個獨立工作單元中所有操作要么全部成功,要么全部失敗。

也就是說如果有任何一條語句因為崩潰或者其它原因導致執行失敗,那么未執行的語句都不會再執行,已經執行的語句會進行回滾操作,這個過程被稱之為事物。

例:最近在寫一個論壇系統,當發布的主題被其它用戶舉報后,后臺會對舉報內容進行審核。

一經審核為違規主題,則進行刪除主題的操作,但不僅僅要刪除主題還要刪除主題下的帖子、瀏覽量,關于這個主題的一切信息都需要進行清理。

刪除流程如下,用上邊概念來說,以下執行的四個流程,每個流程都必須成功否則事務回滾返回刪除失敗。

假設執行到了第三步后 SQL 執行失敗了,那么第一二步都會進行回滾,第四步則不會在執行。

事物四大特征

事物的四大特征:

  • 原子性
  • 一致性
  • 隔離性
  • 持久性

①原子性

事物中所有操作要么全部成功,要么全部失敗,不會存在一部分成功,一部分失敗。

這個概念也是事物最核心的特性,事物概念本身就是使用原子性進行定義的。

原子性的實現是基于回滾日志實現(undo log),當事物需要回滾時就會調用回滾日志進行 SQL 語句回滾操作,實現數據還原。

②一致性

一致性,字面意思就是前后一致唄!在數據庫中不管進行任何操作,都是從一個一致性轉移到另一個一致性。

當事物結束后,數據庫的完整性約束不被破壞。當你了解完事物的四大特征之后就會發現,都是保證數據一致性為最終目標存在的。

在學習事物的過程中大家看到最多的案例就是轉賬,假設用戶 A 與用戶 B 余額共計 1000,那么不管怎么轉倆人的余額自始至終也就只有 1000。

③隔離性

保證事物執行盡可能的不受其它事物影響,這個是隔離級別可以自行設置,在 innodb 中默認的隔離級別為可重復讀(Repeatable Read)。

這種隔離級別有可能造成的問題就是出現幻讀,但是使用間隙鎖可以解決幻讀問題。

學習了隔離性你需要知道原子性和持久性是針對單個事物,而隔離性是針對事物與事物之間的關系。

④持久性

持久性是指當事物提交之后,數據的狀態就是永久的,不會因為系統崩潰而丟失。事物持久性是基于重做日志(redo log)實現的。

事物并發會出現的問題

①臟讀

讀取了另一個事物沒有提交的數據。

以上表為例,事物 A 讀取主題訪問量時讀取到了事物B沒有提交的數據 150。

如果事物 B 失敗進行回滾,那么修改后的值還是會回到 100。然而事物 A 獲取的數據是修改后的數據,這就有問題了。

②不可重復讀

事物讀取同一個數據,返回結果先后不一致問題。 

上表格中,事物 A 在先后獲取主題訪問量時,返回的數據不一致。也就是說在事物 A 執行的過程中,訪問量被其它事物修改,那么事物 A 查詢到的結果就是不可靠的。

臟讀與不可重復讀的區別:臟讀讀取的是另一個事物沒有提交的數據,而不可重復讀讀取的是另一個事物已經提交的數據。

③幻讀

事物按照范圍查詢,倆次返回結果不同。

以上表為例,當對 100-200 訪問量的主題做統計時,第一次找到了 100 個,第二次找到了 101 個。

④區別

臟讀讀取的是另一個事物沒有提交的數據,而不可重復讀讀取的是另一個事物已經提交的數據。

幻讀和不可重復讀都是讀取了另一條已經提交的事務(這點與臟讀不同),所不同的是不可重復讀查詢的都是同一個數據項,而幻讀針對的是一批數據整體(比如數據的個數)。

針對以上的三個問題,產生了四種隔離級別。在第二節中對隔離性進行了簡單的概念解釋,實際上的隔離性是很復雜的。

在 MySQL 中定義了四種隔離級別,分別為:

  • 未提交讀 (Read Uncommitted):倆個事物同時運行,有一個事物修改了數據,但未提交,另一個事物是可以讀取到沒有提交的數據。這種情況被稱之為臟讀。
  • 提交讀(Read committed):一個事物在未提交之前,所做的任何操作其它事物不可見。這種隔離級別也被稱之為不可重復讀。因為會存在倆次同樣的查詢,返回的數據可能會得到不一樣的結果。
  • 可重復讀(Repeatable Read):這種隔離級別解決了臟讀問題,但是還是存在幻讀問題,這種隔離界別在 MySQL 的 innodb 引擎中是默認級別。MySQL 在解決幻讀問題使用間隙鎖來解決幻讀問題。
  • 可串行化 (Serializable):這種級別是最高的,強制事物進行串行執行,解決了可重復讀的幻讀問題。

對于隔離級別,級別越高并發就越低,而級別越低會引發臟讀、不可重復讀、幻讀的問題。

因此在 MySQL 中使用可重復讀(Repeatable Read)作為默認級別。

作為默認級別是如何解決并處理相應問題的呢?那么針對這一問題,是一個難啃的骨頭,我將在下一期 MVCC 文章專門來介紹這塊。

事物日志以及事物異常如何應對

在 Innodb 中事物的日志分為倆種,回滾日志、重做日志。

先來看一下倆個日志的存放位置吧!MySQL 的版本號為 8.0。

在 Linux 下的 MySQL 事物日志存放在 /var/lib/mysql 這個位置中:

從上圖中可以看到分別為 ib_logfile、undo_ 倆個文件:

  • ib_logfile 文件為重做日志
  • undo_ 文件為回滾日志

在這里估計有點小伙伴會有點迷糊這個回滾日志。那是因為在 MySQL 5.6 默認回滾日志沒有進行獨立表空間存儲,而是存放到了 ibdata 文件中。

獨立表空間存儲從 MySQL 5.6 后就已經支持了,但是需要自行配置。

在 MySQL 8.0 是由 innodb_undo_tablespaces 這個參數來設置回滾日志獨立空間個數,這個參數的范圍為 0-128。

默認值為 0 表示不開啟獨立的回滾日志,且回滾日志存儲在 ibdata 文件中。

這個參數是在初始化數據庫時指定的,實例一旦創建這個參數是不能改動的。

如果設置的 innodb_undo_tablespaces 值大于實例創建時的個數,則會啟動失敗。

①重做日志(redo log)(持久性實現原理)

事物的持久性就是通過重做日志來實現的。

當提交事物之后,并不是直接修改數據庫的數據的,而是先保證將相關的操作記錄到 redo 日志中。

數據庫會根據相應的機制將內存的中的臟頁數據刷新到磁盤中。

上圖是一個簡單的重做日志寫入流程。

在上圖中提到倆個陌生概念,Buffer pool、redo log buffer,這個倆個都是 Innodb 存儲引擎的內存區域的一部分。

而 redo log file 是位于磁盤位置。也就說當有 DML(insert、update、delete)操作時,數據會先寫入 Buffer pool,然后在寫到重做日志緩沖區。

重做日志緩沖區會根據刷盤機制來進行寫入重做日志中。

這個機制的設置參數為 innodb_flush_log_at_trx_commit,參數分別為 0,1,2。

上圖即為重做日志的寫入策略:

  • 當這個參數的值為 0 的時,提交事務之后,會把數據存放到 redo log buffer 中,然后每秒將數據寫進磁盤文件。
  • 當這個參數的值為 1 的時,提交事務之后,就必須把 redo log buffer 從內存刷入到磁盤文件里去,只要事務提交成功,那么 redo log 就必然在磁盤里了。
  • 當這個參數的值為 2 的情況,提交事務之后,把 redo log buffer 日志寫入磁盤文件對應的 os cache 緩存里去,而不是直接進入磁盤文件,1 秒后才會把 os cache 里的數據寫入到磁盤文件里去。

②服務器異常停止對事物如何應對(事物寫入過程)

事物寫入過程如下:

  • 當參數為 0 時,前一秒的日志都保存在日志緩沖區,也就是內存上,如果機器宕掉,可能丟失 1 秒的事務數據。
  • 當參數為 1 時,數據庫對 IO 的要求就非常高了,如果底層的硬件提供的 IOPS 比較差,那么 MySQL 數據庫的并發很快就會由于硬件 IO 的問題而無法提升。
  • 當參數為 2 時,數據是直接寫進了 os cache 緩存,這部分屬于操作系統部分,如果操作系統部分損壞或者斷電的情況會丟失 1 秒內的事物數據,這種策略相對于第一種就安全了很多,并且對 IO 要求也沒有那么高。

小結:

  • 關于性能:0>2>1
  • 關于安全:1>2>0

根據以上結論,所以說在 MySQL 數據庫中,刷盤策略默認值為 1,保證事物提交之后,數據絕對不會丟失。

③回滾日志(undo log)(原子性實現原理)

回滾日志保證了事物的原子性。回滾日志相對重做日志來說沒有那么復雜的流程。

當事物對數據庫進行修改時,Innodb 引擎不僅會記錄 redo log 日志,還會記錄 undo log 日志。

如果事物失敗,或者執行了 rollback,為了保證事物的原子性,就必須利用 undo log 日志來進行回滾操作。

回滾日志的存儲形式如下:在 undo log 日志文件,事物中使用的每條 insert 都對應了一條 delete,每條 update 也都對應一條相反的 update 語句。

注意:系統發生宕機或者數據庫進程直接被殺死。當用戶再次啟動數據庫進程時,還能夠立刻通過查詢回滾日志將之前未完成的事物進程回滾。

這也就需要回滾日志必須先于數據持久化到磁盤上,是需要先寫日志后寫數據庫的主要原因。回滾日志不僅僅可以保證事物的原子性,還是實現 mvcc 的重要因素。

以上就是關于事物的倆大日志,重做日志、回滾日志的理解。

鎖機制

鎖在 MySQL 中是是非常重要的一部分,鎖對 MySQL 數據訪問并發有著舉足輕重的作用。

所以說鎖的內容以及細節是十分繁瑣的,本節只是對 Innodb 鎖的一個大概整理。

MySQL中有三類鎖,分別為行鎖、表鎖、頁鎖。首先需要明確的是這三類鎖是是歸屬于那種存儲引擎的:

  • 行鎖:Innodb 存儲引擎
  • 表鎖:Myisam、MEMORY 存儲引擎
  • 頁鎖:BDB 存儲引擎

①行鎖

行鎖又分為共享鎖、排它鎖,也被稱之為讀鎖、寫鎖,Innodb 存儲引擎的默認鎖。

共享鎖(S):假設一個事物對數據 A 加了共享鎖(S),則這個事物只能讀 A 的數據。

其他事物只能再對數據 A 添加共享鎖(S),而不能添加排它鎖(X),直到這個事物釋放了數據 A 的共享鎖(S)。

這就保證了其他事物也可以讀取 A 的數據,但是在這個事物沒有釋放在 A 數據上的共享鎖(S)之前不能對 A 做任何修改。

排它鎖(X):假設一個事物對數據 A 添加了排它鎖(X),則只允許這個事物讀取和修改數據 A。

其他任何事物都不能在對數據A添加任何類型的鎖,直至這個事物釋放了數據 A 上的鎖。

排它鎖阻止其它事物獲取相同數據的共享鎖(S)、排它鎖(X),直至釋放排它鎖(X)。

特點如下:

  • 只針對單一數據進行加鎖
  • 開銷大
  • 加鎖慢
  • 會出現死鎖
  • 鎖粒度最小,發生鎖沖突的概率越低并發越高

還記得在上文中提到的事物并發帶來的問題、臟讀、不可重讀讀、幻讀。

學習到了這里,應該就明白可重復讀(Repeatable Read)如何解決臟讀、不可重讀讀了。

臟讀、和不可重復讀的解決方案很簡單,寫前加排它鎖(X),事務結束才釋放,讀前加共享鎖(S),事務結束就釋放。

②表鎖

表鎖又分為表共享讀鎖、表獨占寫鎖,也被稱之為讀鎖、寫鎖,Myisam 存儲引擎的默認鎖。

表共享讀鎖:針對同一個份數據,可以同時讀取互不影響,但不允許寫操作。

表獨占寫鎖:當寫操作沒有結束時,會阻塞所有讀和寫。

特點如下:

  • 對整張表加鎖
  • 開銷小
  • 加鎖快
  • 無死鎖
  • 鎖粒度最大,發生鎖沖突的概率越大,并發越小

本文主要說明 Innodb 和 Myisam 的鎖,頁鎖不就不做詳細說明了。

③如何加鎖

表鎖:

  • 隱式加鎖:默認自動加鎖釋放鎖,select 加讀鎖、update、insert、delete 加寫鎖。
  • 手動加鎖:lock table tableName read;(添加讀鎖)、lock table tableName write(添加寫鎖)。
  • 手動解鎖:unlock table tableName(釋放單表)、unlock table(釋放所有表)。

行鎖:

  • 隱式加鎖:默認自動加鎖釋放鎖,只有 select 不會加鎖,update、insert、delete 加排它鎖。
  • 手動加共享鎖:select id name from user lock in share mode。
  • 手動加排它鎖:select id name form user for update。
  • 解鎖:正常提交事物(commit)、事物回滾(rollback)、kill 進程。

總結

本文主要對事物的重點知識點進行解讀,內容總結。

事物四大特征實現原理:

  • 原子性:使用事物日志的回滾日志(undo log)實現
  • 隔離性:使用 mvcc 實現(幻讀問題除外)
  • 持久性:使用事物日志的重做日志(redo log)實現
  • 一致性:是事物追求的最終目標,原子性、隔離性、持久性都是為了保證數據庫一致性而存在

事物并發出現問題的區別:

  • 臟讀與不可重復讀的區別:臟讀是讀取沒有提交事物的數據、不可重復讀讀取的是已提交事物的數據。
  • 幻讀與不可重復讀的區別:都是讀取的已提交事物的數據(與臟讀不同),幻讀針對的是一批數據,例如個數。不可重復讀針對的是單一數據。

事物日志:

  • 重做日志(redo log):實現了事物的持久性,提交事物后不是直接修改數據庫,而是保證每次事物操作讀寫入 redo log 中。并且落盤會有三種策略(詳細看四-1節)。
  • 回滾日志(undo log):實現了事物的原子性,針對 DML 的操作,都會有記錄相反的 DML 操作。

作者:咔咔

編輯:陶家龍

征稿:有投稿、尋求報道意向技術人請添加小編微信 gordonlonglong

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

 

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2021-04-06 06:07:37

ZAB 協議原子廣播協議網絡協議

2021-09-16 07:55:39

Kafka事務執行

2020-12-18 08:40:44

Chrome瀏覽器渲染

2021-01-11 07:48:59

CTO團隊職場

2022-07-03 06:26:53

JetBrains插件

2020-09-18 10:00:33

iOS蘋果瀏覽器

2020-11-23 10:06:00

互聯網數據技術

2021-01-06 08:34:21

Spring核心組件

2019-10-23 09:50:53

微信支付寶

2019-07-15 14:13:58

人工智能職業被取代

2021-05-02 23:13:35

人工智能自動化人臉識別

2019-05-13 09:23:50

GitHub代碼開發者

2021-12-08 23:30:14

互聯網裁員危機

2017-11-07 11:49:23

工信部套餐運營商

2022-11-24 15:05:51

谷歌碼農

2025-04-07 03:00:00

Dreamer世界模型

2022-04-22 15:28:22

算法MIT數據

2021-06-03 08:55:54

分布式事務ACID

2025-06-17 08:35:00

2021-09-08 08:06:57

Redis原子性數據類型
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩欧美国产一区二区三区 | 成人免费看黄网站在线观看 | 亚洲午夜视频在线观看 | 欧美久久久网站 | 国产精品污污视频 | 久久精品亚洲一区 | 欧美成人影院 | 黄色一级免费 | 精品国产91久久久久久 | 欧美一区在线视频 | 91精品国产一区二区 | 国产成人综合网 | 日韩av免费看| 欧美v在线观看 | 免费一级欧美在线观看视频 | 精品欧美一区二区三区久久久小说 | 亚欧性视频 | 日日草夜夜草 | 欧美日韩a| 欧美 日韩 中文 | 一区二区小视频 | 91亚洲精品在线观看 | 在线一区 | 亚洲精品一区二区三区中文字幕 | 亚洲网在线 | 草久久久 | 中文字幕免费在线 | 亚洲九色 | 国产精品视频久久久久 | 成人1区| 成人影院在线观看 | 黑色丝袜三级在线播放 | 国产极品车模吞精高潮呻吟 | 就操在线| 亚洲欧美日韩在线一区二区 | 成人综合视频在线观看 | 欧美一级黄色免费看 | av电影一区二区 | 亚洲欧美一区二区三区视频 | av在线一区二区 | 狠狠av |