事務與鎖介紹 1

2021-09-19 05:10:00 字數 3991 閱讀 9068

事務是一系列資料庫操作的有序集合

事務必須服從iso/iec所制定的acid原則。acid是原子性(atomicity)、一致性(consistency)、隔離性 (isolation)和永續性(durability)的縮寫。

通俗的理解,事務是一組原子操作單元,從資料庫角度說,就是一組sql指令,要麼全部執行成功,若因為某個原因其中一條指令執行有錯誤,則撤銷先前執行過的所有指令。更簡答的說就是:要麼全部執行成功,要麼撤銷不執行。

mysql中有多種加鎖機制:

1.共享鎖(share locks簡記為s鎖):又稱讀鎖,若事務t對資料物件a加上s鎖,則事務t可以讀a但不能修改a,其他事務只能再對a加s鎖,而不能加x鎖,直到t釋放a上的s鎖。這保證了其他事務可以讀a,但在t釋放a上的s鎖之前不能對a做任何修改。共享鎖是造成上鎖物件必須被大家共享,它排斥 排他鎖,因此別的會話不能獨佔資源對其修改(「修改」會先給修改物件加上 排他鎖 的)。但不排斥其他共享鎖,所以乙個物件可被多個會話同時加上共享鎖。

2.排它鎖(exclusivelocks簡記為x鎖):又稱寫鎖。若事務t對資料物件a加上x鎖,事務t可以讀a也可以修改a,其他事務不能再對a加任何鎖,直到t釋放a上的鎖。這保證了其他事務在t釋放a上的鎖之前不能再讀取和修改a。排他鎖很好理解,是自己獨佔資源。其它會話想再在同一物件上加共享或排他鎖都是不允許的。不過其它會話可以讀,這也證明普通的讀是不上鎖的。如果查的物件被修改,查詢操作還會會被重定向到對應的撤銷塊(原來的資料),以保證事務事物隔離和讀一致;

3.更新鎖(簡記為u鎖):用來預定要對此物件施加x鎖,它允許其他事務讀,但不允許再施加u鎖或x鎖;當被讀取的物件將要被更新時,則公升級為x鎖,主要是用來防止死鎖的。因為使用共享鎖時,修改資料的操作分為兩步,首先獲得乙個共享鎖,讀取資料,然後將共享鎖公升級為排它鎖,然後再執行修改操作。這樣如果同時有兩個或多個事務同時對乙個物件申請了共享鎖,在修改資料的時候,這些事務都要將共享鎖公升級為排它鎖。這些事務都不會釋放共享鎖而是一直等待對方釋放,這樣就造成了死鎖。如果乙個資料在修改前直接申請更新鎖,在資料修改的時候再公升級為排它鎖,就可以避免死鎖。

髒讀髒讀又稱無效資料的讀出,是指在資料庫訪問中,事務t1將某一值修改,然後事務t2讀取該值,此後t1因為某種原因撤銷對該值的修改,這就導致了t2所讀取到的資料是無效的。

不可重複讀

不可重複讀,是指在資料庫訪問中,乙個事務範圍內兩個相同的查詢卻返回了不同資料。

這是由於查詢時系統中其他事務修改的提交而引起的。比如事務t1讀取某一資料,事務t2讀取並修改了該資料,t1為了對讀取值進行檢驗而再次讀取該資料,便得到了不同的結果。

一種更易理解的說法是:在乙個事務內,多次讀同乙個資料。在這個事務還沒有結束時,另乙個事務也訪問該同一資料。那麼,在第乙個事務的兩次讀資料之間。由於第二個事務的修改,那麼第乙個事務讀到的資料可能不一樣,這樣就發生了在乙個事務內兩次讀到的資料是不一樣的,因此稱為不可重複讀,即原始讀取不可重複。

不可重複讀和髒讀的區別是,髒讀是某一事務讀取了另乙個事務未提交的髒資料,而不可重複讀則是讀取了前一事務提交的資料。

在某些情況下,不可重複讀並不是問題,比如我們多次查詢某個資料當然以最後查詢得到的結果為主。但在另一些情況下就有可能發生問題。

幻讀事務a在執行讀取操作,需要兩次統計資料的總量,前一次查詢資料總量後,此時事務b執行了新增資料的操作並提交。

這個時候事務a讀取的資料總量和之前統計的不一樣,就像產生了幻覺一樣,平白無故的多了幾條資料,稱為幻讀。

幻讀和不可重複讀主要是前者是針對資料的增刪導致的前後讀取不一致,後者則是針對同一條資料的修改導致的前後讀取不一致。

不同的事務隔離等級可以解決不同的事務併發問題

read uncommitted (讀未提交)

加鎖機制:

事務在讀資料的時候不對資料加鎖。

事務在修改資料的時候對資料增加行級x排他鎖,在事務結束時釋放(這點和有些地方說法不同,讀者可以自行實驗證明)。

各問題是否會出現

髒讀:

a事務修改一行資料,加上了x鎖;

