mysql 行級鎖的使用以及死鎖的預防

1、前言php

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

 

  2、MySQL行級鎖sql

 

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

 

    共享鎖:索引

 

      名詞解釋:共享鎖又叫作讀鎖,全部的事務只能對其進行讀操做不能寫操做,加上共享鎖後在事務結束以前其餘事務只能再加共享鎖,除此以外其餘任何類型的鎖都不能再加了。進程

 

      用法:SELECT `id` FROM  table WHERE id in(1,2)   LOCK IN SHARE MODE 結果集的數據都會加共享鎖事務

 

    排他鎖:資源

 

      名詞解釋:若某個事物對某一行加上了排他鎖,只能這個事務對其進行讀寫,在此事務結束以前,其餘事務不能對其進行加任何鎖,其餘進程能夠讀取,不能進行寫操做,需等待其釋放。it

 

      用法:SELECT `id` FROM mk_user WHERE id=1 FOR UPDATEtable

 

  3、實例應用

 

 

<?php

        $uid=$_SESSION['uid'];

        //開啓事務

        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;

        }

 

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

 

  4、死鎖

 

    `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' );

相關文章
相關標籤/搜索