天天看點

mysql之事務和鎖

并發控制:

    MVCC 多版本并發控制。

        使用者在操作時操作的是帶有時間點的快照。而不是表本身。最後将快照進行合并。

鎖:

    讀鎖:共享鎖。讀取操作不會對使用者之間産生影響。

    寫鎖:獨占鎖。一個使用者寫入時,其他使用者就不能寫入。

    可以手動設定:

        LOCK TABLES TBNAME [AS AILAS] LOCK_TYPE,... 給表加鎖

            LOCK_TYPE

                READ 讀鎖

                WRITE 寫鎖

        UNLOCK TABLES 解除所有表的鎖,注意不能指定TBNAME。

    鎖力度:

        表鎖:鎖定整張表

        頁鎖:鎖定頁塊,一個頁塊中包含多個行。

        行鎖:鎖定行

        mysql伺服器僅支援表鎖,行鎖需要存儲引擎支援。每個引擎對鎖的政策都不同。

        力度越精細越能提高并發,越粗糙越能友善管理。

    執行個體:

        1.給tutors表建立讀鎖:

            mysql>LOCK TABLES tutors read;

        2.解鎖:

            mysql>UNLOCK TABLES;

事務:

    事務就是将多個涉及到大量的cpu操作和io操作的多個操作看做一組。這樣的組被稱作事務。

    事務的流程:

        啟動(START TANSACTION)-->寫入撤銷日志中 --> 執行操作(一堆SQL語句)|執行過程中斷後根據撤銷日志復原(ROLLBACK)--> 寫入重做日志中-->  根據重做日志進行磁盤操作 (送出COMMINT)

    多事務并發:

        例如進行io操作時cpu空閑,可以利用cpu進行新的事務,這是多事務并發的基本思想。但是多事務并發有可能造成事物之間進行互動。是以此時要使用隔離機制保證資料庫的一緻性。

        依賴的技術手段:

            鎖

            時間戳

            多版本和快照隔離

    多事務互動:

        通過io産生的資料集,事務之間就可以進行互動。但是資料集是實時變動的。是以這種互動會産生不一緻狀态。在這種狀态下,互動的結果可能産生差錯

        髒讀:

            一個事務未送出前,另一個事務進行讀取操作。讀操未送出的内容稱為髒讀。

        幻讀:

            一個事務對某個表執行查詢操作時,另一個事務對此表進行修改,會造成前後查詢不一緻。

    事務的狀态:

        活動的:正在執行的。

        部分送出的:執行完成,但是最後一條語句正在送出中。

        失敗的:執行完成,送出未能完成。

        終止的:執行過程中終止,未送出。

        送出的:執行完成,送出完成。

        鎖饑餓:

        死鎖:

        注意:事務一旦送出就無法撤銷,隻能通過補償事務。

    事務排程:

        1.可恢複排程:

        2.無級聯排程:

    儲存點(SAVEPOINT):用于在事務中建立儲存點,這樣復原的時候不會全部復原,隻復原到儲存點之前的所有狀态。

        使用SAVEPOINT SPNAME建立儲存點。

        使用ROLLBACK TO SPNAME復原到儲存點。

    支援事務要先支援ACID特性

    ACID特性:

        原子性(Automicity):一個事務當中的操作語句要麼都執行完成,要麼都不執行。

        一緻性(Consistency):事務完成前和完成後,對資料庫來說狀态是沒有改變的。一緻性要在隔離狀态下才能保證。

        隔離性(Isolation):若有2個事務同時執行,其中一個在送出錢前都不被另一個察覺到。即一個事務的中間過程不影響到其他操作。伺服器使用事務排程(例如MVCC)來使事務間影響最小。

        持久性(Durability):一個事務送出後,即便伺服器出現任何故障,也必須保證不引起事務出現不一緻性。即事務的操作是持續有效的。

            實作手段:

                1.事務送出前已經将資料寫入硬碟。要消耗大量的磁盤io。

                2.結合事務日志完成。使用的是順序io而不是向資料檔案那樣使用随機io。速度非常快。

