真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

mariadb事務(wù)隔離級(jí)別相關(guān)實(shí)驗(yàn)

  • 關(guān)于SQL的隔離級(jí)別

    成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)的關(guān)注點(diǎn)不是能為您做些什么網(wǎng)站,而是怎么做網(wǎng)站,有沒有做好網(wǎng)站,給成都創(chuàng)新互聯(lián)公司一個(gè)展示的機(jī)會(huì)來(lái)證明自己,這并不會(huì)花費(fèi)您太多時(shí)間,或許會(huì)給您帶來(lái)新的靈感和驚喜。面向用戶友好,注重用戶體驗(yàn),一切以用戶為中心。

SQL標(biāo)準(zhǔn)定義了4類隔離級(jí)別,如下所示:
1. Read Uncommitted (讀取未提交內(nèi)容)
在該隔離級(jí)別,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果。本隔離級(jí)別很少用于實(shí)際應(yīng)用,因?yàn)樗男阅芤膊槐绕渌?jí)別好多少。讀取未提交的數(shù)據(jù),也被稱之為臟讀(Dirty Read)
 
2. Read Committed (讀取提交內(nèi)容)
這是大多數(shù)數(shù)據(jù)庫(kù)系統(tǒng)的默認(rèn)隔離級(jí)別(但不是MySQL默認(rèn)的)。它滿足了隔離的簡(jiǎn)單定義:一個(gè)事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變。這種隔離級(jí)別 也支持所謂的不可重復(fù)讀(Nonrepeatable Read),因?yàn)橥皇聞?wù)的其他實(shí)例在該實(shí)例處理其間可能會(huì)有新的commit,所以同一select可能返回不同結(jié)果。
 
3. Repeatable Read (可重復(fù)讀)
這是MySQL的默認(rèn)事務(wù)隔離級(jí)別,它確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù)據(jù)行。不過(guò)理論上,這會(huì)導(dǎo)致另一個(gè)棘手的問題:幻讀 (Phantom Read)。簡(jiǎn)單的說(shuō),幻讀指當(dāng)用戶讀取某一范圍的數(shù)據(jù)行時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)插入了新行,當(dāng)用戶再讀取該范圍的數(shù)據(jù)行時(shí),會(huì)發(fā)現(xiàn)有新的“幻影” 行。InnoDB和Falcon存儲(chǔ)引擎通過(guò)多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機(jī)制解決了該問題。
 
4. Serializable (可串行化)
這是最高的隔離級(jí)別,它通過(guò)強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決幻讀問題。簡(jiǎn)言之,它是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖。在這個(gè)級(jí)別,可能導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競(jìng)爭(zhēng)。

在Mariadb中,這4種隔離級(jí)別有可能產(chǎn)生的問題如下圖所示:

mariadb事務(wù)隔離級(jí)別相關(guān)實(shí)驗(yàn)


  • 相關(guān)實(shí)驗(yàn) 
    下面分別針對(duì)不同的隔離狀態(tài)進(jìn)行測(cè)試:
    準(zhǔn)備的環(huán)境如下所示:
    在Mariadb服務(wù)器端,創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)名為hldb,創(chuàng)建一個(gè)INNODB引擎的數(shù)據(jù)表名為test,并提前插入兩條數(shù)據(jù)

準(zhǔn)備兩個(gè)MySQL客戶端線程,連接到服務(wù)器上面:

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               5 |
+-----------------+


MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               6 |
+-----------------+

 
1. Read uncommitted(讀未提交) 
首先將兩個(gè)客戶端的隔離級(jí)別分別都設(shè)置為Read uncommitted模式:

MariaDB [hldb]> select connection_id();                       
+-----------------+
| connection_id() |
+-----------------+
|               5 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> set @@session.tx_isolation='read-uncommitted';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select @@session.tx_isolation;                  
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED       |
+------------------------+
1 row in set (0.00 sec)

......
......

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               6 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> set @@session.tx_isolation='read-uncommitted';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED       |
+------------------------+
1 row in set (0.00 sec)

