Joe*_*ris 7 deadlock mysql-5.6 bulk-insert
我们有一个这样定义的表:
CREATE TABLE ipsum (
id char(40) NOT NULL,
source char(40) NOT NULL,
ip_address varbinary(16) NOT NULL,
port smallint(5) unsigned NOT NULL,
percentage decimal(5,2) NOT NULL DEFAULT '0.00',
first_date datetime NOT NULL,
last_date datetime NOT NULL,
p0 tinyint(1) NOT NULL DEFAULT '0',
p1 tinyint(1) NOT NULL DEFAULT '0',
blocked tinyint(1) NOT NULL,
created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
country varchar(100) DEFAULT NULL,
continent varchar(100) DEFAULT NULL,
note varchar(100) DEFAULT NULL,
PRIMARY KEY (id),
KEY idx_first_seen_peer (first_date),
KEY idx_last_seen_peer (last_date),
KEY ipsum (source,ip_address,port)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
我们正在批量插入这个表,一次最多 15,000 条记录。插入的结构如下:
INSERT INTO ipsum (id, source, ip_address, port, percentage, first_date, last_date, p0, p1, country, continent, note, blocked)
VALUES {{ 15000 legitimate values here sorted alphabetically by the id field }}
ON DUPLICATE KEY UPDATE
p0 = p0 OR VALUES(p0),
p1 = p1 OR VALUES(p1),
last_date = GREATEST(last_date, VALUES(last_date)),
first_date = LEAST(first_date, VALUES(first_date)),
percentage = GREATEST(percentage, VALUES(percentage));
Run Code Online (Sandbox Code Playgroud)
VALUES集合中的记录已按 id 字母顺序排序。
当我们在运行多个查询实例的情况下达到非常高的输入率时,我们开始看到死锁:
错误:ER_LOCK_DEADLOCK:尝试获取锁时发现死锁;尝试重新启动事务]
没有对表执行其他语句——只有如上所述的插入。
如何修改插入查询以防止死锁?
尽管“show processlist”可能会将所有进程显示为睡眠状态,但这并不一定意味着该表没有被另一个进程锁定。
show open tables where name_locked=1;
select *
from performance_schema.table_lock_waits_summary_by_table
where object_schema=@db
and object_name=@tab
\G
Run Code Online (Sandbox Code Playgroud)