亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

MySQL 四種事務隔離級別詳解及對比

2024-07-24 13:11:34
字體:
來源:轉載
供稿:網友

MySQL 四種事務隔離級別詳解及對比

按照SQL:1992 事務隔離級別,InnoDB默認是可重復讀的(REPEATABLE READ)。MySQL/InnoDB 提供SQL標準所描述的所有四個事務隔離級別。你可以在命令行用--transaction-isolation選項,或在選項文件里,為所有連接設置默認隔離級別。
例如,你可以在my.inf文件的[mysqld]節里類似如下設置該選項:

transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}

用戶可以用SET TRANSACTION語句改變單個會話或者所有新進連接的隔離級別。它的語法如下:

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

注意:默認的行為(不帶session和global)是為下一個(未開始)事務設置隔離級別。如果你使用GLOBAL關鍵字,語句在全局對從那點開始創建的所有新連接(除了不存在的連接)設置默認事務級別。你需要SUPER權限來做這個。使用SESSION 關鍵字為將來在當前連接上執行的事務設置默認事務級別。 任何客戶端都能自由改變會話隔離級別(甚至在事務的中間),或者為下一個事務設置隔離級別。

你可以用下列語句查詢全局和會話事務隔離級別:

SELECT @@global.tx_isolation;SELECT @@session.tx_isolation;SELECT @@tx_isolation;

----以上手冊中的理論知識;
===========================================================================================
       隔離級別               臟讀(Dirty Read)          不可重復讀(NonRepeatable Read)     幻讀(Phantom Read)
===========================================================================================

未提交讀(Read uncommitted)        可能                            可能                       可能

已提交讀(Read committed)          不可能                          可能                        可能

可重復讀(Repeatable read)          不可能                          不可能                     可能

可串行化(Serializable )                不可能                          不可能                     不可能

===========================================================================================

·未提交讀(Read Uncommitted):允許臟讀,也就是可能讀取到其他會話中未提交事務修改的數據

·提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重復讀)

·可重復讀(Repeated Read):可重復讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重復讀,但是還存在幻象讀

·串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

用例子說明各個級別的情況:

① 臟讀: 臟讀就是指當一個事務正在訪問數據,并且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問這個數據,然后使用了這個數據。

session 1:mysql> select @@global.tx_isolation;+-----------------------+| @@global.tx_isolation |+-----------------------+| REPEATABLE-READ    |+-----------------------+1 row in set (0.00 sec)mysql> select @@session.tx_isolation;+-----------------------+| @@session.tx_isolation |+-----------------------+| REPEATABLE-READ    |+-----------------------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into ttd values(1);Query OK, 1 row affected (0.05 sec)mysql> select * from ttd;+------+| id  |+------+|  1 |+------+1 row in set (0.00 sec)session 2:mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| REPEATABLE-READ    |+------------------------+1 row in set (0.00 sec)mysql> select @@global.tx_isolation;+-----------------------+| @@global.tx_isolation |+-----------------------+| REPEATABLE-READ  |    --------該隔離級別下(除了 read uncommitted)+-----------------------+1 row in set (0.00 sec)mysql> select * from ttd;Empty set (0.00 sec)       --------不會出現臟讀mysql> set session transaction isolation level read uncommitted;Query OK, 0 rows affected (0.00 sec)mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| READ-UNCOMMITTED    |  --------該隔離級別下+------------------------+1 row in set (0.00 sec)mysql> select * from ttd;+------+| id  |+------+|  1 |                    --------REPEATABLE-READ級別出現臟讀+------+1 row in set (0.00 sec)

結論:session 2 在READ-UNCOMMITTED 下讀取到session 1 中未提交事務修改的數據.

② 不可重復讀:是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那么,在第一個事務中的兩次讀數據之間,由于第二個事務的修改,那么第一個事務兩次讀到的的數據可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱為是不可重復讀。

session 1:mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| READ-COMMITTED     |+------------------------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from ttd;+------+| id  |+------+|  1 |+------+1 row in set (0.00 sec)session 2 :mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| REPEATABLE-READ    |+------------------------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from ttd;+------+| id  |+------+|  1 |+------+1 row in set (0.00 sec)mysql> insert into ttd values(2); /也可以更新數據Query OK, 1 row affected (0.00 sec)mysql> select * from ttd;+------+| id  |+------+|  1 ||  2 |+------+2 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.02 sec)session 2 提交后,查看session 1 的結果;session 1:mysql> select * from ttd;+------+| id  |+------+|  1 |               --------和第一次的結果不一樣,READ-COMMITTED 級別出現了不重復讀|  2 |+------+2 rows in set (0.00 sec)

③ 可重復讀:

session 1:mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| REPEATABLE-READ    |+------------------------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from ttd;+------+| id  |+------+|  1 ||  2 |+------+2 rows in set (0.00 sec)session 2 :mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| REPEATABLE-READ    |+------------------------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into ttd values(3);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.03 sec)session 2 提交后,查看session 1 的結果;session 1:mysql> select * from ttd;+------+| id  |+------+|  1 |                   --------和第一次的結果一樣,REPEATABLE-READ級別出現了重復讀|  2 |+------+2 rows in set (0.00 sec)(commit session 1 之后 再select * from ttd 可以看到session 2 插入的數據3)

