• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    RR與RC隔離級別下索引和鎖的測試腳本示例代碼

    來源:懂視網 責編:小采 時間:2020-11-09 20:21:49
    文檔

    RR與RC隔離級別下索引和鎖的測試腳本示例代碼

    RR與RC隔離級別下索引和鎖的測試腳本示例代碼:基本概念 當前讀與快照讀 在MVCC中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read)。 快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。當前讀,讀取的是記錄的最新版本,并且對返回的記錄,都會加上鎖,保證在事務結
    推薦度:
    導讀RR與RC隔離級別下索引和鎖的測試腳本示例代碼:基本概念 當前讀與快照讀 在MVCC中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read)。 快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。當前讀,讀取的是記錄的最新版本,并且對返回的記錄,都會加上鎖,保證在事務結

    基本概念

    當前讀與快照讀

    在MVCC中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read)。 快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。當前讀,讀取的是記錄的最新版本,并且對返回的記錄,都會加上鎖,保證在事務結束前,這條數據都是最新版本。

    快照讀:簡單的select操作,屬于快照讀,不加鎖(Serializable除外)。

    select * from table where ?;

    當前讀:特殊的讀操作,插入/更新/刪除操作,屬于當前讀,需要加鎖。 

    select * from table where ? lock in share mode;
    select * from table where ? for update;
    insert into table values ();
    update table set ? where ?;
    delete from table where ?;

    隔離級別與加鎖機制

  • Read Uncommitted 會發生臟讀,不考慮。
  • Read Committed (RC) 針對當前讀,RC隔離級別保證對讀取到的記錄加鎖 (Gap Locking),存在幻讀現象。
  • Repeatable Read (RR) 針對當前讀,RR隔離級別保證對讀取到的記錄加鎖 (Record Locking),同時保證對讀取的范圍加鎖,新的滿足查詢條件的記錄不能夠插入 (Gap Locking),不存在幻讀現象。
  • Serializable 所有的讀操作均為退化為當前讀,讀寫沖突,因此并發度急劇下降,不考慮。
  • 測試腳本

    -- 基本操作 --
    -- 查詢事務隔離級別,默認是RR
    show variables like '%isolation%';
    
    -- 設置事務隔離級別為RC
    set session transaction isolation level read committed;
    
    
    -- 數據初始化 --
    begin;
    drop table if exists user;
    CREATE TABLE `user` (
     `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
     `email` varchar(64) NOT NULL,
     `age` int(11) NOT NULL,
     `address` varchar(64) NOT NULL,
     PRIMARY KEY (`id`),
     UNIQUE KEY `uniq_email` (`email`),
     KEY `idx_age` (`age`)
    );
    
    insert into user (email, age, address) values ("test1@elsef.com", 18, "address1");
    insert into user (email, age, address) values ("test2@elsef.com", 20, "address2");
    insert into user (email, age, address) values ("test3@elsef.com", 20, "address3");
    
    commit;
    select * from user;
    
    
    
    -- 一、trx_id示例
    begin;
    SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
    select * from user;
    SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
    SHOW ENGINE INNODB STATUS;
    update user set age = 22 where id = 3;
    -- 查詢事務id
    SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
    -- INNODB 引擎狀態
    SHOW ENGINE INNODB STATUS;
    commit;
    
    -- 二、可重復讀、不可重復讀示例
    
    -- session1
    set session transaction isolation level read committed;
    begin;
    -- session2
    set session transaction isolation level repeatable read;
    begin;
    -- session1
    select * from user;
    -- session2
    select * from user;
    -- session3
    begin;
    insert into user (email, age, address) values ("test4@elsef.com", 30, "address4");
    commit;
    -- session1 這里因為是RC,所以可以讀到trx3提交的新數據,這里如果是證明不可重復讀的話應該使用update而不是insert
    select * from user;
    commit;
    -- session2 這里因為是RR,所以不會讀到trx3提交的新數據
    select * from user;
    commit;
    
    -- 三、快照讀幻讀示例
    -- session1
    set session transaction isolation level repeatable read;
    begin;
    -- 這里使用快照讀
    select * from user;
    -- session2
    begin;
    insert into user (email, age, address) values ("test4@elsef.com", 30, "address4");
    commit;
    select * from user;
    -- session1
    select * from user; -- 這里讀不到test4@的數據,因為是RR
    -- 這里發生了幻讀
    insert into user (email, age, address) values ("test4@elsef.com", 30, "address4"); -- 插入失敗因為email唯一索引沖突
    commit;
    
    -- 四、當前讀幻讀示例
    -- RC
    -- session1
    set session transaction isolation level read committed;
    begin;
    -- 這里會對所有滿足條件的age=20的記錄加鎖,因為是RC,所以沒有GAP鎖
    delete from user where age = 20;
    select * from user;
    -- session2
    set session transaction isolation level read committed;
    begin;
    -- 因為trx1沒有加GAP鎖,所以之類可以插入age=20的記錄
    insert into user (email, age, address) values ("test4@elsef.com", 20, "address4");
    select * from user; -- 可以查到4條數據,可以讀到trx1的刪除數據,因為是RC,trx1未提交所以沒影響trx2
    commit;
    -- session1
    select * from user; -- 可以讀到trx2新插入的數據,雖然trx1是當前讀,但是并未添加相應的next-key鎖,沒有阻止trx2的新數據插入
    commit;
    
    --RR
    -- session1
    set session transaction isolation level repeatable read;
    begin;
    delete from user where age = 20;
    select * from user;
    -- session2
    begin;
    -- 這里會阻塞,因為trx1在age=20周圍加了GAP鎖
    -- 非唯一索引,首先,通過索引定位到第一條滿足查詢條件的記錄,加記錄上的X鎖,加GAP上的GAP鎖,然后加主鍵聚簇索引上的記錄X鎖;
    -- 然后讀取下一條,重復進行。直至進行到第一條不滿足條件的記錄,此時,不需要加記錄X鎖,但是仍舊需要加GAP鎖,最后返回結束。
    insert into user (email, age, address) values ("test4@elsef.com", 20, "address4");
    -- 直到超時,ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
    -- 此時如果查詢可以看到3條記錄
    commit;
    -- session1
    -- 此時只能看到1條記錄,另外兩條被刪除了
    select * from user;
    commit;
    
    -- 唯一索引+RC
    -- session1
    set session transaction isolation level read committed;
    begin;
    delete from user where email = "test3@elsef.com";
    -- session2
    begin;
    -- 可以讀到,因為trx1是RC
    select * from user where email = "test3@elsef.com";
    -- 嘗試更新這個記錄的age,會阻塞直到超時,因為email是唯一索引已經被trx1鎖住了,同時也會在對應的主鍵索引上加鎖
    -- 注意這里操作的id=3就是trx1中操作的email的同一行記錄
    update user set age = 40 where id = 3;
    -- session1
    commit;
    -- session2
    commit;
    
    -- 無索引+RC
    -- session1
    set session transaction isolation level read committed;
    begin;
    -- 由于address字段無索引,所以Innodb會對所有行進行加鎖,由MySQL server進行判斷并釋放鎖
    delete from user where address = "address3";
    -- session2
    set session transaction isolation level read committed;
    begin;
    -- 這一行會成功,因為這一行沒有加鎖(先加了后釋放了)
    update user set age = 10 where address = "address2";
    -- 這一行同樣會被阻塞,原因是它已經被trx1的語句加了鎖了,全部符合條件的都加鎖了
    update user set age = 10 where address = "address3";
    -- session1
    commit;
    -- session2
    commit;
    
    -- 非唯一索引+RR
    -- session1
    set session transaction isolation level repeatable read;
    begin;
    delete from user where age = 20;
    -- session2
    set session transaction isolation level repeatable read;
    begin;
    -- 這里會阻塞,因為trx1中已經鎖住了age=20的記錄以及加上了GAP鎖,所以這里18已經落入鎖區間
    insert into user (email, age, address) values ("test4@elsef.com", 18, "address4");
    -- session1
    commit;
    -- session2
    commit;
    
    -- 無索引RR
    -- session1
    set session transaction isolation level repeatable read;
    begin;
    -- 沒有索引,那么會鎖上表中的所有記錄,同時會鎖上主鍵索引上的所有GAP,杜絕所有的并發更新操作
    delete from user where address = "address3";
    -- session2
    set session transaction isolation level repeatable read;
    begin;
    -- 這里會阻塞,原因是主鍵已經被加上了GAP鎖,所以新的插入不能執行成功
    insert into user (email, age, address) values ("test4@elsef.com", 18, "address4");
    -- session1
    commit;
    -- session2
    commit;
    
    -- 死鎖 簡單示例
    -- session1
    begin;
    delete from user where id = 1;
    -- session2
    begin;
    delete from user where id = 3;
    -- session1
    delete from user where id = 3;
    -- seession2
    -- 這里MySQL判斷發生了死鎖,中斷了一個trx
    -- ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
    delete from user where id = 1;
    -- session1
    rollback;
    -- session2;
    rollback;
    
    -- 五、死鎖 insert示例
    drop table if exists t1;
    begin;
    create table t1 (
     `id` bigint not null auto_increment,
     primary key (`id`)
    );
    insert into t1 values(1);
    insert into t1 values(5);
    commit;
    select * from t1;
    -- session1
    begin;
    insert into t1 values (2);
    -- sessioin2
    begin;
    -- 這里會阻塞
    insert into t1 values (2);
    -- session3
    begin;
    -- 這里會阻塞
    insert into t1 values (2);
    -- session1;
    -- 此時回滾,trx2和trx3收到通知,MySQL自動中斷一個trx,因為發生了死鎖
    -- ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
    rollback;
    --session2;
    rollback;
    --session3;
    rollback;

    總結

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    RR與RC隔離級別下索引和鎖的測試腳本示例代碼

    RR與RC隔離級別下索引和鎖的測試腳本示例代碼:基本概念 當前讀與快照讀 在MVCC中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read)。 快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。當前讀,讀取的是記錄的最新版本,并且對返回的記錄,都會加上鎖,保證在事務結
    推薦度:
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产精品福利电影一区二区三区四区欧美白嫩精品 | 国产成人无码精品久久久免费| 日本精品一区二区三区在线视频| 国产精品欧美一区二区三区不卡 | 日韩福利视频精品专区| 精品国产一区二区三区不卡| 久久夜色撩人精品国产| 国产99久久九九精品无码| 成人久久精品一区二区三区| 久久亚洲精品国产精品| 亚洲精品字幕在线观看| 国产精品VIDEOSSEX久久发布| sihu国产精品永久免费| 久久婷婷国产综合精品| 亚洲精品午夜无码电影网| 久久亚洲精品无码播放| 国产亚洲精品无码专区| 白浆都出来了视频国产精品| 久久99精品国产一区二区三区 | 亚洲精品亚洲人成在线观看下载 | 国产精品国产三级国产| 亚洲国产成人精品不卡青青草原| 99免费精品视频| 91精品在线播放| A级精品国产片在线观看| 久久国产亚洲精品无码| 亚洲国产精品国自产拍AV| 亚洲中文久久精品无码ww16| 亚洲一区二区三区在线观看精品中文| 欧美亚洲综合免费精品高清在线观看| 九九久久精品无码专区| 精品视频在线观看你懂的一区| 精品午夜福利1000在线观看 | 久久亚洲精品无码播放| 欧美黑人巨大videos精品| 人妻VA精品VA欧美VA| 无码人妻精品一区二| 在线精品无码字幕无码AV| 久久影院综合精品| 97久久精品无码一区二区| 久久免费精品视频|