Domanda

I have 3 tables:

Counters: ID, ItemCatalogID, CurrentCounter

Item: ID, ItemCatalogID, Name, Description, OtherValue

ItemCatalog: ID, Name, Description

Counters table contains CurrentCounter of an item catalog, when I insert a row, I have to query DB, get the current counter of corresponding catalog, then update this value by one and use this value for OtherValue field.

For example:

update Counters set CurrentCounter = CurrentCounter + 1 where ItemCatalogID = 100;
select CurrentCounter into v from Counters where ItemCatalogID = 100;
insert into Item(ItemCatalogID, Name, Description, OtherValue) values (100, 'MyItem', 'Short Description', v);

But I wonder race condition can occur? How to improve my solution?

È stato utile?

Soluzione

Yes, your situation may likely provoque a race condition.

Do you need these counters at all? You can easily replace them with appropriate queries:

SELECT COUNT(*) FROM ItemCatalog WHERE ID=100;
SELECT COUNT(*) FROM Item WHERE ID=100;

For successive field contents it is advisable to use AUTO_INCREMENT columns. But it seems that doesn't apply in your case.

But nevertheless, you can use the COUNT(*) approach from above:

insert into Item(ItemCatalogID, Name, Description, OtherValue) values (100, 'MyItem', 'Short Description', (select count(*) from Item where ID=100));

It might be that you'll have to alias one of the occurrences of your table:

insert into Item(ItemCatalogID, Name, Description, OtherValue) values (100, 'MyItem', 'Short Description', (select count(*) from Item AS I where ID=100))

This executes in one step and you won't have to worry about a race condition.

If you cannot change this due to whatever reasons, there is another solution: use table locking.

Prefix your statements with

LOCK TABLES Counters WRITE, Item WRITE

and suffix them with

UNLOCK TABLES

in order to have exclusive write access to them.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top