欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

mysql事務(wù)詳細(xì)介紹

 更新時(shí)間:2021年12月07日 16:57:07   作者:奔跑的蝸牛...  
大家好,本篇文章主要講的是mysql事務(wù)詳細(xì)介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽<BR>

簡(jiǎn)介

事務(wù)是由一組sql語(yǔ)句組成的邏輯處理單元

事務(wù)四個(gè)特性

原子性(Atomicity):
	要么都成功要么都失敗
	undo log實(shí)現(xiàn)
一致性(Consistent):
	如轉(zhuǎn)賬前后兩個(gè)數(shù)額總合保持不變
隔離性(lsolation):數(shù)據(jù)庫(kù)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的“獨(dú)立”環(huán)境下運(yùn)行
	鎖,mvcc多版本并發(fā)控制
持久性(Durable):事務(wù)提交持久化磁盤
	redo log

事務(wù)隔離級(jí)別

數(shù)據(jù)庫(kù)的事務(wù)隔離級(jí)別有四種,分別是讀未提交,讀已提交,可重復(fù)讀,序列化,不同的隔離級(jí)別會(huì)產(chǎn)生臟讀,幻讀,不可重復(fù)讀等相關(guān)問(wèn)題,因此,在選擇隔離級(jí)別的時(shí)候要根據(jù)應(yīng)用場(chǎng)景來(lái)決定,使用不同的隔離級(jí)別

隔離級(jí)別 臟讀 不可重復(fù)讀 幻讀
READ-UNCOMMITTED
READ-COMMITED ×
REPEATABLE-READ × ×
SERIALIZABLE × × ×

事務(wù)隔離級(jí)別帶來(lái)的問(wèn)題

臟讀(Dirty Reads一個(gè)事務(wù)訪問(wèn)到了另外一個(gè)事務(wù)未提交的數(shù)據(jù)):
	當(dāng)一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù),并且對(duì)數(shù)據(jù)進(jìn)行了修改,而這種修改還沒(méi)有提交到數(shù)據(jù)庫(kù)中,這時(shí)另一個(gè)事務(wù)也訪問(wèn)這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。
不可重復(fù)度(Non-Repeatable Reads 一個(gè)事務(wù)兩次同樣的查詢,查詢到了不同的數(shù)據(jù)):
	一個(gè)事務(wù)在讀取某些數(shù)據(jù)后的某個(gè)時(shí)間,再次讀取以前讀過(guò)的數(shù)據(jù),發(fā)現(xiàn)和以前讀出的數(shù)據(jù)不一致
	更新刪除
幻讀(Phantom Reads 一個(gè)事務(wù)兩次同樣的查詢,查詢到了不同的數(shù)據(jù)):
	一個(gè)事務(wù)按照相同的查詢條件重新讀取以前查詢過(guò)的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù)
	插入

驗(yàn)證

查看事務(wù)的隔離級(jí)別show variables like ‘tx_isolation';

查看事務(wù)是否自動(dòng)提交show variables like ‘a(chǎn)utocommit';

關(guān)閉自動(dòng)提交事務(wù)=0|OFF

set autocommit = 0;

臟讀:

設(shè)置事務(wù)隔離級(jí)別A、B
	set session transaction isolation level read uncommitted;
sessionA
開啟事務(wù)
	start transaction;
插入一條數(shù)據(jù)
	INSERT INTO `db_test`.`t_user`(`id`, `name`) VALUES (5, 'DuQi');
sessionB
另一個(gè)連接進(jìn)行查詢
	select * from t_user;
	+----+----------+
	| id | name     |
	+----+----------+
	|  1 | ZhangSan |
	|  2 | LiSi     |
	|  3 | WangWu   |
	|  4 | LaoWang  |
	|  5 | DuQi     |
	+----+----------+
	此時(shí)連接B查詢到連接A未提交的事務(wù)的記錄id為5
	
到這里驗(yàn)證了一個(gè)session讀取到了另一個(gè)事務(wù)未提交的數(shù)據(jù)

不可重復(fù)讀:

修改事務(wù)隔離級(jí)別
	set session transaction isolation level read committed;
A開啟事務(wù)
	start transaction;
驗(yàn)證更新
	B執(zhí)行查詢語(yǔ)句
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | DuQi     |
		+----+----------+
	A執(zhí)行更新語(yǔ)句
		update t_user set name = 'duqi' where id = 5;
	B執(zhí)行查詢語(yǔ)句
		start transaction;
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | DuQi     |
		+----+----------+
	A提交事務(wù)
		commit;
	B執(zhí)行查詢語(yǔ)句(同一個(gè)事務(wù)兩次查詢結(jié)果不一致)
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | duqi     |
		+----+----------+
