简体   繁体   中英

MySQL transactions and concurrent inserts

I've got this script made by someone and I looked over it and found something I'm not sure is safe:

Inside a transaction there are 2 consecutive inserts, in 2 different tables, both with auto incremented primary keys. They are supposed to be the same (the primary key generated from the first insert = the primary key generated from the second insert).

Don't ask me why, it's just how the script was made.

I'm new to transactions and I can't quite figure out if there is a concurrency issue here. I am thinking about the possibility of another thread running in the same time and ending up with keys being generated something like:

Thread #1:    Table_A ID: 3                                        Table_B ID: 4
Thread #2:                      Table_A ID: 4     Table_B ID: 3

I'm pretty sure (I've only ready transaction-related documentation today for the first time) that a transaction would not protect against this, but I just want to be sure I got it right.

Thanks!

You need to put both connections in serializable transaction isolation level in order to avoid the scenario you are describing, either by setting the tx_isolation on each connection with:

SET @@tx_isolation = SERIALIZABLE;

or

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

or by setting the global isolation level with:

SET @@global.tx_isolation = SERIALIZABLE;

or

SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;

which is inherited by any subsequently opened connection. At that level, transactions will block on any queries if another transaction is already in progress, ie. a transaction has already emitted a query (read or write) on the same tables.

See the mysql documentation for further details.

Your scenario is definitely possible.

If the primary keys are supposed to be the same in both tables, you may override the AUTO_INCREMENT in the second table and explicitly insert the value:

INSERT
INTO    a (id)
VALUES  (NULL) -- this inserts an auto incremented value

INSERT
INTO    b (id)
SELECT  LAST_INSERT_ID() -- this inserts the last value inserted into a in this session

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM