2

Let's say I do the following:

$favorite = Mage::getModel('testing/favorites')->load(4);
.....
$favorite->save();

How do I make sure the row 4 has been locked and can't be accessed until I call save()?

Edit:

Essentially, I have one table with a column (not id column, not autoincrement) that is a counter, which increments every time a call is made to a function. If two people access this row concurrently, how can I make sure the value is +2 at the end, and not +1?

For example: User A and B call

incrementAction(4);

If the row 4 has a favorite_count = 500, it should, by the end, have a value of 502. The +1 from user A, and the +1 from user B, rather than each incrementing 500 for each +1 and ending up with 501 when each of them calls save().

Pat
  • 794
  • 1
  • 13
  • 30

2 Answers2

3

Your updated question is answered here: Decrement value instead of setting it like `number = number - 1`. Is it possible in Magento? (in short: use $object->setFoo(new Zend_Db_Expr('foo+4')); to increment foo by 4)

To answer the original question for future reference: You could use a transaction like this:

$model->getResource()->beginTransaction();
$model->load($id);
// do stuff...
$model->save();
$model->getResource()->commitTransaction();
Fabian Schmengler
  • 65,791
  • 25
  • 187
  • 421
  • Alright I read the question you linked me to. So, does doing $favorites->setFavoritesCount(new Zend_Db_Expr('favorites_count-1')); do the same thing you did in your answer? As in, is it atomic/safe to use? Or do I need to use a transaction AND use Zend_Db_Expr? – Pat Jul 09 '15 at 08:55
  • 1
    No need for a transaction then. It will use a query like SET favorites_count=favorites_count-1 for saving the object. – Fabian Schmengler Jul 09 '15 at 08:59
2

Magento will do the lock for you when necessary. If you really want to control this yourself then you could write your own queries and use: LOCK IN SHARE MODE within a transaction, after you commit the lock will be released.

For eg:

START TRANSACTION;

SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;

For more info check here: https://dev.mysql.com/doc/refman/5.5/en/innodb-lock-modes.html

lloiacono
  • 3,386
  • 21
  • 40
  • Currently what I'm doing, I'm accessing a row, incrementing an INT value, and saving it. Will it lock for that? If two people access the same function to increment, I don't want to end up incrementing only once since they'll both increment, for example 500 to 501, and then they'll both save 501 instead of 502. – Pat Jul 09 '15 at 07:47
  • I see, can you then reformulate the question. I think the answer I gave you covers your original question. Let me see If I understand correctly what you need: you have one table with a column (not id column, not autoincrement) that is some sort of counter and you want to add +1, if two people access this row concurrently then the value should be +2 at the end? – lloiacono Jul 09 '15 at 07:58
  • Indeed, that's correct. – Pat Jul 09 '15 at 08:23