Oll*_*lle 5 mysql myisam locking update
我有一个大表(58+ 百万条记录),它表示第二个表中两条记录(玩家和目标)之间的关系。
不幸的是,设计我们模式的人并没有考虑周全,而是选择使用用户名来表示这种关系,而不是用户记录的数字 ID。随着事情的进展(就像他们通常所做的那样),我们的用户名不再是玩家的有效唯一表示,因此我需要将这些关系转换为使用数字 ID。
多亏了 Percona Toolkit,在不加锁的情况下添加字段很容易,它提供了 pt-online-schema-change 可以在实时表上进行 ALTER。但是,填充表格可能会更棘手。
表格看起来像这样(我已经剥离了不相关字段的创建),两个未填充的字段是player_id
和target_id
:
CREATE TABLE `player_targets` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`player` varchar(20) NOT NULL,
`player_id` int(10) unsigned DEFAULT NULL,
`target` varchar(20) NOT NULL,
`target_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=58000000 DEFAULT CHARSET=latin1;
CREATE TABLE 'player_uuids' (
`id`int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=600000 DEFAUL CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)
我打算用这样的查询填充两个新字段:
UPDATE player_targets t
INNER JOIN player_uuids u1
ON u1.username = t.player
INNER JOIN player_uuids u2
ON u2.username = t.target
SET
t.player_id = u1.id,
t.target_id = u2.id
WHERE
t.player_id IS NULL
OR t.player_id IS NULL;
Run Code Online (Sandbox Code Playgroud)
由于表存储关系是 MyISAM,我对文档的解释是 UPDATE 查询将锁定表,直到它完成所有行。由于桌子很大,这在现场环境中可能不会很好地工作。
最好的方法是什么?编写脚本来迭代成批的关系?将表引擎更改为 InnoDB(该表需要大量读取,我认为这是 MyISAM 的原因)?
是的,批量迭代。 该博客提供了一些有关如何执行此操作的建议。
它的表达方式是如何将 big s 分成块DELETE
,但这些原则适用于UPDATE
像你这样的 big s。
它向您展示了如何使用(通常)PRIMARY KEY
使用LIMIT
来决定下一个块。任何步骤都不需要扫描整个表,因为这会破坏分块的目的。
归档时间: |
|
查看次数: |
15942 次 |
最近记录: |