繼續(xù)驗(yàn)證刪除
	A 開啟事務(wù) B開啟事務(wù)
		start transaction ;
	A刪除一條記錄
		delete from t_user where id = 5;
	B事務(wù)查詢正常,查詢被刪除的記錄還在
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | DuQi     |
		+----+----------+
	A commit;
	B 繼續(xù)查詢 發(fā)現(xiàn)同一事物中多次查詢結(jié)果不一致
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		+----+----------+

驗(yàn)證插入
	A、B 開啟事務(wù)
		start transaction;
	A 插入記錄
		INSERT INTO `db_test`.`t_user`(`id`, `name`) VALUES (5, 'DuQi');
	B進(jìn)行查詢
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		+----+----------+	
	A提交事務(wù)
		commit;
	B查詢 也是能查詢到A提交的事務(wù)
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | DuQi     |
		+----+----------+

幻讀:

修改事務(wù)隔離級(jí)別
	set session transaction isolation level repeatable read;
A、B開啟事務(wù)
	start transaction;
A插入一條數(shù)據(jù)	
	INSERT INTO `db_test`.`t_user`(`id`, `name`) VALUES (5, 'DuQi');
B查詢
	MySQL [db_test]> select * from t_user;
	+----+----------+
	| id | name     |
	+----+----------+
	|  1 | ZhangSan |
	|  2 | LiSi     |
	|  3 | WangWu   |
	|  4 | LaoWang  |
	+----+----------+
A提交事務(wù)
	commit;
B事務(wù)查詢
	MySQL [db_test]> select * from t_user;
	+----+----------+
	| id | name     |
	+----+----------+
	|  1 | ZhangSan |
	|  2 | LiSi     |
	|  3 | WangWu   |
	|  4 | LaoWang  |
	|  5 | DuQi     |
	+----+----------+
可能發(fā)現(xiàn),不同事務(wù)之間,插入是可以查詢到的

咱們?cè)倮^續(xù)驗(yàn)證更新和刪除
	A、B開啟事務(wù)
	A更新 update t_user set name = 'duqi' where id = 5;
	B查詢
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | DuQi     |
		+----+----------+	
	A提交事務(wù)commit
	B繼續(xù)查詢
		MySQL [db_test]> select * from t_user;
		+----+----------+
		| id | name     |
		+----+----------+
		|  1 | ZhangSan |
		|  2 | LiSi     |
		|  3 | WangWu   |
		|  4 | LaoWang  |
		|  5 | DuQi     |
		+----+----------+
	咱們?cè)倮^續(xù)驗(yàn)證刪除
		A、B開啟事務(wù)
		A事務(wù)執(zhí)行刪除操作 delete from t_user where id = 5;
		B事務(wù)執(zhí)行查詢
			MySQL [db_test]> select * from t_user;
			+----+----------+
			| id | name     |
			+----+----------+
			|  1 | ZhangSan |
			|  2 | LiSi     |
			|  3 | WangWu   |
			|  4 | LaoWang  |
			|  5 | duqi     |
			+----+----------+
		A提交事務(wù),B繼續(xù)查詢
			MySQL [db_test]> select * from t_user;
			+----+----------+
			| id | name     |
			+----+----------+
			|  1 | ZhangSan |
			|  2 | LiSi     |
			|  3 | WangWu   |
			|  4 | LaoWang  |
			|  5 | duqi     |
			+----+----------+
可能大家會(huì)發(fā)現(xiàn),REPEATABLE-READ 事務(wù)隔離級(jí)別解決了刪除和更新的問(wèn)題,但是插入的問(wèn)題一直存在。		

MVCC

多版本并發(fā)控制。MVCC是一種并發(fā)控制的方法,一般在數(shù)據(jù)庫(kù)管理系統(tǒng)中,實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的并發(fā)訪問(wèn),在編程語(yǔ)言中實(shí)現(xiàn)事務(wù)內(nèi)存

mvcc在Mysql INNODB中的實(shí)現(xiàn)主要是為了提高數(shù)據(jù)庫(kù)并發(fā)性能,用更好的方式去處理讀寫沖突,做到即使有讀寫沖突時(shí),也能做到不加鎖,非阻塞并發(fā)讀。

了解mvcc之前首先要了解兩個(gè)概念,什么是當(dāng)前讀,什么是快照讀

當(dāng)前讀

讀取最新版本的數(shù)據(jù)

