<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          視頻串講大型翻車現(xiàn)場:記錄存在的話就更新,記錄不存在的話就插入

          共 3788字,需瀏覽 8分鐘

           ·

          2021-10-11 11:34




          《為研發(fā)同學定制的MySQL面試指南》?
          貫穿單機、集群、中間件!
          面試官都關注了!你還猶豫?

          Hi,大家好!我是白日夢!本文是MySQL專題的第 27 篇。
          點擊閱讀上一篇文章:“如何實現(xiàn)記錄存在的話就更新,如果記錄不存在的話就插入。”?
          發(fā)布這個話題之后我陸陸續(xù)續(xù)收到了近20條私信。其中有些讀者朋友提到了一些很有價值、值得注意的點。所以就有了這一篇續(xù)文~。
          下文在上一篇的基礎上做一些延伸并且提及到了一些鎖的概念。同樣以問答的方式展現(xiàn)給大家!
          歡迎關注、加入白日夢的圈子,一起系統(tǒng)的學數(shù)據(jù)庫。

          1
          視頻串講本文?













          ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

          視頻是對本篇文章的串講以及一些示例的實戰(zhàn)
          持續(xù)更新~
          歡迎關注我哈~


          2
          好!我們開始吧!?













          ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

          那我們繼續(xù),還是這道場景題:現(xiàn)在我的業(yè)務中有這樣的需求:如果目標記錄存在的話我就更新它,如果記錄不存在的話我就插入。說說看你知道哪些實現(xiàn)方式吧!


          嗯,比如我可以像下面這樣做


          這種方式。

          // 偽代碼user=User.FindById(1)if user == null{  user.Insert()}else{  user.Update()}



          嗯!你這段代碼如果不存在并發(fā)訪問還好,一旦出現(xiàn)并發(fā)訪問的情況。你這段邏輯會有諸多的并發(fā)修改異常的!


          比如這樣的例子:商品有上線和下線的狀態(tài),然后管理員可以在后臺頁面中修改商品的狀態(tài),比如代碼這樣寫的:


          //?偽代碼,如果將狀態(tài)置反if?product.Status?==?“online”{???product.Status?=?"offline";}else{???product.Status?=?"online";??}




          這時管理員A、B并發(fā)的去操作商品狀態(tài):


          ?



          嗯,確實存在這種情況,不過我可以自定義FindById()中的sql語句,通過 select for update的方式,規(guī)避你在圖畫出來的風險。



          比如自定義SQL,讓 user = User.FindByID(1)函數(shù)執(zhí)行的SQL為

          select * from user where id = 1 for update;


          直接select時會給id = 1的行添加一把讀鎖現(xiàn)在我通過select for update檢索,在讀select時給id = 的行添加寫鎖。


          ?那么當我在讀取使用這行數(shù)據(jù)時,其他的人select for update

          就會被阻塞,因為寫鎖之間彼此是互


          斥的。最終也不會出現(xiàn)Update彼此覆蓋的情況



          哦?那你畫一個時序圖出來瞧瞧


          嗯嗯,時序圖大概長下面這樣






          嗯,乍一看你上面畫的這個圖是沒問題的,但我有個問題:如果id = xx的行不存在呢?



          嗯,所以我們不如分不同情況討論一下。下面我列舉不同場景,你畫時序圖怎樣?


          嗯嗯,好的!?




          嗯!首先我們知道了,select for update會嘗試添加X鎖,也就是寫鎖。


          常見的寫鎖有這么幾種:

          1、record lock?給指定行記錄添加鎖

          2、gap lock?間隙鎖

          3、next key lock?


          下面通過在不同條件下執(zhí)行select for update sql,再觀察實驗結果,就能八九不離十的推測出for update的加鎖情況。



          實驗一已知條件如下:

          create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;




          select for update sql為:

          select?*?from?t?where?a=?5?for?update;

          提示:注意id=5的行已經(jīng)存在了。


          下面你畫一下時序圖吧


          嗯嗯,時序圖加鎖情況如下:







          嗯,那如果我們需要執(zhí)行的sql如下:

          select?*?from?t?where?b?=?3?for?update;

          注意b并不是唯一鍵,它只是一個普通索引哦!


          你能畫一下它的加鎖時序圖嗎?


          嗯嗯,時序圖如下:


          (最后一條Sql條件是 where a = 5,不是a=3)




          還是使用這些數(shù)據(jù)

          create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;


          假如我執(zhí)行的sql是:

          select?*?from?t?where?a?=?13?for?update;


          注意:

          1、a=13的行并不存在哦!

          2、a是唯一索引


          你畫一下它的時序圖吧!



          嗯呢,時序圖如下:






          還是使用這些數(shù)據(jù)

          create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;


          假如我執(zhí)行的sql是:

          select?*?from?t?where?a?=?8?for?update;


          注意:

          1、a=8的行并不存在哦!

          2、a是唯一索引


          你畫一下它的時序圖吧!


          嗯嗯、如下:

          對唯一索引來說,gap的上下都鎖不?。?/p>




          還是使用這些數(shù)據(jù)

          create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;


          假如我執(zhí)行的sql是:

          select?*?from?t?where?b?=?5?for?update;


          注意:

          1、b=5的行并不存在哦!

          2、b是普通索引


          你畫一下它的時序圖吧!


          嗯嗯、如下。

          對普通索引來說,gap鎖會 鎖上不鎖下!




          嗯,對的?;氐轿覀円婚_始的主題:如果數(shù)據(jù)存在我們就update

          數(shù)據(jù)不存在我們就insert的話題來看的話。


          通過如下方案:

          begin;select for update# insert?or?update;commit;


          是可以保證并發(fā)修改的安全性的....


          嗯嗯、其實通過實驗來看,確實是安全的。




          小伙子可以的!整體感覺還不錯。


          歡迎關注我。不久會給你安排下一面。


          我沒有問題了,你有什么想問我的嗎?


          暫時沒有了,感謝大佬!




          2
          推薦閱讀

          1、MySQL的修仙之路,圖文談談如何學MySQL、如何進階!

          2、數(shù)據(jù)庫面經(jīng),常見的面試題

          3、談談MySQL中基數(shù)是什么?

          4、聊聊什么是慢查?如何監(jiān)控?如何排查?

          5、對Not Null字段插入Null值有啥現(xiàn)象?

          6、能談談year、date、datetime、time、timestamp的區(qū)別嗎?

          7、你有沒有搞混查詢緩存和Buffer Pool?談談看!

          8、你知道數(shù)據(jù)庫緩沖池中的LRU-List嗎?

          9、了解InnoDB的FreeList嗎?談談看!

          10、了解Flush-List嗎?順便說一下臟頁的落盤機制!

          11、用 11 張圖講清楚,當你CRUD時BufferPool中發(fā)生了什么!以及BufferPool的優(yōu)化!

          12、了解 MySQL的表空間?和?數(shù)據(jù)表嗎?談談看!

          13、了解 MySQL的數(shù)據(jù)行嗎?行溢出機制呢?談談看!

          14、了解MySQL數(shù)據(jù)頁嗎?說說什么是頁分裂吧!

          15、用一分鐘了解fsync這個系統(tǒng)調用

          16、簡述undo log、truncate、以及undo log如何幫你回滾事務?

          17、我勸!這位年輕人不講MVCC,耗子尾汁!

          18、傳說中的MySQL的redo log是什么?談談看!

          19、LSN、Checkpoint?談談MYSQL的崩潰恢復是怎么回事!

          20、MySQL的 bin log有啥用?在哪里?誰寫的?怎么配置?

          21、bin log有哪些格式?有啥區(qū)別?優(yōu)缺點?線上用哪種格式?

          22、刪庫后!除了跑路還能干嘛?

          23、全網(wǎng)最牛X的!MySQL兩階段提交串講!沒有之一!

          24、自導自演的數(shù)據(jù)庫面試現(xiàn)場--談談MySQL的10種文件

          25、大型面試現(xiàn)場:一條update sql的執(zhí)行都經(jīng)歷了什么?

          26、大型翻車現(xiàn)場:如何實現(xiàn)記錄存在的話就更新,如果記錄不存在的話就插入。

          3
          歡迎關注

          歡迎加入白日夢的圈子、一起吃肉!

          長按二維碼、關注白日夢

          贈送精美腦圖

          (操作系統(tǒng)、網(wǎng)絡、Java基礎...)

          長按二維碼

          關注白日夢吧!



          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  狠狠干网站 | 在线无码一区二区三区 | 国产骚比 | 国产91免费视频 | 欧美爆操逼 |