MySQL 事务的面试题总结
事務(wù)是什么?
事務(wù)是一系列的數(shù)據(jù)庫操作,是數(shù)據(jù)庫應(yīng)用的基本單位。MySQL 事務(wù)主要用于處理操作量大,復(fù)雜度高的數(shù)據(jù)。
事務(wù)有哪些特性?
在 MySQL 中只有 InnDB 引擎支持事務(wù),它的四個特性如下:
- 原子性(Atomic):要么全部執(zhí)行,要么全部不執(zhí)行;
- 一致性(Consistency):事務(wù)的執(zhí)行使得數(shù)據(jù)庫從一種正確狀態(tài)轉(zhuǎn)化為另一種正確狀態(tài);
- 隔離性(Isolation):在事務(wù)正確提交之前,不允許把該事務(wù)對數(shù)據(jù)的任何改變提供給其他事務(wù);
- 持久性(Durability):事務(wù)提交后,其結(jié)果永久保存在數(shù)據(jù)庫中。
MySQL 中有幾種事務(wù)隔離級別?分別是什么?
MySQL 中有四種事務(wù)隔離級別,它們分別是:
- read uncommited:未提交讀,讀到未提交數(shù)據(jù);
- read committed:讀已提交,也叫不可重復(fù)讀,兩次讀取到的數(shù)據(jù)不一致;
- repetable read:可重復(fù)讀;
- serializable:串行化,讀寫數(shù)據(jù)都會鎖住整張表,數(shù)據(jù)操作不會出錯,但并發(fā)性能極低,開發(fā)中很少用到。
MySQL 默認(rèn)使用 REPEATABLE-READ 的事務(wù)隔離級別。
幻讀和不可重復(fù)讀的區(qū)別?
- 不可重復(fù)讀的重點是修改:在同一事務(wù)中,同樣的條件,第一次讀的數(shù)據(jù)和第二次讀的數(shù)據(jù)不一樣。(因為中間有其他事務(wù)提交了修改)。
- 幻讀的重點在于新增或者刪除:在同一事務(wù)中,同樣的條件,,第一次和第二次讀出來的記錄數(shù)不一樣。(因為中間有其他事務(wù)提交了插入/刪除)。
并發(fā)事務(wù)一般有哪些問題?
更新丟失(Lost Update):當(dāng)兩個或多個事務(wù)選擇同一行,然后基于最初選定的值更新該行時,由于每個事務(wù)都不知道其他事務(wù)的存在,就會發(fā)生丟失更新問題,最后的更新覆蓋了由其他事務(wù)所做的更新。例如,兩個編輯人員制作了同一文檔的電子副本,每個編輯人員獨立地更改其副本,然后保存更改后的副本,這樣就覆蓋了原始文檔。 最后保存其更改副本的編輯人員覆蓋另一個編輯人員所做的更改,如果在前一個編輯人員完成并提交事務(wù)之前,另一個編輯人員不能訪問同一文件,則可避免此問題。
臟讀(Dirty Reads):一個事務(wù)正在對一條記錄做修改,在這個事務(wù)完成并提交前, 這條記錄的數(shù)據(jù)就處于不一致狀態(tài); 這時, 另一個事務(wù)也來讀取同一條記錄,如果不加控制,第二個事務(wù)讀取了這些臟數(shù)據(jù),并據(jù)此做進(jìn)一步的處理,就會產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系,這種現(xiàn)象被形象地叫做臟讀。
不可重復(fù)讀(Non-Repeatable Reads):一個事務(wù)在讀取某些數(shù)據(jù)后的某個時間,再次讀取以前讀過的數(shù)據(jù),卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變、或某些記錄已經(jīng)被刪除了!這種現(xiàn)象就叫做“不可重復(fù)讀” 。
幻讀(Phantom Reads): 一個事務(wù)按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為“幻讀” 。
并發(fā)事務(wù)有什么什么問題?應(yīng)該如何解決?
并發(fā)事務(wù)可能造成:臟讀、不可重復(fù)讀和幻讀等問題 ,這些問題其實都是數(shù)據(jù)庫讀一致性問題,必須由數(shù)據(jù)庫提供一定的事務(wù)隔離機(jī)制來解決,解決方案如下:
- 加鎖:在讀取數(shù)據(jù)前,對其加鎖,阻止其他事務(wù)對數(shù)據(jù)進(jìn)行修改。
- 提供數(shù)據(jù)多版本并發(fā)控制(MultiVersion Concurrency Control,簡稱 MVCC 或 MCC),也稱為多版本數(shù)據(jù)庫:不用加任何鎖, 通過一定機(jī)制生成一個數(shù)據(jù)請求時間點的一致性數(shù)據(jù)快照(Snapshot), 并用這個快照來提供一定級別 (語句級或事務(wù)級) 的一致性讀取,從用戶的角度來看,好象是數(shù)據(jù)庫可以提供同一數(shù)據(jù)的多個版本。
什么是 MVCC?
MVCC 全稱是多版本并發(fā)控制系統(tǒng),InnoDB 和 Falcon 存儲引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機(jī)制解決幻讀問題。
MVCC 是怎么工作的?
InnoDB 的 MVCC 是通過在每行記錄后面保存兩個隱藏的列來實現(xiàn),這兩個列一個保存了行的創(chuàng)建時間,一個保存行的過期時間(刪除時間)。當(dāng)然存儲的并不是真實的時間而是系統(tǒng)版本號(system version number)。每開始一個新的事務(wù),系統(tǒng)版本號都會自動新增,事務(wù)開始時刻的系統(tǒng)版本號會作為事務(wù)的版本號,用來查詢到每行記錄的版本號進(jìn)行比較。
REPEATABLE READ(可重讀)隔離級別下 MVCC 如何工作?
- SELECT:InnoDB 會根據(jù)以下條件檢查每一行記錄:第一,InnoDB 只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行,這樣可以確保事務(wù)讀取的行要么是在開始事務(wù)之前已經(jīng)存在要么是事務(wù)自身插入或者修改過的。第二,行的刪除版本號要么未定義,要么大于當(dāng)前事務(wù)版本號,這樣可以確保事務(wù)讀取到的行在事務(wù)開始之前未被刪除。
- INSERT:InnoDB 為新插入的每一行保存當(dāng)前系統(tǒng)版本號作為行版本號。
- DELETE:InnoDB 為刪除的每一行保存當(dāng)前系統(tǒng)版本號作為行刪除標(biāo)識。
- UPDATE:InnoDB 為插入的一行新紀(jì)錄保存當(dāng)前系統(tǒng)版本號作為行版本號,同時保存當(dāng)前系統(tǒng)版本號到原來的行作為刪除標(biāo)識保存這兩個版本號,使大多數(shù)操作都不用加鎖。它不足之處是每行記錄都需要額外的存儲空間,需要做更多的行檢查工作和一些額外的維護(hù)工作。
MySQL 事務(wù)實現(xiàn)原理是什么?
事務(wù)的實現(xiàn)是基于數(shù)據(jù)庫的存儲引擎,不同的存儲引擎對事務(wù)的支持程度不一樣。MySQL 中支持事務(wù)的存儲引擎有InnoDB 和 NDB。 InnoDB 是高版本 MySQL 的默認(rèn)的存儲引擎,因此就以 InnoDB 的事務(wù)實現(xiàn)為例,InnoDB 是通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control )解決不可重復(fù)讀問題,加上間隙鎖(也就是并發(fā)控制)解決幻讀問題。因此 InnoDB 的 RR 隔離級別其實實現(xiàn)了串行化級別的效果,而且保留了比較好的并發(fā)性能。事務(wù)的隔離性是通過鎖實現(xiàn),而事務(wù)的原子性、一致性和持久性則是通過事務(wù)日志實現(xiàn)。
如何設(shè)置 MySQL 的事務(wù)隔離級別?
MySQL 事務(wù)隔離級別 MySQL.cnf 文件里設(shè)置的(默認(rèn)目錄 /etc/my.cnf),在文件的文末添加配置:
transaction-isolation = REPEATABLE-READ
可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。
InnoDB 默認(rèn)的事務(wù)隔離級別是什么?如何修改?
InnoDB 默認(rèn)的事務(wù)隔離是 repetable read(可重復(fù)讀);可以通過 set 作用域 transaction isolation level 事務(wù)隔離級別 來修改事務(wù)的隔離級別,比如:
MySQL> set global transaction isolation level read committed; // 設(shè)置全局事務(wù)隔離級別為 read committed
MySQL> set session transaction isolation level read committed; // 設(shè)置當(dāng)前會話事務(wù)隔離級別為 read committed
InnoDB 如何開啟手動提交事務(wù)?
InnoDB 默認(rèn)是自動提交事務(wù)的,每一次 SQL 操作(非 select 操作)都會自動提交一個事務(wù),如果要手動開啟事務(wù)需要設(shè)置 set autocommit=0 禁止自動提交事務(wù),相當(dāng)于開啟手動提交事務(wù)。
在 InnoDB 中設(shè)置了 autocommit=0,添加一條信息之后沒有手動執(zhí)行提交操作,請問這條信息可以被查到嗎?
autocommit=0 表示禁止自動事務(wù)提交,在添加操作之后沒有進(jìn)行手動提交,默認(rèn)情況下其他連接客戶端是查詢不到此條新增數(shù)據(jù)的。
如何手動操作事務(wù)?
使用 begin 開啟事務(wù);rollback 回滾事務(wù);commit 提交事務(wù)。具體使用示例如下:
begin; insert person(uname,age) values('laowang',18); rollback; commit;限時福利
加入作者群,與大佬面對面交流,同時還能獲得最新面試經(jīng)驗。 趕緊添加小助手「xiangcode」,發(fā)送暗號「6000」即可
總結(jié)
以上是生活随笔為你收集整理的MySQL 事务的面试题总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中的一些坑,汇总篇(2万字)
- 下一篇: 忘记MySQL密码怎么办?一招教你搞定!