我在建立一些mysql的遊戲邏輯並遇到了一個難題。玩家擁有可以通過購買升級的技術。然後經過一段時間後,玩家的等級會提高。通過這種方式,關卡實時更新,而不是當玩家通過觸發器進行操作時。 mysql如何根據升級過程是否完成並實時更新來更新播放器的級別?根據在mysql中的時間創建自動更新行
我的第一個想法: 每秒或每分鐘運行一次mysql事件來檢查過期的技術並適當升級它們。在開始構建這個想法之後,我很快發現我的開銷在增加。除非我使用一些健壯的硬件,否則我不認爲我可以在一臺服務器上運行4或5或這些進程並有效運行我的遊戲服務器。
我的新想法: 我在玩意見,並提出了一個有趣的工作,對我的問題進行了排序,使其對資源更友好。
首先我有我的players_technologies表:
CREATE TABLE `players_technologies` (
`playertech_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`player_id` int(10) unsigned NOT NULL,
`tech_id` int(10) unsigned NOT NULL,
`next_update` datetime DEFAULT NULL,
`level` int(11) NOT NULL,
PRIMARY KEY (`playertech_id`),
KEY `fk_players_technologies_1_idx` (`player_id`),
CONSTRAINT `fk_players_technologies_1` FOREIGN KEY (`player_id`) REFERENCES `players` (`player_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
這是玩家的技術水平的存儲位置。 tech_id
僅僅是對名稱等技術細節的引用,不應該對此設置產生太大影響。
然後,我創建了一個VIEW
用於從數據庫中的其他位置訪問的技術。
CREATE VIEW `players_technologies_real` AS
SELECT `players_technologies`.`playertech_id` AS `playertech_id`,
`players_technologies`.`player_id` AS `player_id`,
`players_technologies`.`tech_id` AS `tech_id`,
`players_technologies`.`next_update` AS `next_update`,
`players_technologies`.`level` AS `level`,
if(isnull(`players_technologies`.`next_update`),
`players_technologies`.`level`,
if((`players_technologies`.`next_update` < now()),
(`players_technologies`.`level` + 1),
`players_technologies`.`level`)) AS `real_level`
FROM `players_technologies`;
此檢查的截止日期,next_update
,看看那個時候已經過去。如果有,它將顯示real_level
增加1.這是數據庫的其餘部分應用於邏輯並保持實時的字段。
然後,我可以在player_technologies的一行更新之前添加TRIGGER
,如果過期日期過期,它將拒絕更新next_update
。如果它已經過去,它會增加水平並繼續執行UPDATE
。這TRIGGER
看起來是這樣的:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` TRIGGER `players_technologies_BU` BEFORE UPDATE ON `players_technologies`
FOR EACH ROW
BEGIN
DECLARE msg VARCHAR(255);
IF(NEW.`next_update` <> OLD.`next_update`) THEN
IF(OLD.`next_update` > NOW()) THEN
SET msg = CONCAT('Player Technology Error: Player Tech #',NEW.`playertech_id`,' is not finished with it current research.');
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
ELSE
SET NEW.`level` = OLD.`level` + 1;
END IF;
END IF;
END$$
任何人都可以看到,這是不正確的設置?這有什麼不對嗎?
它會工作,但是在mysql中視圖往往很慢(與優化器有關,除非你破壞mysql)(至少在版本5.7之前),所以要麼升級到mariadb似乎沒有這個問題,或者不使用視圖。 –
@NorbertvanNobelen - 將視圖邏輯封裝到函數中並使用該函數確定級別會更好嗎?即players_tech_real('next_update','level')AS'real_level'。這會跳過對視圖的需求。 – wesleywmd
你可以這樣做。然後,您可以通過在函數中更改查詢來應用任何標準,並且您仍然只有一個位置來維護您的代碼。優化器對該部分沒有問題。 –