On Mar 1, 2011, at 12:46, Ryan Schmidt wrote:

> On Mar 1, 2011, at 11:35, lirc201 wrote:
> 
>> I like the example on the weblink which is just using MySQL
>> functionality, it is very clever.  Thanks for the help and push.  My
>> code is working!  I did like the security tricks I discovered for my
>> updates below to only pass a field list.
>> 
>> function updateInventory($id, $quantity) {
>>              $inv = $this->getQuantity($id);   <- function is in the same 
>> model
>>              $this->data['Model']['id'] = $id;
>>              $this->data['Model']['inventory'] = $inv + $quantity;
>>              if($this->save($this->data, array(
>>                                      'validate' => 'false',
>>                                      'fieldList' => array('id', 
>> 'inventory')))) {
>>                ... logic for return values ...
>>              }
>> }
> 
> This is not atomic. Between the line where you get the current quantity and 
> the line where you save the updated quantity, someone else might have updated 
> the quantity, and you'd be wiping out their change. Consider two managers 
> simultaneously adding 5 to the inventory of the same item. The expected 
> result would be that in the end the inventory is incremented by 10, but 
> because of the race condition in your code, it might only be incremented by 5.

The problem is more apparent if you think about the case of a customer buying 
an item on your site and decreasing the inventory.

Let's say your inventory for item id 3 is 10, and you have two users about to 
buy one each of item id 3. Both users happen to click the Buy button at the 
same instant, which will cause the method updateInventory(3, -1) to be called 
for each user. If this method runs at the same time for both users, then for 
both users getQuantity() will return 10, in both cases you'll add $quantity to 
it, thereby decreasing it by one, and in both cases you'll save 9 to the 
database -- even though two users have successfully bought the item and the 
inventory should now be 8. Clearly this will be a problem as your database 
might say you have more quantity than you actually do and customers will try to 
buy product you no longer have.

The solution is to use a single atomic SQL UPDATE statement, as I showed 
earlier (or rather, the CakePHP equivalent of that), or use an SQL transaction 
(and ensure your database supports transactions -- for example for MySQL, you'd 
use InnoDB tables instead of MyISAM).


-- 
Our newest site for the community: CakePHP Video Tutorials 
http://tv.cakephp.org 
Check out the new CakePHP Questions site http://ask.cakephp.org and help others 
with their CakePHP related questions.


To unsubscribe from this group, send email to
[email protected] For more options, visit this group at 
http://groups.google.com/group/cake-php

Reply via email to