I need to run a query like this to insert a large amount of data (millions of rows) into a MySQL table (InnoDB, 5.6.10):
INSERT INTO target_table (a)
SELECT id FROM source_table
ON DUPLICATE KEY a=a;
This usually takes around 200 seconds to run when no clients are accessing target_table
.
target_table
now has around 20 clients 'polling' to see if data has arrived, so we now have a lot of clients performing queries like this one:
SELECT a FROM target_table WHERE a LIKE '0%';
I'm having trouble with the INSERT INTO
statement now that these clients are polling – it fails with the error Lock wait timeout exceeded; try restarting transaction
.
I'm a bit confused as to why whatever lock is required for INSERT INTO
cannot be acquired because clients are running SELECT
statements.
EDIT:
The CREATE
statements for these tables are as follows:
CREATE TABLE `target_table` (
`a` varchar(32) NOT NULL,
PRIMARY KEY (`a`),
CONSTRAINT `target_table_source_table` FOREIGN KEY (`a`) REFERENCES `source_table` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `source_table` (
`id` varchar(32) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `name_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Best Answer
In
source_table
, are there often duplicate values? I assumea
is thePRIMARY KEY
ofdest_table
? If there are often dups, change toDISTINCT
moves work into theSELECT
, thereby lessening the conflicts over theINSERT
.Better yet, do this:
IGNORE
is probably less work than IODKU.Please provide
SHOW CREATE TABLE
for both tables; there could be subtle issues, especially with thePRIMARY KEY
, timestamps, and secondary indexes.