第一步,在再在id=6的客戶端上面(以后簡(jiǎn)稱為id6)上面完成一次查詢。第二步,在兩個(gè)客戶端上面同時(shí)打開start transaction。第三步,兩個(gè)客戶端都打開了start transaction之后,再在id=5的客戶端上面(以后簡(jiǎn)稱為id5)上面插入一條數(shù)據(jù)。第四步,在id5自身的會(huì)話上面再用select進(jìn)行查詢。第五步,在id6會(huì)話上面用select進(jìn)行查詢。

在id5上面看到的結(jié)果如下:

MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               5 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
+----+------+
2 rows in set (0.00 sec)

MariaDB [hldb]> insert into test(nm) values('c');
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
+----+------+
3 rows in set (0.00 sec)

在id6上面看到的結(jié)果如下:

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
+----+------+
2 rows in set (0.00 sec)

MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               6 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
+----+------+
3 rows in set (0.00 sec)

結(jié)論: 
可以看到,如果事務(wù)級(jí)別設(shè)定成為Read Uncommitted(讀未提交),在id5的事務(wù)并未提交的狀態(tài)下,id6的事務(wù)是可以將其未提交的事務(wù)查詢到的。這種能夠讀取到未提交事務(wù)的現(xiàn)象,稱為臟讀


2. Read Committed (讀取提交內(nèi)容) 
將兩個(gè)客戶端的事務(wù)隔離級(jí)別均設(shè)定為Read Committed,并且查詢一下test數(shù)據(jù)表里面的內(nèi)容

MariaDB [hldb]> set @@session.tx_isolation='read-committed';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               5 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
+----+------+
3 rows in set (0.00 sec)

......
......

MariaDB [hldb]> set @@session.tx_isolation='read-committed';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               6 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
+----+------+
3 rows in set (0.00 sec)

第一步,在兩個(gè)客戶端上面開啟start transaction。第二步,在id5上面添加一條記錄,同時(shí)在id5, id6上面查詢。第三步,在id5上面刪除一條記錄,同時(shí)在id5, id6上面查詢。第四步,在id5上面提交事務(wù),并且在id5, id6上面查詢。

在id5客戶端上面的操作結(jié)果如下所示:

第一步:
MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

第二步:
MariaDB [hldb]> insert into test(nm) values('d');
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
| 23 | d    |
+----+------+
4 rows in set (0.00 sec)

第三步:
MariaDB [hldb]> delete from test where nm='b';
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 22 | c    |
| 23 | d    |
+----+------+
3 rows in set (0.00 sec)

第四步:
MariaDB [hldb]> commit;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 22 | c    |
| 23 | d    |
+----+------+
3 rows in set (0.00 sec)

在id6客戶端上面的操作如下所示:

第一步:
MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

第二步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
+----+------+
3 rows in set (0.00 sec)

第三步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 21 | b    |
| 22 | c    |
+----+------+
3 rows in set (0.00 sec)

第四步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 22 | c    |
| 23 | d    |
+----+------+
3 rows in set (0.01 sec)

結(jié)論: 
Read Committed(讀取提交內(nèi)容)的隔離級(jí)別下,解決了臟讀現(xiàn)象,但是帶來(lái)了另外一種現(xiàn)象:不可重復(fù)讀。id5事務(wù)提交的前后,id6在同一個(gè)事務(wù)中,所查詢到的內(nèi)容不一致。


3. Repeatable Read(可重復(fù)讀) 
首先將兩個(gè)客戶端的事務(wù)隔離級(jí)別都設(shè)置為Repeatable Read,并查詢test數(shù)據(jù)表里面的內(nèi)容:

MariaDB [hldb]> set @@session.tx_isolation='repeatable-read';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               5 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

......
......
MariaDB [hldb]> set @@session.tx_isolation='repeatable-read';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               6 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第一步,在兩個(gè)客戶端上面開啟start transaction。第二步,在id5上面添加一條記錄,同時(shí)在id5, id6上面查詢。第三步,在id5上面刪除一條記錄,同時(shí)在id5, id6上面查詢。第四步,在id5上面提交事務(wù),并且在id5, id6上面查詢。第五步,在id6上面提交事務(wù),并且在id6上面查詢。