像select lock in share mode(共享鎖),select for update;update、insert、delete(排他鎖)這些操作都是一種當(dāng)前讀,
為什么叫當(dāng)前讀?
	就是它讀取的是記錄的最新版本,讀取時(shí)還要保證其他并發(fā)事務(wù)不能修改當(dāng)前記錄,會(huì)對(duì)讀取的記錄進(jìn)行加鎖

快照讀

讀取歷史版本的數(shù)據(jù)

像不加鎖的select操作就是快照讀,既不加鎖的非阻塞讀;
快照讀的前提是隔離級(jí)別不是串行級(jí)別,串行級(jí)別下的快照讀會(huì)退化成當(dāng)前讀;
之所以出現(xiàn)快照讀的情況,是基于提高并發(fā)性能的考慮,快照讀的實(shí)現(xiàn)是基于多版本控制并發(fā)控制,既MVCC,可以認(rèn)為mvcc是行鎖的一個(gè)變種,但它在很多情況下避免了加鎖操作,降低了開銷;

當(dāng)前讀、快照讀、MVCC關(guān)系

MVCC多版本并發(fā)控制指的是維持一個(gè)數(shù)據(jù)的多個(gè)版本,使得讀寫操作沒(méi)有沖突,快照讀是mysql為實(shí)現(xiàn)mvcc的一個(gè)非阻塞讀功能。
mvcc模塊在Mysql中的具體實(shí)現(xiàn)是由三個(gè)隱式字段,undo日志,readview三個(gè)組件來(lái)實(shí)現(xiàn)的。

這里補(bǔ)充一點(diǎn):三個(gè)隱式字段中其中有一個(gè)是列的唯一標(biāo)志。有些同學(xué)設(shè)計(jì)表的時(shí)候一定要加主鍵(列依賴主鍵),即使它幾乎無(wú)用處也要加上。其實(shí)對(duì)于配置表,幾乎不進(jìn)行增刪操作的表完全沒(méi)必要加主鍵,mysql在插入數(shù)據(jù)的時(shí)候會(huì)進(jìn)行判斷表有無(wú)主鍵,如果有主鍵會(huì)使用主鍵作為唯一標(biāo)示,如果沒(méi)有主鍵,會(huì)自動(dòng)生成7byte大小的主鍵,所以表的合理性要根據(jù)不用使用場(chǎng)景進(jìn)行設(shè)計(jì)。

mvcc 解決的問(wèn)題

并發(fā)場(chǎng)景

1、讀讀:不存在任何問(wèn)題,也不需要并發(fā)控制
2、讀寫:有線程安全問(wèn)題,可能會(huì)造成事務(wù)隔離級(jí)別問(wèn)題,可能遇到臟讀、不可重復(fù)讀、幻讀
3、寫寫:有線程安全問(wèn)題,可能存在更新丟失問(wèn)題

解決的問(wèn)題

1、在并發(fā)讀寫數(shù)據(jù)庫(kù)時(shí),可以做到在讀操作時(shí)不用阻塞寫操作,寫操作也不用阻塞讀操作,提高了數(shù)據(jù)庫(kù)并發(fā)讀寫的性能
2、解決臟讀、幻讀、不可重復(fù)讀等事務(wù)隔離問(wèn)題,但是不能解決更新丟失問(wèn)題

MVCC實(shí)現(xiàn)原理

mvcc的實(shí)現(xiàn)原理主要依賴于記錄中的三個(gè)隱藏字段、undolog,read view來(lái)實(shí)現(xiàn)的。

隱藏字段

行記錄除了我們自定義的字段外,還有數(shù)據(jù)庫(kù)隱式定義的DB_TRX_ID,BD_ROLL_PTR,DB_ROW_ID等字段

DB_TRX_ID 最近修改事務(wù)id:
	6字節(jié),記錄創(chuàng)建這條記錄或者最后一次修改該記錄的事務(wù)id
DB_ROLL_PTR 回滾指針:
	7字節(jié),指向這條記錄的上一個(gè)版本,用于配合undolog,指向上一個(gè)舊版本
DB_ROW_ID 隱藏主鍵:
	6字節(jié),如果數(shù)據(jù)庫(kù)表沒(méi)有主鍵,那么innodb會(huì)自動(dòng)生成一個(gè)6字節(jié)的row_id

undo log

undo log被稱之為回滾日志,表示進(jìn)行insert,delete,update操作的時(shí)候產(chǎn)生的方便回滾日志

