Mysql中關(guān)于事務(wù)處理的詳細(xì)介紹

什么是事務(wù)處理呢??事務(wù)處理是用來維護(hù)數(shù)據(jù)庫的完整性的,它保證成批的mysql操作要么完全執(zhí)行,要么完成不執(zhí)行。

一、mysql事務(wù)概念

 MySQL 事務(wù)主要用于處理操作量大,復(fù)雜度高的數(shù)據(jù)。由一步或幾步數(shù)據(jù)庫操作序列組成邏輯執(zhí)行單元,這系列操作要么全部執(zhí)行,要么全部放棄執(zhí)行。在 MySQL 中只有使用了 Innodb 數(shù)據(jù)庫引擎的數(shù)據(jù)庫或表才支持事務(wù)。事務(wù)用來管理 insert,update,delete 語句。

二、事務(wù)特性:Atomicity(原子性)、Consistency(穩(wěn)定性,一致性)、隔離性(Isolation)和Durability(持續(xù)性,可靠性)。這四個特性也簡稱ACID性。

  1.原子性:事務(wù)是應(yīng)用中最小的執(zhí)行單位,就如原子是自然界最小顆粒,具有不可再分的特征一樣。事務(wù)是應(yīng)用中不可再分的最小邏輯執(zhí)行體,一組事務(wù),要么成功;要么撤回。

  2.穩(wěn)定性,一致性:事務(wù)執(zhí)行的結(jié)果,必須使數(shù)據(jù)庫從一個一致性狀態(tài),變到另一個一致性狀態(tài)。當(dāng)數(shù)據(jù)庫中只包含事務(wù)成功提交的結(jié)果時,數(shù)據(jù)庫處于一致性狀態(tài)。一致性是通過原子性來保證的。有非法數(shù)據(jù)(外鍵約束之類),事務(wù)撤回。

  3.隔離性:各個事務(wù)的執(zhí)行互不干擾,任意一個事務(wù)的內(nèi)部操作對其他并發(fā)的事務(wù),都是隔離的。也就是說:并發(fā)執(zhí)行的事務(wù)之間不能看到對方的中間狀態(tài),并發(fā)執(zhí)行的事務(wù)之間不能相互影響。事務(wù)獨(dú)立運(yùn)行。一個事務(wù)處理后的結(jié)果,影響了其他事務(wù),那么其他事務(wù)會撤回。事務(wù)的100%隔離,需要犧牲速度。

  4.持續(xù)性,可靠性:持續(xù)性也稱為持久性,指事務(wù)一旦提交,對數(shù)據(jù)所做的任何改變,都要記錄到永久存儲器中,通常是保存進(jìn)物理數(shù)據(jù)庫。軟、硬件崩潰后,InnoDB數(shù)據(jù)表驅(qū)動會利用日志文件重構(gòu)修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 選項 決定什么時候吧事務(wù)保存到日志里。

  注意事項:存儲引擎MyISAM不支持事物,存儲引擎InnoDB支持事物。事務(wù)只針對對數(shù)據(jù)數(shù)據(jù)產(chǎn)生影響的語句有效。show engines 查看mysql鎖支持的數(shù)據(jù)引擎。

三、讀取數(shù)據(jù)概念

  1.臟讀(Dirty Reads):所謂臟讀就是對臟數(shù)據(jù)的讀取,而臟數(shù)據(jù)所指的就是未提交的數(shù)據(jù)。一個事務(wù)正在對一條記錄做修改,在這個事務(wù)完成并提交之前,這條數(shù)據(jù)是處于待定狀態(tài)的(可能提交也可能回滾),這時,第二個事務(wù)來讀取這條沒有提交的數(shù)據(jù),并據(jù)此做進(jìn)一步的處理,就會產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被稱為臟讀。

  2.不可重復(fù)讀(Non-Repeatable Reads):一個事務(wù)先后讀取同一條記錄,但兩次讀取的數(shù)據(jù)不同,我們稱之為不可重復(fù)讀。也就是說,這個事務(wù)在兩次讀取之間該數(shù)據(jù)被其它事務(wù)所修改。

  3.幻讀(Phantom Reads):一個事務(wù)按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為幻讀。

四、事務(wù)隔離級別

  修改事務(wù)隔離級別語法:

