MySQL table_cache et Opened_tables

14

J'ai vu des gens utiliser la comparaison d'Open_tables et d'Opened_tables pour évaluer si la table_cache est trop petite dans MySQL. Cependant, je pense que Opened_tables est cumulatif sur la disponibilité, donc ce n'est pas une comparaison valide. La seule mise en garde étant que peut-être Opened_tables ne se heurte qu'à des échecs - bien que même si les tables ouvertes par seconde sont encore petites, ce n'est probablement pas un problème pour qu'elle se développe progressivement.

Si la comparaison d'Open_tables à Opened_tables n'est pas valide, existe-t-il un autre moyen d'obtenir des données mesurées pour cela?

C'est sur MySQL 5.0, mais les différences entre les versions sont également les bienvenues.

Sam Brightman
la source
J'aime cette question parce que c'est une question qui fait réfléchir. Cela obtient un +1 pour rappeler aux développeurs MySQL de tirer pleinement parti des variables d'état pour mesurer la santé du serveur DB.
RolandoMySQLDBA

Réponses:

7

La principale raison d'avoir un grand table_cache est que le mutex LOCK_open n'est pas chaud. MySQL avant 5.5 a beaucoup de conflits lorsque vous essayez d'ouvrir / fermer des tables, donc vous voulez limiter autant que possible cela, c'est-à-dire avoir un grand cache de table.

Donc, vous ne vous souciez pas d'un ratio particulier de succès par rapport aux échecs (en fait, vous devez ignorer complètement les ratios - cet article de blog explique pourquoi ). Ce qui vous intéresse, c'est le taux d'échecs , car plus il se produit par seconde, plus les chances de contention sont élevées (un thread doit attendre qu'un autre thread libère le verrou).

Comment repérez-vous le taux de miss? Vous récupérez quelques échantillons d'Opened_Tables à quelques secondes d'intervalle pendant la période la plus occupée de la journée, et s'il y a des augmentations dans chaque échantillon, c'est probablement une bonne idée de voir si vous pouvez augmenter la table_cache.

Remarque: Je ne recommande pas spécifiquement de comparer avec la disponibilité.

Morgan Tocker
la source
5

Tout d'abord, considérons ces variables d'état:

Tables ouvertes : nombre de tables ouvertes.

Opened_tables : Le nombre de tables qui ont été ouvertes. Si Opened_tables est grand, votre valeur table_open_cache est probablement trop petite.

Étonnamment, la réponse à votre question réside dans la question elle-même.

Les deux variables n'auraient plus de sens que si vous jetiez une autre variable d'état dans le mélange: Uptime (ou Uptime_since_flush status pour les moyennes fraîches après FLUSH STATUS ).

Vous devriez comparer Open_tables agsinst (Opened_tables / Uptime) . Si Open_tables grimpe au-dessus (Opened_tables / Uptime) , vous avez maintenant des raisons de vous inquiéter et devez garder un œil ouvert sur des choses comme les suivantes:

MISE À JOUR 2011-08-31 12:18 EDT

Veuillez noter pourquoi j'ai également suggéré d'utiliser Uptime_since_flush_status au lieu d' Uptime pour obtenir un modèle de croissance Opened_tables fixe pour une période donnée.

Par exemple, si vous exécutez FLUSH STATUS;tous les lundis à minuit, vous pouvez générer un OpenTableFactor:

SELECT *, (Open_tables * Uptime / Opened_Tables) OpenTableFactor FROM
(SELECT variable_value Uptime FROM information_schema.global_status
WHERE variable_name = 'Uptime_since_flush_status') up,
(SELECT variable_value Open_tables FROM information_schema.global_status
WHERE variable_name = 'Open_tables') opn,
(SELECT IF(variable_value=0,1,variable_value) Opened_tables
FROM information_schema.global_status
WHERE variable_name = 'Opened_tables') opnd;

Ce facteur de table ouverte correspond au nombre qui représente le nombre de tables ouvertes à un moment donné par rapport au nombre moyen de tables ouvertes tout au long d'une période donnée. Avec un FLUSH HOSTS;chaque semaine / jour / hôte, cette moyenne est contre la semaine / jour / heure.

