SQL第20課:管理事務(wù)處理

事務(wù)定義:
事務(wù)是單個的工作單元。如果某一事務(wù)成功,則在該事務(wù)中進(jìn)行的所有數(shù)據(jù)更改均會提交,成為數(shù)據(jù)庫中的永久組成部分。如果事務(wù)遇到錯誤且必須取消或回滾,則所有數(shù)據(jù)更改均被清除。一般來說,事務(wù)是必須滿足4個條件(ACID)::原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨(dú)立性)、持久性(Durability)。

  • 事務(wù)(transaction)一組SQL指令
  • 回退(rollback)撤銷指定SQL語句的過程
  • 提交(commit)將未存儲的SQL語句結(jié)果寫入數(shù)據(jù)庫表
  • 保留點(diǎn)(savepoint)事務(wù)中設(shè)置的臨時占位符(placeholder),可以對他發(fā)布回退(與回退整個事務(wù)不同)

在用戶操作MySQL過程中,對于一般簡單的業(yè)務(wù)邏輯或中小型程序而言,無需考慮應(yīng)用MySQL事務(wù)。但在比較復(fù)雜的情況下,往往用戶在執(zhí)行某些數(shù)據(jù)操作過程中,需要通過一組SQL語句執(zhí)行多項(xiàng)并行業(yè)務(wù)邏輯或程序,這樣,就必須保證所用命令執(zhí)行的同步性。使執(zhí)行序列中,產(chǎn)生依靠關(guān)系的動作能夠同時操作成功或同時返回初始狀態(tài)。在此情況下,就需要用戶優(yōu)先考慮使用MySQL事務(wù)處理。

在MySQL中,事務(wù)由單獨(dú)單元的一個或多個SQL語句組成。在這個單元中,每個MySQL語句是相互依賴的。而整個單獨(dú)單元作為一個不可分割的整體,如果單元中某條SQL語句一旦執(zhí)行失敗或產(chǎn)生錯誤,整個單元將會回滾。所有受到影響的數(shù)據(jù)將返回到事務(wù)開始以前的狀態(tài);如果單元中的所有SQL語句均執(zhí)行成功,則事務(wù)被順利執(zhí)行。

通過InnoDB和BDB類型表,MySQL事務(wù)能夠完全滿足事務(wù)安全的ACID測試,但是并不是所有表類型都支持事務(wù),如MyISAM類型表就不能支持事務(wù),只能通過偽事務(wù)對表實(shí)現(xiàn)事務(wù)處理。

MySQL事務(wù)的創(chuàng)建與存在周期

創(chuàng)建事務(wù)

創(chuàng)建事務(wù)的一般過程是:初始化事務(wù)、創(chuàng)建事務(wù)、應(yīng)用SELECT語句查詢數(shù)據(jù)是否被錄入和提交事務(wù)。如果用戶不在操作數(shù)據(jù)庫完成后執(zhí)行事務(wù)提交,則系統(tǒng)會默認(rèn)執(zhí)行回滾操作。如果用戶在提交事務(wù)前選擇撤銷事務(wù),則用戶在撤銷前的所有事務(wù)將被取消,數(shù)據(jù)庫系統(tǒng)會回到初始狀態(tài)。

默認(rèn)情況下,在MySQL中創(chuàng)建的數(shù)據(jù)表類型都是MyISAM,但是該類型的數(shù)據(jù)表并不能支持事務(wù)。所以,如果用戶想讓數(shù)據(jù)表支持事務(wù)處理能力,必須將當(dāng)前操作數(shù)據(jù)表的類型設(shè)置為InnoDB或BDB。

在創(chuàng)建事務(wù)的過程中,用戶需要創(chuàng)建一個InnoDB或BDB類型的數(shù)據(jù)表,其基本命令結(jié)構(gòu)如下:

CREATE TABLE table_name(field-defintions)TYPE=INNODB/BDB;

其中,table_name為表名,而field_defintions為表內(nèi)定義的字段等屬性,TYPE為數(shù)據(jù)表的類型,既可以是InnoDB類型,同樣也可以是BDB類型。

當(dāng)用戶希望已經(jīng)存在的表支持事務(wù)處理,則可以應(yīng)用ALTER TABLE命令指定數(shù)據(jù)表的類型實(shí)現(xiàn)對表的類型更改操作,使原本不支持事務(wù)的數(shù)據(jù)表更改為支持事務(wù)處理的類型。其命令如下:

ALTER TABLE table_name TYPE=INNODB/BDB;

