Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid dead lock by ordering explicitly

I want explicitly provide an order on how MySql InnoDB should acquire locks for rows. If this is possible there shouldn't be any dead locks just stalling. (If we follow the convention.)

First, the databse should lock all rows found in table "models" in ascending order. Then all rows in the second table "colors" should get locked in ascending order. Is there a way to control the database to lock table "models" first and then "colors"?

Given for example:

start transaction;
select *
from models m
join colors c on c.model_id = m.id
where c.id IN (101, 105, 106)
order by m.id asc, c.id asc
for update;
like image 858
mazatwork Avatar asked May 31 '12 17:05

mazatwork


People also ask

How do you avoid deadlock in Java?

This kind of deadlock is avoided by establishing an order in which locks are acquired (a lock hierarchy). When all threads always acquire locks in the specified order, this deadlock is avoided. Adhering to a strict order of lock acquisition is not always optimal.

What is an example of a deadlock?

An example of another kind of deadlock is when two threads, thread 1 and thread 2, each acquires a mutex lock, A and B, respectively.

How to avoid deadlock condition in Python?

Although it is not possible to avoid deadlock condition but we can avoid it by using the following ways: Avoid Unnecessary Locks: We should use locks only for those members on which it is required. Unnecessary use of locks leads to a deadlock situation. We recommend you to use a lock-free data structure. If possible, keep your code free form locks.

What is the difference between deadlock prevention and deadlock avoidance?

Note: Deadlock prevention is more strict than Deadlock Avoidance. Writing code in comment? Please use ide.geeksforgeeks.org , generate link and share the link here.


1 Answers

Although you can do it through straight_join, you can also explicitly get the locks on the rows you want by duplicating the select ...for update on the one you want to get first.

CREATE TEMPORARY TABLE colorsToUpdate (
     colorID BIGINT(20) NOT NULL, 
     modelID BIGINT(20) NOT NULL
);

insert into colorsToUpdate ( colorID, modelID)
SELECT  id, model_id
FROM    colors
where id in (101, 105, 106);

#This will try to acquire lock on models
select m.* from models m
join colorsToUpdate c
on c.modelID = m.id
for UPDATE;

#this will try to get locks on models, and colors.
select m.*, c.*
from colorsToUpdate u
left join models m
on u.modelID = m.id
join colors c 
on u.colorID = c.ID
order by m.id asc, c.id asc
for update;

# do your data modification here.

drop table colorsToUpdate;

As the locking is done in multiple steps it would be possible for entries in the table 'colors' to be modified between when you set up the temporary table and when you finish getting the locks on the two tables.

That may be ok for you (i.e. if you only want to modify existing entries, when the transaction start) but could cause subtle bugs if it's not what you want.

like image 171
Danack Avatar answered Oct 15 '22 01:10

Danack