事務(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 默認使用 REPEATABLE-READ 的事務(wù)隔離級別钦听。
幻讀和不可重復(fù)讀的區(qū)別?
- 不可重復(fù)讀的重點是修改:在同一事務(wù)中倍奢,同樣的條件彪见,第一次讀的數(shù)據(jù)和第二次讀的數(shù)據(jù)不一樣。(因為中間有其他事務(wù)提交了修改)娱挨。
- 幻讀的重點在于新增或者刪除:在同一事務(wù)中,同樣的條件,捕犬,第一次和第二次讀出來的記錄數(shù)不一樣跷坝。(因為中間有其他事務(wù)提交了插入/刪除)。
并發(fā)事務(wù)一般有哪些問題碉碉?
更新丟失(Lost Update):當兩個或多個事務(wù)選擇同一行柴钻,然后基于最初選定的值更新該行時,由于每個事務(wù)都不知道其他事務(wù)的存在垢粮,就會發(fā)生丟失更新問題贴届,最后的更新覆蓋了由其他事務(wù)所做的更新。例如蜡吧,兩個編輯人員制作了同一文檔的電子副本毫蚓,每個編輯人員獨立地更改其副本,然后保存更改后的副本昔善,這樣就覆蓋了原始文檔元潘。 最后保存其更改副本的編輯人員覆蓋另一個編輯人員所做的更改,如果在前一個編輯人員完成并提交事務(wù)之前君仆,另一個編輯人員不能訪問同一文件翩概,則可避免此問題。
臟讀(Dirty Reads):一個事務(wù)正在對一條記錄做修改返咱,在這個事務(wù)完成并提交前钥庇, 這條記錄的數(shù)據(jù)就處于不一致狀態(tài); 這時咖摹, 另一個事務(wù)也來讀取同一條記錄评姨,如果不加控制,第二個事務(wù)讀取了這些臟數(shù)據(jù)楞艾,并據(jù)此做進一步的處理参咙,就會產(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ù)隔離機制來解決妥箕,解決方案如下:
- 加鎖:在讀取數(shù)據(jù)前,對其加鎖更舞,阻止其他事務(wù)對數(shù)據(jù)進行修改畦幢。
- 提供數(shù)據(jù)多版本并發(fā)控制(MultiVersion Concurrency Control,簡稱 MVCC 或 MCC)缆蝉,也稱為多版本數(shù)據(jù)庫:不用加任何鎖宇葱, 通過一定機制生成一個數(shù)據(jù)請求時間點的一致性數(shù)據(jù)快照(Snapshot), 并用這個快照來提供一定級別 (語句級或事務(wù)級) 的一致性讀取刊头,從用戶的角度來看黍瞧,好象是數(shù)據(jù)庫可以提供同一數(shù)據(jù)的多個版本。
什么是 MVCC芽偏?
MVCC 全稱是多版本并發(fā)控制系統(tǒng)雷逆,InnoDB 和 Falcon 存儲引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency
Control)機制解決幻讀問題污尉。
MVCC 是怎么工作的膀哲?
InnoDB 的 MVCC
是通過在每行記錄后面保存兩個隱藏的列來實現(xiàn),這兩個列一個保存了行的創(chuàng)建時間被碗,一個保存行的過期時間(刪除時間)某宪。當然存儲的并不是真實的時間而是系統(tǒng)版本號(system
version number)。每開始一個新的事務(wù)锐朴,系統(tǒng)版本號都會自動新增兴喂,事務(wù)開始時刻的系統(tǒng)版本號會作為事務(wù)的版本號,用來查詢到每行記錄的版本號進行比較焚志。
REPEATABLE READ(可重讀)隔離級別下 MVCC 如何工作衣迷?
- SELECT:InnoDB 會根據(jù)以下條件檢查每一行記錄:第一,InnoDB 只查找版本早于當前事務(wù)版本的數(shù)據(jù)行酱酬,這樣可以確保事務(wù)讀取的行要么是在開始事務(wù)之前已經(jīng)存在要么是事務(wù)自身插入或者修改過的壶谒。第二,行的刪除版本號要么未定義膳沽,要么大于當前事務(wù)版本號汗菜,這樣可以確保事務(wù)讀取到的行在事務(wù)開始之前未被刪除让禀。
- INSERT:InnoDB 為新插入的每一行保存當前系統(tǒng)版本號作為行版本號。
- DELETE:InnoDB 為刪除的每一行保存當前系統(tǒng)版本號作為行刪除標識陨界。
- UPDATE:InnoDB 為插入的一行新紀錄保存當前系統(tǒng)版本號作為行版本號巡揍,同時保存當前系統(tǒng)版本號到原來的行作為刪除標識保存這兩個版本號,使大多數(shù)操作都不用加鎖菌瘪。它不足之處是每行記錄都需要額外的存儲空間腮敌,需要做更多的行檢查工作和一些額外的維護工作。
MySQL 事務(wù)實現(xiàn)原理是什么俏扩?
事務(wù)的實現(xiàn)是基于數(shù)據(jù)庫的存儲引擎缀皱,不同的存儲引擎對事務(wù)的支持程度不一樣。MySQL 中支持事務(wù)的存儲引擎有InnoDB 和 NDB动猬。 InnoDB 是高版本
MySQL 的默認的存儲引擎,因此就以 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è)置的(默認目錄 /etc/my.cnf)盯桦,在文件的文末添加配置:
transaction-isolation = REPEATABLE-READ
可用的配置值:READ-UNCOMMITTED、READ-COMMITTED渤刃、REPEATABLE-READ拥峦、SERIALIZABLE。
InnoDB 默認的事務(wù)隔離級別是什么卖子?如何修改略号?
InnoDB 默認的事務(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è)置當前會話事務(wù)隔離級別為 read committed
InnoDB 如何開啟手動提交事務(wù)玄柠?
InnoDB 默認是自動提交事務(wù)的,每一次 SQL 操作(非 select 操作)都會自動提交一個事務(wù)诫舅,如果要手動開啟事務(wù)需要設(shè)置 set autocommit=0
禁止自動提交事務(wù)羽利,相當于開啟手動提交事務(wù)。
在 InnoDB 中設(shè)置了 autocommit=0骚勘,添加一條信息之后沒有手動執(zhí)行提交操作铐伴,請問這條信息可以被查到嗎撮奏?
autocommit=0 表示禁止自動事務(wù)提交,在添加操作之后沒有進行手動提交当宴,默認情況下其他連接客戶端是查詢不到此條新增數(shù)據(jù)的畜吊。
如何手動操作事務(wù)?
使用 begin 開啟事務(wù)户矢;rollback 回滾事務(wù)玲献;commit 提交事務(wù)。具體使用示例如下:
begin;
insert person(uname,age) values('laowang',18);
rollback;
commit;