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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql四种事务隔离级别

發布時間:2024/4/15 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql四种事务隔离级别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

mysql事務并發問題

ACID什么的就不啰嗦了。mysql多個事務并發的時候,可能會出現如下問題:

1. 更新丟失

  即兩個事務同時更新某一條數據,后執行的更新操作會覆蓋先執行的更新操作,導致先執行的更新結果丟失。

2. 臟讀

  即一個事務會讀到另一個事務尚未提交的數據更新,由于該數據更新可能會回滾,所以稱之為臟讀。

3. 不可重復讀

  即一個事務中對同一行數據讀取兩次,會得到不同的結果。原因是在該事務兩次讀取之間,其他事務會修改此數據。

4. 幻讀

  即一個事務對同一個表執行兩次查詢,會得到相同的結果行數。即使在該事務兩次查詢之間,其他事務同時也向此表插入了新的數據。

mysql事務隔離級別

mysql共支持四種事務隔離級別,分別是:

  • read uncommitted(讀取未提交數據):從字面上理解,該事務隔離級別允許讀取未提交數據。僅處理更新丟失的問題,但是不處理臟讀、不可重復讀、幻讀的問題。
  • read committed(讀取已提交數據):從字面上理解,該事務隔離級別允許讀取已經提交的數據,即未提交的數據不可讀取。則該事務隔離級別處理更新丟失、臟讀的問題,不處理不可重復讀、幻讀的問題。
  • repeatable read(重復讀):該事務隔離級別無法從字面上理解了,處理更新丟失、臟讀、不可重復讀的問題,不處理幻讀的問題。
  • serializable(最高隔離級別):該事務隔離級別為最高事務隔離級別,處理以上所有問題,包括:更新丟失、臟讀、不可重復讀、幻讀。
  • 以上四種事務隔離級別依次遞增,事務隔離級別越高,一致性越強可用性越差。

    可以看到,所有的事務隔離界別都會處理更新丟失的問題。mysql默認的事務隔離級別為:repeatable read,即默認不處理幻讀的問題。

    廢話不多說,直接上例子(大前提:數據庫引擎為innoDB):

    1. 首先要注意:mysql自動提交事務要關閉

    查看mysql的autoCommit是否開啟:

    -- 查看mysql是否自動提交事務 show variables like 'autocommit';

    如果需要關閉autoCommit,則執行如下語句:

    -- 關閉autoCommit set autocommit = 0;

    2. 查看、設定mysql的事務隔離級別:注意只在當前會話session有效。

    -- 查看當前數據庫事務隔離級別 select @@tx_isolation;-- 設定當前數據庫隔離級別為 read uncommitted set session transaction isolation level read uncommitted; ---set session transaction isolation level read committed ; -- set session transaction isolation level repeatable read ; -- set session transaction isolation level serializable;

    3.?創建測試表及測試數據

    use test;create table dt_table1 (id int auto_increment primary key,value varchar(50) null );insert into dt_table1 (value) value ('00000000'); insert into dt_table1 (value) value ('00000000'); insert into dt_table1 (value) value ('00000000');

    (1)測試更新丟失

    我們先更新一下數據,以便后續測試。

    update dt_table1 set value = '00000000' where id = 1;

    設定測試環境:創建兩個session連接,并設定事務隔離級別 read uncommited

    set session transaction isolation level read uncommitted;

    打開session連接1,執行如下腳本,通過第三步可以看到數據已經被更新:

    start transaction; -- 第一步 update dt_table1 set value = 'update 1' where id = 1; -- 第二步 select * from dt_table1 where id = 1; -- 第三步

    打開session連接2,執行如下腳本,當執行第五步的時候,可以看到該更新操作被阻塞了。

    start transaction; -- 第四步 update dt_table1 set value = 'update 2' where id = 1; -- 第五步

    回到session連接1,執行commit,可以看到session連接2中第五步的更新操作也取消了阻塞并執行通過了。

    commit; -- 第六步

    回到session連接2,執行查詢并commit。最終數據被更新為值‘update 2’。

    select * from dt_table1 where id = 1; -- 第七步 commit; -- 第八步

    通過以上的例子,我們可以看出,即使是mysql的最低事務隔離級別,也解決了更新丟失的問題。即:在session連接1中執行更新操作但尚未提交事務,session連接2中的更新操作會被阻塞,以避免session連接1中的更新丟失。將兩個session連接的事務隔離級別設定為其他等級也會得到同樣的結果。

    (2)測試臟讀

    我們先更新一下數據,以便后續測試。

    update dt_table1 set value = '00000000' where id = 1;

    設定測試環境:創建兩個session連接,并設定事務隔離級別 read uncommited。在此事務隔離級別下,會出現臟讀的問題。

    set session transaction isolation level read uncommitted;

    打開session連接1,執行如下腳本。

    start transaction; -- 第一步 update dt_table1 set value = 'read uncommitted' where id = 1; -- 第二步

    打開session連接2,執行如下腳本。可以看到讀取到了session連接1中已經更新但尚未提交的數據(查詢值為‘read uncommited’)。

    select * from dt_table1 where id = 1; -- 第三步

    回到session連接1,執行rollback。

    rollback; -- 第四步

    回到session連接2,再次執行查詢,可以看到查詢值已經成功回滾(查詢值為:‘00000000’)

    select * from dt_table1 where id = 1; -- 第五步

    通過以上的例子,我們可以看出,將mysql的事務隔離級別設定為read uncommited,會出現臟讀的問題。即:session連接2中在第三步會讀取到session連接1中已經更新但尚未提交的數據,由于session鏈接1可能會發生事務回滾,那么session連接2中讀取到的數據也就無效了,即讀取臟數據,即臟讀。

    如果設定事務隔離級別為read commited或以上,則不會出現此問題。上例中第三步讀取到的值會為:'00000000'。即不會臟讀。

    (3)嘗試不可重復讀

    我們先更新一下數據,以便后續測試。

    update dt_table1 set value = '00000000' where id = 1;

    設定測試環境:創建兩個session連接,并設定事務隔離級別 read commited。在此事務隔離級別下,會出現不可重復讀情況。

    set session transaction isolation level read committed;

    打開session連接1,執行如下腳本。可以看到查詢值為‘00000000’

    start transaction; -- 第一步 select * from dt_table1 where id = 1; -- 第二步

    打開session連接2,執行如下腳本。

    start transaction; -- 第三步 update dt_table1 set value = 'read committed' where id = 1; -- 第四步 commit; -- 第五步

    回到session連接1,執行如下腳本??梢钥吹讲樵冎禐椤畆ead commited’

    select * from dt_table1 where id = 1; -- 第六步 commit; -- 第七步

    通過以上的例子,我們可以看出,將mysql的事務隔離級別設定為read commited,會出現不可重復讀問題,即在session連接1中的一個事務中,先后兩次讀取到的值不一樣。原因是在該事務兩次讀取之間,session連接2的事務修改并提交了此數據。

    如果設定事務隔離級別為repeatable read或以上,則不會出現此問題。上例中第六步讀取到的數據值依然為‘00000000’

    (4)嘗試幻讀

    設定測試環境:創建兩個session連接,并設定事務隔離級別 repeatable read。在此事務隔離級別下,會出現幻讀的情況。

    set session transaction isolation level repeatable read ;

    我們先更新一下數據,以便后續測試

    update dt_table1 set value = '00000000' where 1=1;

    打開session連接1,執行如下腳本。我們記錄下第二步查詢結果行數,假如為n行。

    start transaction; -- 第一步 select * from dt_table1; -- 第二步

    打開session連接2,執行如下腳本。

    start transaction; -- 第三步 insert into dt_table1 (value) value ('phantom read new'); -- 第四步 commit; -- 第五步

    回到session連接1,執行如下腳本,可以看到第六步查詢結果行數依然為n,但是執行第七步更新操作的時候,更新影響行數卻是n+1。執行第九步查詢的時候結果行數也是n+1

    select * from dt_table1; -- 第六步 update dt_table1 set value = 'phantom read' where 1=1; -- 第七步 commit; -- 第八步 select * from dt_table1; -- 第九步

    通過以上的例子,我們可以看出幻讀問題的存在,即:第六步查詢結果明明是n行,但是第七步跟新操作影響行數卻是n+1,難道是我的幻覺?這就是幻讀。

    如果設定事務隔離級別為serializable,則不會出現此問題。第四步執行輸入插入操作時會被阻塞,第七步更新操作影響結果行數和第六步查詢結果行數也會保持一致,且執行到第九步的時候,可以看到第四步新插入的數據也并沒有被第七步更新掉。

    轉載于:https://www.cnblogs.com/LOVE0612/p/9836530.html

    總結

    以上是生活随笔為你收集整理的mysql四种事务隔离级别的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。