之前,我們有講過數據庫的索引,鏈接爲 數據庫索引詳解 今天,我們將講解數據庫的隔離級別。
一、隔離級別的種類與分別可以解決的問題:
事務的隔離級別分爲4個,即 讀未提交(read uncommitted)、讀已提交(read committed)、可重複讀(Repeatable read)、可串行化(Serializable)
oracle默認的隔離級別爲 讀已提交。mysql的默認隔離級別爲 可重複讀。
其中可以解決的問題如下表:
簡單來說:
髒讀即爲session A讀取到了session B中未提交的數據
不可重複讀即爲session A讀取到了session B提交的數據,即前後session A讀取的數據不一致
幻讀即爲session A讀取到了session B insert的數據。
二、隔離級別的設置與查詢:
1、設置隔離級別:
設置隔離級別分爲設置全局的隔離級別與設置當前的隔離級別
全局設置,已存在的session不會生效,以後的新session會生效(以讀未提交舉例):
set global transaction isolation level read uncommitted;
單獨設置當前連接:
set session transaction isolation level read uncommitted;
2 、查看當前隔離級別:
select @tx_isolation;
三、事務隔離級別的測試:
有一個goods表,裏面有id、count(商品數量)、brandId(品牌id)
CREATE TABLE `goods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`count` int(11) DEFAULT '0',
`brandId` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_brandId` (`brandId`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf-8;
1、髒讀(設置隔離級別爲讀未提交):
髒讀爲讀到其它事務未提交的數據:
A | B |
select * from goods where id = 1; 返回1 |
|
update goods set count = 2 where id = 1; | |
select * from goods where id = 1; 返回2 |
|
commit; |
2、不可重複讀(設置隔離級別爲 讀已提交)
不可重複讀爲讀到其它數據已提交的數據,即前後查詢數據不一致
A | B |
select * from goods where id = 1; 返回1 |
|
update goods set count = 2 where id = 1; | |
select * from goods where id = 1; 返回1 |
|
commit; | |
select * from goods where id = 1; 返回2 |
3、幻讀(設置隔離級別爲 可重複讀):
幻讀爲讀到別人已提交的寫入數據庫的數據。
幻讀與不可重複讀的區別爲幻讀爲讀到新插入的數據(insert),而不可重複讀主要是更改與刪除(update、delete)。
即不可重複讀前後被其它session update、delete的數據沒有問題,不會有變化,但是其它session insert的可能有變化。
A | B |
select * from goods where brandId = 1; 返回有id爲1,2的兩條 |
|
insert into goods (count,brandId) values (3, 1); | |
commit; | |
select * from goods where brandId = 1; 返回有id爲1,2,3的三條 |
當隔離級別爲 可串行化 的時候則不會出現上述問題。