前言
MySQL 事務(wù)主要用于處理操作量大,復(fù)雜度高的數(shù)據(jù)。比如說(shuō),在人員管理系統(tǒng)中, 要?jiǎng)h除一個(gè)人員,即需要?jiǎng)h除人員的基本資料,又需要?jiǎng)h除和該人員相關(guān)的信息,如信箱, 文章等等。這樣,這些數(shù)據(jù)庫(kù)操作語(yǔ)句就構(gòu)成一個(gè)事務(wù)!
一、事物的概念
-
事務(wù)是一種機(jī)制、一個(gè)操作序列,包含了一組數(shù)據(jù)庫(kù)操作命令,并且把所有的命令作為一個(gè)整體一起向系統(tǒng)提交或撤銷(xiāo)操作請(qǐng)求,即這一組數(shù)據(jù)庫(kù)命令要么都執(zhí)行,要么都不執(zhí)行。
-
事務(wù)是一個(gè)不可分割的工作邏輯單元,在數(shù)據(jù)庫(kù)系統(tǒng)上執(zhí)行并發(fā)操作時(shí),事務(wù)是最小的控制單元。
-
事務(wù)適用于多用戶(hù)同時(shí)操作的數(shù)據(jù)庫(kù)系統(tǒng)的場(chǎng)景,如銀行、保險(xiǎn)公司及證券交易系統(tǒng)等等。
-
事務(wù)是通過(guò)事務(wù)的整體性以保證數(shù)據(jù)的一致性。
說(shuō)白了,所謂事務(wù),它是一個(gè)操作序列,這些操作要么都執(zhí)行,要么都不執(zhí)行,它是一個(gè)不可分割的工作單位。
二、事務(wù)的ACID特點(diǎn)
ACID,是指在可靠數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS)中,事務(wù)(transaction)應(yīng)該具有的四個(gè)特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。這是可靠數(shù)據(jù)庫(kù)所應(yīng)具備的幾個(gè)特性。
- 原子性:
-
指事務(wù)是一個(gè)不可再分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
-
事務(wù)是一個(gè)完整的操作,事務(wù)的各元素是不可分的。
-
事務(wù)中的所有元素必須作為一個(gè)整體提交或回滾。
-
如果事務(wù)中的任何元素失敗,則整個(gè)事務(wù)將失敗。
-
案例:
A給B轉(zhuǎn)帳100元錢(qián)的時(shí)候只執(zhí)行了扣款語(yǔ)句,就提交了,此時(shí)如果突然斷電,A賬號(hào)已經(jīng)發(fā)生了扣款,B賬號(hào)卻沒(méi)收到加款,在生活中就會(huì)引起糾紛。這種情況就需要事務(wù)的原子性來(lái)保證事務(wù)要么都執(zhí)行,要么就都不執(zhí)行。
- 一致性:
-
指在事務(wù)開(kāi)始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫(kù)的完整性約束沒(méi)有被破壞。
-
當(dāng)事務(wù)完成時(shí),數(shù)據(jù)必須處于一致?tīng)顟B(tài)。
-
在事務(wù)開(kāi)始前,數(shù)據(jù)庫(kù)中存儲(chǔ)的數(shù)據(jù)處于一致?tīng)顟B(tài)。
-
在正在進(jìn)行的事務(wù)中,數(shù)據(jù)可能處于不一致的狀態(tài)。
-
當(dāng)事務(wù)成功完成時(shí),數(shù)據(jù)必須再次回到已知的一致?tīng)顟B(tài)。
-
案例:
對(duì)銀行轉(zhuǎn)帳事務(wù),不管事務(wù)成功還是失敗,應(yīng)該保證事務(wù)結(jié)束后表中A和B的存款總額跟事務(wù)執(zhí)行前一致。
- 隔離性:
-
指在并發(fā)環(huán)境中,當(dāng)不同的事務(wù)同時(shí)操縱相同的數(shù)據(jù)時(shí),每個(gè)事務(wù)都有各自的完整數(shù)據(jù)空間。
-
對(duì)數(shù)據(jù)進(jìn)行修改的所有并發(fā)事務(wù)是彼此隔離的,表明事務(wù)必須是獨(dú)立的,它不應(yīng)以任何方式依賴(lài)于或影響其他事務(wù)。
修改數(shù)據(jù)的事務(wù)可在另一個(gè)使用相同數(shù)據(jù)的事務(wù)開(kāi)始之前訪(fǎng)問(wèn)這些數(shù)據(jù),或者在另一個(gè)使用相同數(shù)據(jù)的事務(wù)結(jié)束之后訪(fǎng)問(wèn)這些數(shù)據(jù)。
一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾
- 持久性:
-
在事務(wù)完成以后,該事務(wù)所對(duì)數(shù)據(jù)庫(kù)所作的更改便持久的保存在數(shù)據(jù)庫(kù)之中,并不會(huì)被回滾。
-
指不管系統(tǒng)是否發(fā)生故障,事務(wù)處理的結(jié)果都是永久的。
一旦事務(wù)被提交,事務(wù)的效果會(huì)被永久地保留在數(shù)據(jù)庫(kù)中。
- 事務(wù)之間的相互影響分為幾種,分別為
-
臟讀(讀取未提交數(shù)據(jù)):
臟讀指的是讀到了其他事務(wù)未提交的數(shù)據(jù),未提交意味著這些數(shù)據(jù)可能會(huì)回滾,也就是可能最終不會(huì)存到數(shù)據(jù)庫(kù)中,也就是不存在的數(shù)據(jù)。讀到了并一定最終存在的數(shù)據(jù),這就是臟讀- 案列1
比如事務(wù)B執(zhí)行過(guò)程中修改了數(shù)據(jù)X,在未提交前,事務(wù)A讀取了X,而事務(wù)B卻回滾了,這樣事務(wù)A就形成了臟讀。 也就是說(shuō),當(dāng)前事務(wù)讀到的數(shù)據(jù)是別的事務(wù)想要修改成為的但是沒(méi)有修改成功的數(shù)據(jù)。
- 案列1
-
不可重復(fù)讀(前后多次讀取,數(shù)據(jù)內(nèi)容不一致):
一個(gè)事務(wù)內(nèi)兩個(gè)相同的查詢(xún)卻返回了不同數(shù)據(jù)。這是由于查詢(xún)時(shí)系統(tǒng)中其他事務(wù)修改的提交而引起的。- 案列
事務(wù)A第一次查詢(xún)得到一行記錄row1,事務(wù)B提交修改后,事務(wù)A第二次查詢(xún)得到row1,但列內(nèi)容發(fā)生了變化。
- 案列
select * from member;
1 zhangsan 20分
select * from Member;
1 zhangsan 30分
-
幻讀(前后多次讀取,數(shù)據(jù)總量不一致):
一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時(shí),另一個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,操作前一個(gè)事務(wù)的用戶(hù)會(huì)發(fā)現(xiàn)表中還有沒(méi)有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺(jué)一樣。- 案列
假設(shè)事務(wù)A對(duì)某些行的內(nèi)容作了更改,但是還未提交,此時(shí)事務(wù)B插入了與事務(wù)A更改前的記錄相同的記錄行,并且在事務(wù)A提交之前先提交了,而這時(shí),在事務(wù)A中查詢(xún),會(huì)發(fā)現(xiàn)好像剛剛的更改對(duì)于某些數(shù)據(jù)未起作用,但其實(shí)是事務(wù)B剛插入進(jìn)來(lái)的,讓用戶(hù)感覺(jué)很魔幻,感覺(jué)出現(xiàn)了幻覺(jué),這就叫幻讀
select * from member;
查詢(xún)到了6條記錄
- 案列
alter table member change
select * from member;
查詢(xún)到了10條記錄 (更新了6條數(shù)據(jù),還有4條數(shù)據(jù),我沒(méi)有更新到)
- 丟失更新:
兩個(gè)事務(wù)同時(shí)讀取同一條記錄,A先修改記錄,B也修改記錄(B不知道A修改過(guò)),B提交數(shù)據(jù)后B的修改結(jié)果覆蓋了A的修改結(jié)果。- 案列
A 30 ->40 事務(wù) 先完成
B 30 ->50 事務(wù) 后完成
B的事務(wù)結(jié)果會(huì)覆蓋A的事務(wù)結(jié)果,最終值為50
- 案列
三、Mysql及事務(wù)隔離級(jí)別(四種)
- read uncommitted(未提交讀) :
- 讀取尚未提交的數(shù)據(jù) :不解決臟讀
- 允許臟讀,其他事務(wù)只要修改了數(shù)據(jù),即使未提交,本事務(wù)也能看到修改后的數(shù)據(jù)值。也就是可能讀取到其他會(huì)話(huà)中未提交事務(wù)修改的數(shù)居。
- read committed(提交讀):
- 讀取已經(jīng)提交的數(shù)據(jù) :可以解決臟讀
- 只能讀取到已經(jīng)提交的數(shù)據(jù)。Oracle等多數(shù)數(shù)據(jù)庫(kù)默認(rèn)都是該級(jí)別〈不重復(fù)讀)。
- repeatable read(可重復(fù)度):
- 重讀讀取:可以解決臟讀 和 不可重復(fù)讀 —mysql默認(rèn)的
- 可重復(fù)讀。無(wú)論其他事務(wù)是否修改并提交了數(shù)據(jù),在這個(gè)事務(wù)中看到的數(shù)據(jù)值始終不受其他事務(wù)影響
- serializable:串行化:
- 可以解決 臟讀 不可重復(fù)讀 和 虛讀—相當(dāng)于鎖表
-完全串行化的讀,每次讀都需要獲得表級(jí)共享鎖,讀寫(xiě)相互都會(huì)阻塞。
mysql默認(rèn)的事務(wù)處理級(jí)別是 repeatable read ,而Oracle和SQL Server是 read committed 。
- 事務(wù)隔離級(jí)別的作用范圍(2種)
-
全局級(jí):對(duì)所有的會(huì)話(huà)有效(全局級(jí)配置會(huì)在進(jìn)入數(shù)據(jù)庫(kù)中加載到會(huì)話(huà)級(jí)中,全局配置重啟生效)
-
會(huì)話(huà)級(jí):只對(duì)當(dāng)前的會(huì)話(huà)有效(立即生效)
-
查詢(xún)?nèi)质聞?wù)隔離級(jí)別
set global transaction isolation level read committed;
#例:
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like '%isolation%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED | //已經(jīng)改為提交讀
+---------------+----------------+
1 row in set (0.00 sec)
- 置會(huì)話(huà)事務(wù)隔離級(jí)別
set session transaction isolation level read committed;
#例:
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> show session variables like '%isolation%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED | //查看已經(jīng)更改為提交讀
+---------------+----------------+
1 row in set (0.00 sec)
四、事務(wù)控制語(yǔ)句
BEGIN 或 START TRANSACTION:顯式地開(kāi)啟一個(gè)事務(wù)。
COMMIT 或 COMMIT WORK:提交事務(wù),并使已對(duì)數(shù)據(jù)庫(kù)進(jìn)行的所有修改變?yōu)橛谰眯缘摹?
ROLLBACK 或 ROLLBACK WORK:回滾會(huì)結(jié)束用戶(hù)的事務(wù),并撤銷(xiāo)正在進(jìn)行的所有未提交的修改。
SAVEPOINT S1:使用 SAVEPOINT 允許在事務(wù)中創(chuàng)建一個(gè)回滾點(diǎn),一個(gè)事務(wù)中可以有多個(gè) SAVEPOINT;“S1”代表回滾點(diǎn)名稱(chēng)。
ROLLBACK TO [SAVEPOINT] S1:把事務(wù)回滾到標(biāo)記點(diǎn)。
- 模板:
mysql> create database test; //創(chuàng)建test庫(kù)
Query OK, 1 row affected (0.00 sec)
mysql> use test; //切換到test
Database changed
mysql> create table info( //創(chuàng)建info表
-> id int(10) primary key not null,
-> name varchar(40),
-> money double
-> );
Query OK, 0 rows affected (0.15 sec)
mysql> insert into info values(1,'A',1000); //添加數(shù)據(jù)
Query OK, 1 row affected (0.00 sec)
mysql> insert into info values(2,'B',1000); //添加數(shù)據(jù)
Query OK, 1 row affected (0.00 sec)
mysql> select * from info; //查詢(xún)數(shù)據(jù)
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 1000 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec
- 測(cè)試提交事務(wù)
mysql> begin; //開(kāi)啟事務(wù)
Query OK, 0 rows affected (0.00 sec)
mysql> update info set money= money - 100 where name='A'; //事務(wù)
select * from info;
mysql> commit; //提交事務(wù)
###退出重進(jìn)
quit
mysql -u root -p
use SCHOOL;
mysql> select * from info; //數(shù)據(jù)已經(jīng)被更改
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 900 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
- 測(cè)試回滾事務(wù)
mysql> select * from info;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 900 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)begin;
mysql> begin; //開(kāi)啟事務(wù)
Query OK, 0 rows affected (0.00 sec)
mysql> update info set money= money + 100 where name='A'; //修改數(shù)據(jù)
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from info; //查看
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 1000 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> rollback; //回滾
Query OK, 0 rows affected (0.00 sec)
####退出重進(jìn)
mysql> quit
mysql -u root -p
mysql> use SCHOOL;
mysql> select * from info; //再次查看,數(shù)據(jù)已經(jīng)回滾
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 900 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
- 測(cè)試多點(diǎn)回滾
mysql> begin; //開(kāi)啟事務(wù)
mysql> update info set money= money + 100 where name='A'; //修改更新數(shù)據(jù)
mysql> select * from info; //查看數(shù)據(jù)
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 1000 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> savepoint s1; //創(chuàng)建回滾點(diǎn)s1
Query OK, 0 rows affected (0.00 sec)
mysql> update info set money= money + 100 where name='B'; //修改更新數(shù)據(jù)
mysql> select * from info;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 1000 |
| 2 | B | 1100 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> savepoint s2; //創(chuàng)建回滾點(diǎn)s2
Query OK, 0 rows affected (0.00 sec)
mysql> insert into info values(3,'C',1000); //插入新數(shù)據(jù)
Query OK, 1 row affected (0.00 sec)
mysql> select * from info;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 1000 |
| 2 | B | 1100 |
| 3 | C | 1000 |
+----+------+-------+
3 rows in set (0.00 sec)
mysql> rollback to s1; //回滾到s1
Query OK, 0 rows affected (0.00 sec)
mysql> select * from info; //再次查看發(fā)現(xiàn)數(shù)據(jù)已經(jīng)回滾
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | A | 1000 |
| 2 | B | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
- 使用 set 設(shè)置控制事務(wù)
SET AUTOCOMMIT=0; #禁止自動(dòng)提交
SET AUTOCOMMIT=1; #開(kāi)啟自動(dòng)提交,Mysql默認(rèn)為1
SHOW VARIABLES LIKE 'AUTOCOMMIT'; #查看Mysql中的AUTOCOMMIT值
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
如果沒(méi)有開(kāi)啟自動(dòng)提交,當(dāng)前會(huì)話(huà)連接的mysql的所有操作都會(huì)當(dāng)成一個(gè)事務(wù)直到你輸入rollback|commit;當(dāng)前事務(wù)才算結(jié)束。當(dāng)前事務(wù)結(jié)束前新的mysql連接時(shí)無(wú)法讀取到任何當(dāng)前會(huì)話(huà)的操作結(jié)果。
如果開(kāi)起了自動(dòng)提交,mysql會(huì)把每個(gè)sql語(yǔ)句當(dāng)成一個(gè)事務(wù),然后自動(dòng)的commit。
當(dāng)然無(wú)論開(kāi)啟與否,begin; commit|rollback; 都是獨(dú)立的事務(wù)。
use SCHOOL;
select * from info;
SET AUTOCOMMIT=0; //禁止自動(dòng)提交
SHOW VARIABLES LIKE 'AUTOCOMMIT'; //查看Mysql中的AUTOCOMMIT值
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | NO |
+---------------+-------+
update info set money= money + 100 where name='B';
select * from info;
quit
mysql -u root -p
use SCHOOL;
select * from info;
總結(jié)
-
事物的ACID特點(diǎn)為:原子性、一致性、隔離性、持久性
-
事務(wù)之間的相互影響分為:臟讀、不可重復(fù)讀、幻讀、丟失更新
-
事務(wù)隔離級(jí)別分為:read uncommitted(未提交讀)、read committed(提交讀)、repeatable read(可重復(fù)度)、serializable:串行化
-
mysql默認(rèn)的事務(wù)處理級(jí)別是 repeatable read文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-506944.html
-
事務(wù)隔離級(jí)別的作用范圍分為
全局級(jí):對(duì)所有的會(huì)話(huà)有效
會(huì)話(huà)級(jí):只對(duì)當(dāng)前的會(huì)話(huà)有效文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-506944.html
到了這里,關(guān)于MySQL數(shù)據(jù)庫(kù)--事務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!