Mysql 行級鎖的使用及死鎖的預防方案

Mysql關系型數據庫管理系統

mysql是一個開放源碼的小型關聯式數據庫管理系統,開發者為瑞典mysql ab公司。mysql被廣泛地應用在internet上的中小型網站中。由于其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,許多中小型網站為了降低網站總體擁有成本而選擇了mysql作為網站數據庫。

mysql的InnoDB,支持事務和行級鎖,可以使用行鎖來處理用戶提現等業務。使用mysql鎖的時候有時候會出現死鎖,要做好死鎖的預防。這篇文章通過實例應用給大家講解

一、前言

    mysql的InnoDB,支持事務和行級鎖,可以使用行鎖來處理用戶提現等業務。使用mysql鎖的時候有時候會出現死鎖,要做好死鎖的預防。

二、MySQL行級鎖

    行級鎖又分共享鎖和排他鎖。

    共享鎖:

      名詞解釋:共享鎖又叫做讀鎖,所有的事務只能對其進行讀操作不能寫操作,加上共享鎖后其他事務不能再加排他鎖了只能加行級鎖。

      用法:

SELECT?`id`?FROM?table?WHERE id?in(1,2)??LOCK?IN?SHARE?MODE

結果集的數據都會加共享鎖

    排他鎖:

      名詞解釋:若某個事物對某一行加上了排他鎖,只能這個事務對其進行讀寫,其他事務不能對其進行加任何鎖,其他進程可以讀取,不能進行寫操作,需等待其釋放。

      用法:

SELECT?`id`?FROM?mk_user?WHERE?id=1?FOR?UPDATE

三、實例應用

<?php   $uid=$_SESSION[&#39;uid&#39;];    //開啟事務    sql:begin    //開啟行級鎖的排他鎖    sql:SELECT `coin` FROM user WHERE id=$uid FOR UPDATE     //扣除用戶賬戶錢幣    $res=update user set coin=coin-value where id=1;    if($res){     //將用戶的提現信息添加到提現表     sql:insert into user values(null,"{$uid}",value);     //判斷添加結果     if(add_cash_result){      sql:commit     }else{      sql:rollback     }    }else{     sql:rollback;    }

 其實步驟不復雜,就是開啟事務判斷各個結果為真就提交為假就回滾。單個排他鎖沒有什么問題,當一個表關聯到多個排他鎖的時候要注意防止發生死鎖。

四、死鎖

    `id`? 主鍵索引

    `name` index 索引

    `age`? 普通字段

    死鎖產生的根本原因是兩個以上的進程都要求對方釋放資源,以至于進程都一直等待。在代碼上是因為兩個或者以上的事務都要求另一個釋放資源。

    死鎖產生的四個必要條件:互斥條件、環路條件、請求保持、不可剝奪,缺一不可,相對應的只要破壞其中一種條件死鎖就不會產生。

    例如下面兩條語句 第一條語句會優先使用`name`索引,因為name不是主鍵索引,還會用到主鍵索引

    第二條語句是首先使用主鍵索引,再使用name索引 如果兩條語句同時執行,第一條語句執行了name索引等待第二條釋放主鍵索引,第二條執行了主鍵索引等待第一條的name索引,這樣就造成了死鎖。

    解決方法:改造第一條語句 使其根據主鍵值進行更新

#①  update?mk_user?set?name?='1'?where?`name`='idis12';  #②  update?mk_user?set?name='12'?where?id=12;  //改造后  update?mk_user?set?name='1'?where?id=(select?id?from?mk_user?where?name='idis12'?);

以上就是Mysql 行級鎖的使用及死鎖的預防方案的內容,更多相關內容請關注PHP中文網(www.php.cn)!

? 版權聲明
THE END
喜歡就支持一下吧
點贊14 分享