當(dāng)用戶更改完表的類型后,即可使數(shù)據(jù)表支持事務(wù)處理。

應(yīng)用ALTER TABLE操作可能會導(dǎo)致數(shù)據(jù)庫中數(shù)據(jù)丟失,因此為了避免非預(yù)期結(jié)果出現(xiàn),在使用ALTER TABLE命令之前,用戶需要創(chuàng)建一個表備份。

初始化事務(wù)

初始化MySQL事務(wù),首先聲明初始化MySQL事務(wù)后所有的SQL語句為一個單元。在MySQL中,應(yīng)用START TRANSACTION命令來標(biāo)記一個事務(wù)的開始。初始化事務(wù)的結(jié)構(gòu)如下:

START TRANSACTION;

另外,用戶也可以使用BEGIN或者BEGIN WORK命令初始化事務(wù),通常START TRANSACTION命令后面跟隨的是組成事務(wù)的SQL語句。

在命令提示符中輸入如下命令:

start transaction;

如果在用戶輸入以上代碼后,MySQL數(shù)據(jù)庫沒有給出警告提示或返回錯誤信息,則說明事務(wù)初始化成功,用戶可以繼續(xù)執(zhí)行下一步操作。

創(chuàng)建事務(wù)

insert into connection(email, cellphone, QQ, sid)

values('barrystephen@126.com',13456000000,187034000,3);

應(yīng)用SELECT語句查看數(shù)據(jù)是否被正確輸入

SELECT * FROM connection WHERE sid=3;

ps:在用戶插入新表為“InnoDB”類型或更改原來表類型為“InnoDB”時,如果在輸入命令提示后,MySQL提示“The 'InnoDB' feature is disabled;you needInnoDB' to have it working”警告,則說明InnoDB表類型并沒有被開啟,用戶需要找到MySQL文件目錄下的“my.ini”文件,定位“skip_innodb”選項(xiàng)位置,將原來的“skip_innodb”改為“#skip_innodb”后保存該文件,重新啟動MySQL服務(wù)器,即可令數(shù)據(jù)庫支持“InnoDB”類型表。

提交事務(wù)

在用戶沒有提交事務(wù)之前,當(dāng)其他用戶連接MySQL服務(wù)器時,應(yīng)用SELECT語句查詢結(jié)果,則不會顯示沒有提交的事務(wù)。當(dāng)且僅當(dāng)用戶成功提交事務(wù)后,其他用戶才可能通過SELECT語句查詢事務(wù)結(jié)果,由事務(wù)的特性可知,事務(wù)具有孤立性,當(dāng)事務(wù)處在處理過程中,其實(shí)MySQL并未將結(jié)果寫入磁盤中,這樣一來,這些正在處理的事務(wù)相對其他用戶是不可見的。一旦數(shù)據(jù)被正確插入,用戶可以使用COMMIT命令提交事務(wù)。提交事務(wù)的命令結(jié)構(gòu)如下:

COMMIT

一旦當(dāng)前執(zhí)行事務(wù)的用戶提交當(dāng)前事務(wù),則其他用戶就可以通過會話查詢結(jié)果。

撤銷事務(wù)(事務(wù)回滾)

撤銷事務(wù),又被稱作事務(wù)回滾。即事務(wù)被用戶開啟、用戶輸入的SQL語句被執(zhí)行后,如果用戶想要撤銷剛才的數(shù)據(jù)庫操作,可使用ROLLBACK命令撤銷數(shù)據(jù)庫中的所有變化。ROLLBACK命令結(jié)構(gòu)如下:

ROLLBACK

輸入回滾操作后,如何判斷是否執(zhí)行回滾操作了呢?可以通過SELECT語句查看11.2.2小節(jié)中插入的數(shù)據(jù)是否存在.

如果執(zhí)行一個回滾操作,則在輸入START TRANSACTIONA命令后的所有SQL語句都將執(zhí)行回滾操作。故在執(zhí)行事務(wù)回滾前,用戶需要慎重選擇執(zhí)行回滾操作。如果用戶開啟事務(wù)后,沒有提交事務(wù),則事務(wù)默認(rèn)為自動回滾狀態(tài),即不保存用戶之前的任何操作。

事務(wù)的存在周期

事務(wù)的周期由用戶在命令提示符中輸入START TRANSACTION指令開始,直至用戶輸入COMMIT結(jié)束.

事務(wù)不支持嵌套功能,當(dāng)用戶在未結(jié)束第一個事務(wù)又重新打開一個事務(wù),則前一個事務(wù)會自動提交,同樣MySQL命令中很多命令都會隱藏執(zhí)行COMMIT命令。

