mysql中的事務(wù)全方位解析
一、 事務(wù)的概念
- 事務(wù)是一種機(jī)制、一個操作序列,包含了一組數(shù)據(jù)庫操作命令,并且把所有的命令作為一個整體一起向系統(tǒng)提交或撤銷操作請求,即這一組數(shù)據(jù)庫命令要么都執(zhí)行,要么都不執(zhí)行。
- 事務(wù)是一個不可分割的工作邏輯單元,在數(shù)據(jù)庫系統(tǒng)上執(zhí)行并發(fā)操作時,事務(wù)是最小的控制單元。
- 事務(wù)適用于多用戶同時操作的數(shù)據(jù)庫系統(tǒng)的場景,如銀行、保險公司及證券交易系統(tǒng)等等。
- 事務(wù)通過事務(wù)的整體性以保證數(shù)據(jù)的一致性。
- 事務(wù)能夠提高在向表中更新和插入信息期間的可靠性。
總的來說,事務(wù)就是一個操作序列,這些操作要么都執(zhí)行,要么都不執(zhí)行,它是一個不可分割的工作單位。
二、事務(wù)的ACID特點
ACID,是指在可靠數(shù)據(jù)庫管理系統(tǒng)(DBMS)中,事務(wù)(transaction)應(yīng)該具有的四個特性:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔離性(Isolation)
- 持久性(Durability)
2.1 原子性
- 事務(wù)是一個不可再分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
- 事務(wù)是一個完整的操作,事務(wù)的各元素是不可分的。事務(wù)中的所有元素必須作為一個整體提交或回滾。
- 如果事務(wù)中的任何元素失敗,則整個事務(wù)將失敗。
案例: A給B轉(zhuǎn)帳100元錢的時候只執(zhí)行了扣款語句,就提交了,此時如果突然斷電,A賬號已經(jīng)發(fā)生了扣款,B賬號卻沒收到加款,在生活中就會引起糾紛。這種情況就需要事務(wù)的原子性來保證事務(wù)要么都執(zhí)行,要么就都不執(zhí)行。
2.2 一致性
- 指在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性約束沒有被破壞。
- 當(dāng)事務(wù)完成時,數(shù)據(jù)必須處于一致狀態(tài)。
- 在事務(wù)開始前,數(shù)據(jù)庫中存儲的數(shù)據(jù)處于一致狀態(tài)。在正在進(jìn)行的事務(wù)中,數(shù)據(jù)可能處于不一致的狀態(tài)。
- 當(dāng)事務(wù)成功完成時,數(shù)據(jù)必須再次回到已知的一致狀態(tài)。
案例: 對銀行轉(zhuǎn)帳事務(wù),不管事務(wù)成功還是失敗,應(yīng)該保證事務(wù)結(jié)束后表中A和B的存款總額跟事務(wù)執(zhí)行前一致。
2.3 隔離性
- 指在并發(fā)環(huán)境中,當(dāng)不同的事務(wù)同時操縱相同的數(shù)據(jù)時,每個羽務(wù)都有各自的完整數(shù)據(jù)空間。
- 對數(shù)據(jù)進(jìn)行修改的所有并發(fā)事務(wù)是彼此隔離的,表明事務(wù)必須是獨立的,它不應(yīng)以任何方式依賴于或影響其他事務(wù)。
- 修改數(shù)據(jù)的事務(wù)可在另一個使用相同數(shù)據(jù)的事務(wù)開始之前訪問這些數(shù)據(jù),或者在另一個使用相同數(shù)據(jù)的事務(wù)結(jié)束之后訪問這些數(shù)據(jù)。
- 也就是說并發(fā)訪問數(shù)據(jù)庫時,一個用戶的事務(wù)不被其他事務(wù)所干擾,各并發(fā)事務(wù)之間數(shù)據(jù)庫是獨立的。
2.3.1 一致性問題
當(dāng)多個客戶端并發(fā)地訪問同一個表時,可能出現(xiàn)下而的一致性問題
(1)臟讀: 當(dāng)一個事務(wù)正在訪問數(shù)據(jù),并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事務(wù)也訪問這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。
(2)不可重復(fù)讀: 指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)。在這個事務(wù)還沒有結(jié)束時,另外一個事務(wù)也訪問該同一數(shù)據(jù)。那么,在第一個事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個事務(wù)的修改,那么第一個事務(wù)兩次讀到的的數(shù)據(jù)可能是不一樣的。這樣就發(fā)生了在一個事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的,因此稱為是不可重復(fù)讀。(即不能讀到相同的數(shù)據(jù)內(nèi)容)
(3)幻讀: 一個事務(wù)對一個表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時,另一個事務(wù)也修改這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,操作前一個事務(wù)的用戶會發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。
(4)丟失更新: 兩個事務(wù)同時讀取同一條記錄,A先修改記錄,B也修改記錄(B不知道A修改過),B提交數(shù)據(jù)后B的修改結(jié)果覆蓋了A的修改結(jié)果。
2.3.2 事務(wù)之間可見級別
事務(wù)的隔離級別決定了事務(wù)之間可見的級別
MySQL事務(wù)支持如下四種隔離,用以控制事務(wù)所做的修改,并將修改通告至其它并發(fā)的事務(wù):
(1)未提交讀(Read Uncommitted(RU)):
允許臟讀,即允許一個事務(wù)可以看到其他事務(wù)未提交的修改。
(2)提交讀(Read Committed(RC)):
允許一個事務(wù)只能看到其他事務(wù)已經(jīng)提交的修改,未提交的修改是不可見的。防止臟讀。
(3)可重復(fù)讀(Repeatable Read(RR)):—mysql默認(rèn)的隔離級別
確保如果在一個事務(wù)中執(zhí)行兩次相同的SELECT語句,都能得到相同的結(jié)果,不管其他事務(wù)是否提交這些修改??梢苑乐古K讀和不可重復(fù)讀
(4)串行讀(Serializable):
相當(dāng)于鎖表 完全串行化的讀,將一個事務(wù)與其他事務(wù)完全地隔離。
每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞??梢苑乐古K讀,不可重復(fù)讀取和幻讀,(事務(wù)串行化)會降低數(shù)據(jù)庫的效率。
mysql默認(rèn)的事務(wù)處理級別是repeatable read,而oracle和SQL Server是read committed。
2.3.3 事務(wù)隔離級別的作用范圍
事務(wù)隔離級別的作用范圍分為兩種
- 全局級:對所有的會話有效
- 會話級:只對當(dāng)前的會話有效
#查詢?nèi)质聞?wù)隔離級別: show global variables like '%isolation%'; SELECT @@global.tx_isolation; #查詢會話事務(wù)隔離級別: show session variables like '%isolation%'; SELECT @@session.tx_isolation; SELECT @@tx_isolation; #設(shè)置全局事務(wù)隔離級別: set global transaction isolation level read committed; #設(shè)置會話事務(wù)隔離級別: set session transaction isolation level read committed;
2.4 持久性
在事務(wù)完成以后,該事務(wù)所對數(shù)據(jù)庫所作的更改使持久的保存在數(shù)據(jù)庫之中,并不會被回滾。
指不管系統(tǒng)是否發(fā)生故障,事務(wù)處理的結(jié)果都是永久的。
一旦事務(wù)被提交,事務(wù)的效果會被永久地保留在數(shù)據(jù)庫中。
2.5 小結(jié)
在事務(wù)管理中,原子性是基礎(chǔ)、隔離性是手段,一致性是目的,持久性是結(jié)果。
三、事務(wù)控制語句
BEGIN 或 START TRANSACTION:顯式地開啟一個事務(wù).
COMMIT 或 COMMIT WORK:提交事務(wù),并使已對數(shù)據(jù)庫進(jìn)行的所有修改變?yōu)橛谰眯缘?
ROLLBACK 或 ROLLBACKWORK:回滾會結(jié)束用戶的事務(wù),并撤銷正在進(jìn)行的所有未提交的修改.
SAVEPOINT S1:使用SAVEPOINT允許在事務(wù)中創(chuàng)建一個回滾點,一個事務(wù)中可以有多個SAVEPOINT;"S1"代表回滾點名稱.
ROLLBACK TO[SAVEPOINT] S1:把事務(wù)回滾到標(biāo)記點.
#前期準(zhǔn)備 mysql> use stevelu; Database changed mysql> create table account (id int,name char(10),money double); Query OK, 0 rows affected (0.00 sec) mysql> desc account; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | char(10) | YES | | NULL | | | money | double | YES | | NULL | | +-------+----------+------+-----+---------+-------+ 3 rows in set (0.01 sec) mysql> insert into account values(1,'zhangsan',1000); Query OK, 1 row affected (0.00 sec) mysql> insert into account values(2,'lisi',1000); Query OK, 1 row affected (0.01 sec) mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1000 | | 2 | lisi | 1000 | +------+----------+-------+ 2 rows in set (0.00 sec) --------------------------------------------------------------------------------------------------- #再開一個終端,分別設(shè)置兩個當(dāng)前會話事務(wù)隔離級別 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 | +---------------+----------------+ 1 row in set (0.00 sec) ---------------------------------------------------------------------------------------------------
#模擬zhangsan用戶存入100 #開啟事務(wù) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update account set money=money+100 where name='zhangsan'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1100 | | 2 | lisi | 1000 | +------+----------+-------+ 2 rows in set (0.00 sec) --------------------------------------------------------------------------------------------------- #再開一個終端查看 mysql> use stevelu; mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1000 | | 2 | lisi | 1000 | +------+----------+-------+ 2 rows in set (0.00 sec) --------------------------------------------------------------------------------------------------- #第一個終端操作 #打快照點 mysql> savepoint S1; Query OK, 0 rows affected (0.01 sec) #lisi用戶減100元 mysql> update account set money=money-100 where name='lisi'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 #打快照點 mysql> savepoint S2; Query OK, 0 rows affected (0.00 sec) #查看表記錄 mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1100 | | 2 | lisi | 900 | +------+----------+-------+ 2 rows in set (0.00 sec) #繼續(xù)插入記錄 mysql> insert into account values(3,'wangwu',1000); Query OK, 1 row affected (0.01 sec) mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1100 | | 2 | lisi | 900 | | 3 | wangwu | 1000 | +------+----------+-------+ 3 rows in set (0.00 sec) #回退到快照點2 mysql> rollback to S2; Query OK, 0 rows affected (0.00 sec) mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1100 | | 2 | lisi | 900 | +------+----------+-------+ 2 rows in set (0.00 sec)
rollback后這個事務(wù)就結(jié)束了
#第一個終端 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update account set money=money+100 where name='zhangsan'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update account set money=money-100 where name='lisi'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1100 | | 2 | lisi | 900 | +------+----------+-------+ 2 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) #第二個終端 mysql> select * from account; +------+----------+-------+ | id | name | money | +------+----------+-------+ | 1 | zhangsan | 1100 | | 2 | lisi | 900 | +------+----------+-------+ 2 rows in set (0.00 sec)
四、使用set設(shè)置控制事務(wù)
SET AUTOCOMMIT=0; #禁止自動提交 SET AUTOCOMMIT=1; #開啟自動提交.Mysq1默認(rèn)為1 SHOW VARIABLES LIKE'AUTOCOMMIT'; #查看Mysq1中的AUTOCOMMIT值
如果沒有開啟自動提交,當(dāng)前會話連接的mysql的所有操作都會當(dāng)成一個事務(wù)直到你輸入rollbacklcommit;當(dāng)前事務(wù)才算結(jié)束.當(dāng)前事務(wù)結(jié)束前新的mysql連接時無法讀取到任何當(dāng)前會話的操作結(jié)果
如果開起了自動提交,mysql會把每個sq1語句當(dāng)成一個事務(wù),然后自動的commit
當(dāng)然無論開啟與否,begin;commitlrollback;都是獨立的事務(wù)
到此這篇關(guān)于mysql中的事務(wù)全方位解析的文章就介紹到這了,更多相關(guān)mysql中的事務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql?子查詢的概述和分類及單行子查詢功能實現(xiàn)
本文詳細(xì)介紹了MySQL的子查詢概念和應(yīng)用,解釋了子查詢是在主查詢中嵌套另一個查詢,包括外查詢和內(nèi)查詢,并從多個角度進(jìn)行分類,文章還深入探討了子查詢的編寫技巧和使用場景,對于學(xué)習(xí)和應(yīng)用MySQL的人來說,這是一篇非常有價值的指南2024-10-10SQL筆記之?dāng)?shù)據(jù)庫結(jié)構(gòu)優(yōu)化方式
這篇文章主要介紹了SQL筆記之?dāng)?shù)據(jù)庫結(jié)構(gòu)優(yōu)化方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01MySQL主庫binlog(master-log)與從庫relay-log關(guān)系代碼詳解
這篇文章主要介紹了MySQL主庫binlog與從庫relay-log關(guān)系的相關(guān)內(nèi)容,涉及部分代碼,需要的朋友可以參考。2017-10-10云服務(wù)器Ubuntu_Server_16.04.1安裝MySQL并開啟遠(yuǎn)程連接的方法
這篇文章主要介紹了云服務(wù)器Ubuntu_Server_16.04.1安裝MySQL并開啟遠(yuǎn)程連接的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-02-02- 文章介紹了MySQL慢查詢排查的步驟,包括查看當(dāng)前正在運行的事務(wù)狀態(tài)、查看線程狀態(tài)、殺死線程、輔助判斷命令、開啟慢查詢?nèi)罩竞烷_啟通用查詢?nèi)罩?/div> 2025-02-02
最新評論