Given two tables:
Company
[id, name, balance
]Employee
[id, name, company_id
]
I'd like to delete a company and its dependencies but I cannot do so atomically because in my real project a company has multiple levels of dependencies which would be too complex to squeeze into a single SQL statement. Besides, looking at https://stackoverflow.com/a/5598275/14731 I'm not sure a single SQL statement would be atomic.
Instead I do this:
SELECT ... FOR UPDATE
all employees associated with the company (lock them to prevent modification in mid-transaction)- Delete each employee one by one
- Delete the parent Company.
There is one catch: how do I prevent new records that reference the Company from being inserted between step 1 and 2? According to https://stackoverflow.com/a/3602125/14731 SELECT ... FOR UPDATE
does not block inserts. Ideally I want to place a lock on the Company, not one lock per every kind of dependency that could point to it.
UPDATE: I've got an idea but I'm not sure whether it makes sense.
If someone wants to insert a new record that points to the Company, they'd likely need to look it up to make sure it exists. If I SELECT ... FOR UPDATE
on the company before step 1, it should block their reads thereby delaying the subsequent insert. I've got two questions:
- Does
SELECT ... FOR UPDATE
block normalSELECT
queries? If not, I'd have to ensure that inserting threads always useSELECT ... FOR UPDATE
when looking up the Company. - Would this approach work?