
Race condition when inserting data / MySQL 4.0+, MyISAM tables
Hello
I use a table to cache some informations which need lots of resources to
be composed. The first time the info is needed, it will be composed and
written to the cache table ($db in the example is a PEAR DB object; the
question is the same for other ways of accessing the database):
// Retrieve info if present
$details = $db->getOne("SELECT contents FROM cache WHERE id=".$id." AND
info='details'");
// If not present, compose info and write it to the database
if (!is_string($details) || trim($details) == '') {
$details = $this->compose_details();
$data = array('id' => $id, 'info' => 'details', 'contents' => $details);
$db->query("INSERT INTO cache (id, info, contents) VALUES (".$id.",
'details', '".$details."')");
}
Now I encountered that if several users call a page at the same time
after the cache was flushed, it is possible that between the first line
and the INSERT query the info was entered by another user. This results
in a duplicate key error.
Now I wonder which is the best way to handle this. I see various approaches:
- Use ON DUPLICATE KEY UPDATE (which might fail if MySQL 4.0 is used)
- Try to write some kind of locking mechanism
- Suppress the error message for this special case
- Remove the primary key from the cache table (as it is flushed whenever
items are administrated, duplicate entries might not be a big problem)
Which is the recommended way to handle this? I guess, as MySQL 4.0 and
MyISAM tables are a quite common configuration, there must be some
common practice about this, but I did not find anything by googling...
Thanks for comments!
Markus
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
..oO(Markus)
>[handling a race condition]
>
>Which is the recommended way to handle this? I guess, as MySQL 4.0 and
>MyISAM tables are a quite common configuration, there must be some
>common practice about this, but I did not find anything by googling...
Is it really necessary to keep the script compatible to outdated
versions of MySQL? The current stable is 5, the old 4.0 is not even
available for download anymore. If it still has to work on a series 4
server, then I would make at least 4.1 a requirement.
I would even drop support for MyISAM and use InnoDB instead, but that's
just a personal decision. I simply need the features of a modern engine,
so I can't take care of older installations. The same goes for PHP for
example -- my scripts require PHP 5.2, PHP 4 is dead (it's official
now). At some point you simply have to draw the line.
Micha
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
Michael Fesser schrieb:
> .oO(Markus)
>
>> [handling a race condition]
>>
>> Which is the recommended way to handle this? I guess, as MySQL 4.0 and
>> MyISAM tables are a quite common configuration, there must be some
>> common practice about this, but I did not find anything by googling...
>
> Is it really necessary to keep the script compatible to outdated
> versions of MySQL? The current stable is 5, the old 4.0 is not even
> available for download anymore. If it still has to work on a series 4
> server, then I would make at least 4.1 a requirement.
>
> I would even drop support for MyISAM and use InnoDB instead, but that's
> just a personal decision. I simply need the features of a modern engine,
> so I can't take care of older installations. The same goes for PHP for
> example -- my scripts require PHP 5.2, PHP 4 is dead (it's official
> now). At some point you simply have to draw the line.
Thank you, I see the point; anyway the application is supposed to work
with shared hosting, where MySQL 4.0 is still around. Though, dropping
4.0 support is actually an issue - also because it is not natively
supporting UTF-8. And I use MyISAM simply because it is the only engine
that provides fulltext search.
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
..oO(Markus)
>And I use MyISAM simply because it is the only engine
>that provides fulltext search.
OK, that's one point for MyISAM. But my own focus is on data integrity
(most important: foreign keys and transactions), so that's not an issue
here.
Micha
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
..oO(Markus)
>[handling a race condition]
>
>Which is the recommended way to handle this? I guess, as MySQL 4.0 and
>MyISAM tables are a quite common configuration, there must be some
>common practice about this, but I did not find anything by googling...
Is it really necessary to keep the script compatible to outdated
versions of MySQL? The current stable is 5, the old 4.0 is not even
available for download anymore. If it still has to work on a series 4
server, then I would make at least 4.1 a requirement.
I would even drop support for MyISAM and use InnoDB instead, but that's
just a personal decision. I simply need the features of a modern engine,
so I can't take care of older installations. The same goes for PHP for
example -- my scripts require PHP 5.2, PHP 4 is dead (it's official
now). At some point you simply have to draw the line.
Micha
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
Michael Fesser schrieb:
> .oO(Markus)
>
>> [handling a race condition]
>>
>> Which is the recommended way to handle this? I guess, as MySQL 4.0 and
>> MyISAM tables are a quite common configuration, there must be some
>> common practice about this, but I did not find anything by googling...
>
> Is it really necessary to keep the script compatible to outdated
> versions of MySQL? The current stable is 5, the old 4.0 is not even
> available for download anymore. If it still has to work on a series 4
> server, then I would make at least 4.1 a requirement.
>
> I would even drop support for MyISAM and use InnoDB instead, but that's
> just a personal decision. I simply need the features of a modern engine,
> so I can't take care of older installations. The same goes for PHP for
> example -- my scripts require PHP 5.2, PHP 4 is dead (it's official
> now). At some point you simply have to draw the line.
Thank you, I see the point; anyway the application is supposed to work
with shared hosting, where MySQL 4.0 is still around. Though, dropping
4.0 support is actually an issue - also because it is not natively
supporting UTF-8. And I use MyISAM simply because it is the only engine
that provides fulltext search.
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
..oO(Markus)
>And I use MyISAM simply because it is the only engine
>that provides fulltext search.
OK, that's one point for MyISAM. But my own focus is on data integrity
(most important: foreign keys and transactions), so that's not an issue
here.
Micha
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
..oO(Markus)
>[handling a race condition]
>
>Which is the recommended way to handle this? I guess, as MySQL 4.0 and
>MyISAM tables are a quite common configuration, there must be some
>common practice about this, but I did not find anything by googling...
Is it really necessary to keep the script compatible to outdated
versions of MySQL? The current stable is 5, the old 4.0 is not even
available for download anymore. If it still has to work on a series 4
server, then I would make at least 4.1 a requirement.
I would even drop support for MyISAM and use InnoDB instead, but that's
just a personal decision. I simply need the features of a modern engine,
so I can't take care of older installations. The same goes for PHP for
example -- my scripts require PHP 5.2, PHP 4 is dead (it's official
now). At some point you simply have to draw the line.
Micha
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
Michael Fesser schrieb:
> .oO(Markus)
>
>> [handling a race condition]
>>
>> Which is the recommended way to handle this? I guess, as MySQL 4.0 and
>> MyISAM tables are a quite common configuration, there must be some
>> common practice about this, but I did not find anything by googling...
>
> Is it really necessary to keep the script compatible to outdated
> versions of MySQL? The current stable is 5, the old 4.0 is not even
> available for download anymore. If it still has to work on a series 4
> server, then I would make at least 4.1 a requirement.
>
> I would even drop support for MyISAM and use InnoDB instead, but that's
> just a personal decision. I simply need the features of a modern engine,
> so I can't take care of older installations. The same goes for PHP for
> example -- my scripts require PHP 5.2, PHP 4 is dead (it's official
> now). At some point you simply have to draw the line.
Thank you, I see the point; anyway the application is supposed to work
with shared hosting, where MySQL 4.0 is still around. Though, dropping
4.0 support is actually an issue - also because it is not natively
supporting UTF-8. And I use MyISAM simply because it is the only engine
that provides fulltext search.
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
..oO(Markus)
>And I use MyISAM simply because it is the only engine
>that provides fulltext search.
OK, that's one point for MyISAM. But my own focus is on data integrity
(most important: foreign keys and transactions), so that's not an issue
here.
Micha
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
With MyISAM, you can do one of the methods you described or use LOCK
TABLES.
In your case I would do ON DUPLICATE KEY UPDATE or remove the unique
constraint on the id.
Finally, if you need to prevent more than one thread from executing
the generate function, you can use a semaphore with the key being your
id.
On Jul 13, 10:28 am, Markus <derernst [at] NO#SP#AMgmx.ch> wrote:
> Hello
>
> I use a table to cache some informations which need lots of resources to
> be composed. The first time the info is needed, it will be composed and
> written to the cache table ($db in the example is a PEAR DB object; the
> question is the same for other ways of accessing the database):
>
> // Retrieve info if present
> $details = $db->getOne("SELECT contents FROM cache WHERE id=".$id." AND
> info='details'");
> // If not present, compose info and write it to the database
> if (!is_string($details) || trim($details) == '') {
> $details = $this->compose_details();
> $data = array('id' => $id, 'info' => 'details', 'contents' => $details);
> $db->query("INSERT INTO cache (id, info, contents) VALUES (".$id.",
> 'details', '".$details."')");
>
> }
>
> Now I encountered that if several users call a page at the same time
> after the cache was flushed, it is possible that between the first line
> and the INSERT query the info was entered by another user. This results
> in a duplicate key error.
>
> Now I wonder which is the best way to handle this. I see various approaches:
> - Use ON DUPLICATE KEY UPDATE (which might fail if MySQL 4.0 is used)
> - Try to write some kind of locking mechanism
> - Suppress the error message for this special case
> - Remove the primary key from the cache table (as it is flushed whenever
> items are administrated, duplicate entries might not be a big problem)
>
> Which is the recommended way to handle this? I guess, as MySQL 4.0 and
> MyISAM tables are a quite common configuration, there must be some
> common practice about this, but I did not find anything by googling...
>
> Thanks for comments!
> Markus
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
With MyISAM, you can do one of the methods you described or use LOCK
TABLES.
In your case I would do ON DUPLICATE KEY UPDATE or remove the unique
constraint on the id.
Finally, if you need to prevent more than one thread from executing
the generate function, you can use a semaphore with the key being your
id.
On Jul 13, 10:28 am, Markus <derernst [at] NO#SP#AMgmx.ch> wrote:
> Hello
>
> I use a table to cache some informations which need lots of resources to
> be composed. The first time the info is needed, it will be composed and
> written to the cache table ($db in the example is a PEAR DB object; the
> question is the same for other ways of accessing the database):
>
> // Retrieve info if present
> $details = $db->getOne("SELECT contents FROM cache WHERE id=".$id." AND
> info='details'");
> // If not present, compose info and write it to the database
> if (!is_string($details) || trim($details) == '') {
> $details = $this->compose_details();
> $data = array('id' => $id, 'info' => 'details', 'contents' => $details);
> $db->query("INSERT INTO cache (id, info, contents) VALUES (".$id.",
> 'details', '".$details."')");
>
> }
>
> Now I encountered that if several users call a page at the same time
> after the cache was flushed, it is possible that between the first line
> and the INSERT query the info was entered by another user. This results
> in a duplicate key error.
>
> Now I wonder which is the best way to handle this. I see various approaches:
> - Use ON DUPLICATE KEY UPDATE (which might fail if MySQL 4.0 is used)
> - Try to write some kind of locking mechanism
> - Suppress the error message for this special case
> - Remove the primary key from the cache table (as it is flushed whenever
> items are administrated, duplicate entries might not be a big problem)
>
> Which is the recommended way to handle this? I guess, as MySQL 4.0 and
> MyISAM tables are a quite common configuration, there must be some
> common practice about this, but I did not find anything by googling...
>
> Thanks for comments!
> Markus
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
With MyISAM, you can do one of the methods you described or use LOCK
TABLES.
In your case I would do ON DUPLICATE KEY UPDATE or remove the unique
constraint on the id.
Finally, if you need to prevent more than one thread from executing
the generate function, you can use a semaphore with the key being your
id.
On Jul 13, 10:28 am, Markus <derernst [at] NO#SP#AMgmx.ch> wrote:
> Hello
>
> I use a table to cache some informations which need lots of resources to
> be composed. The first time the info is needed, it will be composed and
> written to the cache table ($db in the example is a PEAR DB object; the
> question is the same for other ways of accessing the database):
>
> // Retrieve info if present
> $details = $db->getOne("SELECT contents FROM cache WHERE id=".$id." AND
> info='details'");
> // If not present, compose info and write it to the database
> if (!is_string($details) || trim($details) == '') {
> $details = $this->compose_details();
> $data = array('id' => $id, 'info' => 'details', 'contents' => $details);
> $db->query("INSERT INTO cache (id, info, contents) VALUES (".$id.",
> 'details', '".$details."')");
>
> }
>
> Now I encountered that if several users call a page at the same time
> after the cache was flushed, it is possible that between the first line
> and the INSERT query the info was entered by another user. This results
> in a duplicate key error.
>
> Now I wonder which is the best way to handle this. I see various approaches:
> - Use ON DUPLICATE KEY UPDATE (which might fail if MySQL 4.0 is used)
> - Try to write some kind of locking mechanism
> - Suppress the error message for this special case
> - Remove the primary key from the cache table (as it is flushed whenever
> items are administrated, duplicate entries might not be a big problem)
>
> Which is the recommended way to handle this? I guess, as MySQL 4.0 and
> MyISAM tables are a quite common configuration, there must be some
> common practice about this, but I did not find anything by googling...
>
> Thanks for comments!
> Markus
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
petersprc schrieb:
> With MyISAM, you can do one of the methods you described or use LOCK
> TABLES.
>
> In your case I would do ON DUPLICATE KEY UPDATE or remove the unique
> constraint on the id.
>
> Finally, if you need to prevent more than one thread from executing
> the generate function, you can use a semaphore with the key being your
> id.
Thank you, I will remove the primary key then. As I never heard of
semaphores before, I read about them in Wikipedia; it is an interesting
concept. Before I realized I could remove the unique constraint (and not
aware of LOCK TABLES being available for MyISAM), I had even thought of
some kind of locking mechanism, adding a "locked" field to the items
table, that a thread could set to 1 in order to lock the item, and back
to 0 in order to unlock it. This would be kind of a binary semaphore
emulation for a non-OO environment such as PHP 4.
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
petersprc schrieb:
> With MyISAM, you can do one of the methods you described or use LOCK
> TABLES.
>
> In your case I would do ON DUPLICATE KEY UPDATE or remove the unique
> constraint on the id.
>
> Finally, if you need to prevent more than one thread from executing
> the generate function, you can use a semaphore with the key being your
> id.
Thank you, I will remove the primary key then. As I never heard of
semaphores before, I read about them in Wikipedia; it is an interesting
concept. Before I realized I could remove the unique constraint (and not
aware of LOCK TABLES being available for MyISAM), I had even thought of
some kind of locking mechanism, adding a "locked" field to the items
table, that a thread could set to 1 in order to lock the item, and back
to 0 in order to unlock it. This would be kind of a binary semaphore
emulation for a non-OO environment such as PHP 4.
Re: Race condition when inserting data / MySQL 4.0+, MyISAM tables
petersprc schrieb:
> With MyISAM, you can do one of the methods you described or use LOCK
> TABLES.
>
> In your case I would do ON DUPLICATE KEY UPDATE or remove the unique
> constraint on the id.
>
> Finally, if you need to prevent more than one thread from executing
> the generate function, you can use a semaphore with the key being your
> id.
Thank you, I will remove the primary key then. As I never heard of
semaphores before, I read about them in Wikipedia; it is an interesting
concept. Before I realized I could remove the unique constraint (and not
aware of LOCK TABLES being available for MyISAM), I had even thought of
some kind of locking mechanism, adding a "locked" field to the items
table, that a thread could set to 1 in order to lock the item, and back
to 0 in order to unlock it. This would be kind of a binary semaphore
emulation for a non-OO environment such as PHP 4.
PHP » alt.php » Race condition when inserting data / MySQL 4.0+, MyISAM tables