<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>

                # TP5實戰源碼---樂觀鎖的應用 [TOC] ## 樂觀鎖的概念 >[info] 樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖機制采取了更加寬松的加鎖機制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,以保證操作最大程度的獨占性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。而樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基于數據版本( Version )記錄機制實現。何謂數據版本?即為數據增加一個版本標識,在基于數據庫表的版本解決方案中,一般是通過為數據庫表增加一個 “version” 字段來實現。讀取出數據時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大于數據庫表當前版本號,則予以更新,否則認為是過期數據。 ------- 百度百科 ## 樂觀鎖示例 >[info] 如一個金融系統,當某個操作員讀取用戶的數據,并在讀出的用戶數據的基礎上進行修改時(如更改用戶帳戶余額),如果采用悲觀鎖機制,也就意味著整個操作過 程中(從操作員讀出數據、開始修改直至提交修改結果的全過程,甚至還包括操作 員中途去煮咖啡的時間),數據庫記錄始終處于加鎖狀態,可以想見,如果面對幾百上千個并發,這樣的情況將導致怎樣的后果。 樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基于數據版本 ( Version )記錄機制實現。何謂數據版本?即為數據增加一個版本標識,在基于數據庫表的版本解決方案中,一般是通過為數據庫表增加一個 “version” 字段來實現。 讀取出數據時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大于數據庫表當前版本號,則予以更新,否則認為是過期數據。 對于上面修改用戶帳戶信息的例子而言,假設數據庫中帳戶信息表中有一個 version 字段,當前值為 1 ;而當前帳戶余額字段( balance )為 $100 。 1. 操作員 A 此時將其讀出( version=1 ),并從其帳戶余額中扣除 $50( $100-$50 )。 1. 在操作員 A 操作的過程中,操作員B 也讀入此用戶信息( version=1 ),并從其帳戶余額中扣除 $20 ( $100-$20 )。 1. 操作員 A 完成了修改工作,將數據版本號加一( version=2 ),連同帳戶扣除后余額( balance=$50 ),提交至數據庫更新,此時由于提交數據版本大于數據庫記錄當前版本,數據被更新,數據庫記錄 version 更新為 2 。 1. 4 操作員 B 完成了操作,也將版本號加一( version=2 )試圖向數據庫提交數據( balance=$80 ),但此時比對數據庫記錄版本時發現,操作員 B 提交的數據版本號為 2 ,數據庫記錄當前版本也為 2 ,不滿足 “ 提交版本必須大于記錄當前版本才能執行更新 “ 的樂觀鎖策略,因此,操作員 B 的提交被駁回。 這樣,就避免了操作員 B 用基于 version=1 的舊數據修改的結果覆蓋操作員A 的操作結果的可能。 ## 樂觀鎖Model通用代碼(TP5) 此方法為Model基類通用方法 ~~~ /** * 帶有樂觀鎖的修改 * Power: Mikkle * Email:776329498@qq.com * @param $save_data   修改的數據 * @param string $edit_pk 修改的ID字段名稱 * @param string $version_field  樂觀鎖版本號字段名稱 * @return array */ public function editDateWithLock($save_data,$edit_pk="",$version_field=""){ if (empty($version_field)){ $version_field = isset($this->versionField) ? $this->versionField : "edit_version"; } if (empty($edit_pk)){ $edit_pk = isset($this->editPk) ? $this->editPk : $this->getPk(); } //判斷PK字段是否存在 if (!isset($save_data[$edit_pk])||!isset($save_data[$version_field])){ return self::showReturnCodeWithOutData(1003,"參數缺失"); }else{ //設置升級檢索條件 PK和版本號 $map[$edit_pk] = $save_data[$edit_pk]; $map[$version_field] = $save_data[$version_field]; //剔除PK unset($save_data[$edit_pk]); } try{ //檢測版本字段 if($this->hasColumn($version_field)){ throw new Exception("樂觀鎖版本字段[$version_field]不存在"); } $original_data = $this->where($map)->find(); if (empty($original_data)){ throw new Exception("此條信息已經變動了,請重新操作!"); } foreach ($save_data as $item=>$value){ if (isset($original_data[$item])){ //修改的數值不變時候 剔除 if ($original_data[$item]==$value){ unset( $save_data[$item]); }elseif($item!=$version_field){ unset( $original_data[$item]); } }else{ //修改的字段不存在 剔除 unset( $save_data[$item]); } } if(empty($save_data)){ throw new Exception("修改的數值無變化"); } //版本號升級 $save_data[$version_field]=(int)$original_data[$version_field]+1; if (1!=$this->allowField(true)->save($save_data,$map)){ throw new Exception("修改信息出錯:".$this->getError()); } //記錄修改日志 $this->saveEditLog($original_data,$save_data); return self::showReturnCodeWithOutData(1001); }catch (Exception $e){ $msg=$e->getMessage(); return self::showReturnCodeWithOutData(1003,$msg); } } ~~~ ## 控制器調用方法 最簡單的調用方式 ~~~ $model =new Log(); $data =[ "id"=>1, "text"=> time(), "edit_version"=>2 ]; $model->editDateWithLock($data); ~~~ 使用doModelAction調用 ~~~ public function addStructureData() { if($this->request->isAjax()){ $data = $this->request->post(); $data['project_guid']=$this->request->param('project_guid'); $validate_name='base/ProjectStructure.edit'; $model_name='base/ProjectStructure'; return json($this->doModelAction($data,$validate_name,$model_name,"editDateWithLock")); } } ~~~ ## 使用到的其他方法 * doModelAction方法參見 TP5實戰技巧---整合基類 化繁為簡 教程 * saveEditLog方法示例 (位置模型基類) ~~~ /** * 保存修改信息 * Power: Mikkle * Email:776329498@qq.com * @param $original_data * @param $save_data * @return bool */ protected function saveEditLog($original_data,$save_data){ if (empty($original_data)&&empty($save_data)){ $this->error="保存的修改信息不存在"; return false; } $log_data=[ "uuid"=>Session::get('uuid', 'Global'), "model_data"=>$this->name, "original_data"=>$original_data, "save_data"=>$save_data, "update_time"=>time(), ]; try{ Db::table("update_log")->insert($log_data); return true; }catch (Exception $e){ $log_data["error"]="保存修改信息出錯"; Log::write(json_encode($log_data),"error"); return false; } } ~~~ * hasColumn 判斷字段是否存在(位置模型基類) ~~~ /** * 判斷字段是否存在 * Power: Mikkle * Email:776329498@qq.com * @param $column * @param string $table * @return bool */ protected function hasColumn($column,$table=""){ $table = isset($table)?$table:$this->table; if (empty($table)||$column){ $this->error="hasColumn方法參數缺失"; return false; } $sql = "SELECT * FROM information_schema.columns WHERE table_schema=CurrentDatabase AND table_name = '{$table}' AND column_name = '{$column}'"; return $this->query($sql) ? true : false; } ~~~ 有問題的請留言
                  <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>

                              哎呀哎呀视频在线观看