事務b在a提交前讀該行資料,為什麼可以讀取,看以下官網原文

read uncommitted事務隔離級別沒有使用共享鎖去阻止其他事務修改當前事務讀取的資料。read uncommitted事務也不會使得獨佔鎖阻塞當前事務讀取已被修改但未被其他事務提交的行。設定此隔離級別,可以讀取未提交的修改,稱為髒讀——在事務結束前,資料中的值可能被改變,行也可能出現或者消失。

所以會有髒讀的問題

不可重複讀:

事務a讀取某一資料,不加鎖;

事務b讀取並修改了該資料,加x鎖,隨後提交,釋放鎖;

a為了對讀取值進行檢驗而再次讀取該資料,便讀到了事務b已提交的修改,第一次讀取不可重複。所以會有不可重複讀的問題。

幻讀:

事務a讀取全部資料,不加鎖;

事務b新增一條資料;

a再次讀取全部資料,發現多了一條。所以會有幻讀的問題。

read committed(讀已提交)(這裡介紹的是不用mvcc的情況,與真實情況有出入)

事務對當前被讀取的資料加 行級s鎖,一旦讀完該行,立即釋放該鎖;

事務在修改資料的時候對資料增加行級x排他鎖,在事務結束時釋放。

各問題是否會出現

髒讀:

a事務修改一行資料,加上了x鎖;

事務b在a提交前去讀該行資料,無法讀取。所以不會有髒讀的問題

不可重複讀:

事務a讀取某一資料,讀完立刻解s鎖;

事務b可以修改該資料,加x鎖,隨後提交,釋放x鎖;

a為了對讀取值進行檢驗而再次讀取該資料,便讀到了事務b已提交的修改,第一次讀取不可重複。所以會有不可重複讀的問題。

幻讀:

事務a讀取全部資料,讀完立刻解鎖;

事務b新增一條資料;

a再次讀取全部資料,發現多了一條。所以會有幻讀的問題。

repeatable read(可重複讀)(這裡介紹的是不用mvcc的情況,與真實情況有較大出入)

事務對當前被讀取的資料加 行級s鎖,在事務結束時釋放。

事務在修改資料的時候對資料增加行級x排他鎖,在事務結束時釋放。

各問題是否會出現

髒讀:

a事務修改一行資料,加x鎖;

事務b在a提交前去讀該行資料,無法讀取。所以不會有髒讀的問題

不可重複讀:

事務a讀取某一資料,加s鎖;

事務b試圖修改了該資料,有s鎖無法修改,

a為了對讀取值進行檢驗而再次讀取該資料,其他事務無法修改該資料,第一次讀取可重複。所以不會有不可重複讀的問題。

幻讀:

事務a讀取全部資料;

事務b新增一條資料;

a再次讀取全部資料,發現多了一條。所以會有幻讀的問題。

serializable(序列化)

事務對當前被讀取的資料加 範圍s鎖,在事務結束時釋放。

事務在修改資料的時候對資料增加範圍x排他鎖,在事務結束時釋放。

各問題是否會出現

髒讀:

a事務修改一行資料,加x鎖;

事務b在a提交前去讀該行資料,無法讀取。所以不會有髒讀的問題

不可重複讀:

事務a讀取某一資料,加s鎖;

事務b試圖修改了該資料,有s鎖無法修改,

a為了對讀取值進行檢驗而再次讀取該資料,其他事務無法修改該資料,第一次讀取可重複。所以不會有不可重複讀的問題。

幻讀:

事務a讀取全部資料,對根據索引判斷的範圍(沒有根據索引查詢就會加在主鍵上)加鎖(對於範圍的指定這裡不詳細說明了,比較複雜);

事務b新增一條資料,如果在a讀取產生的加鎖判斷範圍內則不能新增,因為該判斷範圍內對應的行資料已被鎖定,不論是否存在;

所以不會有幻讀的問題。

mysql事務與鎖機制 mysql事務與鎖機制

在併發下事務會容易出現的一些問題 資料更新丟失 兩個事務同時操作一條資料,乙個事務因為異常導致資料更新丟失 髒讀 乙個失誤開始讀取了某行資料,另外乙個事務已經更新了此資料但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都被回滾。不可重複讀 乙個事務對同一行資料重複讀取兩次,但是卻得到了不同的...

oracle事務與鎖

一.事務有4個特性,它們分別是原子性,一致性,分離性,永續性.1 原子性 事務的原子性是指,事務中程式是資料庫的邏輯工作單位,它對資料的修改要麼全部執行,要麼完全不執行.原子也意味著不可分割,不管有多少程式,只要在同乙個事務中,那麼它們就是乙個整體,如果都執行成功才意味著該事務成功,而有乙個操作失敗...

laravel 事務與鎖

接下來我們就測試一下 介面testname public function testname 測試結果 當我訪問test介面後,在訪問testname。很明顯,因為test介面把user表中id為1的資料鎖住,所以testname介面一直處在request中,無法完成。並且當我把2個介面都取消訪問後...