MySQL行為

在MySQL中,存在兩個可以控制行為的變量,它們分別是AUTOCOMMIT變量和TRANSACTION ISOLACTION LEVEL變量。

自動提交

在MySQL中,如果不更改其自動提交變量,則系統(tǒng)會自動向數(shù)據(jù)庫提交結(jié)果,用戶在執(zhí)行數(shù)據(jù)庫操作過程中,不需要使用START TRANSACTION語句開始事務(wù),應(yīng)用COMMIT或者ROLLBACK提交事務(wù)或執(zhí)行回滾操作。如果用戶希望通過控制MySQL自動提交參數(shù),可以更改提交模式,這一更改過程是通過設(shè)置AUTOCOMMIT變量來實(shí)現(xiàn)。

下面通過一個示例向讀者展示如何關(guān)閉自動提交參數(shù)。在命令提示符中輸入以下命令:

SET AUTOCOMMIT=0;

只有當(dāng)用戶輸入COMMIT命令后,MySQL才將數(shù)據(jù)表中的資料提交到數(shù)據(jù)庫中,如果不提交事務(wù),而終止MySQL會話,數(shù)據(jù)庫將會自動執(zhí)行回滾操作。

可以通過查看“@@AUTOCOMMIT”變量來查看當(dāng)前自動提交狀態(tài),查看此變量SELECT @@AUTOCOMMIT。

事務(wù)的隔離級別

基于ANSI/ISO SQL規(guī)范,MySQL提供4種孤立級:

SERIALIZABLE(序列化)

REPEATABLE READ(可重讀)

READ COMMITTED(提交后讀)

READ UNCOMMITTED(未提交讀)

在MySQL中,可以使用TRANSACTION ISOLATION LEVEL變量來修改事務(wù)孤立級,其中,MySQL的默認(rèn)隔離級別為REPEATABLE READ(可重讀),用戶可以使用SELECT命令獲取當(dāng)前事務(wù)孤立級變量的值,其命令如下:

SELECT @@tx_isolation;

如果用戶想要修改事務(wù)的隔離級別,必須首先獲取SUPER優(yōu)先權(quán),以便用戶可以順利執(zhí)行修改操作,set。

事務(wù)的使用技巧和注意事項(xiàng)

應(yīng)用小事務(wù),保證每個事務(wù)不會在執(zhí)行前等待很長時間,從而避免各個事務(wù)因?yàn)榛ハ嗟却鴮?dǎo)致系統(tǒng)性能的大幅度下降。

選擇合適的孤立級,因?yàn)槭聞?wù)的性能與其對服務(wù)器產(chǎn)生的負(fù)載成反比,即當(dāng)事務(wù)孤立級越高,其性能越低,但是其安全性也越高。只有選擇適當(dāng)?shù)墓铝⒓?,才能有效地提高M(jìn)ySQL系統(tǒng)性能和應(yīng)用性。

死鎖的概念與避免,即當(dāng)兩個或者多個處于不同序列的用戶打算同時更新某相同的數(shù)據(jù)庫時,因互相等待對方釋放權(quán)限而導(dǎo)致雙方一直處于等待狀態(tài)。在實(shí)際應(yīng)用中,兩個不同序列的客戶打算同時對數(shù)據(jù)執(zhí)行操作,極有可能產(chǎn)生死鎖。更具體地講,當(dāng)兩個事務(wù)相互等待操作對方釋放所持有的資源,而導(dǎo)致兩個事務(wù)都無法操作對方持有的資源,這樣無限期的等待被稱作死鎖。MySQL的InnoDB表處理程序具有檢查死鎖這一功能,如果該處理程序發(fā)現(xiàn)用戶在操作過程中產(chǎn)生死鎖,該處理程序立刻通過撤銷操作來撤銷其中一個事務(wù),以便使死鎖消失。這樣就可以使另一個事務(wù)獲取對方所占有的資源而執(zhí)行邏輯操作。

MySQL偽事務(wù)

在MySQL中,InnoDB和BDB類型表可以支持事務(wù)處理,但是MySQL中MyISAM類型表并不能支持事務(wù)處理,對于某些應(yīng)用該類型的數(shù)據(jù)表,用戶可以選擇應(yīng)用表鎖定來替代事務(wù)。這種引用表鎖定來替代事務(wù)的事件被稱作偽事務(wù)。使用表鎖定來鎖定表的操作,可以加強(qiáng)非事務(wù)表在執(zhí)行過程的安全性和穩(wěn)定性。

