views:

113

answers:

6
insert into table1 ...;
update table2 set count=count+1;

The above inserts something into table1, and if it succeeds, updates the count field of table2.

Of course this kind of thing can be handled by transactions, but transactions need to lock the table, which will be not efficient in a high concurrent system. And it can be even worse if you need to update multiple tables in that transaction.

What's your solution?

I'm using PHP, and I implement transactions this way:

mysql_query('begin');

mysql_query($statement1);

mysql_query($statement2);
...
mysql_query('commit');

So it looks like all tables referred in those $statement will be locked?

+1  A: 

these looks more like a "Triggers" job to me. onInsert do something.

Rufinus
Which version of MySQL has a stable trigger implemented?
>=5.1.6 http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html
Rufinus
+3  A: 

A transaction (which in context of MySQL assumes InnoDB) will not need to lock the whole table.

The INSERT will lock the individual row without gap locks.

The UPDATE will not lock any gaps too if you provide an equality or IN condition on an indexed field in the WHERE clause.

This means that with a properly indexed table, INSERTs will not block each other, while the UPDATEs will only block each other if they affect the same row.

The UPDATE will of course lock the individual row it affects, but since it is the last operation in your transaction, the lock will be lifted immediately after the operation is commited.

The locking itself is in fact required so that two concurrent updates will increment the counts sequentially.

Quassnoi
INSERTs may not block each other with row-locks, but they can still contend with locks on the indexes in the table, and indeed, deadlock with one another. I have seen it.
MarkR
`@MarkR`: you're right, and that's why I specifically mentioned "properly indexed table". Here's a question about the problem you're talking about: http://stackoverflow.com/questions/1974890/mysql-stored-procedure-causing-problems
Quassnoi
+2  A: 

Use InnoDB storage engine. It is row level locking instead of MyISAM which is table level locking.

Yada
Or you could switch to Oracle which (under most cases) performs NO locking. :)
LBushkin
`@LBushkin`: any `DML` operation on a permanent table in `Oracle` locks the affected rows until the end of transaction.
Quassnoi
Oracle will lock rows where relevant - it is necessary to obtain correct transactional behaviour.
MarkR
+1  A: 

Transactions are great to ensure a "all or nothing" behavior -- even if there is a high load or high concurrency in your system, you shouldn't stop using transactions, at least if you need your data to stay coherent !

(And transactions will not necessarily lock the whole table(s))

Pascal MARTIN
+2  A: 

Transactions will not necessarily request a lock for the whole table.

In addition, InnoDB supports various translation isolation levels using different locking strategies. You may want to check:

Daniel Vassallo
A: 

If speed were of the absolute essence, I might be tempted to cache the update count in memory (using thread-safe code) and only write it back to the database periodically. I would certainly use a transaction when I did so. The downside to this is that you would need to be willing to treat the count as only approximate. If you needed it to be absolutely correct for an operation, then it would need to be recalculated, again within a transaction.

As others have pointed out, using a database that supports row-level locking and simply using an explicit (or implicit via a trigger) transaction is probably easier. It's definitely more accurate and safer.

tvanfosson