简体   繁体   English

SELECT/UPDATE 和 SELECT/INSERT 杀死 MySQL 服务器

[英]SELECT/UPDATE and SELECT/INSERT kills MySQL server

I run a server that is getting killed by the number of requests it is getting from one of our iPhone games for storing scores.我运行的服务器被我们的一款 iPhone 游戏用于存储分数的请求数量所杀死。 By this I mean the server becomes unresponsive.我的意思是服务器变得无响应。

I only really know enough MySQL/PHP to get by, so I am floundering in my attempts to fix this.我真的只知道足够多的 MySQL/PHP 来解决这个问题,所以我在努力解决这个问题。 I am sure its a problem that can be optimised because we have a dedicated server.我确信这是一个可以优化的问题,因为我们有一个专用服务器。 We handle only 300 requests a minute.我们每分钟只处理 300 个请求。

Basically we check the score someone is posting from their iPhone game (using a SELECT) to see if they have an existing score.基本上,我们检查某人从他们的 iPhone 游戏中发布的分数(使用 SELECT)来查看他们是否有现有分数。 If they do, and their new score is better, we do an UPDATE, otherwise we do an INSERT.如果他们这样做了,并且他们的新分数更好,我们执行 UPDATE,否则我们执行 INSERT。 The statements look like this:语句如下所示:

$sql = "SELECT id,score,level FROM $table WHERE board='$board' AND name='$name' AND udid = '$udid' AND fbuid = '$fbuid'" $sql = "SELECT id,score,level FROM $table WHERE board='$board' AND name='$name' AND udid = '$udid' AND fbuid = '$fbuid'"

The UPDATE and INSERT statements look like this: UPDATE 和 INSERT 语句如下所示:

$sql = "UPDATE $table SET score='$score', level='$level', country='$country', date=CURRENT_TIMESTAMP WHERE board='$board' AND name='$name' AND udid = '$udid' AND fbuid = '$fbuid'" $sql = "UPDATE $table SET score='$score', level='$level', country='$country', date=CURRENT_TIMESTAMP WHERE board='$board' AND name='$name' AND udid = ' $udid' AND fbuid = '$fbuid'"

$sql = "INSERT INTO $table(board, udid, fbuid, name, score, level, country) VALUES ('$board', '$udid', '$fbuid', '$name', '$score', '$level', $country')" $sql = "INSERT INTO $table(board, udid, fbuid, name, score, level, country) VALUES ('$board', '$udid', '$fbuid', '$name', '$score', '$level', $country')"

And for completeness, here is the definition for the table:为了完整起见,这里是表的定义:

CREATE TABLE $table (创建表$table (
id int(11) NOT NULL auto_increment, id int(11) 不是 NULL auto_increment,
board tinyint(4) NOT NULL, board tinyint(4) 不是 NULL,
udid varchar(45) default NULL, udid varchar(45) 默认 NULL,
fbuid bigint(20) unsigned default NULL, fbuid bigint(20) 无符号默认 NULL,
name varchar(25) default NULL, name varchar(25) 默认 NULL,
country tinyint(4) default NULL, country tinyint(4) 默认 NULL,
level tinyint(4) default NULL, level tinyint(4) 默认 NULL,
score decimal(10,0) default NULL, score小数(10,0)默认NULL,
date timestamp NOT NULL default CURRENT_TIMESTAMP, date时间戳 NOT NULL 默认 CURRENT_TIMESTAMP,
PRIMARY KEY ( id ),主键( id ),
KEY scoreidx ( score ), KEY scoreidx ( score ),
KEY udididx ( udid ),udididx ( udid ),
KEY fbuididx ( fbuid ),fbuididx ( fbuid ),
KEY boardidx ( board ), KEY boardidx ( board ),
KEY levelidx ( level ), KEY levelidx ( level ),
KEY countryidx ( country ) KEY countryidx ( country )
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) 引擎=MyISAM 默认字符集=latin1

I currently connect to the MySQL server from PHP using:我目前使用以下命令从 PHP 连接到 MySQL 服务器:

$conn = mysql_pconnect(DB_HOST,DB_USER,DB_PASSWORD,MYSQL_CLIENT_INTERACTIVE); $conn = mysql_pconnect(DB_HOST,DB_USER,DB_PASSWORD,MYSQL_CLIENT_INTERACTIVE);

But used to use msql_connect previously, but did not notice an improvement with that.但是以前使用过 msql_connect ,但没有注意到它的改进。

Any pointers on how I can optimise this, or links to any web pages that describe what I should be doing would be HUGELY appreciated.任何关于我如何优化它的指针,或任何 web 页面的链接都将非常感激。

MyISAM has table-locks instead of the InnoDB row-locks. MyISAM具有表锁而不是InnoDB行锁。 You could create a copy of your table, alter the engine to InnoDB, and (on a testserver) test the load with mysqlslap or similar stress testing tools. 您可以创建表的副本,将引擎更改为InnoDB,并(在测试服务器上)使用mysqlslap或类似的压力测试工具测试负载。

Also, very important: 另外,非常重要:

ALTER TABLE tablename ADD INDEX(board,name,udid,fbuid)

MySQL can only use 1 index at a time, so your several 'loose' ones don't do that much good when always querying for this specific combination. MySQL一次只能使用1个索引,所以当你总是查询这个特定组合时,你的几个“松散”索引并没有那么好。

"MySQL uses table-level locking for MyISAM, MEMORY and MERGE tables, page-level locking for BDB tables, and row-level locking for InnoDB tables." “MySQL对MyISAM,MEMORY和MERGE表使用表级锁定,对BDB表使用页级锁定,对InnoDB表使用行级锁定。”

http://dev.mysql.com/doc/refman/5.0/en/internal-locking.html http://dev.mysql.com/doc/refman/5.0/en/internal-locking.html

So, each time you update, the full table gets a lock. 因此,每次更新时,完整表都会获得锁定。 You might want to switch to InnoDB. 您可能想切换到InnoDB。

you could try optimizing by not doing the select and updating on duplicate primary key.. You would need a primary key like email address or something though. 您可以尝试通过不对重复的主键进行选择和更新进行优化。您需要一个主键,如电子邮件地址或其他东西。

$sql = "INSERT INTO $table(board, udid, fbuid, name, score, level, country) VALUES
('$board', '$udid', '$fbuid', '$name', '$score', '$level', $country') ON DUPLICATE KEY
UPDATE score = '$score'";

==sorry wrong language but could be done with a text file of lines. ==对不起语言错误,但可以用文本文件来完成。 If it is the number of incoming connections, you may need to make a timer unit In the game binaries to call and receive to find if it must retry, while holding the data with a token number exchanged back to the game from the web server (data jobs on a queue eg EJB).如果是传入的连接数,你可能需要在游戏二进制文件中创建一个定时器单元来调用和接收以查找是否必须重试,同时持有从 web 服务器交换回游戏的令牌号数据(队列上的数据作业,例如 EJB)。 When each step is verified occured the timer and waiting process in the game can be stopped.当每个步骤都被验证发生时,游戏中的计时器和等待过程可以停止。 In the web server ServletContext persistent object to store jobs with an I'd token, and a mirror List holding token and job completed status.在 web 服务器 ServletContext 中持久化 object 以存储带有 Id 令牌的作业,以及一个包含令牌和作业完成状态的镜像列表。 That way, the webserver to MySQL can simply work through the list one by one until it is retriggered by a game request and data entered in eg the hashmao List.这样,MySQL 的网络服务器可以简单地逐个处理列表,直到它被游戏请求和输入例如 hashmao 列表的数据重新触发。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM