mysql查看版本号_十分钟了解MySQL事务机制
讀書百遍其義自現。
MySQL數據庫在我們平時工作學習中的使用頻率是相當之高,徹底掌握MySQL的事務機制對我們平時工作會有非常大的幫助,仔細回憶一下,你是否對MySQL事務相關的知識是否完全掌握?是否感覺有的地方有些模糊?通過這篇文章讓你徹底理順邏輯,下面就開始吧!
01事務的特性事務的特點
提到數據庫的事務,我們肯定脫口而出的就是ACID,但是有的時候并不清楚ACID到底是什么,掌握事務的特性對于我們接下來學習是相當重要的。
首先舉個例子,老王去銀行轉賬的例子將農業銀行的100元轉到老劉農業銀行卡,主要有以下三步
1.首先判斷老王的農業銀行的賬戶金額是否大于100元
2.老王的農業銀行的賬戶余額減去100元
3.老劉的農業銀行的賬戶余額加100元
試想一下如果其中某一步失敗就會導致非常嚴重的問題,我們需要把操作放到一個事務中去執行,如果其中有一步執行失敗,那么所有操作都將回滾,通過這種方式來保證數據一致性。
?start transaction;select balance from account where uid = 60610;update account set balance = balance - 100 where uid = 60610;update account set balance = balance + 100 where uid = 60611;commit;原子性(atomicity)
原子在化學中表示不可再進行分割的基本微粒,在事務表示的是這是一個不能再被分割的最小工作單元,整個事務的所有操作,要么全部成功,要么全部失敗回滾,而不可能僅僅執行某一部分。
一致性(consistency)
數據庫總是從一個一致性的狀態轉化到另一個一致性的狀態,老王轉賬即使第二步和第三步之間系統崩潰了,也不會出現問題,因為數據并沒有提交,沒有提交事務,所做的修改也并不會保存到數據庫中。
隔離性(isolation)
通常來說,一個事務所做的修改在最終提交前,對其他的事務是不可見的,這里為什么說“通常是不可見的”,因為這和具體的事務隔離級別有關,后面我們會進行分析。
持久性(durability)
一旦事務提交,則其他的修改就會永遠保存到數據庫中。即使系統崩潰,修改的數據也不會丟失。
02事務隔離級別事務隔離級別
所謂事務隔離級別,就是用來定義一個事務所做的修改,哪些在事務內和事務間是可見的,哪些是不可見的。較低級別的隔離通常可以執行更高的并發,系統開銷也更低 。
在MySQL中一共有四種事務隔離級別:讀未提交、讀提交、可重復讀、可串行化,下面我們將分別簡單介紹四種隔離級別。
讀未提交 read uncommitted
在此事務隔離級別下,修改數據庫中的數據,即使沒有提交,對其他事務也是可見的。事務可以讀到未被提交的數據,這種情況也被稱為臟讀,這種隔離級別下會出現很多問題,但性能也不會比read committed好太多。
讀提交 read committed
大多的數據庫的默認事務隔離都是讀提交,但是MySQL的默認事務隔離基本是可重復讀,在這種隔離級別下,只有當事務提交后,事務中的修改才會對其他事務可見,但是會出現在同一個事務中多次查詢數據結果可能不同,因為中間可能有修改數據的事務提交了,這種現象叫不可重復讀。
可重復讀 repeatable read
該級別不僅解決了臟讀,還可以在一個事務中,同一個事務多次讀取同樣的記錄結果是一樣,但是理論上,還是無法解決幻讀現象,所謂幻讀,就是在一個事務執行中,其他事務插入了新的行并且提交,就會產生幻行。但實際上MySQL通過MVCC(多版本并發控制)解決了幻讀的問題。
可串行化 serializable
該級別是最高的隔離級別,避免了前面說的幻讀的問題,顧名思義是對于同一行記錄,“寫”會加“寫鎖”,“讀”會加“讀鎖”。當出現讀寫鎖沖突的時候,后訪問的事務必須等前一個事務執行完成,才能繼續執行。實際中很少使用這個隔離級別,因為使用這個隔離級別,幾乎沒有并發可言。
各個事務級別對應的能力
03驗證事務隔離級別MySQL基礎設置
首先登錄MySQL。
查看當前數據庫
創建測試數據庫
可以看到剛剛新建的數據庫
使用剛剛創建的數據庫
創建測試表
?create table tb_user ( id bigint not null auto_increment comment "用戶id", name varchar(50) not null comment "用戶姓名", ? age int not null comment "用戶年齡", ? balance int not null comment "用戶余額",PRIMARY KEY (`id`))ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='用戶表';初始化數據
SQL數據
?insert into tb_user(name, age, balance) values('老王', 24, 100);insert into tb_user(name, age, balance) values('老劉', 25, 500);測試之前做的一些準備
MySQL中默認的是事務自動提交的,在測試我們需要控制事務提交的時機,所以我們將MySQL改為非自動提交事務,這種方式僅僅是當前session關閉自動提交。
設置全局關閉自動提交
查看自動提交事務狀態,可以看到當前session和全局的自動提交都已經關閉。
驗證讀未提交 read uncommitted
這里我們約定,每次測試完成后都將余額還原成初始值,即老王余額100元,老劉余額500元。
因為MySQL的默認事務隔離級別是可重復讀,我們先將當前session的事務隔離級別設置為讀未提交。
修改之后的事務隔離級別
下面啟動兩個事務A、B并設置它們的事務隔離級別為讀未提交。
開啟事務A和事務B
事務A查詢老王的余額(下圖應是查詢結果)
老王充值50元
事務B讀到了未提交的數據,出現了臟讀。
事務A回滾
老王賬戶減少150元,并提交事務B
此時查看老王的賬戶余額可以發現為-50,可以看出由臟讀引發的問題。
驗證讀已提交 read committed
首先我們需要把數據進行初始化,即老王余額100元,老劉余額500元。將兩個session的事務隔離級別設置為讀已提交。
讓事務A、B依次執行測試讀未提交時的邏輯,同樣的條件下,在讀已提交的情況下,事務B并沒有讀到臟數據。
接下來,我們做下一組測試,事務A和事務B按照下面的順序進行執行。
事務B查詢老劉賬戶余額為500元。
事務A向老劉賬戶充值500元并提交事務。
事務B再次查詢老劉的余額,為1000元,在同一個事務中,重復進行查詢返回的結果不同,這就是不可重復讀。
可重復讀 repeatable read
首先我們需要把數據進行初始化,即老王余額100元,老劉余額500元。將兩個session的事務隔離級別設置為可重復讀。
下面我們啟動事務A、B,重新按順序執行讀已提交的測試邏輯,通過測試我們發現,在可重復讀級別下,在同一個事務中多次查詢結果是一致的,解決了不可重復讀。
接下來,我們來看另一組測試,把數據進行初始化,即老王余額100元,老劉余額500元。
查詢當前用戶表中有幾個用戶,可以看到查詢到了兩個用戶。
在事務B中插入用戶老趙,并提交事務,此時數據中應該有三條記錄。
在事務A中查詢數據庫記錄條數,我們發現記錄數還是2,說明MySQL在repeatable read級別成功避免了幻讀,那么MySQL是如何在RR級別避免幻讀的呢?下文會進行分析。
驗證可串行化 serializable
這里沒有對可串行化 serializable隔離級別進行驗證,因為在此隔離級別會給所有的讀取行加鎖,所有事務只能串行執行。
04MVCC如何解決幻讀問題MVCC(Multiversion Concurrency Control)即多版本并發控制,大多數的數據庫都實現了MVCC,但是實現機制各不相同,并且沒有統一的標準。
以InnoDB引擎為例,對MVCC的工作流程進行講解。
在使用InnoDB引擎的表中是通過在每條記錄后面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的創建的時間,另一個保存行的刪除時間。
這里其實保存的并不是創建時間,而是系統的版本號(system version number)。每開始一個新事務,系統版本號都會自動遞增,事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到的每行記錄版本號進行比較。
下面通過在repeatable read隔離級別下,對于增刪改查MVCC是如何操作的。
SELECT查詢
InnoDB會根據兩個條件去檢查每行記錄。
1、InnoDB只查版本早于當前事務的數據行(也就是,行的創建版本號小于或者等于事務的系統版本號),這樣做是為了保證,事務讀取的行,要么是事務開始前已經存在了,要么是事務自身插入或者修改過的。
2、關于行的刪除版本,我們讀取的行,要么沒有定義,要么大于當前事務的系統版本號(這說明是事務開啟之后修改的),這樣就可以確保我們讀取到的數據,都是在事務開啟之前未刪除。
這也就解釋了為什么在可重復級別可以避免幻讀,等同于給數據庫的表和數據做了一個快照,相當于在一個視圖上進行操作,無論其他事務怎么修改數據,在當前事務提交之前,多次查詢的結果都是相同的,除此之外我們可以發現,在數據庫中同一條記錄可能存在多個版本。
INSERT插入
InnoDB為新插入的每一行保存當前事務的系統版本號,作為行的創建版本號。
DELETE刪除
InnoDB為刪除的每一行保存當前事務的系統版本號,作為行刪除標記。
UPDATE更新
InnoDB為插入一行新記錄,保存當前事務系統版本號作為行的創建版本號,同時保存當前事務的系統版本號作為行刪除標記。
關于MVCC
通過上述介紹的機制,通過兩個額外的版本號字段,使得大多數的讀操作不需要加鎖,這樣設計使得讀數據操作很簡單,性能很好,但是需要額外的存儲空間,并且需要更多的檢查和維護工作。
此外,MVCC只在REPEATABLE READ和READ COMMITTED兩個隔離級別下工作。其他兩個隔離級別和MVCC都不兼容,因為讀未提交總是讀取最新的數據行,而可串行化則會對所有行都加鎖。
05總結本文主要介紹了,MySQL的事務的特性ACID,除此還介紹了事務的各個隔離級別的特征,不同的隔離級別會出現什么樣的問題,理論上,事務的隔離級別越高消耗的資源越多,在平時的業務開發中,需要根據業務特點去選擇不同的事務隔離級別,最后我們介紹了MVCC,并說明它如何解決幻讀問題的,以及MVCC在可重復讀下,增刪改查的操作,希望讀者能夠掌握本文的內容,相信對理解MySQL的事務會有一定的幫助。
總結
以上是生活随笔為你收集整理的mysql查看版本号_十分钟了解MySQL事务机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html中表格与字对齐,html – 中
- 下一篇: ruby mysql dbi_Ruby