The magento ORM layer doesn`t seem to handle concurrent saving of the same object gracefully. When saving a model the ORM issues an update sql query that just tests for the primary key.
Lets say you updated the customer_lastname of an order and save it to the database. The ORM layer will issue a query like this:
UPDATE sales_flat_order SET customer_lastname=`Test` WHERE entity_id=3
If another process (e.g. the paypal ipn controller) changed the same order at the same time (e.g. mark the order as payed), its changes might be overwritten.
This seems to me like a major flaw in the design of the ORM. Is there a reason the ORM layer doesn`t test for changes in the database upon saving?
The ORM layer might issue a query like:
UPDATE sales_flat_order SET customer_lastname=`Test` WHERE entity_id=3
AND state='pending' AND status='pending' …
If the number of altered rows returned by the db is 1 it is certain that the database had not changed since the model was loaded. If the number of altered rows is 0 then the database was changed by another process after the model was loaded and the new changes were not saved and the save method should fail.
Is there a reason Magento doesn`t already do that (perhaps performance)?
Update
When creating a shipment in magento this happens (not only when creating a shipment, but this mechanism can be found throughout the codebase):
- Load the order from the database using SELECT into model object
- Create shipment model object from order
- Loads all order items in model objects
- gets QtyToShip from item model object (qty_ordered - qty_shipped - qty_refunded - qty_canceled)
- updates qty_shipped in order_item model object
- Save in DB
- START TRANSACTION
- save shipment model object in db
- save order model object in db
- save order_item model objects in db
- COMMIT
When two processes try to create a shipment for the same order at the same time and process B is able to finish step 3 outlined above while process A is in step 2 then once process A finishes step 3 the changes made to the order_items by process B are overwritten.