Talking about the use and principle of Yii optimistic lock, talking about yii
This article introduces the use and principles of Yii optimistic locks. I will take a study note and share it with you. I hope it will be useful to you.
Principle:
The data table uses an int type field to store the version number, that is, the version number recorded in this row. When updating data, compare whether the version number is consistent
The SQL query code is as follows (pseudocode)
update `test_ver` set `name`="lili" and `ver`=2 where `id`=1 and `ver`=1
That is, when updating the where query condition, the version number obtained from the previous query record is included. If other threads have modified this record, the version number is bound to be inconsistent, and the update fails.
Example
Data Table
Assume that the following data table is available:
Model class
AppmodelsTestVer
This model class is used to override the optimisticLock method in the BaseActiveRecord class.
Declare fields used to record version numbers
/*** Optimistic lock * @ return string */public function optimisticLock () {return 'ver ';} public function updateRecord () {$ ver = self :: findOne (['id' => 1]); $ ver-> name = "lili"; $ res = $ ver-> update (); return $ res ;}
UpdateRecord: Record whose id is changed to 1
Controller
Call the updateRecord method in the Controller
public function actionVersion(){ $testVer = new TestVer(); $res = $testVer->updateRecord(); return $this->render('version');}
Yii Debugger result
Check the database option to view the actually executed SQL statements.
One statement is as follows:
UPDATE `test_ver` SET `name`='lili', `ver`='2' WHERE (`id`='1') AND (`ver`='1')
Yii optimistic lock implementation principle
The implementation principle is in the yiidbBaseActiveRecord: updateInteranl () method.
Protected function updateInternal ($ attributes = null) {if (! $ This-> beforeSave (false) {return false ;} // obtain the fields to be updated and the new field values. $ values = $ this-> getDirtyAttributes ($ attributes); if (empty ($ values )) {$ this-> afterSave (false, $ values); return 0;} // use the primary key of the original ActiveRecord as the condition for updating the record. // That is to say, only one record is allowed. $ Condition = $ this-> getOldPrimaryKey (true); // obtain the field name of the version number field, such as ver $ lock = $ this-> optimisticLock (); // If optimisticLock () if null is returned, the optimistic lock is not enabled. If ($ lock! = Null) {// $ this-> $ lock here is the meaning of $ this-> ver. // here, ver + 1 is used as one of the fields to be updated. $ Values [$ lock] = $ this-> $ lock + 1; // here, the old version number is used as another condition for updating $ condition [$ lock] = $ this-> $ lock;} $ rows = $ this-> updateAll ($ values, $ condition); // If the optimistic lock is enabled but the update is not completed, or the number of updated records is 0; // It indicates that the ver does not match, if the record has been modified, an exception is thrown. If ($ lock! = Null &&! $ Rows) {throw new StaleObjectException ('the object being updated is outdated. ');} $ changedAttributes = []; foreach ($ values as $ name => $ value) {$ changedAttributes [$ name] = isset ($ this-> _ oldAttributes [$ name])? $ This-> _ oldAttributes [$ name]: null; $ this-> _ oldAttributes [$ name] = $ value ;}$ this-> afterSave (false, $ changedAttributes ); return $ rows ;}
From the code above, we can easily conclude that:
- When optimisticLock () returns null, the optimistic lock is not enabled.
- The version number only increases or decreases.
- There are two conditions for optimistic locks. One is that the primary key must exist, and the other is that the update must be completed.
- When optimistic lock is enabled, StaleObjectException is thrown in only the following two cases:
- After a record is deleted, the update fails because the primary key does not exist.
- The version number has changed and does not meet the second update condition.
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.