【问题标题】:MySQL Replication and table locksMySQL 复制和表锁
【发布时间】:2011-06-12 18:19:04
【问题描述】:

我有以下问题。

我有一个基于 PHP 和 MySQL 的 MMORPG 游戏,现在平均每秒大约 600 个查询。 我碰巧遇到了锁定时间过长并且阻止其他查询的表的问题。 (例如更新查询需要等待 Select 查询)并且这些查询必须等待很长时间以致内存已满。

需要这些查询,我认为我无法再优化它们了。

为主从使用复制是一个聪明的主意吗?写入的主控和选择的从属? 从属设备在写入语句(来自日志箱)方面的性能问题是否比主设备少?它真的有助于减少表锁定问题吗?

提前致谢,马丁


好的,谢谢你的回答。 因此,如果我对这些表使用 InnoDB。将它们与 MyISAM 混合起来是否明智?

因为 MyISAM 的 70MB 测试表变成了 InnoDB 的 200MB。我宁愿有一些表锁 InnoDB 有问题的表,而其他的只是 MyISAM。

提前致谢,马丁。

【问题讨论】:

  • 马丁,欢迎来到 stackoverflow。
  • 我已合并您的两个未注册帐户。您现在可以编辑您的问题并将 cmets 留在个别答案下。

标签: mysql replication


【解决方案1】:

在你考虑复制和其他东西之前,试试这个:

我假设您的表正在使用 MyISAM。
MyISAM 将整个表锁定在 select 上,并让更新等到 select 完成。

在考虑复制之前需要考虑的一些想法

使用 InnoDB
将您的表切换到 InnoDB。
InnoDB 执行行锁定而不是表锁定。只有那些更新和选择的行才会被锁定。

考虑使用聚合表
如果您执行大量聚合查询,例如:

select sum(score) from score where player_id = 1

考虑制作一个像这样的memory 表:

CREATE TABLE `test`.`totals` (
  `user_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `score` INTEGER UNSIGNED NOT NULL,
  other_fields .....
  PRIMARY KEY  USING HASH(`user_id`)
)
ENGINE = MEMORY;

像这样触发after updateafter insert

DELIMITER $$

CREATE TRIGGER au_score_each AFTER UPDATE ON score FRO EACH ROW
BEGIN
  UPDATE totals SET score = score + (new.score - old.score) 
  WHERE totals.user_id = new.user_id;
END $$

DELIMITER ;

现在您可以从totals 表中获取聚合的select 查询,并且您不再需要在完整的表上碰撞数据库。

关于主从的几点说明
注意 MySQL 中的主从是异步的。这意味着,如果您从从属服务器中选择并在主服务器上进行更新,您的从属数据将会滞后。
这意味着您正在用锁定问题换取时滞问题。
在有分数的游戏中,这可能是个问题。
此外,您使设置复杂化。

我不是复制方面的专家,所以我会在这里停下来,但我认为您在探索替代方案之前会跳入主从。

【讨论】:

    【解决方案2】:

    从属更新是单线程的,只需重复在主控上执行的更新。因此,尽管您可能会从单个从站获得小幅提升,但您确实需要多个从站才能显着提高 SELECT 速度。这会显着增加游戏的复杂性。

    如果您可以升级服务器,那么我建议您首先查看 MySQL 的可调参数,确保充分利用可用内存等。

    【讨论】:

    • 啊,好吧,我怀疑我的系统可以处理多个从站。 :S 我现在将按照下面的建议来看看使用 InnoDB。 (谢谢约翰!)谢谢你们俩的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多