日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Mysql-innoDB存储引擎(事务,锁,MVCC)

發(fā)布時間:2024/9/20 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mysql-innoDB存储引擎(事务,锁,MVCC) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

innoDB的特性:

  從圖中由上至下紅色框中的信息是:基于主鍵的聚集索引 ,數(shù)據(jù)緩存,外鍵支持(邏輯上建立外鍵),行級別鎖,MVCC多版本控制,事務(wù)支持。這些也是InnoDB最重要的特性。

事務(wù):

  數(shù)據(jù)庫操作的最小工作單元,是作為單個邏輯工作單元執(zhí)行的一系列操作;事務(wù)是一組不可再分割的操作集合(工作邏輯單元)。典型事務(wù)場景(轉(zhuǎn)賬):這是兩個事務(wù)

  update user_account set balance = balance - 1000 where userID = 3;

  update user_account set balance = balance +1000 where userID = 1;

mysql中如何開啟事務(wù):

  通過navicat使用命令 showvariables like ‘a(chǎn)utocommit’; 查看自動提交是否開啟。當(dāng)開啟后執(zhí)行update語句會自動提交,當(dāng)自動提交是關(guān)閉的,可以通過以下方式來創(chuàng)建事務(wù)提交:

BEGIN;-- 這兩個二選一開啟事務(wù) START TRANSACTION; -- 這是一個事務(wù) UPDATE ...... UPDATE ......COMMIT;-- 提交或者回滾 ROLLBACK;

  begin / start transaction -- 手工開啟事務(wù)。

  commit / rollback -- 事務(wù)提交或回滾。

  set session autocommit = on/off; -- 從Session的角度設(shè)定事務(wù)是否自動開啟。

JDBC 編程:

  connection.setAutoCommit(boolean);

Spring 事務(wù)AOP編程:

  expression=execution(com.gpedu.dao.*.*(..))

事務(wù)ACID特性:

  • 原子性(Atomicity):最小的工作單元,整個工作單元要么一起提交成功,要么全部失敗回滾
  • 一致性(Consistency):事務(wù)中操作的數(shù)據(jù)及狀態(tài)改變是一致的,即寫入資料的結(jié)果必須完全符合預(yù)設(shè)的規(guī)則,不會因?yàn)槌霈F(xiàn)系統(tǒng)意外等原因?qū)е聽顟B(tài)的不一致
  • 隔離性(Isolation):數(shù)據(jù)并發(fā)的時候,一個事務(wù)所操作的數(shù)據(jù)在提交之前,對其他事務(wù)的可見性設(shè)定(一般設(shè)定為不可見)
  • 持久性(Durability):事務(wù)所做的修改就會永久保存,不會因?yàn)橄到y(tǒng)意外導(dǎo)致數(shù)據(jù)的丟失

事務(wù)并發(fā)帶來什么問題:

  先來看第一張圖:在下圖中,一張表中記錄只有一條,事務(wù)B修改該條記錄的 age字段,而此刻 事務(wù)A來查詢了,獲得的age是18,接著事務(wù)B 回滾了,這樣子就出現(xiàn)了臟讀問題。

  再來看第二個圖:事務(wù)A先查詢了數(shù)據(jù)信息,此刻事務(wù)B進(jìn)行了修改并提交,然后事務(wù)A又去查詢了一遍,這個時候就會出現(xiàn)不可重復(fù)讀的問題。

  第三張圖:通過范圍查詢獲得一條數(shù)據(jù),此刻事務(wù)B 插入了一條數(shù)據(jù),事務(wù)A又去查詢獲得了兩條數(shù)據(jù),此刻就發(fā)生了幻讀。

  綜上,事務(wù)并發(fā)給我們帶來了三個主要問題:臟讀,不可重復(fù)讀,幻讀。

事務(wù)的隔離級別:

  • Read Uncommitted(未提交讀) --未解決并發(fā)問題,事務(wù)未提交對其他事務(wù)也是可見的,臟讀(dirty read)。
  • Read Committed(提交讀) --解決臟讀問題,一個事務(wù)開始之后,只能看到自己提交的事務(wù)所做的修改,不可重復(fù)讀(nonrepeatableread)。
  • Repeatable Read (可重復(fù)讀) --解決不可重復(fù)讀問題在同一個事務(wù)中多次讀取同樣的數(shù)據(jù)結(jié)果是一樣的,這種隔離級別未定義解決幻讀的問題。
  • Serializable(串行化) --解決所有問題,最高的隔離級別,通過強(qiáng)制事務(wù)的串行執(zhí)行。

