事物隔離級別詳解(實踐)

宏觀

在這裏插入圖片描述

併發造成什麼問題?

  1. 髒讀 : 一個事物讀取了另一個事物未提交的數據
  2. 不可重複讀 : 一個事物多次讀取一行數據導致前後數據不一致
  3. 幻讀: 一個事物讀取了別的事物插入的數據

後面會詳細的講解爲什麼,O(∩_∩)O嘿嘿~

模擬事物隔離級別

事物特性

  1. 原子性A ,指的是不可再次分割, 也就是A和B事物要麼成功, 要麼失敗
  2. 一致性C: 表示,事物讀取數據要保證正確,一致性
  3. 隔離性I: 事物A不可以對事物B的數據進行更改
  4. 持久性D: 事物A操作之後數據存儲在了磁盤上,不會丟失

隔離級別

  1. 讀未提交: 髒讀, 不可重複讀, 幻讀
  2. 讀已提交: 不可重複讀, 幻讀
  3. 可重複讀 : 幻讀
  4. 串行化 : 安全, 都沒有

隔離級別舉栗子

首先根據下面的sql結構測試栗子

-- ----------------------------
-- Table structure for t_student
-- ----------------------------
DROP TABLE IF EXISTS `t_student`;
CREATE TABLE `t_student` (
  `sno` int(11) NOT NULL,
  `sname` varchar(255) CHARACTER SET gbk DEFAULT NULL,
  `sdree` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
  `ssex` char(255) CHARACTER SET utf8 DEFAULT NULL,
  `sage` decimal(10,0) DEFAULT NULL,
  PRIMARY KEY (`sno`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of t_student
-- ----------------------------
INSERT INTO `t_student` VALUES ('1', 'judy', '天融信', '男', '26');
INSERT INTO `t_student` VALUES ('2', '杜雨', '中銀', '男', '26');
INSERT INTO `t_student` VALUES ('3', '雅雯雯', '買賣寶', '男', '27');
INSERT INTO `t_student` VALUES ('4', '子騰', 'IBM', '男', '23');
INSERT INTO `t_student` VALUES ('5', '旭日', '微軟', '女', '25');

1 查看當前數據庫隔離級別, 設置隔離級別

SELECT @@tx_isolation;
-- 非正常情況下
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

讀未提交出現的併發問題

A 窗口執行sql

start transaction;
select * FROM t_student WHERE sno ='1';

結果: 
1	judy	天融信	男	26

B 窗口執行sql

start transaction;
select * FROM t_student WHERE sno ='1';
UPDATE t_student SET sname='wangxuefen' WHERE sno =1;

執行後的結果
1	wangxuefen	天融信	男	26

A 窗口執行查詢語句(這句話出現的問題)

select * FROM t_student WHERE sno ='1';

得到結果: 1	wangxuefen	天融信	男	26

B 窗口執行

ROLLBACK;
select * FROM t_student WHERE sno ='1';

得到的結果是
1	judy	天融信	男	26

A 窗口執行

select * FROM t_student WHERE sno ='1';

得到的結果是
1	judy	天融信	男	26

從最後的執行結果中我們可以發現A讀取了B未提交的數據, 當B事物回滾的時候, A之前讀到的數據變成了髒數據, 這就是髒讀

提交讀出現的問題

1 更改事物的隔離級別

SELECT @@tx_isolation;
SET SESSION  TRANSACTION ISOLATION LEVEL READ COMMITTED;

A 窗口

start transaction;
select * FROM t_student WHERE sno ='1';

執行結果
1	judy	天融信	男	26

B 窗口

start transaction;
UPDATE t_student SET sname='12' WHERE sno =1;

A 窗口 (出現問題的原因,B還沒有提交但是已經讀了,發送不可重複讀問題)

select * FROM t_student WHERE sno ='1';

執行結果
1	judy		天融信	男	26

B 窗口 (出現問題的原因)

COMMIT

A 窗口

select * FROM t_student WHERE sno ='1';

執行結果
1	12   天融信	男	26

讀已提交,出現不可重複讀問題

可重複讀 REPEATABLE-READ(mysql默認級別)

A 窗口

start transaction;
SELECT * FROM t_student WHERE sno='1'

執行結果:1	judy	天融信	男	26

B 窗口

start transaction;
SELECT * FROM t_student WHERE sno='1';
UPDATE t_student SET sname='wxf' WHERE sno =1;
SELECT * FROM t_student WHERE sno='1';

執行結果
1	wxf	天融信	男	26

A 窗口 (這裏可以跟讀已提交隔離級別進行對比)

1	judy	天融信	男	26

B 窗口

COMMIT

A 窗口

SELECT * FROM t_student WHERE sno='1'

得到結果:
1	judy	天融信	男	26

從得出的結果可以看出我們已經避免了可重複讀的問題, 但是發現最後一次的A窗口得到的結果卻不是我們想要的數據,也就是不是最後更改後的數據.

事物隔離級別設置爲串行化 Serializable

事物隔離級別是最爲安全的,設置隔離級別

SET SESSION tx_isolation='SERIALIZABLE';

A窗口

start transaction ;

B 窗口

start transaction ;

A窗口

SELECT * FROM t_student WHERE sno='1';

得到結果:1	wxf	天融信	男	26

B窗口

  UPDATE t_student SET sname='judy' WHERE sno =1
  
  得到結果: 被卡住了, 無法得到結果

爲什麼會出現被卡住呢? 原因是因爲當A去開啓事物並且去執行查詢事件, 這個時候B去執行更新操作,那麼這個時候會被卡住,原因是因爲A的select操作被上了鎖, 所以B窗口的update操作是無法執行的, 所以就解決了我們上述所有問題,簡單粗暴~

悲觀鎖

悲觀鎖分爲共享鎖和排它鎖

什麼是共享鎖

共享鎖的意思是多個事物對一行數據操作的時候, 可以共享一把鎖,都可以訪問到數據,但是隻能讀不能更改,寫.
排他鎖的意思是指當有一行數據是排他鎖的時候, 其他事物就不能再獲取該鎖的其他鎖,包括共享鎖和排它鎖,

A 窗口 ,(FOR UPDATE指的是悲觀鎖)

START TRANSACTION;

SELECT * FROM t_student WHERE sno ='1' FOR UPDATE

B 窗口

START TRANSACTION;
SELECT * FROM t_student WHERE sno ='1' FOR UPDATE

執行結果:
 被卡住了

樂觀鎖

依靠數據本身來保證數據的正確性
樂觀鎖的兩種方式
1 使用版本號
2 使用時間戳

A 窗口

SELECT * FROM t_student WHERE sno='1'
UPDATE t_student SET sname='judy',version=version+1 WHERE sno='1'

B窗口

SELECT * FROM t_student WHERE sno='1'
UPDATE t_student SET sname='judy',version=version+1 WHERE sno='1' AND version =1

如果你再說看不懂, 哼 我就生氣了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章