日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql怎么实现事务序列化_MySQL 架构 - 事务处理

發布時間:2025/4/16 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql怎么实现事务序列化_MySQL 架构 - 事务处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

事務處理

在事務處理之前,你不能知道數據庫系統有如此多的高級功能。一個事物就是一組SQL查詢。這一組被看做是原子的。也就是一個單獨的工作單元。如果數據庫引擎可以應用整個組的查詢,就執行完畢。但是如果其中一條語句出現問題,整個組的語句都不會被執行。也就是要么全部執行,要么全部不執行。

這部分所講到的事物很少是針對MySQL的,如果你已經熟悉了ACID事務處理,可以跳過這一部分。

銀行的應用是解釋為什么需要事務處理的經典案例。假設銀行數據有兩張表。checking以及savings.從Jane的checking賬戶轉賬200到她的saving賬戶。至少要三步

確定她的checking賬戶至少有200

從checking賬戶扣除200

把200添加到她的savings賬戶中。

整個操作封裝為了一個事物。因此其中一個操作失敗,整個操作都會回滾。

開始一個事物的語句是START TRANSACTION以及修改成功用COMMIT或者放棄改變用ROLLBACK。因此這個例子的SQL語句如下

START TRANSACTION;

SELECT balance FROM checking WHERE customer_id = 10233276;

UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;

UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276;

COMMIT;

但是單獨的事物并不能代表全部。如果在數據庫服務器在執行到第四行的時候掛掉呢?用戶可能就白白損失了200。以及如果有個處理出現在了3,4行之間,而不會去扣除checking帳戶的余額。那么銀行就白白給了用戶200.

在系統沒有通過ACID的測試之前,僅僅有事物還是不夠的。ACID的意思是原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。這些都是一個好的事務處理系統所要遵循的標準。

原子性(Atomicity):

一個事物必須做為一個單獨不可分割的工作單元來運行。因此整個事物要么全部成功要么全部失敗。當事物具有原子性的時候,不能一部分的執行。要么全部執行,要么全部失敗。

一致性(Consistency):

數據庫應該總是從一個一致的狀態到另一個。在我們的例子中,一致性要確保程序在3,4行崩潰并不會使checking帳戶減少200。因為事物沒有提交。數據庫沒有任何變化。

隔離性(Isolation):

當這個事物沒有完成的時候,它的結果對于其他的事物是不可見的。這點確保了在運行完第3行,以及在第4行之前。200還是在checking帳戶中。當我們討論隔離性的時候,我們常常用到不可見(invisible)這個詞。

持久性(Durability):

當事物提交,這個事物的改變就被持久化了。意思就是更改被記錄了。數據不會丟失了。持久性是個挺模糊的概念。因為它有很多級別。一些持久性策略比其他的有更強的安全性保證。但是絕對沒有100%的持久。我們會在以后的章節討論在MySQL中持久性的意思。

ACID事物保證了銀行不會損失錢。這點在業務邏輯上很難或者根本做不到。一個有ACID的數據庫服務器已經把各種各樣復雜的事情都解決了,使你沒有必要自己去確保ACID。

隨著鎖的顆粒度上升,數據庫服務器要在安全性上做更多的工作了。數據庫的ACID事物也需要更多的CPU,內存,硬盤空間。我們多次說過MySQL存儲引擎架構的優勢。你可以決定到底是否使用事物。如果不需要可以選擇更好的沒有事務支持的存儲引擎。在沒有事物的時候,你可以使用LOCK TABLES來保護數據。決定權在于你。

隔離級別

隔離要比看上去復雜的多。SQL定義了4種隔離級別。這些規則讓更改對事物的內部和外部可見和不可見。低級別的隔離可以高并發低消耗。

(每個存儲引擎的隔離級別實現都是不同的,如果你過去經常使用其他數據庫產品,存儲引擎不一定符合你的需求,你應該看手冊決定使用哪個存儲引擎。)

未提交讀(READ UNCOMMITTED)

