Transaction usage and code examples in Yii2
Preface
In general, we do business logic, will not only be associated with a data table, so we will face transaction problems.
Database Transaction refers to a series of operations performed as a single logical unit of work, either completely or completely not. Transaction processing ensures that data-oriented resources are not permanently updated unless all operations within the transactional unit are successfully completed. By combining a set of related operations into a unit that either succeeds or fails altogether, error recovery can be simplified and the application becomes more reliable. To become a transaction, a logical unit of work must satisfy the so-called ACID (atomicity, consistency, isolation and persistence) attributes. Transaction is a logical unit of work in database operation. Transaction management subsystem in DBMS is responsible for transaction processing.
Get ready
The database engine is innodb
The yii version used in this article is 2.0.5, so long as it is above 2.0, there is no problem.
The running environment is PHP 7.0.0, Mysql 5.6
Transactions in Yii
Handling exceptions
/** * Test transaction */ public function actionTest(){ //Create a transaction $tr = Yii::$app->db->beginTransaction(); try { for($i=1;$i<=3;$i++){ $test = new Areas(); $test->name = 'name'.$i; $test->sort=1; if($test->save()){ echo "save $i | "; } } $test = new Areas(); $test->name = 'ab'.$i; $test->sorta=1; //Write fields that do not exist if(!$test->save()){ "save fail"; //Output without writing } //Submission $tr->commit(); } catch (Exception $e) { //RollBACK $tr->rollBack(); echo "rollback"; } }
Operation results
save 1 | save 2 | save 3 | rollback
Note that because the last data was not inserted successfully, the transaction rollback was triggered, so no new data was generated in the data table.
The cause of the transaction rollback is an exception to the code.
Failure to process data
Generally speaking, there is no such obvious exception in our running code, which will be eliminated in the development and testing process.
What really causes data to roll back is a problem in one of our businesses, which results in data not being written in part.
/** * Test transaction */ public function actionTest(){ //Create a transaction $tr = Yii::$app->db->beginTransaction(); try { for($i=1;$i<=3;$i++){ $test = new Areas(); $test->name = 'name'.$i; $test->sort=1; if($test->save()){ echo "save $i | "; } } $test = new Areas(); $test->name = null; //The name of the database design cannot be empty, resulting in write failure artificially. $test->sort=1; //Write fields that do not exist if(!$test->save()){ echo "save fail"; //Output without writing } //Submission $tr->commit(); } catch (Exception $e) { //RollBACK $tr->rollBack(); echo "rollback"; } }
The results are as follows. Three data are inserted into the database.
save 1 | save 2 | save 3 | save fail
That is to say, if a data table is not written to data because of business logic, there is no corresponding rollback.
The improvement scheme is as follows.
/** * Test transaction */ public function actionTest(){ //Create a transaction $tr = Yii::$app->db->beginTransaction(); try { for($i=1;$i<=3;$i++){ $test = new Areas(); $test->name = 'name'.$i; $test->sort=1; if($test->save()){ echo "save $i | "; } } $test = new Areas(); $test->name = null; //The name of the database design cannot be empty, resulting in write failure artificially. $test->sort=1; //Write fields that do not exist if(!$test->save()){ throw new \yii\db\Exception(); //Manually throw the exception and capture it from below. } //Submission $tr->commit(); } catch (Exception $e) { //RollBACK $tr->rollBack(); echo "rollback"; } }
As a result, no new data was inserted into the database and transactions were rolled back.
save 1 | save 2 | save 3 | rollback
Decentralized data processing
Due to the complexity of the actual project, our database operations are scattered in different models.
So the actual project code will not look like that.
Simulate requirements
Receiving parameters:
Name
Gender
autograph
Business Processing Processes:
Receiving parameters
The user's uid is obtained from the emitter, which adds a digit to the corresponding data table.
Write the name, gender, signature and the next uid to the user information table
Initialize user balance sheet
Rollback trigger timing:
Initialize balance sheet without importing uid export without writing data
Actual code
//Controller
/** * Test Transaction - Registered Users */ public function actionReg() { //Acquisition request $request = Yii::$app->request; //Setting the return format $response = Yii::$app->response; $response->format = \yii\web\Response::FORMAT_JSON; //Return to json //Test the code to remove the authentication step $name = $request->get("name"); $gender = $request->get("gender"); $sign = $request->get("sign"); //Test code, omit parameter checking steps $tr = Yii::$app->db->beginTransaction(); try { //Get uid $uid = App::getSeNo(); UserProfile::add($uid, $name, $gender, 1, $sign); $user_balance = UserBalance::initUserBalance($uid); $tr->commit(); //Submission of data } catch (Exception $e) { //RollBACK $tr->rollBack(); return $e->getMessage(); //Returns custom exception information } return $user_balance; }
//UserProfile
/** * Adding user information * @param $user_id * @param $nikename * @param $gender * @param $user_type * @param string $intro * @return UserProfile * @throws \Exception */ public static function add($user_id, $nikename, $gender,$user_type,$intro="") { $model = new UserProfile(); $model->gender = $gender; $model->nikename = $nikename; $model->user_id = $user_id; $model->user_type=$user_type; $model->intro=$intro; $model->update_time = time(); $insert =$model->insert(); if(!$insert){ throw new Exception("No user data was written"); } return $model; }
//UserBalance
/** * Initialize user's withdrawable balance * @param $user_id */ public static function initUserBalance($user_id){ $info=self::find()->where(['user_id'=>$user_id])->one(); if(!$info ){ $model=new UserBalance(); $model->user_id = $user_id; $model->price= "0"; $model->update_time=time(); $insert = $model->insert(); if(!$insert){ throw new Exception("User balance not initialized"); } $info=$model; } return $info->attributes; }
The normal results are as follows
{"id":124,"user_id":1473179883,"price":"0","update_time":1473179883}
If the user_id of the initialization user balance part is not passed successfully, the result is as follows
"No initialized user balance"
We can locate the error location according to the specific situation and correct it in time.
Transaction
As can be seen from the actual code above, transactions are created, so long as within the scope, even the other models introduced can return the exception NG and complete the rollback operation.
Usually, the whole Yii application uses the same database connection, or singleton.
In yii db Connection, transaction objects are cached:
class Connection extends Component
{
// Save the valid Transaction object of the current connection
private $_transaction;
// If a transaction object is cached and the transaction object is valid, the transaction object is returned. // Otherwise return null public function getTransaction() { return $this->_transaction && $this->_transaction->getIsActive() ? $this->_transaction : null; } // See how transaction objects are used when transactions are enabled public function beginTransaction($isolationLevel = null) { $this->open(); // If the cached transaction object is valid, the transaction object in the cache is used // Otherwise, create a new transaction object if (($transaction = $this->getTransaction()) === null) { $transaction = $this->_transaction = new Transaction(['db' => $this]); } $transaction->begin($isolationLevel); return $transaction; }
}
Therefore, it can be considered that the entire Yii application uses the same Transaction object, that is to say, Transaction:_level is continuous throughout the life cycle of the application. This is the key and prerequisite for transaction nesting.
summary
Technical level growth comes from trampling pits, trampling pits from business growth.
Have time to talk about career planning and development. )
Reference material
http://www.yiichina.com/question/1576
http://www.digpage.com/transaction.html
http://baike.baidu.com/link?url=1-LvBZQ2hgY9-9HcjQrzf3KCsf-iGzRK3FggAYC5mldYukCQ44B2aNTds7ODDz7bLBNtYfxpjH_tpSsNeoMAsK