設(shè)置read uncommitted級別:set session transaction isolation level read uncommitted;

?

innoDB對隔離級別的支持程度:

  在InnoDB中隔離級別到底如何實(shí)現(xiàn)的呢? --通過鎖、MVCC。

InnoDB中的鎖:

  鎖是用于管理不同事務(wù)對共享資源的并發(fā)訪問,InnoDB存儲引擎支持行鎖和表鎖(另類的行鎖,通過行鎖鎖住所有的行)。官方文檔:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html。表鎖與行鎖的區(qū)別:

  • 鎖定粒度:表鎖 > 行鎖
  • 加鎖效率:表鎖 > 行鎖
  • 沖突概率:表鎖 > 行鎖
  • 并發(fā)性能:表鎖 < 行鎖

MYSQL innoDB鎖類型:

  • l 共享鎖(行鎖):Shared Locks
  • l 排它鎖(行鎖):Exclusive Locks
  • l 意向共享鎖(表鎖):Intention Shared Locks
  • l 意向排它鎖(表鎖):Intention Exclusive Locks
  • l 自增鎖:AUTO-INC Locks

行鎖的算法:

  • l 記錄鎖 Record Locks
  • l 間隙鎖 Gap Locks
  • l 臨鍵鎖 Next-key Locks

?共享鎖:

  又稱為讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務(wù)對于同一數(shù)據(jù)可以共享一把鎖,都能訪問到數(shù)據(jù),但是只能讀不能修改,加鎖釋鎖方式:

-- 共享鎖加鎖 BEGIN select * from users WHERE id=1 LOCK IN SHARE MODE; rollback; commit; -- 在以上的SQL枷鎖后未執(zhí)行提交或者回滾執(zhí)行其他事務(wù)執(zhí)行 select * from users where id =1; -- 可以執(zhí)行,共享鎖特性 update users set age=19 where id =1;--會阻塞

排他鎖:

  又稱為寫鎖,簡稱X鎖,排他鎖不能與其他鎖并存,如一個事務(wù)獲取了一個數(shù)據(jù)行的排他鎖,其他事務(wù)就不能再獲取該行的鎖(共享鎖、排他鎖),只有該獲取了排他鎖的事務(wù)是可以對數(shù)據(jù)行進(jìn)行讀取和修改,(其他事務(wù)要讀取數(shù)據(jù)可來自于快照),加鎖釋鎖方式:delete / update / insert 默認(rèn)加上X鎖。

-- 自動獲取排它鎖 set session autocommit = OFF; -- 設(shè)置手動提交事務(wù) update users set age = 23 where id =1; --執(zhí)行該語句后未提交,在其他線程上,執(zhí)行下列其他事務(wù)執(zhí)行語句會處于阻塞commit; ROLLBACK;-- 手動獲取排它鎖 set session autocommit = ON; begin select * from users where id =1 for update; commit;-- 其他事務(wù)執(zhí)行 select * from users where id =1 lock in share mode; select * from users where id =1 for update; select * from users where id =1;

innoDB--行鎖到底鎖了什么?

  首先先來看一下測試表的結(jié)構(gòu),其中用的是InnoDB引擎,有一個name的唯一索引,主鍵自增,有3條數(shù)據(jù)

