Answer the question
In order to leave comments, you need to log in
What sequence of row locks occurs in the case of SELECT ... INNER JOIN ... FOR UPDATE and how to avoid deadlock?
Percona MySQL 5.7.21-20
-- Memory temporary table TQueue
CREATE TEMPORARY TABLE IF NOT EXISTS TQueue (
ID bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
QUEUE_STATUS enum ('ADDED', 'PROCESSED', 'SUCCESS', 'ERROR') NOT NULL DEFAULT 'ADDED',
QUEUE_TIMEOUT datetime NOT NULL,
ACTION enum ('INSERT', 'DELETE', 'UPDATE') NOT NULL,
REPORT_ID tinyint(4) UNSIGNED NOT NULL,
LOGIN int(11) NOT NULL,
`GROUP` char(16) NOT NULL,
ENABLE int(11) NOT NULL,
ENABLE_CHANGE_PASS int(11) NOT NULL,
ENABLE_READONLY int(11) NOT NULL,
ENABLE_OTP int(11) NOT NULL,
PASSWORD_PHONE char(32) NOT NULL,
NAME char(128) NOT NULL,
COUNTRY char(32) NOT NULL,
CITY char(32) NOT NULL,
STATE char(32) NOT NULL,
ZIPCODE char(16) NOT NULL,
ADDRESS char(128) NOT NULL,
LEAD_SOURCE char(32) NOT NULL,
PHONE char(32) NOT NULL,
EMAIL char(48) NOT NULL,
COMMENT char(64) NOT NULL,
ID_DOCUMENT char(32) NOT NULL,
STATUS char(16) NOT NULL,
REGDATE datetime NOT NULL,
LASTDATE datetime NOT NULL,
LEVERAGE int(11) NOT NULL,
AGENT_ACCOUNT int(11) NOT NULL,
TIMESTAMP int(11) NOT NULL,
BALANCE double NOT NULL,
PREVMONTHBALANCE double NOT NULL,
PREVBALANCE double NOT NULL,
CREDIT double NOT NULL,
INTERESTRATE double NOT NULL,
TAXES double NOT NULL,
SEND_REPORTS int(11) NOT NULL,
MQID int(10) UNSIGNED NOT NULL,
USER_COLOR int(11) NOT NULL,
EQUITY double NOT NULL,
MARGIN double NOT NULL,
MARGIN_LEVEL double NOT NULL,
MARGIN_FREE double NOT NULL,
CURRENCY char(16) NOT NULL,
API_DATA blob DEFAULT NULL,
MODIFY_TIME datetime NOT NULL,
PRIMARY KEY (ID),
INDEX IDX_JOIN USING BTREE (LOGIN, REPORT_ID)
)
ENGINE = MEMORY;
CREATE TABLE `MT4_USERS` (
ID bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
REPORT_ID tinyint(4) UNSIGNED NOT NULL,
LOGIN int(11) NOT NULL,
`GROUP` char(16) NOT NULL,
ENABLE int(11) NOT NULL,
ENABLE_CHANGE_PASS int(11) NOT NULL,
ENABLE_READONLY int(11) NOT NULL,
ENABLE_OTP int(11) NOT NULL,
PASSWORD_PHONE char(32) NOT NULL,
NAME char(128) NOT NULL,
COUNTRY char(32) NOT NULL,
CITY char(32) NOT NULL,
STATE char(32) NOT NULL,
ZIPCODE char(16) NOT NULL,
ADDRESS char(128) NOT NULL,
LEAD_SOURCE char(32) NOT NULL,
PHONE char(32) NOT NULL,
EMAIL char(48) NOT NULL,
COMMENT char(64) NOT NULL,
ID_DOCUMENT char(32) NOT NULL,
STATUS char(16) NOT NULL,
REGDATE datetime NOT NULL,
LASTDATE datetime NOT NULL,
LEVERAGE int(11) NOT NULL,
AGENT_ACCOUNT int(11) NOT NULL,
TIMESTAMP int(11) NOT NULL,
BALANCE double NOT NULL,
PREVMONTHBALANCE double NOT NULL,
PREVBALANCE double NOT NULL,
CREDIT double NOT NULL,
INTERESTRATE double NOT NULL,
TAXES double NOT NULL,
SEND_REPORTS int(11) NOT NULL,
MQID int(10) UNSIGNED NOT NULL,
USER_COLOR int(11) NOT NULL,
EQUITY double NOT NULL,
MARGIN double NOT NULL,
MARGIN_LEVEL double NOT NULL,
MARGIN_FREE double NOT NULL,
CURRENCY char(16) NOT NULL,
API_DATA blob DEFAULT NULL,
MODIFY_TIME datetime NOT NULL,
PRIMARY KEY (ID),
UNIQUE KEY IDX_LOGIN_REPORT_ID (`LOGIN`,`REPORT_ID`)
)
ENGINE=InnoDB
ROW_FORMAT=COMPRESSED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
-- hold exclusive lock on MT4_USERS table
SELECT
u.*
FROM
TQueue q
INNER JOIN MT4_USERS u USING (LOGIN, REPORT_ID)
FOR UPDATE;
-- insert to MT4_USERS form TQueue ON DUPLICATE KEY UPDATE
INSERT MT4_USERS (REPORT_ID, LOGIN, `GROUP`, ENABLE …)
SELECT
REPORT_ID, LOGIN, `GROUP`, ENABLE, ENABLE_CHANGE_PASS …
FROM TQueue
ORDER BY ID ASC
ON DUPLICATE KEY UPDATE
`GROUP` = VALUES(`GROUP`),
ENABLE = VALUES(ENABLE),
ENABLE_CHANGE_PASS = VALUES(ENABLE_CHANGE_PASS),
…
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
-- hold exclusive lock on MT4_TRADES table
SELECT
t.*
FROM
TQueue q
INNER JOIN MT4_TRADES t USING (TICKET, REPORT_ID)
FOR UPDATE;
-- insert to MT4_TRADES form TQueue ON DUPLICATE KEY UPDATE
INSERT MT4_TRADES (REPORT_ID, TICKET, LOGIN, SYMBOL, …)
SELECT
q.REPORT_ID, q.TICKET, q.LOGIN, q.SYMBOL, …
FROM
TQueue q
LEFT JOIN MT4_USERS mu USING(REPORT_ID, LOGIN)
ORDER BY
q.ID ASC
ON DUPLICATE KEY UPDATE
LOGIN = VALUES(LOGIN)
,SYMBOL = VALUES(SYMBOL)
,DIGITS = VALUES(DIGITS)
,…
COMMIT;
------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-05-05 00:24:35 0x7fd53e5a6700
*** (1) TRANSACTION:
TRANSACTION 178168806, ACTIVE 1 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 17 lock struct(s), heap size 1136, 45 row lock(s)
MySQL thread id 17661615, OS thread handle 140555520485120, query id 4591798647 event_scheduler Sending data
SELECT u.* FROM TQueue q INNER JOIN MT4_USERS u USING (LOGIN, REPORT_ID) FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 876643 page no 46339 n bits 952 index IDX_LOGIN_REPORT_ID of table `Developer`.`MT4_USERS` trx id 178168806 lock_mode X locks rec but not gap waiting
*** (2) TRANSACTION:
TRANSACTION 178168783, ACTIVE 3 sec starting index read
mysql tables in use 6, locked 4
8870 lock struct(s), heap size 1138896, 22372 row lock(s), undo log entries 1876
MySQL thread id 17661574, OS thread handle 140553850873600, query id 4591797640 event_scheduler
INSERT MT4_TRADES
(
REPORT_ID, TICKET, LOGIN, SYMBOL, DIGITS, CMD, VOLUME, OPEN_TIME, OPEN_PRICE, SL, TP, CLOSE_TIME,
EXPIRATION, REASON, CONV_RATE1, CONV_RATE2, COMMISSION, COMMISSION_AGENT, SWAPS, CLOSE_PRICE,
PROFIT, TAXES, COMMENT, INTERNAL_ID, MARGIN_RATE, `TIMESTAMP`, MAGIC, GW_VOLUME, GW_OPEN_PRICE,
GW_CLOSE_PRICE, MODIFY_TIME, CURRENCY, DELIMER, RATE, TICKET_STATUS
)
SELECT
q.REPORT_ID, q.TICKET, q.LOGIN, q.SYMBOL, q.DIGITS, q.CMD, q.VOLUME, q.OPEN_TIME, q.OPEN_PRICE, q.SL, q.TP, q.CLOSE_TIME,
q.EXPIRATION, q.REASON, q.CONV_RATE1, q.CONV_RATE2, q.COMMISSION, q.COMMISSION_AGENT, q.SWAPS, q.CLOSE_PRICE,
q.PROFIT, q.TAXES, q.COMMENT, q.INTERNAL_ID, q.MARGIN_RATE, q.`TIMESTAMP`, q.MAGIC, q.GW_VOLUME, q.GW_OPEN_PRICE,
q.GW_CLOSE_PRICE, q.MODIFY_TIME, mu.CURRENCY, mu.DELIMER, IF(mu.CURRENCY = 'USD', 1, SearchOfRate(q.REPORT_ID, mu.CURRENCY, 'USD', q.MODIFY_TIME, -1)), IF(q.`
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 876643 page no 46339 n bits 952 index IDX_LOGIN_REPORT_ID of table `Developer`.`MT4_USERS` trx id 178168783 lock_mode X locks rec but not gap
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 876643 page no 46338 n bits 952 index IDX_LOGIN_REPORT_ID of table `Developer`.`MT4_USERS` trx id 178168783 lock_mode X locks rec but not gap waiting
*** WE ROLL BACK TRANSACTION (1)
Answer the question
In order to leave comments, you need to log in
What sequence of row locks occurs in the case of SELECT ... INNER JOIN ... FOR UPDATE
SELECT... MT4_USERS... FOR UPDATE
. In MT4_USERS it locks, for example, 1, 2... 3 INSERT MT4_TRADES... MT4_USERS...
. In MT4_USERS it locks, for example, 3... 2 ... ORDER BY MT4_USERS.id ASC
SELECT... FOR UPDATE
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question