當(dāng)進(jìn)行insert操作的時(shí)候,產(chǎn)生的undo log只在事務(wù)回滾的時(shí)候需要,并且在事務(wù)提交之后可以被立刻丟棄
當(dāng)進(jìn)行update和delete操作的時(shí)候,產(chǎn)生的undo log不僅僅在事務(wù)回滾的時(shí)候需要,在快照讀的時(shí)候也需要,所以不能隨便刪除,只有在快照讀或事務(wù)回滾不涉及該日志時(shí),對(duì)應(yīng)的日志才會(huì)被purge線程統(tǒng)一清除(當(dāng)數(shù)據(jù)發(fā)生更新和刪除操作的時(shí)候都只是設(shè)置一下老記錄,如果某個(gè)記錄的deleted_id為true,并且DB_TRX_ID相對(duì)于purge線程的read view可見(jiàn),那么這條記錄一定可以被清除的)

原理

當(dāng)進(jìn)行insert操作時(shí),會(huì)生成對(duì)應(yīng)delete語(yǔ)句
當(dāng)進(jìn)行delete操作時(shí),會(huì)備份原數(shù)據(jù)的insert語(yǔ)句
當(dāng)進(jìn)行update時(shí),會(huì)記錄原數(shù)據(jù)的update語(yǔ)句
這樣操作方便記錄回滾

read View

READ View是事務(wù)進(jìn)行快照讀操作的時(shí)候產(chǎn)生的讀視圖,在該事務(wù)執(zhí)行快照的那一刻,會(huì)生成一個(gè)數(shù)據(jù)系統(tǒng)當(dāng)前的快照,記錄并維護(hù)系統(tǒng)當(dāng)前活躍事務(wù)的id,事務(wù)的id值是遞增的。

DB_ROW_ID DB_TRX_ID DB_ROLL_PTR c_name i_age
1 1 zhangsan1 18
2 2 1 zhangsan2 19
READ VIEW的最大作用是用來(lái)做可見(jiàn)性判斷的,也就是說(shuō)當(dāng)某個(gè)事務(wù)在執(zhí)行快照讀的時(shí)候,對(duì)該記錄創(chuàng)建一個(gè)Read View的視圖,把它當(dāng)作條件去判斷當(dāng)前事務(wù)能夠看到哪個(gè)版本的數(shù)據(jù),有可能讀取到的是最新的數(shù)據(jù),也有可能讀取到的是最新的數(shù)據(jù),也有可能讀取的是當(dāng)前記錄的undolog中某個(gè)版本的數(shù)據(jù)
read view遵循的可見(jiàn)性算法主要是將要被修改的數(shù)據(jù)的最新記錄中的DB_TRX_ID取出來(lái),與系統(tǒng)當(dāng)前其他活躍事務(wù)的id去對(duì)比,如果DB_TRX_ID跟READ VIEW的屬性做了比較,不符合可見(jiàn)性,那么就通過(guò)DB_ROLL_PTR回滾指針去取出undolog中的DB_TRX_ID做比較,既遍歷鏈表中的DB_TRX_ID,直到找到滿足條件的DB_TRX_ID,這個(gè)DB_TRX_ID所在的舊記錄就是當(dāng)前事務(wù)能看到的最新老版本數(shù)據(jù)

可見(jiàn)性規(guī)則

了解可見(jiàn)性規(guī)則之前首先要了解下Read View中的三個(gè)全局屬性

trx_list:
	一直數(shù)值列表,用來(lái)維護(hù)Read View生成時(shí)刻系統(tǒng)正活躍的事務(wù)ID
up_limit_id:
	記錄trx_list列表中事務(wù)ID的最小ID
low_limit_id:
	Read View生成時(shí)刻系統(tǒng)尚未分配下一個(gè)事務(wù)ID

比較規(guī)則

1、首先判斷DB_TRX_ID < up_limit_id,如果小于,則當(dāng)前事務(wù)能看到DB_TRX_ID所在的記錄,如果大于等于進(jìn)入下一個(gè)判斷
2、判斷DB_TRX_ID >= low_limit_id,如果大于等于則代表DB_TRX_ID所在的記錄在Read View生成后才出現(xiàn)的,那么對(duì)于當(dāng)前事務(wù)肯定不可見(jiàn),如果小于,進(jìn)入下一步判斷
3、判斷DB_TRX_ID是否在活躍事務(wù)中,如果在,則代表在Read View生成時(shí)刻,這個(gè)事務(wù)還是活躍狀態(tài),還沒(méi)有commit,修改的數(shù)據(jù),當(dāng)前事務(wù)也是看不到,如果不在,則說(shuō)明這個(gè)事務(wù)在Read View生成之前就已經(jīng)開始commit,那么修改的結(jié)果是能夠看到的。

到此這篇關(guān)于mysql事務(wù)詳細(xì)介紹的文章就介紹到這了,更多相關(guān)mysql事務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論