游戏服务器的数据库有个表account_role是用来绑定账号与角色(一个账号对应一个角色)之间的关系,表结构如下
+--+--+--+--+--+--+ | Field | Type | Null | Key | Default | Extra | +--+--+--+--+--+--+ | role_id | int(10) unsigned | NO | PRI | NULL | auto_increment | | server_id | tinyint(4) | YES | MUL | NULL | | | account_id | bigint(20) | YES | | NULL | | | account_name | varchar(32) | YES | | NULL | | +--+--+--+--+--+--+
字段分别是:角色ID,账号库id,账号id,账号
DDL
CREATE TABLE `account_role` ( `role_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `server_id` tinyint(4) DEFAULT NULL, `account_id` bigint(20) DEFAULT NULL, `account_name` varchar(32) DEFAULT NULL, PRIMARY KEY (`role_id`), UNIQUE KEY `index_account` (`server_id`,`account_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
由于可以用多种账号库登陆,例如可以用网易账号和百度账号登录,由客户端选择,两个账号库的账号ID可能相同,所以有个账号库字段
server_id和account_id有个联合唯一索引
现在有大约20-30个线程用于登录检查绑定关系,假如没有绑定角色,则插入一条记录,否则读取role_id获取角色信息
大致是这样的
select role_id from account_role where server_id=1 and account_id=1000000;
假如没找到则插入
insert into account_role values(0, 1, 1000000, "asdfghj");
假如insert成功,则查询刚才插入的role_id
select last_insert_id();
这个server_id和account_id联合唯一索引的目的是多线程insert同一个玩家时(例如玩家点击了多次登录,在不同的线程同时处理,要做线程同步),保证只有一个insert成功,也就是利用数据库的唯一索引来同步线程
现在的问题是数据库中有约40W条数据,当新玩家进来时,insert这句经常会超时(100多秒)?
解决方案
15
这里的账户表不能够拆成多个表么?
多个线程同时查询多个表,当有一个查询出结果,通知其他线程停止搜索。
当然,前提该数据必须有唯一设定,假如可以查出多条数据的话不在我们的讨论范围。
多个线程同时查询多个表,当有一个查询出结果,通知其他线程停止搜索。
当然,前提该数据必须有唯一设定,假如可以查出多条数据的话不在我们的讨论范围。
15
LZ你好
这样的数据库系统应该将读写分开,并且应用cache缓存等技术,才能明显的提高性能
这样的数据库系统应该将读写分开,并且应用cache缓存等技术,才能明显的提高性能
10
select role_id from account_role where server_id=1 and account_id=1000000;
看下这个sql的执行计划
最好索引创建的时候是UNIQUE KEY `index_account` (`account_id`,`server_id`)
看下这个sql的执行计划
最好索引创建的时候是UNIQUE KEY `index_account` (`account_id`,`server_id`)