SET?[SESSION?|?GLOBAL]?TRANSACTION?ISOLATION?LEVEL?{READ?UNCOMMITTED?|?READ?COMMITTED?|?REPEATABLE?READ?|?SERIALIZABLE}

  1、Read Uncommitted(未授權(quán)讀取、讀未提交):這是最低的隔離等級,允許其他事務(wù)看到?jīng)]有提交的數(shù)據(jù)。這種等級會導(dǎo)致臟讀。如果一個事務(wù)已經(jīng)開始寫數(shù)據(jù),則另外一個事務(wù)則不允許同時進(jìn)行寫操作,但允許其他事務(wù)讀此行數(shù)據(jù)。該隔離級別可以通過“排他寫鎖”實(shí)現(xiàn)。避免了更新丟失,卻可能出現(xiàn)臟讀。也就是說事務(wù)B讀取到了事務(wù)A未提交的數(shù)據(jù)。SELECT語句以非鎖定方式被執(zhí)行,所以有可能讀到臟數(shù)據(jù),隔離級別最低。

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表,設(shè)置id和name,num字段,開啟事務(wù)1對表新增通過存儲過程,事務(wù)不提交,查看當(dāng)前數(shù)據(jù)庫事務(wù)狀態(tài),可以看到一條數(shù)據(jù)事務(wù),事務(wù)級別為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();

  新建事務(wù)2,查詢student表,我們在READ UNCOMMITTED級別下,可以看到其他事務(wù)未提交的數(shù)據(jù):再去查看數(shù)據(jù)庫事務(wù)狀態(tài),我們會看到狀態(tài)正常。

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

  2.Read Committed(授權(quán)讀取、讀提交):讀取數(shù)據(jù)的事務(wù)允許其他事務(wù)繼續(xù)訪問該行數(shù)據(jù),但是未提交的寫事務(wù)將會禁止其他事務(wù)訪問該行。該隔離級別避免了臟讀,但是卻可能出現(xiàn)不可重復(fù)讀。事務(wù)A事先讀取了數(shù)據(jù),事務(wù)B緊接了更新了數(shù)據(jù),并提交了事務(wù),而事務(wù)A再次讀取該數(shù)據(jù)時,數(shù)據(jù)已經(jīng)發(fā)生了改變。

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(可重復(fù)讀取):就是在開始讀取數(shù)據(jù)(事務(wù)開啟)時,不再允許修改操作,事務(wù)開啟,不允許其他事務(wù)的UPDATE修改操作,不可重復(fù)讀對應(yīng)的是修改,即UPDATE操作。但是可能還會有幻讀問題。因?yàn)榛米x問題對應(yīng)的是插入INSERT操作,而不是UPDATE操作。避免了不可重復(fù)讀取和臟讀,但是有時可能出現(xiàn)幻讀。這可以通過“共享讀鎖”和“排他寫鎖”實(shí)現(xiàn)。

set?session?transaction?isolation?level?repeatable?read;

  4.串行化、序列化:提供嚴(yán)格的事務(wù)隔離。它要求事務(wù)序列化執(zhí)行,事務(wù)只能一個接著一個地執(zhí)行,但不能并發(fā)執(zhí)行。如果僅僅通過“行級鎖”是無法實(shí)現(xiàn)事務(wù)序列化的,必須通過其他機(jī)制保證新插入的數(shù)據(jù)不會被剛執(zhí)行查詢操作的事務(wù)訪問到。序列化是最高的事務(wù)隔離級別,同時代價也花費(fèi)最高,性能很低,一般很少使用,在該級別下,事務(wù)順序執(zhí)行,不僅可以避免臟讀、不可重復(fù)讀,還避免了幻像讀。

set?session?transaction?isolation?level?serializable;

      隔離等級   臟讀   不可重復(fù)讀   幻讀
      讀未提交   YES   YES      YES
      讀已提交   NO    YES     ??? YES
      可重復(fù)讀   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;  --?如果出現(xiàn)異常,會自動處理并rollback  declare?exit?handler?for?sqlexception?ROLLBACK?;?  --?啟動事務(wù)  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);  --?運(yùn)行沒有異常,提交事務(wù)  commit;  --?設(shè)置返回值為1  set?rtn=1;  set?autocommit=1;  end  ;;  delimiter?;;  set?@n=1;  call?pro_new(@n);  select?@n;

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊10 分享