Java MySQL在同一个表上的多个更新超时
我正在运行一个用Java编写的带有MySQL数据库的MMORPG服务器。几个月来,它运行得很好,但随着我们越来越受欢迎,数据库越来越大,我们开始遇到问题。这些查询都是在同样的线程中运行的,这些线程也处理数据包(是的,它的设计非常糟糕),这导致了严重的延迟-我们通过实现一个save-worker来伪造这一点,它在5个线程中周期性地保存10分钟内没有保存的字符。另外,还有五个线程处理在游戏过程中需要即时处理的数据库查询 我们的问题是,由于某种原因,访问包含字符一般信息的表的更新需要很长时间,然后超时 进程列表:Java MySQL在同一个表上的多个更新超时,java,mysql,timeout,Java,Mysql,Timeout,我正在运行一个用Java编写的带有MySQL数据库的MMORPG服务器。几个月来,它运行得很好,但随着我们越来越受欢迎,数据库越来越大,我们开始遇到问题。这些查询都是在同样的线程中运行的,这些线程也处理数据包(是的,它的设计非常糟糕),这导致了严重的延迟-我们通过实现一个save-worker来伪造这一点,它在5个线程中周期性地保存10分钟内没有保存的字符。另外,还有五个线程处理在游戏过程中需要即时处理的数据库查询 我们的问题是,由于某种原因,访问包含字符一般信息的表的更新需要很长时间,然后超时
字符
更新包含大约30多个字段,并以id=
processlist中显示的表的布局:
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;
它是一个运行WS2008R2、MySQL 5.5.22和Java 7的专用服务器。Java通过JDBC(MySQL连接器5.1.18)连接到数据库,对于这些查询,autoCommit设置为false,isloation为事务读取未提交。服务器有32GB内存,其中24个用于Java,其余用于MySQL。
一些设置:
innodb_buffer_pool_size=8G
innodb_log_file_size=1024M
innodb_thread_concurrency=10
导致这种行为的原因是什么?访问表时是否正确使用了锁?我不知道您的访问设置,但听起来您可能正处于读/写饥饿状态。访问表时是否正确使用了锁?我不知道您的访问设置,但听起来您可能正处于读/写饥饿状态。不,我们没有在任何地方使用锁。你能解释一下我们将如何添加它们吗?保存字符的方法首先更新
characters
表,然后更新所有其他表(这需要一些时间,具体取决于数据库负载),最后提交数据。不,我们没有在任何地方使用锁。你能解释一下我们将如何添加它们吗?保存字符的方法首先更新characters
表,然后更新所有其他表(这需要一些时间,具体取决于数据库负载),最后提交数据。