<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ![淺談mysql事務](https://pic2.zhimg.com/v2-3fd14aec59f46f7959421473a4693213_1440w.jpg?source=172ae18b) # 淺談mysql事務 https://zhuanlan.zhihu.com/p/52677680 在技術面試中,面試官經常能夠問到關于數據庫事務相關的,通常數據庫事務具備四大特性(ACID),分別是: 1、原子性 2、一致性 3、隔離性 4、持久性 所謂原子性:是指事務是一個最小單元,不可再分隔,成為一個整體。 所謂一致性:是指事務中的方法要么同時成功,要么都不成功。比如A向B轉賬,要不都成功,要不都失敗。 所謂隔離性:是指當多個事務操作數據庫中同一個記錄或多個記錄時,對事務進行隔離開來有序執行,避免同時對同一數據做操作。這時候就需要使用鎖來解決這個問題了(后面講)。 所謂持久性:即當成功插入一條數據庫記錄時,數據庫必須保證有一條數據永久的寫入到數據庫磁盤中。 我們可以分析一下,事務的四大特征中,所有的操作都會走向磁盤,所以持久性是事務操作的目的,而原子性是實現事務的基礎,隔離性是實現數據安全的一種策略、手段,而最終維護的,就是數據的一致性,一致性才是事務中最重要的。四大特征之間,隔離性是為了達到一致性的手段。 ACID四大特征中,最難理解的不是一致性,而是事務的隔離性,數據庫權威專家針對事務的隔離性研究出來了事務的隔離四種級別,四種事務隔離級別就是為了解決數據在高并發下產生的問題(臟讀、不可重復讀、幻讀)。 ![](https://pic1.zhimg.com/80/v2-19a4864e39e6e9a257532d4ab8c94a3e_720w.jpg) Mysql默認使用的數據隔離級別是REPEATABLE READ ,可重復讀,允許幻讀。 ~~~text 省查看數據庫默認隔離級別 SELECT @@tx_isolation ~~~ 什么是臟讀、不可重復讀、幻讀呢?我們來看看。 ## **臟讀** 臟讀:比如有兩個事務并行執行操作同一條數據庫記錄,A事務能讀取到B事務未提交的數據。如下圖所示:事務B操作了數據庫但是沒有提交事務,此時A讀取到了B沒有提交事務的數據。這就是臟讀的體現。 ![](https://pic2.zhimg.com/80/v2-22fe34b33a0b4dc74373fdfc638f503d_720w.jpg) 我們用數據庫實例來演示一下臟讀現象,首先我本地安裝了mysql5.7,關閉數據庫自動提交事務開關 ~~~text 臨時有效 mysql數據庫事務開關 開啟自動提交事務:set autocommit = 1; 關閉自動提交事務:set autocommit = 0 ; 查看事務開關:show variables like '%autocommit%'; ~~~ ![](https://pic2.zhimg.com/80/v2-56d61517ccd08c1290b0d3ad4d57b46d_720w.jpg) 然后我們修改數據庫的事務級別,命令如下: ~~~text //全局的 ---此處演示我們設置全局的 set global transaction isolation level read uncommitted; //當前會話 set session transaction isolation level read uncommitted; ~~~ 我們使用Navicat演示一下臟讀,打開兩個窗口,命令如下: ~~~text /**數據庫建表語句*/ CREATE TABLE `user_money` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `user_id` bigint(20) NOT NULL COMMENT '用戶id', `money` decimal(25, 2) NOT NULL COMMENT '余額', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶余額表' ROW_FORMAT = Dynamic; /**插入一條數據*/ INSERT INTO `user_money` VALUES (1, 2628, 1000.00); ~~~ Navicat窗口A,查詢指定用戶信息(此處不提交事務) ~~~text ---------- 窗口A ------------------------------------------ -- 關閉自動提交事務 set autocommit = 0 -- 查詢指定用戶 select * from user_money where user_id = '2628' -- 修改指定用戶余額 update user_money a set a.money = 500; -- 提交事務 -- commit; -- 回滾事務 -- ROLLBACK; ~~~ Navicat窗口B,當窗口A操作完成后再查詢指定用戶信息 ~~~text ---------- 窗口B ------------------------------------------ -- 關閉自動提交事務 set autocommit = 0 -- 查詢指定用戶 select * from user_money where user_id = '2628' ~~~ 此時我們看看查詢結果: ![](https://picb.zhimg.com/80/v2-65a752065b7bb7c777a3575c1fb6a819_720w.jpg) 很顯然,事務A修改了數據后還沒有提交事務,此時事務B可以讀取到事務A沒有提交的事務的數據。這就是臟讀,臟讀情況下的數據是不可取的,所以一般沒有數據庫事務級別設置為允許臟讀。 一句話總結:**臟讀就是指事務A讀取到事務B修改但未提交事務的數據。** ## **不可重復讀** 學習完臟讀后,我們再來看看什么是不可重復讀。比如事務A在同一事務中多次讀取同一記錄,此時事務B修改了事務A正在讀的數據并且提交了事務,但是事務A讀取到了事務B所提交的數據,導致兩次讀取數據不一致。如下圖所示: ![](https://picb.zhimg.com/80/v2-ceff3aeabc16afc0033c5060abe8e14c_720w.jpg) 然后我們修改數據庫的事務級別,命令如下: ~~~text //全局的 ---此處演示我們設置全局的 set global transaction isolation level read committed; //當前會話 set session transaction isolation level read committed; ~~~ 我們使用Navicat演示一下臟讀,打開兩個窗口,命令如下: ~~~text ---------- 窗口A ------------------------------------------ -- 關閉自動提交事務 set autocommit = 0 -- 查詢指定用戶 select * from user_money where user_id = '2628' -- 查詢指定用戶 select * from user_money where user_id = '2628' -- 提交事務 commit; ~~~ 窗口A先是開啟事務,然后查詢指定用戶信息,然后窗口B開啟事務,查詢數據指定用戶,修改數據,提交事務,然后再回到窗口A,查詢指定用戶信息;窗口B代碼如下: ~~~text ---------- 窗口B ------------------------------------------ -- 關閉自動提交事務 set autocommit = 0 -- 查詢指定用戶 select * from user_money where user_id = '2628' -- 修改指定用戶余額 update user_money a set a.money = 500; -- 提交事務 commit; ~~~ ![](https://pic3.zhimg.com/80/v2-18f7c12a9c13229210911f7ce9702573_720w.jpg) 事務A在兩次查詢中,查詢的數據不一樣,這就是不可重復讀。Mysql默認采用的就是不可重復讀的隔離級別,用一句話總結,**不可重復讀就是事務A讀取到事務B已提交事務的數據,導致兩次讀取數據信息不一致。** ## **幻讀** 上面我我們學習了一下什么不可重復讀,在mysql數據庫中,不可重復讀是不被允許的,mysql默認的隔離級可重復讀,也就是幻讀。 下面我們再來看看幻讀,什么是幻讀呢? \-------------------------2020年5月31日 10:11:42------------------ 之前關于幻讀這一塊描述有問題,此處進行更正; 從字面上看幻讀二字,更多的感覺像是讀取到了一個虛幻的假象。 幻讀,并不是說兩次讀取獲取的結果集不同,幻讀側重的方面是某一次的 select 操作得到的結果所表征的數據狀態無法支撐后續的業務操作。 更為具體一些:select 某記錄是否存在,不存在,準備插入此記錄,但執行 insert 時發現此記錄已存在,無法插入,此時就發生了幻讀。 ![](https://pic1.zhimg.com/80/v2-f56a3fc90e7e43afbf6e1eb5364cf9b3_720w.jpg) 幻讀 然后我們修改數據庫的事務級別,命令如下: ~~~text //全局的 ---此處演示我們設置全局的 set global transaction isolation level repeatable read; //當前會話 set session transaction isolation level repeatable read; ~~~ 我們使用Navicat演示一下臟讀,打開兩個窗口,命令如下: ~~~text -- -------- 窗口A ------------------------------------------ -- 關閉自動提交事務 set autocommit = 0; select * from user_money where id = 5; -- 沒有查詢到結果,進行插入 insert into user_money (id, user_id , money) values (5, 5,5); -- 再查詢id為5的 select * from user_money where id = 5; commit; ~~~ 此處,事務A中查詢指定id為5的記錄,沒有查詢到結果后,事務B進行插入了一條id為5的記錄并且提交事務; ~~~text ---------- 窗口B ------------------------------------------ -- 關閉自動提交事務 set autocommit = 0; -- 插入一條記錄 insert into user_money (id, user_id , money) values (5, 5,5); -- 提交事務 commit; ~~~ 此時事務A執行插入一句會報錯主鍵沖突,但是再進行查詢的時候又查詢不到 ![](https://pic2.zhimg.com/80/v2-4d53febf48057617c1851457bac6af82_720w.jpg) 在上述事務A中,不提交事務的情況下,插入id為5的記錄會一直報錯主鍵沖突,但是再怎么查詢id為5的記錄都查詢不到;這是因為在MySql的設計中,事務中查詢的是被修改前的日志,即Undo log(MVCC中的一個概念);可參考 [加耀:Mysql中InnoDB學習MVCC知識點總結?zhuanlan.zhihu.com![圖標](https://pic3.zhimg.com/v2-3623df34c76a5df765fece138f66cc48_180x120.jpg)](https://zhuanlan.zhihu.com/p/75825571) 關于幻讀的問題,可以通過加鎖的方式進行解決。 ## **串行化** 另外還有一種事務級別就是序列化方式SERIALIZABLE,序列化事務級別既不允許臟讀,也不允許不可重復讀,并且還不允許幻讀。 事務隔離級別越嚴格,越消耗計算機性能,效率也越低,通常情況下,設置為允許不可重復讀就可以解決大多數的問題了。 這里,我們對數據庫事務基本上已經有了一個新的認識了。那么,數據庫是怎么來隔離事務的呢?這時候就涉及到了數據庫鎖了。這個我們在下一章節中會詳細描述的。 2020年5月31日 10:45:10
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看