首頁  >  文章  >  資料庫  >  Mysql中關於事務處理的詳細介紹

Mysql中關於事務處理的詳細介紹

黄舟
黄舟原創
2017-08-20 15:41:241492瀏覽

什麼是事務處理呢? ?事務處理是用來維護資料庫的完整性的,它保證成批的MySQL操作要麼完全執行,要麼完成不執行。

一、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語句以非鎖定方式執行,所以有可能讀到髒數據,隔離等級最低。


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:


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層級下,可以看到其他事務未提交的資料:再去查看資料庫事務狀態,我們會看到狀態正常。


start transaction ;
select * from student;
commit;
select * from information_schema.INNODB_TRX;

  2.Read Committed(授權讀取、讀取提交):讀取資料的事務允許其他事務繼續存取該行數據,但是未提交的寫入事務將會禁止其他事務存取該行。此隔離等級避免了髒讀,但是卻可能出現不可重複讀。事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經改變了。


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

五、完整例子包括提交和回滚完整例子


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;

以上是Mysql中關於事務處理的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn