mysql中的事務全方位解析
一、 事務的概念
- 事務是一種機制、一個操作序列,包含了一組數(shù)據(jù)庫操作命令,并且把所有的命令作為一個整體一起向系統(tǒng)提交或撤銷操作請求,即這一組數(shù)據(jù)庫命令要么都執(zhí)行,要么都不執(zhí)行。
- 事務是一個不可分割的工作邏輯單元,在數(shù)據(jù)庫系統(tǒng)上執(zhí)行并發(fā)操作時,事務是最小的控制單元。
- 事務適用于多用戶同時操作的數(shù)據(jù)庫系統(tǒng)的場景,如銀行、保險公司及證券交易系統(tǒng)等等。
- 事務通過事務的整體性以保證數(shù)據(jù)的一致性。
- 事務能夠提高在向表中更新和插入信息期間的可靠性。
總的來說,事務就是一個操作序列,這些操作要么都執(zhí)行,要么都不執(zhí)行,它是一個不可分割的工作單位。
二、事務的ACID特點
ACID,是指在可靠數(shù)據(jù)庫管理系統(tǒng)(DBMS)中,事務(transaction)應該具有的四個特性:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔離性(Isolation)
- 持久性(Durability)
2.1 原子性
- 事務是一個不可再分割的工作單位,事務中的操作要么都發(fā)生,要么都不發(fā)生。
- 事務是一個完整的操作,事務的各元素是不可分的。事務中的所有元素必須作為一個整體提交或回滾。
- 如果事務中的任何元素失敗,則整個事務將失敗。
案例: A給B轉(zhuǎn)帳100元錢的時候只執(zhí)行了扣款語句,就提交了,此時如果突然斷電,A賬號已經(jīng)發(fā)生了扣款,B賬號卻沒收到加款,在生活中就會引起糾紛。這種情況就需要事務的原子性來保證事務要么都執(zhí)行,要么就都不執(zhí)行。
2.2 一致性
- 指在事務開始之前和事務結(jié)束以后,數(shù)據(jù)庫的完整性約束沒有被破壞。
- 當事務完成時,數(shù)據(jù)必須處于一致狀態(tài)。
- 在事務開始前,數(shù)據(jù)庫中存儲的數(shù)據(jù)處于一致狀態(tài)。在正在進行的事務中,數(shù)據(jù)可能處于不一致的狀態(tài)。
- 當事務成功完成時,數(shù)據(jù)必須再次回到已知的一致狀態(tài)。
案例: 對銀行轉(zhuǎn)帳事務,不管事務成功還是失敗,應該保證事務結(jié)束后表中A和B的存款總額跟事務執(zhí)行前一致。
2.3 隔離性
- 指在并發(fā)環(huán)境中,當不同的事務同時操縱相同的數(shù)據(jù)時,每個羽務都有各自的完整數(shù)據(jù)空間。
- 對數(shù)據(jù)進行修改的所有并發(fā)事務是彼此隔離的,表明事務必須是獨立的,它不應以任何方式依賴于或影響其他事務。
- 修改數(shù)據(jù)的事務可在另一個使用相同數(shù)據(jù)的事務開始之前訪問這些數(shù)據(jù),或者在另一個使用相同數(shù)據(jù)的事務結(jié)束之后訪問這些數(shù)據(jù)。
- 也就是說并發(fā)訪問數(shù)據(jù)庫時,一個用戶的事務不被其他事務所干擾,各并發(fā)事務之間數(shù)據(jù)庫是獨立的。
2.3.1 一致性問題
當多個客戶端并發(fā)地訪問同一個表時,可能出現(xiàn)下而的一致性問題
(1)臟讀: 當一個事務正在訪問數(shù)據(jù),并且對數(shù)據(jù)進行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事務也訪問這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。

(2)不可重復讀: 指在一個事務內(nèi),多次讀同一數(shù)據(jù)。在這個事務還沒有結(jié)束時,另外一個事務也訪問該同一數(shù)據(jù)。那么,在第一個事務中的兩次讀數(shù)據(jù)之間,由于第二個事務的修改,那么第一個事務兩次讀到的的數(shù)據(jù)可能是不一樣的。這樣就發(fā)生了在一個事務內(nèi)兩次讀到的數(shù)據(jù)是不一樣的,因此稱為是不可重復讀。(即不能讀到相同的數(shù)據(jù)內(nèi)容)

(3)幻讀: 一個事務對一個表中的數(shù)據(jù)進行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時,另一個事務也修改這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,操作前一個事務的用戶會發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。

(4)丟失更新: 兩個事務同時讀取同一條記錄,A先修改記錄,B也修改記錄(B不知道A修改過),B提交數(shù)據(jù)后B的修改結(jié)果覆蓋了A的修改結(jié)果。

