關(guān)于設(shè)計圖的網(wǎng)站天津seo排名扣費(fèi)
目錄
1.為什么要有隔離性
2.事務(wù)的隔離級別
讀未提交
讀提交
可重復(fù)讀
串行化
3.演示事務(wù)隔離級別的操作
查看與設(shè)置事務(wù)的隔離級別
演示讀提交操作
演示可重復(fù)讀操作
1.為什么要有隔離性
? ? ? ? 在真正的業(yè)務(wù)場景下,MySQL服務(wù)在同一時間一定會有大量的客戶端進(jìn)程并發(fā)的去訪問同一個MySQL服務(wù),而且一定會同一時間有多個客戶端訪問和操作同一張表。而且我們在業(yè)務(wù)層面,一個事務(wù)很多情況下都需要多條SQL語句組成,那么這樣的話,操作雖然是原子性的,但是過程卻可以明顯的分成執(zhí)行前、執(zhí)行中以及執(zhí)行后三個階段。
????????那么在執(zhí)行中的階段,一個客戶端在執(zhí)行事務(wù)操作數(shù)據(jù)庫表,但是事務(wù)還沒有完成提交,其其他客戶端如果查看到該客戶端沒有提交的數(shù)據(jù),會不會有問題呢?如果客戶端查看了另一個客戶端沒有提交的數(shù)據(jù),但是另一個客戶端最后執(zhí)行了回滾操作,那么該客戶端查看的數(shù)據(jù)就不是真實(shí)的數(shù)據(jù)了,出現(xiàn)了數(shù)據(jù)的二義性。
? ? ? ? 所以說為了保證數(shù)據(jù)庫在執(zhí)行事務(wù)操作過程中盡量不受到干擾,就有了一個重要的特性就是隔離性。但是也并非客戶端在執(zhí)行事務(wù)的時候,不能讓其他客戶端查看自己沒有提交的數(shù)據(jù),在一些更關(guān)注數(shù)據(jù)的實(shí)時性的業(yè)務(wù)操作中,就能夠接受短暫的數(shù)據(jù)不一致問題。
2.事務(wù)的隔離級別
? ? ? ? 事務(wù)的隔離級別分為讀未提交、讀提交、可重復(fù)讀、串行化,不同的隔離界別可以讓蛇舞收到不同程度的干擾,可以用于不同的業(yè)務(wù)場景。對于隔離級別的實(shí)現(xiàn)基本上都是通過鎖實(shí)現(xiàn)了,因?yàn)槎嗫蛻舳嗽L問也相當(dāng)于是多線程的并發(fā)訪問,所以說還是要用鎖。對于不同的隔離級別,鎖的使用是不同的,常見的有表鎖、行鎖、讀鎖、寫鎖等等。
? ? ? ? 對于事務(wù)的隔離級別是相對于自己而言的,如果說一個客戶端A是讀未提交,客戶端B是讀提交,那么客戶端B想要提取客戶端A在事務(wù)中操作的結(jié)果就需要在客戶端A提交之后才可以看得到。
讀未提交
? ? ? ? 該隔離級別屬于是最低的隔離界別,相當(dāng)于沒隔離一樣,所有的事物都可以看到其他事物沒有提交的執(zhí)行結(jié)果,這種隔離界別在實(shí)際的業(yè)務(wù)中基本上是不會使用的。會有很多的并發(fā)問題,例如臟讀、幻讀、不可重復(fù)讀等問題。
臟讀 | 一個事務(wù)讀取到了另一個事務(wù)未提交的操作結(jié)果就是臟讀。由于未提交的事務(wù)數(shù)據(jù)可能回因?yàn)槭聞?wù)的回滾而改變,所以讀到的數(shù)據(jù)可能回出問題。 |
幻讀 | 在一個事務(wù)內(nèi),按照某個條件進(jìn)行數(shù)據(jù)查詢的時候,第一次查詢和第二次查詢的結(jié)果集不同??赡苁且?yàn)槠渌聞?wù)在這個期間對數(shù)據(jù)進(jìn)行了操作。 |
不可重復(fù)讀 | 在一個事務(wù)內(nèi),對于同一個數(shù)據(jù)的多次讀取結(jié)果不一致叫做不可重復(fù)讀??赡芤?yàn)樵谠撌聞?wù)執(zhí)行期間,其他事務(wù)對這個數(shù)據(jù)進(jìn)行了修改等操作,導(dǎo)致了讀取數(shù)據(jù)的變化,造成了該問題。 |
? ? ? ? 臟讀更加聚焦于數(shù)據(jù)的插入和刪除操作,兩次查看的數(shù)據(jù)量不一樣,而不可重復(fù)讀更聚焦于數(shù)據(jù)的修改和刪除的操作,兩次查看的數(shù)據(jù)量可能一樣,但是里面的數(shù)據(jù)不一樣。
讀提交
? ? ? ? 該隔離級別是大多數(shù)數(shù)據(jù)庫的默認(rèn)隔離級別(但不是MySQL的),也是普遍理解上最合適的一個隔離級別。該隔離級別規(guī)定了,一個事務(wù)只能看到其他的已經(jīng)提交的事務(wù)所改變的數(shù)據(jù)操作。這種級別的隔離就不會產(chǎn)數(shù)據(jù)的臟讀問題了。因?yàn)橹荒茏x取到提交之后的存放在磁盤當(dāng)中的永久化數(shù)據(jù)。但是還是會有不同重復(fù)讀取的問題,因?yàn)槎啻尾榭幢頂?shù)據(jù)的時候,在此其他其他事務(wù)可能回修改表并提交事務(wù)。
可重復(fù)讀
? ? ? ? 這是MySQL的默認(rèn)隔離級別,他確保同一個事務(wù),在執(zhí)行的過程中多次讀取操作數(shù)據(jù)的時候,回看到同樣的數(shù)據(jù)行。使得數(shù)據(jù)不會出現(xiàn)臟讀、不可重復(fù)讀取的問題,但是會有幻讀的問題。
串行化
? ? ? ? 串行化是數(shù)據(jù)庫事務(wù)隔離級別中最高的級別。在串行化隔離級別下,事務(wù)的執(zhí)行是順序的,一個事務(wù)必須等待前一個事務(wù)完成(提交或者回滾)之后才能開始執(zhí)行,在等待過程中就會放入等待隊(duì)列。就好像多個事務(wù)是在一條單行道上排隊(duì)依次通過一樣,完全避免了并發(fā)事務(wù)之間的相互干擾。他會在每個讀的數(shù)據(jù)行上面加上共享鎖,但是加鎖就會有鎖的競爭問題,會大大降低效率。這種級別不會有任何的事務(wù)之間相互影響的問題了。
3.演示事務(wù)隔離級別的操作
查看與設(shè)置事務(wù)的隔離級別
? ? ? ? 事務(wù)隔離級別的設(shè)置分為全局的和會話級別的設(shè)置,如果設(shè)置會話級別的話,就相當(dāng)于是對于一個客戶端連接的設(shè)置,關(guān)閉之后再重啟還是會重制事務(wù)的隔離級別,會按照全局的事務(wù)隔離界別來定義。
? ? ? ? 對于設(shè)置會話級別的事務(wù)隔離性不需要重啟服務(wù)器,但是設(shè)置全局級別話需要重啟,因?yàn)槭聞?wù)的隔離級別是受會話影響的,客戶端啟動的會話隔離級別是從全局隔離級別復(fù)制過來的,所以說全局隔離級別決定了客戶端啟動的時候的事務(wù)隔離級別,但是事務(wù)在操作的時候,是看會話的事務(wù)隔離級別的。
查看語法:SELECT @@[SESSION | GLOBAL].TRANSACTION_ISOLATION;
設(shè)置語法:SELECT [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
演示讀提交操作
//客戶但A————————————————————————————————————————————————————————
//設(shè)置會話隔離級別為讀提交
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)//開啟事務(wù)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)//插入與提交事務(wù)
mysql> insert into account values(1, '張三', 100), (2, '李四', 200);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> commit;
Query OK, 0 rows affected (0.01 sec)//客戶但B————————————————————————————————————————————————————————
//設(shè)置會話隔離級別為讀提交
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)//開啟事務(wù)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)//在客戶端A提交之前查看表數(shù)據(jù)
mysql> select * from account;
Empty set (0.00 sec)//在客戶端A提交之后查看表數(shù)據(jù)
mysql> select * from account;
+----+--------+--------+
| id | name | blance |
+----+--------+--------+
| 1 | 張三 | 100.00 |
| 2 | 李四 | 200.00 |
+----+--------+--------+
2 rows in set (0.00 sec)//提交數(shù)據(jù)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
? ? ? ? 該操作,客戶端B在事務(wù)期間,兩次查看表數(shù)據(jù)的數(shù)據(jù)不一樣,這就是不可重復(fù)讀。
演示可重復(fù)讀操作
//客戶但A————————————————————————————————————————————————————————
//設(shè)置會話隔離級別為可重復(fù)讀
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)//開啟事務(wù),插入數(shù)據(jù),提交事務(wù)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into account values(3, '王五', 300);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)//客戶但B————————————————————————————————————————————————————————
//設(shè)置會話隔離級別為可重復(fù)讀
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)//開啟事務(wù)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
//客戶端A提交之前
mysql> select * from account;
+----+--------+--------+
| id | name | blance |
+----+--------+--------+
| 1 | 張三 | 100.00 |
| 2 | 李四 | 200.00 |
+----+--------+--------+
2 rows in set (0.00 sec)//客戶端A提交之后
mysql> select * from account;
+----+--------+--------+
| id | name | blance |
+----+--------+--------+
| 1 | 張三 | 100.00 |
| 2 | 李四 | 200.00 |
+----+--------+--------+
2 rows in set (0.00 sec)//提交事務(wù)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)//自己提交事務(wù)之后查看表數(shù)據(jù)
mysql> select * from account;
+----+--------+--------+
| id | name | blance |
+----+--------+--------+
| 1 | 張三 | 100.00 |
| 2 | 李四 | 200.00 |
| 3 | 王五 | 300.00 |
+----+--------+--------+
3 rows in set (0.00 sec)