1. 什麼是ACID
- 原子性(Atomicity): 事務是最小的執行單位,不容許分隔。事務的原子性確保動做要麼所有完成,要麼徹底不起做用
- 一致性(Consistency): 執行事務先後,數據保持一致,多個事務對同一個數據讀取的結果是相同的
- 隔離性(Isolation): 併發訪問數據庫時,一個用戶的事務不被其餘事務所幹擾,個併發事務之間數據庫是獨立的
- 持久性(Durability): 一個事務被提交以後,它對數據庫中數據的改變是持久的,即便數據庫發生故障也不該該對其有任何影響
2. 併發形成的問題
2.1. 髒讀
場景:兩個操做同時到達數據庫,操做A爲查詢數據X的age;操做B爲更新數據X的age面試
徹底符合ACID的狀況下:數據庫
這種狀況下,操做A和操做B的事務是串行化的,要麼先執行操做A,要麼先執行操做B,事務沒有交叉,一切正常。markdown
併發狀況下:併發
當操做B的事務對數據X進行了修改,但事務尚未提交的同時,操做A開始查詢數據X,獲得查詢結果後,操做B的事務完成了提交。此時,事務A查詢的數據是過期的,這種狀況就叫作髒讀。ui
2.2. 丟失修改
場景: 操做A和操做B同時查詢{id=1,age=20}的數據X,並對age進行+1操做spa
徹底符合ACID的狀況下:code
- 第一步:操做A的事務查詢到數據X.age=20,進行更新X.age = age + 1 = 21,事務結束。
- 第二步:操做A的事務結束後,啓動操做B的事務,查詢到數據X.age=21,進行更新X.age = age + 1 = 22,事務結束。
- 最終結果,X.age=22
併發狀況下:orm
- 操做A的事務查詢X.age=20,進行更新X.age = age + 1 = 21,此時事務尚未提交;
- 操做B在事務A沒有提交的狀況下,查詢X.age=20,進行更新X.age = age + 1 = 21,提交事務X.age=21
- 操做A的事務提交,X.age=21
- 最終結果X.age=21
後提交的事務將先提交的事務覆蓋,這種狀況就是丟失修改。事務
2.3. 不可重複讀
場景:操做A同一次事務內執行兩次uid=1的用戶年齡,原始數據age=18;操做B更新uid=1的age=20ci
徹底符合ACID的狀況下:
- 操做A的事務內,連續執行兩次查詢,此時其它事務不容許開始,因此在此事務內無論查詢多少次uid=1的age都爲18,事務提交後
- 此時事務A提交,啓動操做B事務,更新uid=1的age=20,提交事務。
- 操做A查詢到的age=18是固定的,爲正常結果
併發狀況下:
- 操做A事務內,第一次查詢age=18,此時操做B併發執行
- 操做B更新age=20,在操做A事務未進行第二次查詢時,操做B事務提交
- 操做A此時進行事務內的第二次查詢,age=20
- 同一個事務內兩次查詢結果不一樣,這種狀況叫不可重複讀
2.4. 幻讀
場景:操做A同一個事務內兩次查詢age < 20的全部用戶,好比爲20條信息;操做B新增條用戶信息,且用戶age < 20
徹底符合ACID的狀況下:
- 操做A事務未提交前,其它事務不容許執行,因此此操做內的每次查詢都爲20條結果
- 操做A事務提交後,操做B執行
- 兩次操做事務串行,操做結果正常
併發狀況下:
- 操做A事務開啓,第一次查詢結果爲20條
- 在操做A未進行第二次查詢時,操做B事務開啓,插入一條用戶age<20的數據,提交事務
- 操做A進行第二次查詢,結果爲21條
- 此時,兩次查詢結果的數量不一致,好像出現了幻覺。咱們把這種屢次查詢數據增多或減小的狀況稱爲幻讀
2.5. 髒讀和不可重複的區別
這兩種狀況十分相似,能夠這樣理解:
- 髒讀: 在一次事務內,只進行一次查詢,查詢時數據發生了改變,此事務不知道它查詢的數據已經發生了變化,這種叫髒讀
- 不可重複讀: 在一次事務內,進行屢次查詢的過程當中,此事務知道查詢的數據有變化,這種叫不可重複讀
主要區別就在因而一次查詢,仍是屢次查詢。
3. MySQL的隔離級別
- READ-UNCOMMITTED(讀取未提交): 最低隔離級別,容許讀取還沒有提交的數據變動,可能會致使髒讀、幻讀、不可重複讀。
- READ-COMMITTED(讀取已提交): 容許讀取併發事務已提交的數據,能夠阻止髒讀,可是幻讀、不可重複讀仍有可能發生
- 兩個事務,其中一個事務沒有提交的話,另外一個事務是沒辦法讀取的,因此能夠避免髒讀
- 兩個事務,事務A中,第一次讀取多條信息時,事務B尚未提交;事務B提交後,事務A進行了第二次查詢,可能會查詢到事務B提交的數據;若是事務B是插入操做,則是幻讀;若是事務B是更新操做,則是不可重複讀
- REPEATABLE-READ(可重複讀): 對同一個字段屢次讀取結果都是一致的,除非數據是被自己事務本身所修改,能夠阻止髒讀和不可重複讀,但幻讀仍可能發生
- 兩個事務,事務A中,第一次查詢到多條數據,事務B能夠是插入或更新;若是事務B是更新,因爲數據不是被自己事務修改的,因此不會有髒讀和不可重複讀;若是事務B是插入,仍會被事務A查詢到,形成幻讀
- SERIALIZABLE(可串行化): 最高的隔離級別,徹底服從ACID的隔離級別。全部事務串行化依次執行,事務之間徹底不可能產生干擾,該級別能夠防止髒讀、不可重複讀和幻讀。
MySQL InnoDB 存儲引擎的默認⽀持的隔離級別是 REPEATABLE-READ(可重複讀)
4. 最後
面試官: 請講一下MySQL的事務
