服务器端数据库写入的最佳策略



我有一个服务器,它为连接到它的客户端对数据库进行多次写入。与它的联系越多,写它做的就越多。我的问题是..我怎样才能最优雅地处理这个问题?随着数据库变得越来越大,插入/更新所需的时间越来越长,这反过来又使客户端滞后,因为来自服务器的响应越来越慢。

我想过的一件事是拥有一个数据库助手程序,我将其写入 QUEUE 数据库,并作为单独的应用程序在分配时写入。这将使服务器更加专注,但我不确定这是否是最佳路线。

任何帮助都会很棒。

<Debug> -- 10/6/2012 8:57:15 PM -- UPDATE mapdata SET X = @1, Y = @2, Rank = @3, Health = @4, Beacons = @20,Armors = @5, Duals = @6, Missiles = @7, Homings = @8, Radars = @9, HasRankKill = @10, TotalPP = @11, RankPP = @12, KillCount = @13, DeathCount = @14, TimePlayed = @15, EnabledEquipment = @16 WHERE MapID = @17 AND TankID = @18 AND Color = @19;
<Debug> -- 10/6/2012 8:57:15 PM -- Time to execute: 00:00:00.0468003

这需要半秒钟才能执行。

我在MapData上有索引如下:

PRIMARY: MapID, TankID, Color
MapID: MapID
TankID: TankID
'MapData', 'CREATE TABLE `mapdata` (n  `MapID` int(11) NOT NULL,n  `TankID` int(11) NOT NULL,n  `Color` tinyint(4) NOT NULL,n  `X` int(11) DEFAULT '-1',n  `Y` int(11) DEFAULT '-1',n  `Rank` tinyint(4) NOT NULL DEFAULT '0',n  `Health` int(11) NOT NULL DEFAULT '1200',n  `Armors` tinyint(4) NOT NULL DEFAULT '0',n  `Duals` tinyint(4) NOT NULL DEFAULT '0',n  `Missiles` tinyint(4) NOT NULL DEFAULT '0',n  `Homings` tinyint(4) NOT NULL DEFAULT '0',n  `Radars` tinyint(4) NOT NULL DEFAULT '0',n  `Beacons` tinyint(4) NOT NULL DEFAULT '0',n  `HasRankKill` bit(1) NOT NULL DEFAULT b'0',n  `TotalPP` bigint(20) NOT NULL DEFAULT '0',n  `RankPP` bigint(20) NOT NULL DEFAULT '0',n  `KillCount` int(11) NOT NULL DEFAULT '0',n  `DeathCount` int(11) NOT NULL DEFAULT '0',n  `TimePlayed` time NOT NULL DEFAULT '00:00:00',n  `EnabledEquipment` tinyint(4) NOT NULL DEFAULT '0',n  `Prestige` tinyint(4) NOT NULL DEFAULT '0',n  PRIMARY KEY (`MapID`,`TankID`,`Color`),n  KEY `MapID` (`MapID`),n  KEY `TankID` (`TankID`),n  CONSTRAINT `mapdata_ibfk_1` FOREIGN KEY (`MapID`) REFERENCES `maps` (`ID`) ON DELETE CASCADE,n  CONSTRAINT `mapdata_ibfk_2` FOREIGN KEY (`TankID`) REFERENCES `tank` (`ID`) ON DELETE CASCADEn) ENGINE=InnoDB DEFAULT CHARSET=latin1'

防止服务器陷入困境的典型方法是使用多线程。 这允许服务器在线程处理数据库更新时继续响应传入的请求。 我不确定 mysql 是否是线程安全的,因此您可能必须在数据库周围实现锁定。

我为多人游戏执行此操作的方式是在线程上生成DBManager。

DBManager 将是一个单例类,其中包含一个名为 lock 的静态对象

这有一个单一的公共方法"Enqueue",它将采用原始SQL或特定的游戏对象保存到数据库(在这种情况下为Tanks)。

当您进入 enqueue 时,您在上面的锁定对象上调用 Lock,并排队到需要保存到数据库的项目列表并返回,以便应用程序可以继续。

线程大约每 30 秒唤醒一次,处理队列,然后返回睡眠状态。

这种方法的缺点是您可能会丢失数据,因此您可能会失去睡眠/唤醒周期以降低风险,但显然这需要更多的数据/处理器。

最新更新