2011-06-12 5 views
2

J'ai le problème suivant. J'ai un MMORPG basé sur PHP et MySQL avec environ 600 requêtes par seconde en moyenne. J'ai des problèmes avec des tables qui sont verrouillées trop longtemps et qui bloquent d'autres requêtes. (Les requêtes de mise à jour doivent par exemple attendre sur les requêtes Select) et celles-ci doivent attendre si longtemps que la mémoire est pleine.Réplication MySQL et verrous de table

Ces requêtes sont nécessaires et je ne pense pas que je puisse les optimiser.

Est-ce une bonne idée d'utiliser la réplication pour Master-Slave? Maître pour les écritures et esclave pour les sélections? L'esclave a-t-il moins de problèmes de performances avec les instructions d'écriture (à partir de la corbeille) que le maître? Et cela va-t-il vraiment aider à réduire les problèmes de verrouillage de la table?

Merci à l'avance, Martin


Ah ok, merci pour répondre. Donc si j'utilise InnoDB pour ces tables. Est-il intelligent de les mélanger avec MyISAM? Parce qu'une table de test qui était 70 Mo avec MyISAM est devenue 200 Mo avec InnoDB

Je préférerais avoir quelques tables qui ont des problèmes avec les tablelocks InnoDB et les autres juste MyISAM.

Merci d'avance, Martin.

+0

Martin, bienvenue à stackoverflow. – Johan

+0

J'ai fusionné vos deux comptes non enregistrés. Vous pouvez maintenant modifier votre question et laisser des commentaires sous des réponses individuelles. –

Répondre

4

Avant de penser à la réplication et d'autres choses, essayez ceci:

Je suppose que vos tables MyISAM utilisent.
MyISAM verrouille toute la table sur select et fait attendre la mise à jour jusqu'à ce que la sélection soit terminée.

Quelques idées à considérer avant de penser à la réplication

Utilisez InnoDB
Passer vos tables InnoDB.
InnoDB assure le verrouillage des rangées au lieu du verrouillage de la table. Seules les lignes mises à jour et sélectionnées sont verrouillées.

Envisagez d'utiliser des tables d'agrégation
Si vous faites beaucoup de questions globales comme:

select sum(score) from score where player_id = 1 

Pensez à faire une table memory comme ceci:

CREATE TABLE `test`.`totals` (
    `user_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, 
    `score` INTEGER UNSIGNED NOT NULL, 
    other_fields ..... 
    PRIMARY KEY USING HASH(`user_id`) 
) 
ENGINE = MEMORY; 

Mettre un déclencheur after update et after insert comme ça:

DELIMITER $$ 

CREATE TRIGGER au_score_each AFTER UPDATE ON score FRO EACH ROW 
BEGIN 
    UPDATE totals SET score = score + (new.score - old.score) 
    WHERE totals.user_id = new.user_id; 
END $$ 

DELIMITER ; 

Maintenant, vous pouvez obtenir vos requêtes agrégées select à partir de la table totals et vous n'avez plus besoin de remonter la base de données sur les tables complètes.

Quelques remarques sur maître-esclave
Notez que maître-esclave dans MySQL est asynchrone.Cela signifie que si vous sélectionnez l'esclave et que vous le mettez à jour sur le maître, vos données esclaves seront en retard.
Cela signifie que vous échangez vos problèmes de verrouillage contre des problèmes de décalage horaire.
Dans un jeu avec des scores cela pourrait être un problème.
En outre, vous compliquez votre configuration.

Je ne suis pas un expert de la réplication, donc je vais m'arrêter ici mais je pense que vous êtes en train de sauter dans maître-esclave avant d'explorer les alternatives.

0

Les mises à jour d'esclave sont mono-thread et répètent simplement les mises à jour qui ont été effectuées sur le maître. Donc même si vous pouvez obtenir une petite augmentation de la vitesse d'un seul esclave, vous avez vraiment besoin d'avoir plusieurs esclaves pour obtenir une augmentation significative de la vitesse de SELECT. Cela augmenterait significativement la complexité de votre jeu.

Si vous pouvez mettre à jour votre serveur, je vous recommande d'abord, ont aussi un regard sur les paramètres réglables pour MySQL, assurez-vous d'utiliser au mieux la mémoire disponible, etc.

+0

Ah d'accord, je doute que mon système puisse gérer plusieurs esclaves. : S Je vais maintenant utiliser InnoDB comme suggéré ci-dessous. (merci Johan!) Merci à vous deux d'avoir répondu! – Martin