DROP TABLE IF EXISTS `users`; CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`uname` varchar(32) NOT NULL,`userLevel` int(11) NOT NULL,`age` int(11) NOT NULL,`phoneNum` char(11) NOT NULL,`createTime` datetime NOT NULL,`lastUpdate` datetime NOT NULL,PRIMARY KEY (`id`),KEY `idx_name` (`uname`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=100006 DEFAULT CHARSET=utf8mb4;-- ---------------------------- -- Records of users -- ---------------------------- INSERT INTO `users` VALUES ('1', '李二狗', '2', '18', '13666666666', '2018-12-01 15:39:46', '2018-12-01 15:39:50'); INSERT INTO `users` VALUES ('2', '張三豐', '1', '29', '13777777777', '2018-12-01 16:35:41', '2018-12-01 16:35:44'); INSERT INTO `users` VALUES ('3', '武大郎', '2', '44', '13888888888', '2018-12-01 16:36:01', '2018-12-01 16:36:03');

案例1:緊接著在一個事務(wù)中執(zhí)行以下語句:可以發(fā)現(xiàn)我們把事務(wù)設(shè)置成手動提交,但是我并未提交或者回滾:

set session autocommit = OFF; update users set lastUpdate=NOW() where phoneNum = '13666666666';

然后在其他事務(wù)中執(zhí)行如下語句:會發(fā)現(xiàn),上述SQL執(zhí)行修改會獲得默認(rèn)的排它鎖,而此刻并未釋放,鎖的列是ID為1,然后我們下列要修改ID為2的數(shù)據(jù)也是出于阻塞,這是為什么呢?

update users set lastUpdate=NOW() where id =2; update users set lastUpdate=NOW() where id =1;

案例2,執(zhí)行以下語句,可以發(fā)現(xiàn)我們把事務(wù)設(shè)置成手動提交,但是我并未提交或者回滾:

set session autocommit = OFF; update users set lastUpdate=NOW() where id = 1;

然后在其他事務(wù)上執(zhí)行:會發(fā)現(xiàn)下面2條SQL執(zhí)行后 第一條會順利執(zhí)行,而第二條會被阻塞。

update users set lastUpdate=NOW() where id =2; update users set lastUpdate=NOW() where id =1;

案例三:執(zhí)行一下語句:

set session autocommit = OFF; update users set lastUpdate=NOW() where `name` = '李二狗';

然后在其他事務(wù)上執(zhí)行:會發(fā)現(xiàn)前面兩條會執(zhí)行失敗,而后面兩條執(zhí)行成功

-- 其他查詢執(zhí)行 update users set lastUpdate=NOW() where `name` = '李二狗'; update users set lastUpdate=NOW() where id =1; update users set lastUpdate=NOW() where `name` = '張三豐'; update users set lastUpdate=NOW() where id =2;

  InnoDB的行鎖是通過給索引上的索引項(xiàng)加鎖來實(shí)現(xiàn)的。對于二級索引,會對一級索引也加鎖。只有通過索引條件進(jìn)行數(shù)據(jù)檢索,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖(鎖住索引的所有記錄)表鎖:lock tables xx read/write;

意向共享鎖(IS):表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入共享鎖,即一個數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖,意向共享鎖之間是可以相互兼容的。

意向排它鎖(IX):表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入排他鎖,即一個數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖,意向排它鎖之間是可以相互兼容的。

  意向鎖(IS、IX)是InnoDB數(shù)據(jù)操作之前自動加的,不需要用戶干預(yù)。

  意義:相當(dāng)于一個標(biāo)記flgs,當(dāng)事務(wù)想去進(jìn)行鎖表時,可以先判斷意向鎖是否存在,存在時則可快速返回該表不能啟用表鎖。

自增鎖 AUTO-INC Locks:

  針對自增列自增長的一個特殊的表級別鎖,查看自增鎖默認(rèn)值:show variables like 'innodb_autoinc_lock_mode';默認(rèn)取值1,代表連續(xù),事務(wù)未提交ID永久丟失。當(dāng)級別為1,執(zhí)行一下SQL:在插入數(shù)據(jù)的時候,這個表的ID為自增,連續(xù)回滾3次,這3次的ID會永久消失,在下次執(zhí)行commit的時候ID會在原來的數(shù)值上加3.

begin; insert into users(name , age ,phoneNum ,lastUpdate ) values ('tom2',30,'1344444444',now()); ROLLBACK;

針對行鎖的算法:

臨鍵鎖 Next-key Locks:

  Next-key locks:InnoDB行鎖的默認(rèn)算法。鎖住記錄+區(qū)間(左開右閉),當(dāng)sql執(zhí)行按照索引進(jìn)行數(shù)據(jù)的檢索時,查詢條件為范圍查找(between and、<、>等)并有數(shù)據(jù)命中則此時SQL語句加上的鎖為Next-key locks,鎖住索引的記錄+區(qū)間(左開右閉)。先來搞一張表:

DROP TABLE IF EXISTS `test`; CREATE TABLE `test` (`id` int(11) NOT NULL ,`name` varchar(32) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- ---------------------------- -- Records of users -- ---------------------------- INSERT INTO `test` VALUES ('1', '1'); INSERT INTO `test` VALUES ('4', '4'); INSERT INTO `test` VALUES ('7', '7'); INSERT INTO `test` VALUES ('10', '10');

  在InnoDB的默認(rèn)行級算法中會對數(shù)據(jù)行進(jìn)劃分:可以看到是一個左開右閉的這個一個展現(xiàn)。

  執(zhí)行以下sql不提交:由于有數(shù)據(jù)命中則會鎖住(4,7](7,10] 兩個區(qū)間。未提交的情況下執(zhí)行下列其他事務(wù)中前四條全部阻塞而最后一條會成功執(zhí)行。

begin; select * from test where id>5 and id<9 for update; -- 其他事務(wù) select * from test where id=4 for update; -- 阻塞 select * from test where id=7 for update; -- 阻塞 select * from test where id=10 for update; -- 阻塞 INSERT INTO `test` (`id`, `name`) VALUES (9, '9'); -- 阻塞 INSERT INTO `test` (`id`, `name`) VALUES (11, '11');-- 成功

  為什么InnoDB要選擇(臨鍵鎖)Next-key locks作為InnoDB行鎖的默認(rèn)算法?解決幻讀,因?yàn)锽+Tree是有順序的,從左往右順序遞增,把臨鍵區(qū)間也鎖住,其他事務(wù)要往里插入數(shù)據(jù)是插不進(jìn)去的。

間隙鎖 Gap Locks:繼臨鍵鎖要是沒有命中數(shù)據(jù)的情況下:

  Gap鎖只在?Repeatable Read (可重復(fù)讀)? 的隔離級別的情況下才存在。

記錄鎖 Record Locks:繼臨鍵鎖之后,在條件為精準(zhǔn)匹配的時候。

?

那么鎖是怎么解決上述產(chǎn)生 臟讀,不可重復(fù)讀,以及幻讀的情況呢?

解決臟讀:

解決不可重復(fù)讀:

解決幻讀:

死鎖:

  • 多個并發(fā)事務(wù)(2個或者以上);
  • 每個事務(wù)都持有鎖(或者是已經(jīng)在等待鎖);
  • 每個事務(wù)都需要再繼續(xù)持有鎖;
  • 事務(wù)之間產(chǎn)生加鎖的循環(huán)等待,形成死鎖

避免死鎖:

  • 類似的業(yè)務(wù)邏輯以固定的順序訪問表和行。
  • 大事務(wù)拆小。大事務(wù)更傾向于死鎖,如果業(yè)務(wù)允許,將大事務(wù)拆小。
  • 在同一個事務(wù)中,盡可能做到一次鎖定所需要的所有資源,減少死鎖概率。
  • 降低隔離級別,如果業(yè)務(wù)允許,將隔離級別調(diào)低也是較好的選擇
  • 為表添加合理的索引。可以看到如果不走索引將會為表的每一行記錄添加上鎖(或者說是表鎖)

Mysql 中MVCC版本控制:

  MVCC是multiversion concurrency control的縮寫,并發(fā)訪問(讀或?qū)?數(shù)據(jù)庫時,對正在事務(wù)內(nèi)處理的數(shù)據(jù)做多版本的管理。以達(dá)到用來避免寫操作的堵塞,從而引發(fā)讀操作的并發(fā)問題 。提供MySQL事物隔離級別下無鎖讀,例如一個事物在執(zhí)行update等修改數(shù)據(jù)的sql,并未提交時其他事物進(jìn)行數(shù)據(jù)讀取是不影響的,而且讀取內(nèi)容為數(shù)據(jù)變更之前的數(shù)據(jù)。

?  MVCC多本版快照由innodb的rollback segment構(gòu)照的,一個sql進(jìn)行查找數(shù)據(jù)當(dāng)查找到某一個數(shù)據(jù)需要到回滾段中查找數(shù)據(jù)時,就會根據(jù)當(dāng)前頁上行數(shù)據(jù)的一個指針到回滾段中查找對應(yīng)數(shù)據(jù),在innodb的表主鍵中都會存在三個隱藏的字段:

  • ????DB_TRX_ID:該字段存儲最后一個修改該行數(shù)據(jù)的事務(wù)ID,占用6byte的空間,MySQL的delete操作是標(biāo)記刪除,所以對應(yīng)行數(shù)據(jù)的該字段就為一個刪除標(biāo)記。
  • ????DB_ROLL_PTR:該字段就記錄執(zhí)行roll segment的指針信息,當(dāng)事務(wù)需要rollback時就通過該字段尋找記錄重新構(gòu)照行數(shù)據(jù),該字段占用7byte空間。
  • ????DB_ROW_ID:記錄每個行ID,該ID值為單調(diào)遞增型整數(shù),在innodb表指定了主鍵之后DB_ROW_ID存在于主鍵索引上,如果無主鍵該值就不會存在,占用6byte空間。

?  在一個sql進(jìn)行查詢時,讀取到一行數(shù)據(jù)的DB_TRX_ID值和自己事物ID的對比,假如隔離級別為MySQL的默認(rèn)級別,就只讀取該ID值小于本身事物ID的數(shù)據(jù),其余數(shù)據(jù)就需要通過DB_ROLL_PTR的信息到回滾段中讀取。MVCC是否起到相應(yīng)的作用需取決于數(shù)據(jù)庫隔離級別的配置。

?  在insert和update、delete的操作是有區(qū)別的,一個insert語句插入數(shù)據(jù)再rollback就是直接對undo log的刪除,他并不會影響其他事物的讀取操作,而update、delete操作是在原有數(shù)據(jù)做更改,可能有其他事物在對該行數(shù)據(jù)做讀取操作,所以update、delete產(chǎn)生的undo log數(shù)據(jù)是由內(nèi)部線程自動清理,在該數(shù)據(jù)無任何事務(wù)在使用時清理掉,所以在undo log中insert和update、delete產(chǎn)生的數(shù)據(jù)存于不同位置。

  下面通過一個案例來熟悉一下MVCC的效果:

-- 數(shù)據(jù)準(zhǔn)備 insert into teacher(name,age) value ('seven',18) ;--假設(shè)事務(wù)版本為1 insert into teacher(name,age) value ('qing',20) ;--假設(shè)事務(wù)版本為1 begin; ----------1 select * from users ; ----------2begin; ----------3 update teacher set age =28 where id =1;----------4

  在每一行數(shù)據(jù) 插入數(shù)據(jù)表的時候,都會開啟一個事務(wù),每一行數(shù)據(jù)都會保存執(zhí)行的時候所獲取的事務(wù)版本號,當(dāng)進(jìn)行修改的時候會先copy一份待修改的數(shù)據(jù)到 Undo 緩沖區(qū),在提交后然寫入磁盤,在此過程中會將原先的數(shù)據(jù)行的刪除版本號置為當(dāng)前事務(wù)ID,然后再在新的數(shù)據(jù)行把數(shù)據(jù)行版本號置為當(dāng)前事務(wù)ID。

  當(dāng)我們按照 1,2,3,4,2 的順序去執(zhí)行的時候,首先執(zhí)行 1 拿到的事務(wù)ID 是2,那么執(zhí)行2查詢出來就是原始數(shù)據(jù),這個時候事務(wù)并沒有提交或者回滾,然后執(zhí)行3開啟一個事務(wù)拿到的事務(wù)ID 為3 ,此刻執(zhí)行4(在更新操作的時候,采用的是先標(biāo)記舊的那行記錄為已刪除,并且刪除版本號是事務(wù)版本號,然后插入一行新的記錄的方式。)進(jìn)行 update 操作的時候會 copy 數(shù)據(jù)到Undo 緩沖區(qū),然后將Undo.log的原始數(shù)據(jù)的刪除版本號置為3,把新數(shù)據(jù)的事務(wù)版本號置為3,再執(zhí)行2的時候由于此刻事務(wù)ID 還是為2,所以根據(jù)查詢規(guī)則查找數(shù)據(jù)行版本號小于當(dāng)前事務(wù)版本的數(shù)據(jù)行,查找刪除版本號大于當(dāng)前事務(wù)版本的或者刪除版本為nul的數(shù)據(jù)行,由于修改操作未提交,所以最終得到的結(jié)果數(shù)據(jù)還是原始數(shù)據(jù)的值,并不會把修改的數(shù)據(jù)加載回來,解決了不可重復(fù)讀的問題。

  如果按照這樣的邏輯通過 3,4,1,2的順序去執(zhí)行,那么首先修改的操作會拿到事務(wù)ID為2,將原來的數(shù)據(jù)行copy出來,將原來的刪除版本號置為當(dāng)前事務(wù)ID,接著將備份數(shù)據(jù)的版本號置為當(dāng)前版本號,然后執(zhí)行查詢操作再開啟一個新事務(wù),拿到的事務(wù)ID為3,根據(jù)查詢規(guī)則,拿到的是進(jìn)行了update 操作但并未提交的新數(shù)據(jù),造成了臟讀,這是為什么呢?那么是由誰去解決這個問題的呢?其實(shí)這里面涉及到了 Undo.log的機(jī)制以及當(dāng)前讀,快照讀的問題,那么接下來看看他們是怎么處理這個問題的 。

Undo Log:

  Undo Log 是什么:undo意為取消,以撤銷操作為目的,返回指定某個狀態(tài)的操作,undo log指事務(wù)開始之前,在操作任何數(shù)據(jù)之前,首先將需操作的數(shù)據(jù)備份到一個地方 (Undo Log),UndoLog是為了實(shí)現(xiàn)事務(wù)的原子性而出現(xiàn)的產(chǎn)物。

  Undo Log實(shí)現(xiàn)事務(wù)原子性:事務(wù)處理過程中如果出現(xiàn)了錯誤或者用戶執(zhí)行了 ROLLBACK語句,Mysql可以利用Undo Log中的備份將數(shù)據(jù)恢復(fù)到事務(wù)開始之前的狀態(tài)。

  UndoLog在Mysql innodb存儲引擎中用來實(shí)現(xiàn)多版本并發(fā)控制。

  Undo log實(shí)現(xiàn)多版本并發(fā)控制:事務(wù)未提交之前,Undo保存了未提交之前的版本數(shù)據(jù),Undo 中的數(shù)據(jù)可作為數(shù)據(jù)舊版本快照供其他并發(fā)事務(wù)進(jìn)行快照讀。

  如下圖這樣的處理就避免了臟讀的問題。

當(dāng)前讀,快照讀:

快照讀:SQL讀取的數(shù)據(jù)是快照版本,也就是歷史版本,普通的SELECT就是快照讀innodb快照讀,數(shù)據(jù)的讀取將由 cache(原本數(shù)據(jù)) + undo(事務(wù)修改過的數(shù)據(jù)) 兩部分組成

當(dāng)前讀:SQL讀取的數(shù)據(jù)是最新版本。通過鎖機(jī)制來保證讀取的數(shù)據(jù)無法通過其他事務(wù)進(jìn)行修改UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE都是當(dāng)前讀。

Redo Log:

  Redo Log 是什么:Redo,顧名思義就是重做。以恢復(fù)操作為目的,重現(xiàn)操作;Redo log指事務(wù)中操作的任何數(shù)據(jù),將最新的數(shù)據(jù)備份到一個地方 (Redo Log)。

  Redo log的持久:不是隨著事務(wù)的提交才寫入的,而是在事務(wù)的執(zhí)行過程中,便開始寫入redo 中。具體的落盤策略可以進(jìn)行配置.RedoLog是為了實(shí)現(xiàn)事務(wù)的持久性而出現(xiàn)的產(chǎn)物。

  Redo Log實(shí)現(xiàn)事務(wù)持久性:防止在發(fā)生故障的時間點(diǎn),尚有臟頁未寫入磁盤,在重啟mysql服務(wù)的時候,根據(jù)redolog進(jìn)行重做,從而達(dá)到事務(wù)的未入磁盤數(shù)據(jù)進(jìn)行持久化這一特性。

?  流程圖如下:

  指定Redo log 記錄在{datadir}/ib_logfile1&ib_logfile2 可通過innodb_log_group_home_dir 配置指定目錄存儲。一旦事務(wù)成功提交且數(shù)據(jù)持久化落盤之后,此時Redo log中的對應(yīng)事務(wù)數(shù)據(jù)記錄就失去了意義,所以Redo log的寫入是日志文件循環(huán)寫入的。

  • 指定Redo log日志文件組中的數(shù)量 innodb_log_files_in_group 默認(rèn)為2
  • 指定Redo log每一個日志文件最大存儲量innodb_log_file_size 默認(rèn)48M
  • 指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默認(rèn)16M

  Redo buffer 持久化Redo log的策略, Innodb_flush_log_at_trx_commit:

  • 取值 0 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丟失一秒內(nèi)的事務(wù)數(shù)據(jù)]。
  • 取值 1 默認(rèn)值,每次事務(wù)提交執(zhí)行Redo buffer --> Redo log OS cache -->flush cache to disk[最安全,性能最差的方式]。
  • 取值 2 每次事務(wù)提交執(zhí)行Redo buffer --> Redo log OS cache 再每一秒執(zhí)行 ->flush cache todisk操作。

來源:https://www.cnblogs.com/wuzhenzhao/p/10348566.html

總結(jié)

以上是生活随笔為你收集整理的Mysql-innoDB存储引擎(事务,锁,MVCC)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。