1. 程式人生 > 實用技巧 >Mysql事務和鎖機制

Mysql事務和鎖機制

Mysql事務和鎖機制

事務概念

資料庫事務是資料庫管理系統執行過程中的一個邏輯單位,由一個有限的資料庫操作序列構成。但不是任意的資料庫操作序列都能成為事務  
對mysql常見的引擎有:MyISAM和InnoDB,MyISAM是預設高速的引擎並不支援事務功能,InnoDB支援行鎖定和事務處理,速度比MyISAM稍慢。  
它的存在包含有以下兩個目的:  
	1.為資料庫操作序列提供了一個從失敗中恢復到正常狀態的方法,同時提供了資料庫即使在異常狀態下仍能保持一致性的方法。  
    2.當多個應用程式在併發訪問資料庫時,可以在這些應用程式之間提供一個隔離方法,以防止彼此的操作互相干擾。  

事務四大特性(ACID)

  • 原子性(Autmic):一個原子事務要麼完整執行,要麼乾脆不執行。也就是說,工作單元中的每項任務都必須正確執行,如果有任一任務執行失敗,則整個事務就會被終止並且此前對資料所作的任何修改都將被撤銷。如果所有任務都被成功執行,事務就會被提交,那麼對資料所作的修改將會是永久性的
  • 一致性(Consistency):一致性代表了底層資料儲存的完整性。 它是由事務系統和應用開發人員共同來保證。事務系統通過保證事務的原子性,隔離性和永續性來滿足這一要求; 應用開發人員則需要保證資料庫有適當的約束(主鍵,引用完整性等),並且工作單元中所實現的業務邏輯不會導致資料的不一致(資料預期所表達的現實業務情況不相一致)。例如,在剛才的AB轉賬過程中,從A賬戶中扣除的金額必須與B賬戶中存入的金額相等。
  • 隔離性(Isolation):隔離性是指事務必須在不干擾其他事務的前提下獨立執行,也就是說,在事務執行完畢之前,其所訪問的資料不能受系統其他部分的影響。
  • 永續性(Durability):永續性指明當系統或介質發生故障時,確保已提交事務的更新資料不能丟失,也就意味著一旦事務提交,DBMS保證它對資料庫中資料的改變應該是永久性的,耐得住任何系統故障,永續性可以通過資料庫備份和恢復來保證。

隔離級別

  • READ_UNCOMMITTED:這是事務最低的隔離級別,它充許別外一個事務可以看到這個事務未提交的資料,會出現髒讀、不可重複讀、幻讀 (隔離級別最低,併發效能高)

  • READ_COMMITTED:保證一個事務修改的資料提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的資料。可以避免髒讀,但會出現不可重複讀、幻讀問題(鎖定正在讀取的行,mysql預設隔離級別)

  • REPEATABLE_READ:可以防止髒讀、不可重複讀,但會出幻讀(鎖定所讀取的所有行)

  • SERIALIZABLE:這是花費最高代價但是最可靠的事務隔離級別,事務被處理為順序執行。保證所有的情況不會發生(鎖表,併發性及其低)

隔離級別 讀未提交 不可重複讀 幻讀
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE
  • 讀未提交:事務T2能讀取事務T1未提交的資料,當事務T1執行回滾時,T2讀取的資料就無效

  • 不可重複讀:事務T2讀取事務T1未開啟時和T1提交後的資料不一致(主要是資料更新導致不一致

  • 幻讀:事務T2讀取事務T1未開啟時和T1提交後的資料不一致(此時已鎖定T2讀取行,主要是插入和刪除資料導致不一致

    // 設定當前連線的事務隔離級別
    SET SESSION TRANSACTION ISOLATION LEVEL 事務隔離級別;
    //設定全部連線(包括新連線)的事務隔離級別
    SET GLOBAL TRANSACTION ISOLATION LEVEL 事務隔離級別;

悲觀鎖和樂觀鎖的

悲觀鎖:假設會發生併發衝突,迴避一切可能違反資料完整性的操作。

樂觀鎖:假設不會發生併發衝突,只在提交操作時檢查是否違反資料完整性,注意樂觀鎖並不能解決髒讀的問題。

在一般情況下,悲觀鎖依靠資料庫的鎖機制實現,以保證操作最大程度的排他性和獨佔性,因而會導致資料庫效能的大量開銷和併發性很低,特別是對長事務而言,這種開銷往往過於巨大而無法承受。為了解決這樣的問題,樂觀鎖機制便出現了。樂觀鎖,大多情況下是基於資料版本( Version )記錄機制實現。何謂資料版本?即為資料增加一個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加一個 “version” 欄位來實現。讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交資料的版本資料與資料庫表對應記錄的當前版本資訊進行比對,如果提交的資料版本號大於資料庫表當前版本號,則給予更新,否則認為是過期資料。ok~,關於悲觀鎖和樂觀鎖的簡單概念就先了解到這。

共享鎖與排他鎖

在mysql中,為了保證資料一致性和防止資料處理衝突,引入了加鎖和解鎖的技術,這樣可以使資料庫中特定的資料在使用時不讓其他使用者(程序或事務)操作而為該資料加鎖,直到該資料被處理完成後再進行解鎖。根據使用目的不同把鎖分為共享鎖定(也稱為讀取鎖定)和排他鎖定(寫入鎖定)。

共享鎖定:將物件資料變為只讀形式的鎖定,這樣就允許多方同時讀取一個數據,此時資料將無法修改。
排他鎖定:在對資料進行insert/update/delete時進行鎖定,在此時其他使用者(程序或事務)一律不能讀取資料,從而也保證資料完整性。

事務、隔離級別、鎖之間的關係

通過上述的分析,我們也理解了事務、鎖和隔離級別的概念,但鎖和事務以及分離水平關係如何呢?實際上,事務是解決多條sql執行執行過程的原子性、一致性、隔離性、永續性的整體解決方案,而事務分離水平則是併發控制的整體解決方案,其實際是綜合利用各種型別的鎖來解決併發問題。鎖是資料庫併發控制的內部基礎機制。對應用開發人員來說,只有當事務分離水平無法解決併發問題和需求時,才有必要在語句中手動設定鎖。關於鎖的鎖定,對於UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及資料集加排他鎖(X);對於普通SELECT語句,InnoDB不會加任何鎖,事務可以通過以下語句顯示給記錄集加共享鎖或排他鎖。請注意InnoDB行鎖是通過給索引上的索引項加鎖來實現的,也就是說,只有通過索引條件檢索資料,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖。