事務(wù)就是要保證一組數(shù)據(jù)庫(kù)操作每瞒,要么全部成功金闽,要么全部失敗。在MySQL中剿骨,事務(wù)支持是在引擎層實(shí)現(xiàn)的
ACID(Atomicity代芜、Consistency、Isolation浓利、Durability挤庇,即原子性、一致性贷掖、隔離性嫡秕、持久性)
InnoDB里面每個(gè)事務(wù)有一個(gè)唯一的事務(wù)ID,叫作transaction id羽资。它是在事務(wù)開(kāi)始的時(shí)候向InnoDB的事務(wù)系統(tǒng)申請(qǐng)的淘菩,是按申請(qǐng)順序嚴(yán)格遞增的
隔離性與隔離級(jí)別
讀未提交(read uncommitted) 一個(gè)事務(wù)還沒(méi)提交時(shí),它做的變更就能被別的事務(wù)看到
讀提交(read committed)一個(gè)事務(wù)提交之后屠升,它做的變更才會(huì)被其他事務(wù)看到,查詢只承認(rèn)在語(yǔ)句啟動(dòng)前就已經(jīng)提交完成的數(shù)據(jù)
可重復(fù)讀(repeatable read) 一個(gè)事務(wù)執(zhí)行過(guò)程中看到的數(shù)據(jù)潮改,總是跟這個(gè)事務(wù)在啟動(dòng)時(shí)看到的數(shù)據(jù)是一致的,未提交變更對(duì)其他事務(wù)也是不可見(jiàn)的,查詢只承認(rèn)在事務(wù)啟動(dòng)前就已經(jīng)提交完成的數(shù)據(jù)
串行化(serializable )同一行記錄腹暖,“寫”會(huì)加“寫鎖”汇在,“讀”會(huì)加“讀鎖”。當(dāng)出現(xiàn)讀寫鎖沖突的時(shí)候脏答,后訪問(wèn)的事務(wù)必須等前一個(gè)事務(wù)執(zhí)行完成糕殉,才能繼續(xù)執(zhí)行
長(zhǎng)事務(wù)和回滾日志
回滾日志: 在MySQL中,每條記錄在更新的時(shí)候都會(huì)同時(shí)記錄一條回滾操作殖告。記錄上的最新值阿蝶,通過(guò)回滾操作,都可以得到前一個(gè)狀態(tài)的值
在查詢這條記錄的時(shí)候黄绩,不同時(shí)刻啟動(dòng)的事務(wù)會(huì)有不同的read-view,要獲取舊的視圖羡洁,必須將當(dāng)前值依次執(zhí)行回滾操作得到
當(dāng)沒(méi)有事務(wù)再需要用到這些回滾日志時(shí),就是當(dāng)系統(tǒng)里沒(méi)有比這個(gè)回滾日志更早的read-view的時(shí)候爽丹,回滾日志會(huì)被刪除
長(zhǎng)事務(wù)的影響系統(tǒng)里面會(huì)存在很老的事務(wù)視圖筑煮,在這個(gè)事務(wù)提交之前數(shù)據(jù)庫(kù)里面它可能用到的回滾記錄都必須保留辛蚊,這就會(huì)導(dǎo)致大量占用存儲(chǔ)空間
set autocommit=0 這個(gè)命令會(huì)將這個(gè)線程的自動(dòng)提交關(guān)掉,只執(zhí)行一個(gè)select語(yǔ)句真仲,這個(gè)事務(wù)就啟動(dòng)了袋马,而且并不會(huì)自動(dòng)提交。持續(xù)存在直到你主動(dòng)執(zhí)行commit 或 rollback 語(yǔ)句秸应,或者斷開(kāi)連接
commit work and chain 提交事務(wù)并自動(dòng)啟動(dòng)下一個(gè)事務(wù)虑凛,省去了再次執(zhí)行begin語(yǔ)句的開(kāi)銷
查找持續(xù)時(shí)間超過(guò)60s的事務(wù)
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60
SET MAX_EXECUTION_TIME
命令,來(lái)控制每個(gè)語(yǔ)句執(zhí)行的最長(zhǎng)時(shí)間灸眼,避免單個(gè)語(yǔ)句意外執(zhí)行太長(zhǎng)時(shí)間
監(jiān)控 information_schema.Innodb_trx表卧檐,設(shè)置長(zhǎng)事務(wù)閾值墓懂,超過(guò)就報(bào)警/或者kill
設(shè)置innodb_undo_tablespaces
(默認(rèn)值為0焰宣,表示不獨(dú)立設(shè)置undo的tablespace,默認(rèn)記錄到ibdata系統(tǒng)表空間中,否則捕仔,則在undo目錄下創(chuàng)建這么多個(gè)undo文件)成2(或更大的值)匕积,如果真的出現(xiàn)大事務(wù)導(dǎo)致回滾段過(guò)大方便清理
可重復(fù)讀和MVCC
MVCC 數(shù)據(jù)表中的一行記錄,其實(shí)可能有多個(gè)版本(row)榜跌,每個(gè)版本有自己的row trx_id,舊版本需要根據(jù)當(dāng)前版本和undo log計(jì)算出來(lái)
begin/start transaction 命令并不是一個(gè)事務(wù)的起點(diǎn)闪唆,在執(zhí)行到它們之后的第一個(gè)操作InnoDB表的語(yǔ)句(第一個(gè)快照讀語(yǔ)句),事務(wù)才真正啟動(dòng)钓葫。如果想要馬上啟動(dòng)一個(gè)事務(wù)悄蕾,可以使用start transaction with consistent snapshot1
InnoDB為每個(gè)事務(wù)構(gòu)造了一個(gè)數(shù)組,用來(lái)保存這個(gè)事務(wù)啟動(dòng)瞬間础浮,當(dāng)前正在“活躍”的所有事務(wù)ID帆调。“活躍”指的就是豆同,啟動(dòng)了但還沒(méi)提交,數(shù)組里面事務(wù)ID的最小值記為低水位番刊,當(dāng)前系統(tǒng)里面已經(jīng)創(chuàng)建過(guò)的事務(wù)ID的最大值加1記為高水位。
這個(gè)視圖數(shù)組和高水位影锈,就組成了當(dāng)前事務(wù)的一致性視圖(read-view)芹务,只有版本已提交,而且是在視圖創(chuàng)建前提交的才可見(jiàn)
更新數(shù)據(jù)都是先讀后寫的鸭廷,而這個(gè)讀枣抱,只能讀當(dāng)前的值,稱為“當(dāng)前讀”(current read) set k=k+1會(huì)拿最新的值做更新辆床,更新后的trx_id是自己的更新佳晶,可以直接使用,如果當(dāng)前的記錄的行鎖被其他事務(wù)占用的話佛吓,就需要進(jìn)入鎖等待