④ 幻讀:第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那么,以后就會發生操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺一樣。

mysql>CREATE TABLE `t_bitfly` (`id` bigint(20) NOT NULL default '0',`value` varchar(32) default NULL,PRIMARY KEY (`id`)) ENGINE=InnoDBmysql> select @@global.tx_isolation, @@tx_isolation;+-----------------------+-----------------+| @@global.tx_isolation | @@tx_isolation |+-----------------------+-----------------+| REPEATABLE-READ    | REPEATABLE-READ |+-----------------------+-----------------+實驗一:t Session A          Session B|| START TRANSACTION;     START TRANSACTION;|| SELECT * FROM t_bitfly;| empty set|               INSERT INTO t_bitfly|               VALUES (1, 'a');|| SELECT * FROM t_bitfly;| empty set|               COMMIT;|| SELECT * FROM t_bitfly;| empty set|| INSERT INTO t_bitfly VALUES (1, 'a');| ERROR 1062 (23000):| Duplicate entry '1' for key 1v (shit, 剛剛明明告訴我沒有這條記錄的)如此就出現了幻讀,以為表里沒有數據,其實數據已經存在了,傻乎乎的提交后,才發現數據沖突了。實驗二:t Session A         Session B|| START TRANSACTION;     START TRANSACTION;|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+|              INSERT INTO t_bitfly|              VALUES (2, 'b');|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+|              COMMIT;|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+|| UPDATE t_bitfly SET value='z';| Rows matched: 2 Changed: 2 Warnings: 0| (怎么多出來一行)|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | z   || |  2 | z   || +------+-------+

本事務中第一次讀取出一行,做了一次更新后,另一個事務里提交的數據就出現了。也可以看做是一種幻讀。

當隔離級別是可重復讀,且禁用innodb_locks_unsafe_for_binlog的情況下,在搜索和掃描index的時候使用的next-key locks可以避免幻讀。

再看一個實驗,要注意,表t_bitfly里的id為主鍵字段。

實驗三:t Session A         Session B|| START TRANSACTION;    START TRANSACTION;|| SELECT * FROM t_bitfly| WHERE id<=1| FOR UPDATE;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+|              INSERT INTO t_bitfly|              VALUES (2, 'b');|              Query OK, 1 row affected|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+|              INSERT INTO t_bitfly|              VALUES (0, '0');|              (waiting for lock ...then timeout)|              ERROR 1205 (HY000):|              Lock wait timeout exceeded;|              try restarting transaction|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+|              COMMIT;|| SELECT * FROM t_bitfly;| +------+-------+| | id  | value || +------+-------+| |  1 | a   || +------+-------+

可以看到,用id<=1加的鎖,只鎖住了id<=1的范圍,可以成功添加id為2的記錄,添加id為0的記錄時就會等待鎖的釋放。

實驗四:一致性讀和提交讀t Session A           Session B|| START TRANSACTION;       START TRANSACTION;|| SELECT * FROM t_bitfly;| +----+-------+| | id | value || +----+-------+| | 1 | a   || +----+-------+|                INSERT INTO t_bitfly|                VALUES (2, 'b');|                COMMIT;|| SELECT * FROM t_bitfly;| +----+-------+| | id | value || +----+-------+| | 1 | a   || +----+-------+|| SELECT * FROM t_bitfly LOCK IN SHARE MODE;| +----+-------+| | id | value || +----+-------+| | 1 | a   || | 2 | b   || +----+-------+|| SELECT * FROM t_bitfly FOR UPDATE;| +----+-------+| | id | value || +----+-------+| | 1 | a   || | 2 | b   || +----+-------+|| SELECT * FROM t_bitfly;| +----+-------+| | id | value || +----+-------+| | 1 | a   || +----+-------+

如果使用普通的讀,會得到一致性的結果,如果使用了加鎖的讀,就會讀到“最新的”“提交”讀的結果。

本身,可重復讀和提交讀是矛盾的。在同一個事務里,如果保證了可重復讀,就會看不到其他事務的提交,違背了提交讀;如果保證了提交讀,就會導致前后兩次讀到的結果不一致,違背了可重復讀。

可以這么講,InnoDB提供了這樣的機制,在默認的可重復讀的隔離級別里,可以使用加鎖讀去查詢最新的數據(提交讀)。
MySQL InnoDB的可重復讀并不保證避免幻讀,需要應用使用加鎖讀來保證。而這個加鎖度使用到的機制就是next-key locks。

總結:

四個級別逐漸增強,每個級別解決一個問題。事務級別越高,性能越差,大多數環境read committed 可以用.記住4個隔離級別的特點(上面的例子);

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