用表鎖定代替事務(wù)

在MySQL的MyISAM類型數(shù)據(jù)表中,并不支持COMMIT(提交)和ROLLBACK(回滾)命令。當(dāng)用戶對數(shù)據(jù)庫執(zhí)行插入、刪除、更新等操作時,這些變化的數(shù)據(jù)都被立刻保存在磁盤中。這樣,在多用戶環(huán)境中,會導(dǎo)致諸多問題。為了避免同一時間有多個用戶對數(shù)據(jù)庫中指定表進(jìn)行操作,可以應(yīng)用表鎖定來避免在用戶操作數(shù)據(jù)表過程中受到干擾。當(dāng)且僅當(dāng)該用戶釋放表的操作鎖定后,其他用戶才可以訪問這些修改后的數(shù)據(jù)表。

設(shè)置表鎖定代替事務(wù)基本步驟如下:

(1)為指定數(shù)據(jù)表添加鎖定。其語法如下:

LOCK TABLES table_name lock_type,……

其中,table_name為被鎖定的表名,lock_type為鎖定類型,該類型包括以讀方式(READ)鎖定表,以寫方式(WRITE)鎖定表。

(2)用戶執(zhí)行數(shù)據(jù)表的操作,可以添加、刪除或者更改部分?jǐn)?shù)據(jù)。

(3)用戶完成對鎖定數(shù)據(jù)表的操作后,需要對該表進(jìn)行解鎖操作,釋放該表的鎖定狀態(tài)。其語法如下:

UNLOCK TABLES

以讀方式鎖定數(shù)據(jù)表,該方式是設(shè)置鎖定用戶的其他方式操作,如刪除、插入、更新都不被允許,直至用戶進(jìn)行解鎖操作。

lock table studentinfo read;

其中的lock_type參數(shù)中,用戶指定數(shù)據(jù)表以讀方式(READ)鎖定數(shù)據(jù)表的變體為READ LOCAL鎖定,其與READ鎖定的不同點(diǎn)是,該參數(shù)所指定的用戶會話可以執(zhí)行INSERT操作,它是為了使用MySQL dump工具而創(chuàng)建的一種變體形式。

以寫方式鎖定數(shù)據(jù)表,該方式是是設(shè)置用戶可以修改數(shù)據(jù)表中的數(shù)據(jù),但是除自己以外其他會話中的用戶不能進(jìn)行任何讀操作。在命令提示符中輸入如下命令:

lock table studentinfo write;

當(dāng)數(shù)據(jù)表被釋放鎖定后,其他訪問數(shù)據(jù)庫的用戶即可查看數(shù)據(jù)表的內(nèi)容。

應(yīng)用表鎖實(shí)現(xiàn)偽事務(wù)

通過使用表鎖定對MyISAM表進(jìn)行鎖定操作,以此過程來代替事務(wù)型表InnoDB,即應(yīng)用表鎖定來實(shí)現(xiàn)偽事務(wù)。實(shí)現(xiàn)偽事務(wù)的一般步驟如下:

(1)對數(shù)據(jù)庫中的數(shù)據(jù)表進(jìn)行鎖定操作,可以對多個表做不同的方式鎖定,其代碼格式如下:

LOCK TABLE table_name1 lock_type1,table_name2 lock_type2,……

(2)執(zhí)行數(shù)據(jù)庫操作,向鎖定的數(shù)據(jù)表中執(zhí)行添加、刪除、修改操等操作。

如前面提到的INSERT、UPDATE、DELETE等操作。用戶可以對鎖定的數(shù)據(jù)表執(zhí)行上述操作,在執(zhí)行過程中,該偽事務(wù)所產(chǎn)生的結(jié)果是不會被其他用戶更改的。

(3)釋放鎖定的數(shù)據(jù)表,以便讓正在隊(duì)列中等待查看或操作的其他用戶可以瀏覽數(shù)據(jù)表中的數(shù)據(jù)或?qū)Σ僮鞅韴?zhí)行各種數(shù)據(jù)的操作。

如果存在其他會話要求訪問已鎖定的多個表格,則該會話必須被迫等待當(dāng)前鎖定用戶釋放鎖定表。才允許其他會話訪問該數(shù)據(jù)表,表鎖定使不同會話執(zhí)行的數(shù)據(jù)庫操作彼此獨(dú)立。應(yīng)用數(shù)據(jù)表鎖定方式可以使不支持事務(wù)類型的表實(shí)現(xiàn)偽事務(wù)。

MySql的事務(wù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容