我正在运行一个用 Java 编写的带有 MySQL 数据库的 MMORPG 服务器。几个月来它运行得很好,但是随着我们变得越来越流行并且数据库变得越来越大,我们开始遇到问题。查询都在处理数据包的同一线程中运行(是的,它的设计很糟糕),这导致了严重的延迟——我们通过实现一个保存工作程序来伪造这一点,它定期保存 10 分钟未保存的字符在 5 个线程中。此外,还有五个其他线程处理在游戏过程中需要即时处理的数据库查询。
我们的问题是访问包含字符一般信息的表的更新由于某种原因需要很长时间然后超时。
进程列表: http ://i.imgur.com/Fr0kD.png
characters
更新包含大约 30 个字段,并以 WHERE id = ? .
进程列表中出现的表格布局:
TABLE `characters` ( -- Contains about 300.000 rows
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`accountid` int(10) unsigned NOT NULL DEFAULT '0',
`world` int(11) NOT NULL DEFAULT '0',
`name` varchar(13) NOT NULL DEFAULT '',
`level` int(11) NOT NULL DEFAULT '0',
`exp` int(11) NOT NULL DEFAULT '0',
`str` int(11) NOT NULL DEFAULT '0',
`dex` int(11) NOT NULL DEFAULT '0',
`luk` int(11) NOT NULL DEFAULT '0',
`int` int(11) NOT NULL DEFAULT '0',
...
`job` int(11) NOT NULL DEFAULT '0',
...
PRIMARY KEY (`id`),
KEY `accountid` (`accountid`),
KEY `ranking1` (`level`,`exp`),
KEY `ranking2` (`job`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
TABLE `items` ( -- contains 34 million rows
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`type` tinyint(3) unsigned NOT NULL,
`inventoryType` tinyint(4) NOT NULL,
`characterId` int(10) unsigned DEFAULT NULL,
`accountId` int(10) unsigned DEFAULT NULL,
`itemId` int(10) unsigned NOT NULL,
...
PRIMARY KEY (`id`),
KEY `FK_items_1` (`characterId`),
KEY `FK_items_2` (`accountId`),
CONSTRAINT `FK_items_1` FOREIGN KEY (`characterId`) REFERENCES `characters` (`id`) ON DELETE CASCADE,
CONSTRAINT `FK_items_2` FOREIGN KEY (`accountId`) REFERENCES `accounts` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
TABLE `wishlists` ( -- contains ~75.000 rows
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`characterId` int(10) unsigned NOT NULL,
`serialNumber` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_wishlists_1` (`characterId`),
CONSTRAINT `FK_wishlists_1` FOREIGN KEY (`characterId`) REFERENCES `characters` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
它是运行 WS2008 R2、MySQL 5.5.22 和 Java 7 的专用服务器。Java 通过 JDBC(MySQL 连接器 5.1.18)连接到数据库,并且这些查询的 autoCommit 设置为 false,isloation 为 TRANSACTION_READ_UNCOMMITTED。服务器有 32 GB RAM,其中 24 个用于 Java,其余用于 MySQL。一些设置:
innodb_buffer_pool_size=8G
innodb_log_file_size=1024M
innodb_thread_concurrency=10
这种行为的原因可能是什么?