一、Mysql事務概念
MySQL 事務主要用于處理操作量大,復雜度高的數據。由一步或幾步數據庫操作序列組成邏輯執行單元,這系列操作要么全部執行,要么全部放棄執行。在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。事務用來管理 insert,update,delete 語句。
二、事務特性:Atomicity(原子性)、Consistency(穩定性,一致性)、隔離性(Isolation)和Durability(持續性,可靠性)。這四個特性也簡稱ACID性。
1.原子性:事務是應用中最小的執行單位,就如原子是自然界最小顆粒,具有不可再分的特征一樣。事務是應用中不可再分的最小邏輯執行體,一組事務,要么成功;要么撤回。
2.穩定性,一致性:事務執行的結果,必須使數據庫從一個一致性狀態,變到另一個一致性狀態。當數據庫中只包含事務成功提交的結果時,數據庫處于一致性狀態。一致性是通過原子性來保證的。有非法數據(外鍵約束之類),事務撤回。
3.隔離性:各個事務的執行互不干擾,任意一個事務的內部操作對其他并發的事務,都是隔離的。也就是說:并發執行的事務之間不能看到對方的中間狀態,并發執行的事務之間不能相互影響。事務獨立運行。一個事務處理后的結果,影響了其他事務,那么其他事務會撤回。事務的100%隔離,需要犧牲速度。
4.持續性,可靠性:持續性也稱為持久性,指事務一旦提交,對數據所做的任何改變,都要記錄到永久存儲器中,通常是保存進物理數據庫。軟、硬件崩潰后,InnoDB數據表驅動會利用日志文件重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 選項 決定什么時候吧事務保存到日志里。
注意事項:存儲引擎MyISAM不支持事物,存儲引擎InnoDB支持事物。事務只針對對數據數據產生影響的語句有效。show engines 查看mysql鎖支持的數據引擎。
三、讀取數據概念
1.臟讀(Dirty Reads):所謂臟讀就是對臟數據的讀取,而臟數據所指的就是未提交的數據。一個事務正在對一條記錄做修改,在這個事務完成并提交之前,這條數據是處于待定狀態的(可能提交也可能回滾),這時,第二個事務來讀取這條沒有提交的數據,并據此做進一步的處理,就會產生未提交的數據依賴關系。這種現象被稱為臟讀。
2.不可重復讀(Non-Repeatable Reads):一個事務先后讀取同一條記錄,但兩次讀取的數據不同,我們稱之為不可重復讀。也就是說,這個事務在兩次讀取之間該數據被其它事務所修改。
3.幻讀(Phantom Reads):一個事務按相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務插入了滿足其查詢條件的新數據,這種現象就稱為幻讀。
四、事務隔離級別
修改事務隔離級別語法:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
1、Read Uncommitted(未授權讀取、讀未提交):這是最低的隔離等級,允許其他事務看到沒有提交的數據。這種等級會導致臟讀。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。避免了更新丟失,卻可能出現臟讀。也就是說事務B讀取到了事務A未提交的數據。SELECT語句以非鎖定方式被執行,所以有可能讀到臟數據,隔離級別最低。
1
2
3
4
5
|
SET session transaction isolation level read uncommitted ; SET global transaction isolation level read uncommitted ;/*全局建議不用*/ SELECT @@ global .tx_isolation; SELECT @@session.tx_isolation; SELECT @@tx_isolation; |
新建一個簡單的student表,設置id和name,num字段,開啟事務1對表新增通過存儲過程,事務不提交,查看當前數據庫事務狀態,可以看到一條數據事務,事務級別為READ UNCOMMITTED:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
drop table if exists student; create table student( id int primary key auto_increment comment 'id' , name varchar (100) comment '名稱' , num int ); drop procedure if exists proc_on_sw; delimiter ;; create procedure proc_on_sw() begin start transaction ; insert into student( name ,num) value( 'aaa' ,1); select * from information_schema.INNODB_TRX; end ;; delimiter ;; call proc_on_sw(); |
新建事務2,查詢student表,我們在READ UNCOMMITTED級別下,可以看到其他事務未提交的數據:再去查看數據庫事務狀態,我們會看到狀態正常。
1
2
3
4
|
start transaction ; select * from student; commit ; select * from information_schema.INNODB_TRX; |
2.Read Committed(授權讀取、讀提交):讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。該隔離級別避免了臟讀,但是卻可能出現不可重復讀。事務A事先讀取了數據,事務B緊接了更新了數據,并提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
SET session transaction isolation level read committed ; SET global transaction isolation level read committed ; /*全局建議不用*/ drop procedure if exists proc_on_up; delimiter ;; create procedure proc_on_up() begin set autocommit=0; update student set name = 'cc' where id=1; commit ; set autocommit=1; end ;; delimiter ;; call proc_on_up(); select * from student; |
3.repeatable read(可重復讀取):就是在開始讀取數據(事務開啟)時,不再允許修改操作,事務開啟,不允許其他事務的UPDATE修改操作,不可重復讀對應的是修改,即UPDATE操作。但是可能還會有幻讀問題。因為幻讀問題對應的是插入INSERT操作,而不是UPDATE操作。避免了不可重復讀取和臟讀,但是有時可能出現幻讀。這可以通過“共享讀鎖”和“排他寫鎖”實現。
set session transaction isolation level repeatable read;
4.串行化、序列化:提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個地執行,但不能并發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。序列化是最高的事務隔離級別,同時代價也花費最高,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免臟讀、不可重復讀,還避免了幻像讀。
set session transaction isolation level serializable;
隔離等級 臟讀 不可重復讀 幻讀
讀未提交 YES YES YES
讀已提交 NO YES YES
可重復讀 NO NO YES
串行化 NO NO NO
五、完整例子包括提交和回滾完整例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
drop procedure if exists pro_new; delimiter;; create procedure pro_new( out rtn int ) begin declare err INT default 0; -- 如果出現異常,會自動處理并rollback declare exit handler for sqlexception ROLLBACK ; -- 啟動事務 set autocommit=0; start transaction ; insert into student( name ,num) values ( NULL ,2.3); -- set err = @@IDENTITY; -- = 獲取上一次插入的自增ID; set err =last_insert_id(); -- 獲取上一次插入的自增ID insert into student( name ,num) VALUEs ( 'ccc' ,err); -- 運行沒有異常,提交事務 commit ; -- 設置返回值為1 set rtn=1; set autocommit=1; end ;; delimiter ;; set @n=1; call pro_new(@n); select @n; |
原文鏈接:http://www.cnblogs.com/sztx/p/7361954.html