In the development of requirements will encounter such a situation , Concurrent requests . The database update is not finished yet , the other one select Data found , It will be the data before the update , That will cause inaccurate query data .
How to solve it ? use innoDB Transaction and lock can solve this problem . Before the end of our current line update ,select Data querying this row will be locked .
For example, our database has two lines of data
We put id=1 Of num Update data to 1000,sleep10 second , At this time we select id=1 Data of , Will wait update End of update for , If we select
id=2 When I was young , There is no need to wait 10 second , We'll get the data right away .
This is it. InnoDB Row lock for , Only current lock update That line of data , Can't lock the whole watch .
The test code is listed below , Remember, the engine changed to innoDB, no MYISAM.
class Index extends Controller { public function index() {
$model=Db::name('test'); $model->startTrans(); try{
$list=$model->lock(true)->find();
$model->where(['id'=>1])->data(['num'=>900])->update();//id by 1 Updates for
sleep(10);// wait for 10 second $model->commit(); print_r($list); }catch (\Exception
$exception){ $model->rollback(); throw $exception; } } public function
index2(){ $model=Db::name('test'); $model->startTrans(); try{
$list=$model->lock(true)->where(['id'=>1])->find();//id by 1 On update ,select id=1
Will wait . hold ID Change to 2 Time , Don't wait $model->commit(); print_r($list); }catch (\Exception
$exception){ $model->rollback(); throw $exception; } } }
testing procedure : request index after , On request index2, You'll see index2 I'll wait index End of loading , Only then can we see index2 Print results of . If index2 Of id Change to 2 after , It will not be affected index The impact of
Technology