注:相關教程知識閱讀請移步到MYSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲自拍小视频免费观看| 亚洲精品av在线播放| 国产精品久久久久久久app| 在线观看日韩欧美| 亚洲国产小视频在线观看| 国产精品久久久久久久久借妻| 色婷婷av一区二区三区久久| 成人伊人精品色xxxx视频| www.日韩av.com| 91亚洲精品一区二区| 久久精品国产99国产精品澳门| 91视频免费网站| 国产日韩换脸av一区在线观看| 久久青草福利网站| 欧美亚洲另类在线| 亚洲国内高清视频| 久久久亚洲国产天美传媒修理工| 国产日韩欧美一二三区| 国产91在线视频| 欧美色播在线播放| 亚洲xxxx3d| 亚洲天堂2020| 亚洲精品电影在线观看| 97人洗澡人人免费公开视频碰碰碰| 成人精品aaaa网站| 亚洲国产97在线精品一区| 91精品在线观| 欧美在线性爱视频| 亚洲黄页视频免费观看| 国产精品视频999| 伦理中文字幕亚洲| 国产精品久久久久av免费| 日韩69视频在线观看| 51色欧美片视频在线观看| 永久免费看mv网站入口亚洲| 精品毛片三在线观看| 亚洲国产高清高潮精品美女| 欧美一级淫片播放口| 国产欧美精品va在线观看| 国产999精品久久久影片官网| 久久精品91久久久久久再现| www.日韩av.com| 国产精品黄色av| 久久国产视频网站| 欧美高清视频在线| 欧美最猛性xxxxx免费| 成人天堂噜噜噜| 亚洲视频综合网| 最近中文字幕2019免费| 欧美专区中文字幕| 久久香蕉国产线看观看av| 精品日本高清在线播放| 久久久99久久精品女同性| 久热99视频在线观看| 欲色天天网综合久久| 亚洲天堂男人的天堂| 中文字幕日韩在线播放| 福利一区福利二区微拍刺激| 日韩中文在线不卡| 久热在线中文字幕色999舞| 国产精品免费一区二区三区都可以| 亚洲视频免费一区| 午夜精品久久久久久久久久久久久| 欧美性猛交99久久久久99按摩| 欧美人成在线视频| 懂色av影视一区二区三区| 久久久噜噜噜久久久| 国产精品久久久久久久一区探花| 一区二区三区天堂av| 在线成人激情视频| 国产精品一区二区三区毛片淫片| 日韩欧美在线视频观看| 久久久久一本一区二区青青蜜月| 91久久综合亚洲鲁鲁五月天| 国产精品久久久久久久9999| 成人午夜高潮视频| 欧美精品激情视频| 成人网在线观看| 欧美亚洲国产另类| x99av成人免费| 国模叶桐国产精品一区| 91精品国产乱码久久久久久久久| www.亚洲免费视频| 亚洲精品免费一区二区三区| 91po在线观看91精品国产性色| 成年无码av片在线| 一区二区亚洲精品国产| 91国产中文字幕| 国产成人精品免高潮在线观看| 亚洲欧美日韩在线高清直播| 欧美极品第一页| 成人亚洲欧美一区二区三区| 欧美精品videos| 亚洲精品mp4| 91产国在线观看动作片喷水| 色哟哟亚洲精品一区二区| 中文字幕一区二区精品| 精品av在线播放| 日韩精品在线看| 久久精品中文字幕电影| 在线午夜精品自拍| 国产日本欧美视频| 中文字幕亚洲精品| 福利微拍一区二区| 一本色道久久88综合亚洲精品ⅰ| 日韩电影免费观看中文字幕| xvideos亚洲| 97国产精品人人爽人人做| 久久久久久69| 91中文字幕在线观看| 亚洲国产精品va在线观看黑人| 国产精品美女www| 欧洲成人午夜免费大片| 日韩中文字在线| 亚洲中国色老太| 91啪国产在线| 亚洲а∨天堂久久精品9966| 国产999视频| 亚洲永久免费观看| 亚洲欧美一区二区精品久久久| 欧美亚洲国产日韩2020| 91香蕉电影院| 91精品久久久久久久久久久久久久| 国产成人亚洲精品| 国产精品一区二区久久精品| 国产精品久久久久免费a∨大胸| 欧美人在线视频| 成人网中文字幕| 91九色单男在线观看| 中文字幕亚洲字幕| 欧美日韩中文在线| 在线精品视频视频中文字幕| 69视频在线免费观看| 国产精品wwww| 国语自产精品视频在线看一大j8| 国产精品亚洲激情| 国产精品久久久久福利| 青草青草久热精品视频在线观看| 91精品国产免费久久久久久| 亚洲免费伊人电影在线观看av| 日韩欧美在线免费观看| 狠狠久久亚洲欧美专区| 午夜精品一区二区三区在线播放| 国产精品一二三视频| 最新的欧美黄色| 亚洲精品av在线| 国产精品99一区| 国自产精品手机在线观看视频| 亚洲免费视频观看| 日韩美女视频中文字幕| 日韩美女视频免费看| 欧美中文字幕精品| 96精品视频在线| 97在线观看视频| 精品电影在线观看| 国产性色av一区二区| 欧美重口另类videos人妖| 日韩福利视频在线观看| 亲子乱一区二区三区电影| 精品国偷自产在线视频99| 日韩国产在线播放| 精品久久久久久亚洲精品| 欧美野外wwwxxx| 欧美午夜激情小视频|