MySQL : Can I use one SELECT ... FOR UPDATE to "protect" multiple tables? ( LOCKING )

Zoltan

I'm reading the MySQL docs for hours but I still cannot answer to myself a couple of pretty simple questions... :(

Here is my (simplified) scenario: I have two tables in a database: tablea and tableb, both tables use the InnoDB storage engine. tablea (which is my main table) has a PRIMARY index (id) with autoincrement. Now here is what I want to achieve and please keep in mind that the following business logic can be and will be run concurrently:

I start a transaction: START TRANSACTION BEGIN then I check if an id exists in tablea if yes, I SELECT the row FOR UPDATE, let's call the id I am looking for myid : SELECT `id` FROM `tablea` WHERE `id`='myid' FOR UPDATE; if the above SELECT returns no rows, I simply ROLLBACK the transaction and exit from my function. In other words I'm done when myid is not present in tablea. On the other hand when myid exists then first I need to update some values in tablea: UPDATE `tablea` SET `somefield`='somevalue' WHERE `id`='myid'; then I need to check if myid also exists in tableb: SELECT * FROM `tableb` WHERE `id`='myid' FOR UPDATE; my first question is about the above SELECT statement: Is it okay to do another SELECT FOR UPDATE here (on tableb) ??? Or "FOR UPDATE" is not needed here when dealing with tableb, because I already started a transaction and also acquired a lock based on a row in tablea ??? Can someone please answer this?

The last SELECT statement above either returns a row from tableb (and locks that row for update) or it turns out that myid does not exist in tableb. When myid is present in tableb then I just need to update some values in that row, it's simple: UPDATE `tableb` SET `somefieldintableb`='somevaluefortableb' WHERE `id`='myid'; On the other hand when myid is not in tableb I need to insert it, and here comes my 2nd question: Should I lock tableb before I issue my INSERT INTO statement, like this: LOCK TABLES `tableb` WRITE; INSERT INTO `tableb` (`id`,`somefieldintableb`) VALUES ('myid','somevaluefortableb'); UNLOCK TABLES `tableb`; and then finally, I do: COMMIT

My goal is this: Since the above described function (with the MySQL transaction) will run in many instances in parallel, I want to prevent any of those instances updating the same row in either tablea or tableb at the same time. I also want to prevent double-insertion of myid into tableb, hence I thought about using LOCK TABLES when myid was not found in tableb.

So I have two questions: Should I do a SELECT ... FOR UPDATE within my already started transaction when I want to update tableb or locking tableb with SELECT ... FOR UPDATE is unnecessary, because holding the lock on tablea already "protects" tableb too from simultaneous UPDATEs in this case ??? Thanks to the way I started my transaction, I mean.

2nd question: When I need to INSERT a new row into tableb should I lock the whole table for that insertion? Or is that something that is totally unnecessary in this case? (Do I need LOCK TABLES tableb or not?)

I would appreciate if an expert can answer these two questions for me, because reading the various docs and examples online simply won't help me answering these questions. :(

Bill Karwin

I would do it this way:

BEGIN;

SELECT a.`id` AS a_id, b.`id` AS b_id 
FROM `tablea` AS a LEFT OUTER JOIN `tableb` AS b ON a.id=b.id
WHERE a`id`='myid' 
FOR UPDATE;

Now you have row locks on both tablea and tableb if rows exist. If the SELECT returns nothing, you know the id is not present in tablea. If the SELECT returns a row with a value for a_id, but a NULL for b_id, then you know it's present in tablea and not in tableb.

If the row is present in both tables, this locks rows in both tables simultaneously. If you do it in two steps, you might risk a race condition and deadlock.

Try the INSERT and use ON DUPLICATE KEY UPDATE:

INSERT INTO `tableb` (id, somefieldintableb) VALUES ('myid', 'somevaluefortableb') 
ON DUPLICATE KEY UPDATE `somefieldintableb`='somevaluefortableb';

If the row with your desired id value is not present, this will insert it. If the row is present, this will update the row. And you're sure to have access to an existing row, because your SELECT FOR UPDATE locked it earlier.

Don't use table locks if you can avoid it. That's a sure way to create a bottleneck in your application.


Re your comments:

Yes, you can use extra join conditions for the date column.

