cosie
asked on
Mysql locking question
Hi Guys,
I'm using mysql 5.0.42 with InnoDB tables and I'm looking for the best locking methods....
I have a simple table like this:
CREATE TABLE `tblaccess` (
`accessid` int(11) NOT NULL auto_increment,
`stateid` int(11) default 0,
PRIMARY KEY (`accessid`),
KEY `tblaccess_stateid_idx` (`stateid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I have about 1.000.000 rows in the table.
There are about 30 clients which connects to the databease and issue the same query and select a simple row from the table, works with tha data, and after some minutes, it request another row to work with...
Initially the stateid of all rows are 0 = unprocessed, the processed rows should have a stateid=1 means processed.
the query could look like this:
CREATE DEFINER = 'root'@'localhost' PROCEDURE `sp_getaccessid`()
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
begin
declare _accessid int default 0;
start transaction;
select _accessid into _accessid from tblaccess where stateid=0 order by accessid limit 1 for update;
if _accessid >0 then # we ha a macthing row
update tblaccess set stateid=1 where acceesid=_accessid;
end if;
commit;
select _accessid;
end;
This metchod works but seems to lock the whole table instead of only one row....
And sometimes I got an erro in my client:
Deadlock found when trying to get lock; try restarting transaction
How to perform the same action with better performance and without deadlock???
I would like to select a row from a large table in the client and update is't state to processed...
I have 30 simulteanous clients and one row could be processed by only one client...
In other words every row could be processed by only one client...
How do I have to perform the locking???
I'm using mysql 5.0.42 with InnoDB tables and I'm looking for the best locking methods....
I have a simple table like this:
CREATE TABLE `tblaccess` (
`accessid` int(11) NOT NULL auto_increment,
`stateid` int(11) default 0,
PRIMARY KEY (`accessid`),
KEY `tblaccess_stateid_idx` (`stateid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I have about 1.000.000 rows in the table.
There are about 30 clients which connects to the databease and issue the same query and select a simple row from the table, works with tha data, and after some minutes, it request another row to work with...
Initially the stateid of all rows are 0 = unprocessed, the processed rows should have a stateid=1 means processed.
the query could look like this:
CREATE DEFINER = 'root'@'localhost' PROCEDURE `sp_getaccessid`()
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
begin
declare _accessid int default 0;
start transaction;
select _accessid into _accessid from tblaccess where stateid=0 order by accessid limit 1 for update;
if _accessid >0 then # we ha a macthing row
update tblaccess set stateid=1 where acceesid=_accessid;
end if;
commit;
select _accessid;
end;
This metchod works but seems to lock the whole table instead of only one row....
And sometimes I got an erro in my client:
Deadlock found when trying to get lock; try restarting transaction
How to perform the same action with better performance and without deadlock???
I would like to select a row from a large table in the client and update is't state to processed...
I have 30 simulteanous clients and one row could be processed by only one client...
In other words every row could be processed by only one client...
How do I have to perform the locking???
CREATE DEFINER = 'root'@'localhost' PROCEDURE `sp_getaccessid`()
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
begin
declare _accessid int default 0;
start transaction;
select _accessid into _accessid from tblaccess where stateid=0 order by accessid limit 1 for update;
if _accessid >0 then # we ha a macthing row
update tblaccess set stateid=1 where acceesid=_accessid;
end if;
commit;
select _accessid;
end;
You should try using 'advisory locks' with MySQL. The lock names could be the row identifier, and from within the application check for a lock before you try and modify a row. This also would not actually lock your tables.
ASKER
Check for a lock within the application????
I use VB6 and ODBC on client side...
Please explain what are you talking about a bit more in details...
I use VB6 and ODBC on client side...
Please explain what are you talking about a bit more in details...
Step 1: Read this web page. http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html
Step 2: write some utility functions that call get_lock(name_here, timeout), is_lock_used, and release_lock(name_here).
Calling these functions is no different than calling a query. They return a result just like a query. They are a query.
In your code, before you need to do a transaction, check for a lock, acquire it if necessary, to your processing, and then release it. If the lock is already being used, wait until its available.
locking could be one way to do it, but I would almost take a different approach to solving the problem. Develop a FIFO Queue for items that need to be updated. Have multiple threads in the application. All threads will share the FIFO Queue. One thread will write to the front of the queue, adding to the list of transactions, and one thread will pop off the end of the queue the transaction to be done. You wont have collisions then.
If you aren't experienced in writing threaded applications, then use locking.
I can't say which one will be faster unless its tested.
Step 2: write some utility functions that call get_lock(name_here, timeout), is_lock_used, and release_lock(name_here).
Calling these functions is no different than calling a query. They return a result just like a query. They are a query.
In your code, before you need to do a transaction, check for a lock, acquire it if necessary, to your processing, and then release it. If the lock is already being used, wait until its available.
locking could be one way to do it, but I would almost take a different approach to solving the problem. Develop a FIFO Queue for items that need to be updated. Have multiple threads in the application. All threads will share the FIFO Queue. One thread will write to the front of the queue, adding to the list of transactions, and one thread will pop off the end of the queue the transaction to be done. You wont have collisions then.
If you aren't experienced in writing threaded applications, then use locking.
I can't say which one will be faster unless its tested.
ASKER
hi blckholehorizon,
Maybe you didn't understand my problem...
The FIFO quee is a bad idea, since using it only one transaction can run at the same time...
This would meen while one client is waiting for selecting a row from the large table all other clients have to wait for it... Anyway implementing this behaviour is easy usind a dummy update on a specific record at the start of the transaction... I've tested it, but the problem is that the query response time on the 2.5 million records table is about 500msec...
When 10-15 clients try to lock a new row at the same time this result 5-6 seconds wait times in the client which is too much...
I need a row lewel locking mechanism, which allows simultaneous querries (from different clients = sessions) perform locking different (and unique) rows in the SAME time...
I know how to use functions, of course...
The problem is how to put on locks paralell to the same table?
Maybe you didn't understand my problem...
The FIFO quee is a bad idea, since using it only one transaction can run at the same time...
This would meen while one client is waiting for selecting a row from the large table all other clients have to wait for it... Anyway implementing this behaviour is easy usind a dummy update on a specific record at the start of the transaction... I've tested it, but the problem is that the query response time on the 2.5 million records table is about 500msec...
When 10-15 clients try to lock a new row at the same time this result 5-6 seconds wait times in the client which is too much...
I need a row lewel locking mechanism, which allows simultaneous querries (from different clients = sessions) perform locking different (and unique) rows in the SAME time...
I know how to use functions, of course...
The problem is how to put on locks paralell to the same table?
Read more about advisory locks and you can effectively have row level locking at the application level.
InnoDB supports row level locking, http://dev.mysql.com/doc/refman/5.0/en/internal-locking.html
but the performance overhead of such row level locks may not make your application any faster.
InnoDB supports row level locking, http://dev.mysql.com/doc/refman/5.0/en/internal-locking.html
but the performance overhead of such row level locks may not make your application any faster.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.