We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Prevent database update if not really necessary

I'm using Phalcon 3.4. When executing save() on a model, why is an update forced even no data has changed? Assume a model worker with existing data

$worker = ModelWorker::findFirstById(1);

// $worker->getName() returns 'Michael'

$worker->save([ 'name' => 'Michael' ]);

Why is an UPDATE executed when name doesn't have changed? Is there no internal check for changed data before issuing an operation on database?



6.4k
Accepted
answer
edited Oct '18

How you detect what update executed ?

Did you read chapter about snapshots ?

my model

public function beforeUpdate()
{
  if ($this->hasChanged()) {
    $datetime = new \DateTime('now', new \DateTimeZone('UTC'));
    $this->updated_at = $datetime->format('Y-m-d H:i:s');
  }
 }

public function initialize()
{
  $this->keepSnapshots(true);
}

That's how it works - ORM. If you want full speed and low overhead - well, go with plain PDO then and build your models on top.

What would you expect in this case? to have ORM intelligent logic not to roll out your command implicitly since the data equals? What would happen if you would save int instead of string? 1 is equal to '1' from our perspective, but from machine it isn't.

Also, what would happen if your code block takes time to do something, and afterwards call $worker->save([ 'name' => 'Michael' ]);, whilst in the meantime - someone else already updated that record in DB (another user), so in reality it's changed to Peter but your runtime holds info about Michael...

ORM layer is not in a good position to decide, it's job is something completely else.



4.2k

What would you expect in this case? to have ORM intelligent logic not to roll out your command implicitly since the data equals? What would happen if you would save int instead of string? 1 is equal to '1' from our perspective, but from machine it isn't.

Yes, I would have expected this, if data is strictly equal. I'm using snapshot now, to detect if data has changed and block UPDATE else.

Also, what would happen if your code block takes time to do something, and afterwards call $worker->save([ 'name' => 'Michael' ]);, whilst in the meantime - someone else already updated that record in DB (another user), so in reality it's changed to Peter but your runtime holds info about Michael...

ORM layer is not in a good position to decide, it's job is something completely else.

Hum, I think you are right. All these possible phantom data and race conditions and so on, which can happen when executing parallel database operations have to be handled in another way. Also, your assumption is not trivial. Does it has to be Peter? Phalcon ORM would revert it to Michaeleven it has to be Peter. When I know, that I want to update database data, than it has to be queried together with a row lock, so no one other can change it. Even if the request is running long. ACID at its best. Thank god, I'm not working on project for financial world ;-)