在這個級別中,事物可以看到未提交事物的結果。這個級別有很多問題會發生,除非你真的真的明白你在做什么以及有足夠的理由去做。這級別在實踐中很少使用。因為性能相對于其他級別也沒什么優勢。讀取未提交的數據,也叫臟讀(dirty read)

已提交讀(READ COMMITTED)

有許多數據庫系統默認的隔離級別都是已提交讀(MySQL并不是)。它滿足了早期使用的隔離簡單定義:一個事物可以看到事物提交后的改變。這種改變在提交之前對于其他事物是不可見的。這級別也經常叫做不可重復讀(nonrepeatable read)。意思就是你運行同一語句兩次,可以看到不同的數據。

可重復讀(REPEATABLE READ)

可重復讀解決了未提交讀的問題。它保證了在同一個事物中,連續任意行的讀的數據都是相同的。但這種方式也引起了其他惡心的問題。幻讀(phantom reads.)。簡單地說就是,當你選擇一定范圍的行,另一個事物想這個范圍新增加了一行。之后有查詢相同的范圍。你就會發現出現了像幻覺一樣的一行。InnoDB和Falcon用多版本并發控制來解決了幻讀的問題。

可重復讀是MySQL默認的事物隔離級別。InnoDB和Falcon也是遵循這個設置。以后會講到怎樣修改這個設置。其他的引擎也是這樣的,但是決定權在于引擎。

可序列化(SERIALIZABLE)

最高的隔離級別。解決的幻讀的問題。強迫事物是有序的。因此他們不可能沖突。簡單的意思就是可序列化把每一行加一個鎖。這一級別許多超時和鎖的競爭將出現。我們很少看見人們使用這個級別的隔離。你的應用也有可能強迫你把隔離級別設置那么高,而忽視并發性。重視數據的穩定性。

隔離級別

臟讀

不可重復讀

幻讀

讀取鎖

未提交讀

已提交讀

可重復讀

可序列化

死鎖(Deadlocks)

死鎖就是當兩個以上的事物相互的等待和請求同一資源,產生了循環依賴就導致死鎖。死鎖存在事物嘗試不同的順序去鎖定資源的時候。在任何時候多事物鎖定同一資源都會發生死鎖。舉個例子。。有兩個事物運行在StockPrice的表。

事物一

START TRANSACTION;

UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4 and date = '2002-05-01';

UPDATE StockPrice SET close = 19.80 WHERE stock_id = 3 and date = '2002-05-02';

COMMIT;

事物二

START TRANSACTION;

UPDATE StockPrice SET high = 20.12 WHERE stock_id = 3 and date = '2002-05-02';

UPDATE StockPrice SET high = 47.20 WHERE stock_id = 4 and date = '2002-05-01';

COMMIT;

如果你足夠的倒霉,可能會發生如下情況。每個事物都完成第一條語句更新了StockPrice表。給它加了鎖。每個事物都試圖執行第二行。發現它被加鎖了。這兩個事物都會等待除自己另外一個事物結束。除非有操作能破壞這個死鎖狀況。

為了解決這個問題,數據庫系統實現了許多種死鎖的檢測和超時處理。在更復雜的系統中,如InnoDB存儲引擎。會發現循環依賴并且及時的返回錯誤。真是非常好的方式,否則死鎖會降低語句的執行效率。其他的方式是在鎖等待超時之后,放棄操作。這個方式不太好。InnoDB處理死鎖的方式是,回滾有最少行級鎖的事物。

鎖的行為和順序是存儲引擎特定的。因此有些存儲引擎可能在特定的一系列語句發生死鎖,其他的也許不會。死鎖有雙重特性:一些是不可避免的,因為確實是數據沖突。一些是由于存儲引擎工作方式所引起的。

事務日志

事物日志的幫助可以讓事物更有效率。存儲引擎更改存儲在內存中的數據拷貝,取代每次修改都要更新硬盤上的表。這種方法非常高效。之后,存儲引擎就向事務日志添加一條記錄。這個日志存放在硬盤中,因此是持久的。這個操作相對來說能快點。因為附加記錄事件使用小范圍的連續IO取代了大范圍的隨機IO。之后,在晚一點,會更新硬盤上的表。所以大部分存儲引擎都使用這個技術(write-ahead logging 預寫式記錄),會兩次向硬盤寫入更改的信息。