Voici un échantillon de l'un des clients de mon employeur:

mysql> SELECT *, (Open_tables * Uptime / Opened_Tables) OpenTableFactor FROM     (SELECT variable_value Uptime FROM information_sc    hema.global_status     WHERE variable_name = 'Uptime_since_flush_status') up,     (SELECT variable_value Open_tables FROM informat    ion_schema.global_status     WHERE variable_name = 'Open_tables') opn,     (SELECT IF(variable_value=0,1,variable_value) Opened_ta    bles     FROM information_schema.global_status     WHERE variable_name = 'Opened_tables') opnd;
+----------+-------------+---------------+-------------------+
| Uptime   | Open_tables | Opened_tables | OpenTableFactor   |
+----------+-------------+---------------+-------------------+
| 14385123 | 16326       | 30429078      | 7717.996519579068 |
+----------+-------------+---------------+-------------------+
1 row in set (0.00 sec)

Ce client maintient normalement environ 7745 OpenTableFactor à max. Si OpenTableFactor tombe soudainement (même si c'est un peu), cela pourrait indiquer des modèles de trafic plus faibles, des connexions avortées élevées, etc. Si OpenTableFactor ne change jamais (même un peu), cela pourrait vous offrir la possibilité de modifier ces paramètres:

Une fois réglé, l'OpenTableFactor peut changer constamment ou atteindre un autre plafond ou plateau. Ainsi, l'utilisation de différentes unités dans les variables d'état devient vitale pour ce type de réglage.

MISE À JOUR 2011-08-31 12:42 EDT

La requête SQL que j'ai exécutée pour OpenTableFactor ne fonctionne pas pour MySQL 5.0 et inversement. Si vous utilisez MySQL Administrator ou MONyog , vous pouvez personnaliser un graphique en utilisant la formule dans la requête et le moniteur. MONyog collecte l'historique à l'aide de SQLLite pour un graphique historique ultérieur. Cela peut être fait pour n'importe quelle version de MySQL.

RolandoMySQLDBA
la source
Quelques bonnes suggestions, mais je ne pense pas que vous vouliez comparer deux choses avec des unités différentes pas plus que vous ne voulez comparer une valeur cumulative à une valeur actuelle. Et la question de savoir si ces mesures ne sont pas respectées demeure.
Sam Brightman
3

À partir de l'un des commentaires des utilisateurs sur la page de documentation de table_cache :

Opened_tables est une variable d'état qui conserve un décompte en cours du nombre de descripteurs de fichiers supplémentaires qui ont été alloués pour l'ouverture des tables lorsque les descripteurs de fichiers disponibles dans table_cache ont été épuisés. ...

Cela signifie qu'il est incrémenté lorsque vous dépassez votre table_cachevaleur. Donc, la façon dont je vérifie normalement cela est de comparer opened_tablesavec uptime, mais la clé ici est de le prendre sur un intervalle défini (une fois par minute sur dix minutes, par exemple). Si elle augmente, cela peut être une indication que vous devez augmenter votre table_cache.

Quelques mises en garde à mentionner:

  • Un autre commentaire dans cette documentation ci-dessus: "La variable d'état 'Opened_tables' sera également incrémentée de 2 chaque fois que vous créez une table temporaire." Donc, si vos requêtes nécessitent de nombreuses tables temporaires, cela pourrait être la cause d'une augmentation rapide de opened_tables. Vous pouvez voir votre utilisation de table temporaire à l'aide de la requête suivante:

    SHOW GLOBAL STATUS LIKE '%tmp%';

  • N'augmentez pas le table_cache trop haut

    La raison d'un tel comportement est que, si vous avez un grand non. de tables avec des requêtes compliquées joignant plusieurs tables et plusieurs connexions exécutant ces requêtes compliquées, vous pourriez finir par utiliser le cache de tous vos descripteurs de fichiers (table_cache) dans ce cas, MySQL utilise un algorithme pour trouver le descripteur le moins récemment utilisé, le ferme et remplace avec un nouveau descripteur.

Derek Downey
la source