事務相關

事務

事務(Transaction)是一組SQL組成的執行單元(unit),是數據庫併發控制和恢復回滾的基本單位mysql

一個事務可能包含多個SQL,要麼都失敗,要麼都成功sql

事務具有4個基本屬性:數據庫

Atomic,同一個事務裏,要麼都提交,要麼都回滾session

Consistency,即在事務開始以前和事務結束之後,數據庫的完整性約束沒有被破壞併發

Isolation,併發事務間的數據是彼此隔離的app

Durability,事務提交後,全部結果務必被持久化優化

支持事務的引擎:InnoDB、TokuDB、MyRocks.net

不支持事務的引擎:MyISAM、MEMORY/HEAPblog

mysql> show engines\G事務

顯示開始事務 

START TRANSACTION

    [READ WRITE]  默認

    [WITH CONSISTENT SNAPSHOT]

    [READ ONLY]

BEGIN/BEGIN WORK

開啓/關閉自動提交

set autocommit | @@autocommit = 0 | 1

提交事務

顯示提交

COMMIT

隱式提交

BEGIN/BEGIN WORK

START TRANSACTION

SET AUTOCOMMIT = 1

其餘非事務語句(DDL/DCL)

回滾事務

顯式回滾

ROLLBACK

隱式回滾

鏈接斷開,mysql > exit;

超時斷開,mysql > timeout; 鎖等待超時

被kill,mysql > kill x;

異常宕機

 

autocommit = 0 必要嗎

好處:

    多語句提交時,不會每一個SQL單獨提交,提升事務提交效率

麻煩:

    有個事務忘記提交,鎖一直未釋放

    另外一個事務長期鎖等待,嚴重影響tps

 

Python中的autocommit

import MySQLdb
from time import sleep
conn = MySQLdb.connect(host='1.2.3.4',port=3306,user='app')
conn.autocommit = True
cur = conn.cursor()
cur.execute("show global status")
while 1:
    sleep(1)

是Python方法,而不是數據庫的

cur.execute("set autocommit=1") 纔是數據庫的

 

事務隔離級別

若是沒有事務控制的話,那麼併發讀寫數據庫會有什麼隱患

髒讀:

事務T1修改了一行數據,事務T2在事務T1提交以前讀到了該行數據

不可重複讀:

一樣的條件,讀取過的數據,再次讀取出來發現值不同了,更改數據(修改或刪除)

幻讀:

一樣的條件,第1次和第2次讀取出來的記錄數不同,新增數據

丟失更新:

第一類丟失更新,即回滾致使的另外一個事務的更新丟失

第二類丟失更新,即事務A覆蓋事務B已經提交的數據

 

Read Uncommitted (讀未提交) 隔離級別最低

容許髒讀,容許事務查看其餘事務所進行的未提交的更改

Read Committed (讀已提交)

容許幻讀,不可重複讀,容許事務查看其餘事務所進行的已提交的更改

Repeatable Read (可重複讀)

消除了髒讀,不可重複讀,幻讀,保證事務一致性

確保每一個事務的讀取結果老是同樣,默認隔離級別

Serializable (串行) 隔離級別最高

串行化讀,每次讀都須要得到表級共享鎖,讀寫間相互都會阻塞

隔離級別和可能發現的現象總結以下:

 

my.cnf配置

[mysqld]分段中,加入一行

transaction-isolation = "READ-COMMITTED" #默認值是REPEATABLE-READ

在線(全局)修改

set [global] transaction isolation level read committed;

查看當前隔離級別

select @@global.transaction_isolation,@@session.transaction_isolation;

https://blog.csdn.net/qq_37771475/article/details/86493631 很詳細

 

InnoDB讀

快照讀,snapshot read

    基於read view讀可見版本,不加鎖

    start transaction with consistent read + select

    普通select

    由基於某個時間點的一組InnoDB內部(活躍)事務構建而成的列表

當前讀,current read

    讀(已提交的)最新版本,並加鎖

    select ... for update/lock in share mode

    DML

 

InnoDB只讀事務

5.6開始支持

5.7進一步優化,不記錄redo log

5.7起,非顯示聲明的事務,默認都是以只讀模式啓動,事務過程當中有數據被修改時,才自動變動爲讀寫模式

顯式聲明的只讀事務時innodb_trx.trx_is_read_only = 1

mysql> start transaction read only; 

mysql> select * from t1;

 

 

InnoDB是如何解決幻讀的

RR級別下解決了幻讀問題

引入gap lock,把2條記錄中間的gap鎖住,避免其餘事務寫入

存在幻讀的條件:

    <= RC級別

    innodb_locks_unsafe_for_binlog = 1

8.0版本innodb_lock_unsafe_for_binlog沒有這個參數

 

InnoDB semi-consistent read

semi-consistent read是read committed與consistent read的結合 

一個update語句,若是讀到一行已經加鎖的記錄,此時InnoDB返回記錄最近提交的版本,由MySQL上層判斷此版本是否知足update的where條件。若知足,則MySQL會從新發起一次讀操做,此時會讀取行的最新版本(並加鎖)

semi-consistent read發生的條件:

    <= read committed隔離級別

    innodb_locks_unsafe_for_binlog = 1 時

    update請求(不含insert、delete)

相關文章
相關標籤/搜索