前言:前一篇文章關於事務處理的博文沒有寫清楚,讀起來很是晦澀。很是難理解,因此有整理了一些資料,幫助理解。見諒!mysql
關於MySQL事務處理學習記 sql
START TRANSACTION安全
COMMIT多線程
ROLLBACK併發
語法post
START TRANSACTION | 性能
BEGIN [WORK] 學習
COMMIT [WORK] [AND [NO] CHAIN] [ [NO] RELEASE ] spa
ROLLBACK [WORK] [AND [NO] CHAIN] [ [NO] RELEASE ] 線程
SET AUTOCOMMIT = {0 | 1}
START TRANSACTION或BEGIN語句可以開始一項新的事務。
COMMIT可以提交當前事務。是變動成爲永久變動。
ROLLBACK可以 回滾當前事務,取消其變動。
SET AUTOCOMMIT語句可以禁用或啓用默認的autocommit模式,用於當前鏈接。
自選的WORK關鍵詞被支持。用於COMMIT和RELEASE。與CHAIN和RELEASE子句。
CHAIN和RELEASE可以被用於對事務完畢進行附加控制。
Completion_type系統變量的值決定了默認完畢的性質。
AND CHAIN子句會在當前事務結束時。立馬啓動一個新事務。並且新事務與剛結束的事務有一樣的隔離等級。
RELEASE子句在終止了當前事務後。會讓server斷開與當前client的鏈接。包括NO關鍵詞可以抑制CHAIN或RELEASE完畢。
假設completion_type系統變量被設置爲必定的值。使連鎖或釋放完畢可以默認進行,此時NO關鍵詞實用。
默認狀況下,MySQL採用autocommit模式執行。這意味着。當您執行一個用於更新(改動)表的語句以後。MySQL立馬把更新存儲到磁盤中。
假設您正在使用一個事務安全型的存儲引擎(如InnoDB, BDB或NDB簇)。則您可以使用下面語句禁用autocommit模式:
SET AUTOCOMMIT=0; 經過把AUTOCOMMIT變量設置爲零。禁用autocommit模式以後。您必須使用COMMIT把變動存儲到磁盤中。或着假設您想要忽略從事務開始進行以來作出的變動。使用ROLLBACK。
假設您想要對於一個單一系列的語句禁用autocommit模式。則您可以使用START TRANSACTION語句:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1; COMMIT;
使用START TRANSACTION,autocommit仍然被禁用,直到您使用COMMIT或ROLLBACK結束事務爲止。
而後autocommit模式恢復到原來的狀態。
BEGIN和BEGIN WORK被做爲START TRANSACTION的別名受到支持,用於對事務進行初始化。
START TRANSACTION是標準的SQL語法。並且是啓動一個ad-hoc事務的推薦方法。
BEGIN語句與BEGIN關鍵詞的使用不一樣。BEGIN關鍵詞可以啓動一個BEGIN...END複合語句。後者不會開始一項事務。
您也可以依照例如如下方法開始一項事務:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
WITH CONSISTENT SNAPSHOT子句用於啓動一個一致的讀取。用於具備此類功能的存儲引擎。
眼下,該子句僅僅適用於InnoDB。該子句的效果與公佈一個START TRANSACTION,後面跟一個來自不論什麼InnoDB表的SELECT的效果同樣。
開始一項事務會形成一個隱含的UNLOCK TABLES被運行。
爲了得到最好的結果,事務應僅僅使用由單一事務存儲引擎管理的表運行。
不然,會出現下面問題:
假設您使用的表來自多個事務安全型存儲引擎(好比InnoDB和BDB)。並且事務隔離等級不是SERIALIZABLE,則有可能當一個事務提交時。其餘正在進行中的、使用相同的表的事務將僅僅會發生由第一個事務產生的變動。
也就是。用混合引擎不能保證事務的原子性。並會形成不一致。(假設混合引擎事務不經常有,則您可以依據需要使用
SET TRANSACTION ISOLATION LEVEL把隔離等級設置到SERIALIZABLE。)
假設您在事務中使用非事務安全型表,則對這些表的不論什麼變動被立馬存儲,不論autocommit模式的狀態怎樣。
假設您在更新了事務中一個事務表以後。公佈一個ROLLBACK語句,則會出現一個ER_WARNING_NOT_COMPLETE_ROLLBACK警告。
對事務安全型表的變動被 回滾,但是對非事務安全型表沒有變動。
每個事務被存儲在一個組塊中的二進制日誌中,在COMMIT之上。被回滾的事務不被計入日誌。(例外狀況:對非事務表的更改不會被 回滾。假設一個被回滾的事務包含對非事務表的更改,則整個事務使用一個在末端的ROLLBACK語句計入日誌,以確保對這些表的更改進行復制。)
您可以使用SET TRANSACTION ISOLATION LEVEL更改事務的隔離等級。
回滾可以慢速執行。在用戶沒有明白要求時,也可以進行回滾(好比。當發生錯誤時)。所以,在明白地和隱含的(ROLLBACK SQL命令)回滾時。SHOW PROCESSLIST會在Stage列中顯示Rolling back。用於鏈接。
事務處理和併發性
1.1. 基礎知識和相關概念
1 )全部的表類型都可以使用鎖。但是僅僅有 InnoDB 和 BDB 纔有內置的事務功能。
2 )使用 begin 開始事務,使用 commit 結束事務。中間可以使用 rollback 回滾事務。
3 )在默認狀況下, InnoDB 表支持一致讀。
SQL 標準中定義了 4 個隔離級別: read uncommited 。 read commited , repeatable read 。 serializable 。
read uncommited 即髒讀。一個事務改動了一行。還有一個事務也可以讀到該行。
假設第一個事務運行了回滾,那麼第二個事務讀取的就是歷來沒有正式出現過的值。
?
read commited 即一致讀。試圖經過僅僅讀取提交的值的方式來解決髒讀的問題,但是這又引發了不可反覆讀取的問題。
一個事務運行一個查詢。讀取了大量的數據行。
在它結束讀取以前,還有一個事務可能完畢了對數據行的更改。當第一個事務試圖再次運行同一個查詢,server就會返回不一樣的結果。
repeatable read 就能夠反覆讀。在一個事務對數據行運行讀取或寫入操做時鎖定了這些數據行。
但是這樣的方式又引起了幻想讀的問題。
因爲僅僅能鎖定讀取或寫入的行,不能阻止還有一個事務插入數據,後期運行相同的查詢會產生不少其它的結果。
serializable 模式中,事務被強制爲依次運行。這是 SQL 標準建議的默認行爲。
4 )假設多個事務更新了同一行。就可以經過回滾當中一個事務來解除死鎖。
5 ) MySQL 贊成利用 set transaction 來設置隔離級別。
6 )事務僅僅用於 insert 和 update 語句來更新數據表。不能用於對錶結構的更改。運行一條更改表結構或 begin 則會立刻提交當前的事務。
7 )所有表類型都支持表級鎖,但是 MyISAM 僅僅支持表級鎖。
8 )有兩種類型的表級鎖:讀鎖和寫鎖。
讀鎖是共享鎖。支持併發讀。寫操做被鎖。
寫鎖是獨佔鎖,上鎖期間其它線程不能讀表或寫表。
8 )假設要支持併發讀寫,建議採用 InnoDB 表,因爲它是採用行級鎖,可以得到不少其它的更新性能。
9 )很是多時候,可以經過經驗來評估什麼樣的鎖相應用程序更合適。只是一般很是難說一個鎖比別的更好。這全都要根據應用程序來決定。不一樣的地方可能需要不一樣的鎖。
當前 MySQL 已經支持 ISAM, MyISAM, MEMORY (HEAP) 類型表的表級鎖了。 BDB 表支持頁級鎖, InnoDB 表支持行級鎖。
10 ) MySQL 的表級鎖都是寫鎖優先,而且是採用排隊機制,這樣不會出現死鎖的狀況。對於 InnoDB 和 BDB 存儲引擎來講,是可能產生死鎖的。這是因爲 InnoDB 會本身主動捕獲行鎖。 BDB 會在運行 SQL 語句時捕獲頁鎖的。而不是在事務的開始就這麼作。
1.2. 不一樣鎖的優缺點及選擇
行級鎖的長處及選擇 :
1 )在很是多線程請求不一樣記錄時下降衝突鎖。
2 )事務回滾時下降改變數據。
3 )使長時間對單獨的一行記錄加鎖成爲可能。
行級鎖的缺點 :
1 )比頁級鎖和表級鎖消耗不少其它的內存。
2 )當在大量表中使用時。比頁級鎖和表級鎖更慢。因爲他需要請求不少其它的所資源。
3 )當需要頻繁對大部分數據作 GROUP BY 操做或者需要頻繁掃描整個表時。就明顯的比其餘鎖更糟糕。
4 )使用更高層的鎖的話,就能更方便的支持各類不一樣的類型應用程序,因爲這樣的鎖的開銷比行級鎖小多了。
5 )可以用應用程序級鎖來取代行級鎖。好比 MySQL 中的 GET_LOCK() 和 RELEASE_LOCK() 。
但它們是勸告鎖(原文: These are advisory locks ),所以僅僅能用於安全可信的應用程序中。
6 )對於 InnoDB 和 BDB 表, MySQL 僅僅有在指定用 LOCK TABLES 鎖表時才使用表級鎖。
在這兩種表中,建議最好不要使用 LOCK TABLES 。因爲 InnoDB 本身主動採用行級鎖。 BDB 用頁級鎖來保證事務的隔離。
表鎖的長處及選擇:
1 )很是多操做都是讀表。
2 )在嚴格條件的索引上讀取和更新。當更新或者刪除可以用單獨的索引來讀取獲得時: UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;DELETE FROM tbl_name WHERE unique_key_col=key_value;
3 ) SELECT 和 INSERT 語句併發的運行,但是僅僅有很是少的 UPDATE 和 DELETE 語句。
4 )很是多的掃描表和對全表的 GROUP BY 操做,但是沒有不論什麼寫表。
表鎖的缺點:
1 )一個client提交了一個需要長時間執行的 SELECT 操做。
2 )其它client對同一個表提交了 UPDATE 操做。這個client就要等到 SELECT 完畢了才幹開始運行。
3 )其它client也對同一個表提交了 SELECT 請求。由於 UPDATE 的優先級高於 SELECT 。因此 SELECT 就會先等到 UPDATE 完畢了以後才開始運行,它也在等待第一個 SELECT 操做。
1.3. 怎樣避免鎖的資源競爭
1 )讓 SELECT 速度儘可能快,這可能需要建立一些摘要表。
2 )啓動 mysqld 時使用參數 --low-priority-updates 。這就會讓更新操做的優先級低於 SELECT 。
這樣的狀況下,在上面的若是中,第二個 SELECT 就會在 INSERT 以前運行了,而且也無需等待第一個 SELECT 了。
3 )可以運行 SET LOW_PRIORITY_UPDATES=1 命令,指定所有的更新操做都放到一個指定的連接中去完畢。
4 )用 LOW_PRIORITY 屬性來減小 INSERT 。 UPDATE 。 DELETE 的優先級。
5 )用 HIGH_PRIORITY 來提升 SELECT 語句的優先級。
6 )從 MySQL 3.23.7 開始,可以在啓動 mysqld 時指定系統變量 max_write_lock_count 爲一個比較低的值。它能強制暫時地提升表的插入數達到一個特定值後的所有 SELECT 操做的優先級。它贊成在 WRITE 鎖達到必定數量後有 READ 鎖。
7 )當 INSERT 和 SELECT 一塊兒使用出現故障時。可以轉而採用 MyISAM 表,它支持併發的 SELECT 和 INSERT 操做。
8 )當在同一個表上同一時候有插入和刪除操做時。 INSERT DELAYED 可能會很是實用。
9 )當 SELECT 和 DELETE 一塊兒使用出現故障時, DELETE 的 LIMIT 參數可能會很是實用。
10 )運行 SELECT 時使用 SQL_BUFFER_RESULT 有助於減短鎖表的持續時間。
11 )可以改動源碼 `mysys/thr_lock.c' ,僅僅用一個所隊列。這樣的狀況下,寫鎖和讀鎖的優先級就同樣了。這對一些應用可能有幫助。