ACID規則簡單理解

關係型數據庫遵循ACID規則

TRANSACTION(事務)

事務在英文中是transaction,和現實世界中的交易很類似,它有如下四個特性:

1、A (Atomicity) 原子性

原子性很容易理解,也就是說事務裏的所有操作要麼全部做完,要麼都不做,事務成功的條件是事務裏的所有操作都成功,只要有一個操作失敗,整個事務就失敗,需要回滾。

比如銀行轉賬,從A賬戶轉100元至B賬戶,分爲兩個步驟:1)從A賬戶取100元;2)存入100元至B賬戶。這兩步要麼一起完成,要麼一起不完成,如果只完成第一步,第二步失敗,錢會莫名其妙少了100元。

2、C (Consistency) 一致性

一致性也比較容易理解,也就是說數據庫要一直處於一致的狀態,事務的運行不會改變數據庫原本的一致性約束。

例如現有完整性約束a+b=10,如果一個事務改變了a,那麼必須得改變b,使得事務結束後依然滿足a+b=10,否則事務失敗。

3、I (Isolation) 獨立性

所謂的獨立性是指併發的事務之間不會互相影響,如果一個事務要訪問的數據正在被另外一個事務修改,只要另外一個事務未提交,它所訪問的數據就不受未提交事務的影響。

比如現在有個交易是從A賬戶轉100元至B賬戶,在這個交易還未完成的情況下,如果此時B查詢自己的賬戶,是看不到新增加的100元的。

4、D (Durability) 持久性

持久性是指一旦事務提交後,它所做的修改將會永久的保存在數據庫上,即使出現宕機也不會丟失。

RDBMS隔離級別設置

數據庫
set [session | global ] transaction_isolation level 設置事務隔離級別
select @@transaction_isolation 查詢當前事務隔離級別

mysql8 以上更改了原來的事務隔離級別字段 以前老版本是 tx_isolation

如果你的版本比較老 就可以改成 tx_isolation 執行就可以了。

設置 描述
Serializable 可避免髒讀、不可重複讀、虛讀情況的發生。(串行化)
Repeatable read 可避免髒讀、不可重複讀情況的發生。(可重複讀)
Read committed 可避免髒讀情況發生(讀已提交)。
Read uncommitted 最低級別,以上情況均無法保證。(讀未提交)

三種不考慮隔離出現的問題:

  • 1.髒讀

    髒讀的意思就是在你進行一個事務的同時,讀取到了另一個事務未提交的數據

    Example:

    好比別人在銀行轉賬,錯轉了一筆1個億的金額到你的賬戶裏面,最後收回去了:

    模擬一下sql:

    update account set money = money + 1000000000 where name = ‘yourname’;

    update account set money = money - 1000000000 where name = ‘others’;

    這兩條sql是一個事務,此時別人操作完成 但是並沒有提交事務(並沒有確定)。


    而你恰好這個時候去查了一下你的賬戶餘額:

    select money from accout where name = ‘yourname’;

    這是一個同時的事務,發現你的賬戶多出了100000000這麼多錢 你很開心,奔走相告,炒了老闆魷魚,

    然後,別人賬戶發現轉錯了,開始了回滾,rollback。

    然後你的錢就沒有了。 等過兩天你再去查的時候發現錢沒了,你很傷心,哭着打電話給老闆求他讓你回去上班。

  • 2.不可重複讀

    不可重複讀是指在對於數據庫中的某個數據,一個事務範圍內多次查詢卻返回了不同的數據值,這是由於在查詢間隔,被另一個事務修改並提交了。

    例如事務1在讀取某一數據,而事務2突然修改了這個數據並且把事務提交了,事務1這時需要再次讀取該數據,然後得到了不同的結果,這就是不可重複讀。

    不可重複讀和髒讀的區別是,髒讀是某一事務讀取了另一個事務未提交的髒數據,而不可重複讀則是讀取了前一事務提交的數據。

    這裏主要是指“update”數據,導致前後讀取的數據不一致。 跟幻讀需要區分開(後面解釋幻讀)

    Example:

    你和小明有一個數據庫,專門用來記錄你倆一起吃飯的日子。

    某一天你們同時想知道上個星期你們什麼時候一起吃的飯,然後先後去查了數據庫:

    你先查:

    事務1 part1:

    select day_of_week from date_time where time = ‘20200427’;

    你獲得的結果是"Wednesday" 此時事務還未結束 小明還要查。


    事務2:

    然後此時柯南中的小黑悄悄登錄了你們的數據庫,修改了這條記錄,改成了"Monday";

    update date_time set day_of_week = ‘Monday’ where time = ‘20200427’;

    commit

    並且提交了該事務,動作十分迅速,只用了零點幾秒。


    事務1 part2:

    然後小明的查詢語句纔開始作用:

    select day_of_week from date_time where time = ‘20200427’;

    他得到的結果就是"Monday" 然後他說你查的不對,你又說他查的不對。 然後你們倆互相指責對方根本不在乎對方,扭打在一起,最後不歡而散,形同陌路,好可惜。

  • 3.幻讀

    所謂幻讀,指的是當某個事務在讀取某個範圍內的記錄時,另外一個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會產生幻行。

    但是在可重複讀的隔離級別上,會產生幻讀的問題。

    Example:

    小明和他老婆相敬如賓,十分恩愛。

    這天小明想給自己的老婆買一個好看的包包,是CHANEL的,買之前,他特意查了下自己老婆的存儲寶寶信息的數據庫:

    事務1 part1:

    select count(*) from bag_infor where bag_name = ‘channel’;

    結果是0,雖然老婆有20個包包了,但他知道自己從來沒有給老婆買過chanel的包包,很慚愧,於是他馬上就下單購買。


    事務2:

    小明老婆在外面有情人,叫隔壁老王,隔壁老王也幾乎同時給小明老婆買了個chanel的包包,於是:

    insert into bag_info(bag_id, bag_name, worth) values(21, “channel”, “1000000”);

    commit;

    小明老婆就有了第一個包包。 她也很開心,想到小明從來沒給自己買過 她覺得心裏很不是滋味


    事務1 part2:

    然後小明買的包包也到了,就往裏面插入自己買的包包:

    insert into bag_info(bag_id, bag_name, worth) values(21, “channel”, “10000”);

    然後就報錯了,主鍵重複,插入失敗!

    select count(*) from bag_infor where bag_name = ‘channel’;

    他又查詢,結果發現還是沒有記錄呀。

    小明百思不得其解 自己買的包包還沒有插入啊 咋會突然裏面有了一個chanel包包呢。

    小明一直被矇在鼓裏 好慘

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章