在id5客戶端上面的操作結(jié)果如下所示:

第一步:
MariaDB [hldb]> start transaction;               
Query OK, 0 rows affected (0.00 sec)

第二步:
MariaDB [hldb]> insert into test(nm) values('b');  
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
| 25 | b    |
+----+------+
2 rows in set (0.00 sec)

第三步:
MariaDB [hldb]> delete from test where id=1;
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
| 25 | b    |
+----+------+
1 row in set (0.00 sec)

第四步:
MariaDB [hldb]> commit;
Query OK, 0 rows affected (0.01 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
| 25 | b    |
+----+------+
1 row in set (0.00 sec)

在id6上面的操作結(jié)果如下所示:

第一步:
MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

第二步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第三步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.01 sec)

第四步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第五步:
MariaDB [hldb]> commit;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
| 25 | b    |
+----+------+
1 row in set (0.00 sec)

結(jié)論: 
由上述實(shí)驗(yàn)可以看出,事務(wù)隔離級(jí)別Repeatable read(可重復(fù)讀)Read Committed(已提交讀)的不同之處在于,在同一事務(wù)環(huán)境下,前后兩次讀取的內(nèi)容是一致的,而不受其他事務(wù)是否提交的影響。 
注: 
Repeatable read(可重復(fù)讀)的條件下,有可能會(huì)出現(xiàn)Phantom Read(幻讀)現(xiàn)象。該現(xiàn)象可以通過(guò)模擬update來(lái)實(shí)現(xiàn): 
第一步,客戶端兩邊都開啟start transaction。第二步,在id6上面新增一個(gè)字段,并在id5和id6上面分別查詢。第三步,在id6上面提交,并在id5和id6上面分別查詢。第四步,在id5上面對(duì)所有行的nm字段進(jìn)行更新,并在id5和id6上面分別查詢。 
id6上面的結(jié)果如下所示:

第一步:
MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第二步:
MariaDB [hldb]> insert into test(nm) values('b');
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

第三步:
MariaDB [hldb]> commit;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

在id5上面的操作如下所示:

第一步:
MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第二步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第三步:
MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)

第四步:
MariaDB [hldb]> update test set nm='c';
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
|  1 | c    |
|  2 | c    |
+----+------+
2 rows in set (0.00 sec)

可以看到,通過(guò)更新命令,在未結(jié)束的事務(wù)里面竟然也讀到了“新的數(shù)據(jù)”,這便是一種Phantom Read(幻讀)


4. Serializable(可序列化) 
首先將兩個(gè)客戶端的事務(wù)隔離級(jí)別都設(shè)置為Serializable,并查詢test數(shù)據(jù)表里面的內(nèi)容:

MariaDB [hldb]> set @@session.tx_isolation='serializable';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               5 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
| 26 | a    |
| 27 | b    |
+----+------+
2 rows in set (0.00 sec)

......
......


MariaDB [hldb]> set @@session.tx_isolation='serializable';
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               6 |
+-----------------+
1 row in set (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
| 26 | a    |
| 27 | b    |
+----+------+
2 rows in set (0.00 sec)

第一步,在兩個(gè)客戶端上面開啟start transaction。第二步,在id5上面添加一條記錄,同時(shí)在id5, id6上查詢

在id5上面查詢的結(jié)果如下:

MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> insert into test(nm) values('c');
Query OK, 1 row affected (0.00 sec)

MariaDB [hldb]> select * from test;
+----+------+
| id | nm   |
+----+------+
| 26 | a    |
| 27 | b    |
| 28 | c    |
+----+------+
3 rows in set (0.00 sec)

在id6上面查詢的結(jié)果如下:

MariaDB [hldb]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [hldb]> select * from test;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

由上述結(jié)果可以看到,在id5未提交事務(wù)之前,即使是select查詢操作,在其他事務(wù)里面也是不允許執(zhí)行的,只有等待id5提交事務(wù)之后,其他事務(wù)才可以進(jìn)行更新或者修改的操作。


網(wǎng)站題目:mariadb事務(wù)隔離級(jí)別相關(guān)實(shí)驗(yàn)
URL鏈接:http://weahome.cn/article/pojjdp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部