事務(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 很詳細
快照讀,snapshot read
基於read view讀可見版本,不加鎖
start transaction with consistent read + select
普通select
由基於某個時間點的一組InnoDB內部(活躍)事務構建而成的列表
當前讀,current read
讀(已提交的)最新版本,並加鎖
select ... for update/lock in share mode
DML
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沒有這個參數
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)