在更新日志之后,更改數據之前發生了錯誤。存儲引擎仍然在重啟后恢復更改。各個存儲引擎的恢復方法各不相同。

MySQL中的事物

MySQL提供了三種支持事物的存儲引擎:?InnoDB, NDB Cluster, Falcon。許多第三方的引擎也可以使用,比較有名的就是solidDB 以及PBXT。在下一部分會詳細介紹這些存儲引擎。

AUTOCOMMIT

MySQL的AUTOCOMMIT是默認的。意思就是無論你是否開始一個事物,在每個語句都會自動執行。當然你可以設置這個AUTOCOMMIT的變量,方法如下

1和ON是一樣的。0也就是OFF。當AUTOCOMMIT=0的時候,你必須COMMIT或ROLLBACK,不然的話你就總在一個事物中,語句不會執行。如果表的存儲引擎不支持事物,改變AUTOCOMMIT的值,不會有任何的效果。這些存儲引擎是MyISAM或者Memory.它們總是自動提交。

一些命令,當開始一個事物,在執行之前,MySQL會自動提交事物。這些命令就是DDL。如果ALTER TABLE等,還有一些特殊如LOCK TABLES也會有這樣的效果。具體的查看數據庫版本的文檔。來查看哪些命令是自動提交的。

MySQL允許設置隔離級別。命令是SET TRANSACTION ISOLATION LEVEL 。這會影響下一個事物的開始時間。你也可以通過配置文件來設置整個服務器的隔離級別,這個將在以后說。也可以針對當前會話。如

mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

MySQL能識別所有標準的隔離級別,以及InnoDB存儲引擎支持這些隔離級別。其他的存儲引擎不同程度上支持不同的隔離級別。

在事物中混合使用存儲引擎

在服務器級別,MySQL不能管理事物。而事物是由存儲引擎所實現的。意思就是你不能在一個單獨事物中混合使用不同的存儲引擎。MySQL AB給服務器添加了一個更高級別的事務管理服務。這樣就會在一個事物中,混合和匹配事務表更加安全。在此之前一定要小心。

如果在一個事物中混合了事物和非事物表。如果一切正常,這個事物就沒有問題,但是如果執行回滾操作,非事物表改變的數據并不會回滾。數據庫的一致性遭到了破壞,很難恢復和呈現完整的事物。這就是為什么給表選擇存儲引擎是如此的重要。

如果你在非事物表上做事物操作,MySQL并不會提示或者拋出異常。有的時候,回滾會有一定的提示?!癝ome nontransactional changed tables couldn’t be rolled back”。但是一般都不會有什么提示。

隱式和顯式的鎖定

InnoDB使用兩階段鎖定協議(two-phase locking protocol)。它能任意時間在一個事物之中獲得鎖。但是只要執行COMMIT或ROLLBACK才會釋放鎖。它總在同一時刻釋放鎖。鎖機制的描述都是隱式的。InnoDB根據你設置的隔離級別自動處理鎖。

然而,InnoDB也支持顯式加鎖。SQL的標準并沒有提到:

? SELECT ... LOCK IN SHARE MODE

? SELECT ... FOR UPDATE

MySQL也支持LOCK TABLES 和UNLOCK TABLES命令。這個是由服務器實現的。并不是存儲引擎。這個可以使用,但它并不不能取代事物。如果你要用事物,請使用支持事物的存儲引擎。

我們看到很多應用從MyISAM轉到InnoDB,但是還在使用LOCK TABLES.這沒什么必要,因為行級別的鎖定。LOCK TABLE也會引起性能問題。

(LOCK TABLES和事物之間的交互是復雜的??赡苡行┮庀氩坏降漠惓3霈F。所以我們建議除非你不使用事物和把AUTOCOMMIT關閉,否則永遠不要使用LOCK TABLES。)

大小: 17.8 KB

分享到:

2009-06-01 17:01

瀏覽 1859

評論

總結

以上是生活随笔為你收集整理的mysql怎么实现事务序列化_MySQL 架构 - 事务处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。