You don't have to update all the columns when you use ON DUPLICATE KEY UPDATE. You can leave most of them alone if the row exists, and just update one, or a few, or whatever.

Also you can reference the value you tried to insert.

INSERT INTO `tableb` (id, date, col1, col2, col3, col4, col5, col6) 
  VALUES ('myid', $a_date, ?, ?, ?, ?, ?, ?) 
ON DUPLICATE KEY UPDATE col4=VALUES(col4);

For more details, I recommend reading http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Can I use one route for multiple functions?

From Dev

Can I use += on multiple variables on one line?

From Dev

MySQL How can I select data from two tables so that rows from the second one overwrote those from the first one?

From Dev

Error in updating multiple MySQL tables in one update statement

From Dev

How to use Beautiful Soup to select only one of multiple tables

From Dev

Can I use one stored procedure to insert values into two tables

From Dev

MySQL select values from Multiple Tables dependent on latest value in one

From Dev

use update to update any one of the two tables

From Dev

Yii2 How can I use one active record class and reuse it for multiple tables having same schema

From Dev

Insert and update into multiple tables, MySQL

From Dev

Can I use select from derived tables with JPA?

From Dev

MySQL: How can I use InnoDB locking to increment a non-primary value while preventing duplication of that value?

From Dev

use one table data on multiple tables mysql

From Dev

Sqoop - can I bulk import multiple mysql tables to one HBase/Hive table

From Dev

how can i do update select in MySQL?

From Dev

Mysql : how i can get 3 columns from multiple tables?

From Dev

Can I use one select statement to get multiple rows from 2 tables with FK

From Dev

How can I select from different tables in one MySQL query?

From Dev

How can I update two unrelated mysql tables with a php script?

From Dev

Can I purchase only one certificate and use it to sign/protect many resources?

From Dev

Select from multiple tables Mysql?

From Dev

MySQL : Can I use one SELECT ... FOR UPDATE to "protect" multiple tables? ( LOCKING )

From Dev

How can I update two different tables in one query?

From Dev

locking tables in MySql

From Dev

How can I use a select in update?

From Dev

How can I get data for one field from multiple tables?

From Dev

How do I compare two MySQL tables and then update one of them

From Dev

Mysql join multiple tables with one select phrase

From Dev

PHP can't select anything from only one of the mysql tables

Related Related

  1. 1

    Can I use one route for multiple functions?

  2. 2

    Can I use += on multiple variables on one line?

  3. 3

    MySQL How can I select data from two tables so that rows from the second one overwrote those from the first one?

  4. 4

    Error in updating multiple MySQL tables in one update statement

  5. 5

    How to use Beautiful Soup to select only one of multiple tables

  6. 6

    Can I use one stored procedure to insert values into two tables

  7. 7

    MySQL select values from Multiple Tables dependent on latest value in one

  8. 8

    use update to update any one of the two tables

  9. 9

    Yii2 How can I use one active record class and reuse it for multiple tables having same schema

  10. 10

    Insert and update into multiple tables, MySQL

  11. 11

    Can I use select from derived tables with JPA?

  12. 12

    MySQL: How can I use InnoDB locking to increment a non-primary value while preventing duplication of that value?

  13. 13

    use one table data on multiple tables mysql

  14. 14

    Sqoop - can I bulk import multiple mysql tables to one HBase/Hive table

  15. 15

    how can i do update select in MySQL?

  16. 16

    Mysql : how i can get 3 columns from multiple tables?

  17. 17

    Can I use one select statement to get multiple rows from 2 tables with FK

  18. 18

    How can I select from different tables in one MySQL query?

  19. 19

    How can I update two unrelated mysql tables with a php script?

  20. 20

    Can I purchase only one certificate and use it to sign/protect many resources?

  21. 21

    Select from multiple tables Mysql?

  22. 22

    MySQL : Can I use one SELECT ... FOR UPDATE to "protect" multiple tables? ( LOCKING )

  23. 23

    How can I update two different tables in one query?

  24. 24

    locking tables in MySql

  25. 25

    How can I use a select in update?

  26. 26

    How can I get data for one field from multiple tables?

  27. 27

    How do I compare two MySQL tables and then update one of them

  28. 28

    Mysql join multiple tables with one select phrase

  29. 29

    PHP can't select anything from only one of the mysql tables

HotTag

Archive