2.3.2 事務之間可見級別
事務的隔離級別決定了事務之間可見的級別
MySQL事務支持如下四種隔離,用以控制事務所做的修改,并將修改通告至其它并發(fā)的事務:
(1)未提交讀(Read Uncommitted(RU)):
允許臟讀,即允許一個事務可以看到其他事務未提交的修改。
(2)提交讀(Read Committed(RC)):
允許一個事務只能看到其他事務已經(jīng)提交的修改,未提交的修改是不可見的。防止臟讀。
(3)可重復讀(Repeatable Read(RR)):—mysql默認的隔離級別
確保如果在一個事務中執(zhí)行兩次相同的SELECT語句,都能得到相同的結(jié)果,不管其他事務是否提交這些修改??梢苑乐古K讀和不可重復讀
(4)串行讀(Serializable):
相當于鎖表 完全串行化的讀,將一個事務與其他事務完全地隔離。
每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞??梢苑乐古K讀,不可重復讀取和幻讀,(事務串行化)會降低數(shù)據(jù)庫的效率。

mysql默認的事務處理級別是repeatable read,而oracle和SQL Server是read committed。
2.3.3 事務隔離級別的作用范圍
事務隔離級別的作用范圍分為兩種
- 全局級:對所有的會話有效
- 會話級:只對當前的會話有效
#查詢?nèi)质聞崭綦x級別: show global variables like '%isolation%'; SELECT @@global.tx_isolation; #查詢會話事務隔離級別: show session variables like '%isolation%'; SELECT @@session.tx_isolation; SELECT @@tx_isolation; #設置全局事務隔離級別: set global transaction isolation level read committed; #設置會話事務隔離級別: set session transaction isolation level read committed;



2.4 持久性
在事務完成以后,該事務所對數(shù)據(jù)庫所作的更改使持久的保存在數(shù)據(jù)庫之中,并不會被回滾。
指不管系統(tǒng)是否發(fā)生故障,事務處理的結(jié)果都是永久的。
一旦事務被提交,事務的效果會被永久地保留在數(shù)據(jù)庫中。
2.5 小結(jié)
在事務管理中,原子性是基礎、隔離性是手段,一致性是目的,持久性是結(jié)果。
三、事務控制語句
BEGIN 或 START TRANSACTION:顯式地開啟一個事務.
COMMIT 或 COMMIT WORK:提交事務,并使已對數(shù)據(jù)庫進行的所有修改變?yōu)橛谰眯缘?
ROLLBACK 或 ROLLBACKWORK:回滾會結(jié)束用戶的事務,并撤銷正在進行的所有未提交的修改.
SAVEPOINT S1:使用SAVEPOINT允許在事務中創(chuàng)建一個回滾點,一個事務中可以有多個SAVEPOINT;"S1"代表回滾點名稱.
ROLLBACK TO[SAVEPOINT] S1:把事務回滾到標記點.
#前期準備 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) --------------------------------------------------------------------------------------------------- #再開一個終端,分別設置兩個當前會話事務隔離級別 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 #開啟事務 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后這個事務就結(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設置控制事務
SET AUTOCOMMIT=0; #禁止自動提交 SET AUTOCOMMIT=1; #開啟自動提交.Mysq1默認為1 SHOW VARIABLES LIKE'AUTOCOMMIT'; #查看Mysq1中的AUTOCOMMIT值
如果沒有開啟自動提交,當前會話連接的mysql的所有操作都會當成一個事務直到你輸入rollbacklcommit;當前事務才算結(jié)束.當前事務結(jié)束前新的mysql連接時無法讀取到任何當前會話的操作結(jié)果
如果開起了自動提交,mysql會把每個sq1語句當成一個事務,然后自動的commit
當然無論開啟與否,begin;commitlrollback;都是獨立的事務



到此這篇關于mysql中的事務全方位解析的文章就介紹到這了,更多相關mysql中的事務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mysql觸發(fā)器之創(chuàng)建使用觸發(fā)器簡單示例
這篇文章主要介紹了mysql觸發(fā)器之創(chuàng)建使用觸發(fā)器,結(jié)合實例形式分析了mysql創(chuàng)建、查看、調(diào)用觸發(fā)器的相關操作技巧,需要的朋友可以參考下2019-12-12
MySQL中用通用查詢?nèi)罩菊页霾樵兇螖?shù)最多的語句的教程
這篇文章主要介紹了MySQL中用通用查詢?nèi)罩菊页霾樵兇螖?shù)最多的語句的教程,文中附帶了通用查詢?nèi)罩镜拈_啟和清除技巧,需要的朋友可以參考下2015-12-12
percona-toolkit之pt-kill 殺掉mysql查詢或連接的方法
本文主要描述了percona-toolkit中pt-kill的 使用實例 ,及 一些重要參數(shù)的介紹,需要的朋友可以參考下2016-04-04