存儲引擎對事務的支援:

    mysql中,是否支援事務,是根據存儲引擎來定義的。

    MyISAM不支援事務。

    InnoDB支援事務。若不明确啟動事務,預設autocommit是啟動的,會自動送出。建議明确使用事務,并關閉自動送出。關閉後若不明确事務,則執行的所有操作都被看成在一個事務中。

事務日志:

    重做日志(redo log):

        每次操作都在記憶體中操作,并寫入重做日志中記錄。一旦操作完成則表示事務送出。一段時間後,根據日志内容将操作寫入硬碟。

    撤銷日志(undo log):

        保留每一次操作前的狀态。以便恢複。

日志組:

    日志也是檔案,檔案中隻記錄操作,不記錄對應的資料。

    多個日志檔案構成日志組。

    日志檔案是輪流使用。一個記錄滿以後自動記錄到下個檔案中。記錄滿的日志檔案會将操作同步到硬碟。然後清空日志。

    日志檔案的大小要根據具體需求定義。

    詳細請參考日志相關。

事務隔離等級:

    為了解決多事務互動中出現的各種問題。采用此機制

    級别越高,安全性越好,并發能力越弱。

    READ-UNCOMMITED 讀未送出。最低級别。一個事務執行完成後另一個事務馬上能看到。此時前一個事務還未能送出。事務之間幹擾最大。

    READ-COMMITTED 讀送出。一個事務送出後才能看到。不送出其他事務看到的不變化。

    REPEATABLE-READ 可重讀。一個事務無論送出與否,另一個事務在送出前看到的不變化,一旦該事務送出,則看到的是最終值。InnoDB預設級别為此。

    SERIALIZABLE 可串行。最進階别。可以同時啟動多個事務,但一個時間内隻能執行一個事務。另一個事務想要操作必須等前面的事務送出完畢後才行。

    mysql預設是REPEATABLE-READ。大多數SQL預設是READ-COMMITTED

    使用SHOW GOBAL VARIABLES LIKE ‘tx_isolation’檢視。

分布式事務(XA):

    是一種高層次的事務,使用兩段式方式(準備-送出 prepare-then-commit)将ACID屬性擴充到存儲引擎的外币,甚至是資料庫外部。

    準備階段:

        事務協調員同時所有參與者準備送出事務

    送出階段:

        事務協調員在收到所有參與者發出的就緒資訊是,會訓示所有參與者進行真正的送出操作。

    預設InnoDB是啟用分布式事務的,使用SHOW GLOBAL VARIABLES LIKE ‘innodb_support_xa’檢視

執行個體:

    1.啟動一個事務:

        mysql>START TRANSACTION;

        啟動後的操作都被認為是事務中的操作

    2.執行操作:

        mysql> DELETE FROM students WHERE Name LIKE 'stu%';

    3.完成操作後送出:

        mysql>COMMIT;

        注意:一旦送出将不能復原。

    4.或者是復原:

        mysql>ROLLBACK;

    5.修改伺服器設定,禁用自動送出

        mysql預設是啟動自動送出的,即執行操作後馬上送出,這樣會占用大量的磁盤io,降低性能。

        mysql> SELECT @@autocommit;

        mysql> SET autocommit=0;

    6.建立儲存點:

        使用

        mysql>SAVEPOINT abc;

    7.復原到某個儲存點:

        mysql>ROLLBACK TO abc;

    8.檢視目前的隔離級别:

        mysql>SELECT @@tx_isolation;

    9.修改目前會話隔離級别:

        mysql>SET tx_isolation=‘LEVEL’;

    10.修改全局隔離級别:

        #vim /etc/my.cnf

            [mysqld]

            ...

            transaction-isolation = LEVEL