mysql与缓存脏读_MySQL 事务的隔离级别问题 之 脏读
1. 臟讀
所謂的臟讀就是指一個事務(wù)讀取了另一個事務(wù)未提取的數(shù)據(jù)。
試想一下:a賬戶要給b賬戶100元購買商品,如果a賬戶開啟一個事務(wù),執(zhí)行下面的update語句做了如下轉(zhuǎn)賬的工作:
update account set money=money-100 where name='a';
update account set money=money+100 where name='b';
如果a賬戶先不提交事務(wù),通知b賬戶來查詢,由于b的隔離級別比較低,此時就會讀取a事務(wù)中未提交的數(shù)據(jù),發(fā)現(xiàn)a確實給自己轉(zhuǎn)了100元,然后給a發(fā)貨,等b發(fā)貨成功之后,a再將事務(wù)回滾,此時b就會受到損傷,這就是臟讀造成的。
為了演示上面的情況,這里我們開啟了兩個命令行窗口(相當于開啟兩個線程),分別模擬a賬戶和b賬戶,如下:
(1)設(shè)置b賬戶中事務(wù)的隔離級別
大家都知道MySQL的默認隔離級別是Repeatable Read(可重復(fù)讀),該級別是可以避免臟讀的,因此需要將b賬戶中事務(wù)的隔離級別設(shè)置為Read Uncommitted(讀未提交),具體語句如下:
set session transaction isolation level read uncommitted;
如下:
上述語句之中,session表示當前會話,transaction就表示事務(wù),isolation表示隔離,level表示級別,read uncommitted表示當前的隔離級別,該語句執(zhí)行成功之后,使用select語句查詢事務(wù)的隔離級別,結(jié)果如下:
select @@tx_isolation;
如下:
從上述結(jié)果可以看出,b賬戶的事務(wù)隔離級別以及修改為Read Uncommitted,接下來就是演示臟讀的情況
2)演示臟讀
b賬戶:為了證明出現(xiàn)了臟讀的情況,首先在b賬戶中開戶一個事務(wù),并在該事務(wù)中查詢當前賬戶的余額信息,查詢結(jié)果如下:
start transaction;
select * from account;
如下:
a賬戶:在a賬戶中開啟一個事務(wù),并在當前窗口中執(zhí)行轉(zhuǎn)賬功能,具體語句如下:
start transaction;
update account set money=money-100 where name='a';
update account set money=money+100 where name='b';
如下:
需要注意的是:此時不要提交事務(wù),如果提交事務(wù)就無法演示出現(xiàn)臟讀的情況。
b賬戶:a賬戶執(zhí)行完轉(zhuǎn)賬語句后,b賬戶查詢當前賬戶,如下:
從上面的查詢結(jié)果來看,a賬戶已經(jīng)成功給b賬戶轉(zhuǎn)賬了100元,這是由于b賬戶的事務(wù)隔離級別比較低,因此才讀取了a賬戶還沒有提交的數(shù)據(jù)內(nèi)容,出現(xiàn)了臟讀的情況,這時候,b誤以為a賬戶以及轉(zhuǎn)賬成功,便會給a發(fā)貨,當b發(fā)貨之后a如果不提交事務(wù)將事務(wù)回滾,b就會受到損失。
上面演示完畢了,需要將a賬戶中的事務(wù)回滾,b賬戶中的事務(wù)提交。
(3)設(shè)置b賬戶的事務(wù)隔離級別
為了防止臟讀發(fā)生,可以將b賬戶中的事務(wù)隔離級別設(shè)置為Read Committed(讀提交),該級別會避免臟讀,具體語句如下:
set session transaction isolation level read committed;
上述的語句執(zhí)行成功之后,b賬戶的隔離級別已經(jīng)設(shè)置成Read Committed
(4)驗證是否出現(xiàn)臟讀
b賬戶:為了說明沒有出現(xiàn)臟讀的情況,首先要在b賬戶中開啟一個事務(wù),并在該事務(wù)中查詢各賬戶的余額情況,查詢結(jié)果如下:
a賬戶:在a賬戶中重新開啟一個事務(wù),實現(xiàn)了轉(zhuǎn)賬功能,如下:
start transaction;
update account set money=money-100 where name='a';
update account set money=money+100 where name='b';
b賬戶:當a 賬戶轉(zhuǎn)賬成功之后,可以在b賬戶中再次查詢各賬戶的余額信息,查詢結(jié)果如下:
通過上面的對比兩次查詢結(jié)果可以發(fā)現(xiàn),b賬戶在同一個事務(wù)中的查詢結(jié)果是一致的,并沒有查詢到a賬戶中未提交的內(nèi)容,因此可以說明Read Committed 隔離級別可以避免臟讀,最后分別將a賬戶和b賬戶中的事務(wù)回滾.
總結(jié)
以上是生活随笔為你收集整理的mysql与缓存脏读_MySQL 事务的隔离级别问题 之 脏读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 提高性能的 容器库_容器隔离性
- 下一篇: oschina mysql limit_