Featured Database Articles

Table locking for all table types

InnoDB and BDB tables
both make use of row level locking, whereby only the row/s being manipulated
are locked. This means that other rows can still be manipulated, reducing the
risk of contention, but is also a less optimal process than table level locking
if most of the queries are SELECT's. MyISAM tables do not have row-locking,
which is why they are not a great choice if the application has a high ration
of INSERT's or UPDATE's to SELECT's. However, all table types can make use of table-locking,
using the LOCK TABLE statement.

Since this is the only
kind of locking available to MyISAM tables, let's create a MyISAM table to test
on:

There are two main kinds
of locks - read locks and write locks. A read lock only allows
reads on the table, not writes, while a write lock only allows that connection
to read and write - all other connections are blocked. Let's see these in
action:

If you have been thinking
about this a bit, you may wonder what happens if the connection that creates a
READ lock attempts to INSERT a record. Since this is forbidden on a read lock
even to the originating connection, and if the connection had to wait, there
would be deadlock since it would then be unable to release the lock, MySQL
returns an immediate error.

Now there are two locks
waiting, a read lock, and a write lock requested after the read lock. When we
release the first lock, the lock from the third connection, since it is a
higher precedence write lock, is obtained.

Connection
1:

mysql> UNLOCK TABLE;
Query OK, 0 rows affected (0.00 sec)

Connection 2 is still
waiting, but connection 3 is ready for action again:

Only now is the second
connection's lock obtained. It does not take much imagination to understand why
table locking can lead to performance implications if there are many write
locks.

Sometimes you genuinely
want a write lock to have a lower priority than a read lock. An example we use
at Independent Online is the article
tracker. Every article read is tracked, but the INSERT statement is a lower
priority than the read, which of course impacts a reader. Using the same MyISAM
table and the same set of locks as before except that the third connection is a
low priority lock, let's examine what happens.

Savepoints

Finally,
for this month, we will go back to InnoDB tables, and examine a recent addition
to MySQL - savepoints. These allow you to rollback part of a transaction,
rather than the all or nothing approach usually found with transactions. Savepoints
only work with InnoDB tables - for those who have not been following the
series, you can recreate the table as it is with the following statements
(though the records are not really necessary):

The first insert has been
performed - effectively a savepoint could also be termed COMMIT UNTIL, so
anything before the savepoint is now committed. The second insert, after the savepoint,
is rolled back.

That concludes the series
on transactions. I hope that you have gotten a taste for how MySQL handles
them, and some of its quirks, but as always, there is no better way to learn
than diving in and making all the mistakes yourself. Good luck.