web-dev-qa-db-fra.com

Combien de temps une table MEMORY temporaire persistera si je ne la laisse pas tomber (MySQL)

J'utilise une procédure stockée récursive dans MySQL pour générer une table temporaire appelée id_list, mais je dois utiliser les résultats de cette procédure dans une requête de sélection de suivi, donc je ne peux pas DROP la table temporaire dans la procédure ...

BEGIN;

/* generates the temporary table of ID's */
CALL fetch_inheritance_groups('abc123',0);

/* uses the results of the stored procedure in the WHERE */
SELECT a.User_ID
FROM usr_relationships r 
INNER JOIN usr_accts a ON a.User_ID = r.User_ID 
WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list) 
GROUP BY r.User_ID;

COMMIT;

Lors de l'appel de la procédure, la première valeur est l'ID supérieur de la branche que je veux, et la seconde est le tier que la procédure utilise lors des récursions. Avant la boucle récursive, il vérifie si tier = 0 et si c'est le cas, il s'exécute:

DROP TEMPORARY TABLE IF EXISTS id_list;
CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;

Donc, ma question est: Si je ne DROP pas la table temporaire MEMORY à la fin de la procédure, ou dans ma transaction, combien de temps cette table persistera-t-elle en mémoire? Est-il automatiquement supprimé une fois la session terminée ou restera-t-il en mémoire tant que la connexion sera ouverte?

** N.B. La réponse évidente pourrait être de supprimer la table temporaire avant l'instruction commit, mais supposons un instant que je ne puisse pas faire cela. *


EDIT : Pour être un peu plus précis, que se passe-t-il si des connexions persistantes sont utilisées, la table persistera-t-elle à travers plusieurs requêtes? Jusqu'à présent, il semble que ce sera le cas et que nous devions supprimer explicitement la table temporaire pour libérer cette ressource.


UPDATE : Sur la base des conseils des commentateurs, j'ai trouvé un moyen d'ajuster ma procédure stockée pour pouvoir utiliser la table TEMP MEMORY, mais soyez capable de explicitement DROP à la fin ...

Plutôt que d'appeler simplement la procédure stockée et d'utiliser la table TEMP restante pour rassembler les résultats dans la requête réelle, j'ai changé le format CALL pour utiliser une troisième variable OUT comme ceci:

CALL fetch_inheritance_groups('abc123','0',@IDS);

... puis dans la procédure stockée, j'ai ajouté un second IF tier = 0 à la fin avec ce qui suit:

IF tier = 0
    THEN
    SELECT GROUP_CONCAT(DISTINCT iid SEPARATOR ',') FROM id_list INTO inherited_set;
    DROP TEMPORARY TABLE IF EXISTS id_list;
END IF;

Ainsi, le résultat de la procédure stockée est maintenant une liste d'ID séparés par des virgules qui est compatible avec FIND_IN_SET, et donc la requête finale a été modifiée pour que:

WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list)

... est maintenant ...

WHERE r.Group_ID = 'abc123' OR FIND_IN_SET(r.Group_ID,@IDS)

Voila! Merci aux commentateurs pour votre contribution et pour m'avoir donné la raison pour laquelle je devais essayer un peu plus fort :)

13
oucil

Ce qui est drôle à propos des tables temporaires dans une procédure stockée, ce n'est pas tant l'existence transitoire de la table (qui est supprimée à la fin de la connexion DB), mais la portée de la procédure stockée.

Quelqu'un a posé cette question sur StackOverflow: Portée des tables temporaires créées dans la procédure stockée MySQL . Cela fait plus d'un an et personne n'a répondu à la question? Permettez-moi de remettre les pendules à l'heure. Le fait est: La table temporaire existe à l'intérieur et à l'extérieur de la procédure stockée, mais vous pouvez faire des choses avec la table temporaire uniquement à l'intérieur de la portée d'une procédure stockée en cours.

Selon ( le Livre

kdsjx

Le chapitre 5 a un sous-titre Retour des jeux de résultats à une autre procédure stockée .

Il est dit au paragraphe 2 de la page 117:

Malheureusement, la seule façon de passer un jeu de résultats d'une procédure stockée à une autre est de passer les résultats via une table temporaire. Il s'agit d'une solution maladroite b, et - parce que la table temporaire a une portée tout au long de la session - elle crée bon nombre des mêmes problèmes de maintenabilité soulevés par l'utilisation de variables globales. mais si un programme stocké doit fournir des résultats à un autre programme stocké, une table temporaire peut être la meilleure solution.

En regardant la question StackOverflow , je peux voir quelqu'un appelé la procédure stockée depuis le client mysql. Étant donné que le client mysql n'est pas une procédure stockée, les résultats ne peuvent pas être manipulés au niveau du client mysql via DML à part faire un SELECT pour voir les résultats. Puisque vous appelez une procédure stockée récursive, vous pouvez être assuré que la table temporaire est entièrement accessible pendant la durée de la connexion DB .

J'espère que cela répond à votre question.

MISE À JOUR 2014-01-31 11:26 EST

Dans votre dernier commentaire, vous avez dit

Si nous utilisons des connexions persistantes, la table MEMORY persistera-t-elle à travers plusieurs DEMANDES, et il semble que ce sera le cas, donc pour des raisons de performances, je suppose que l'utilisation de cette méthode * nous obligera à DROP explicitement DROP la table MEMORY temporaire. Dois-je supposer correctement?

Oui et non. Je dis oui parce que c'est une façon de le faire. Je dis non parce qu'une autre façon de procéder est:

CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;
TRUNCATE TABLE id_list;

Quelle que soit la méthode choisie, l'opération est toujours la même puisque TRUNCATE TABLE supprime et recrée la table. Cela ne nuira pas aux autres connexions DB, car chaque connexion a sa propre table id_list.

17
RolandoMySQLDBA

Dans la plupart des SGBD, les tables temporaires survivent jusqu'à la fin de la connexion actuelle, sauf indication contraire ou à moins qu'il y ait un retour en arrière explicite des transactions (dans certains systèmes, un retour en arrière peut affecter uniquement le contenu de la table, laissant l'objet lui-même autour pour être repeuplé si nécessaire) . Le tableau ne sera pas (par défaut) visible pour les autres connexions, quelle que soit la durée de la connexion qui le crée.

Une analyse rapide sur Google semble indiquer que c'est ainsi que fonctionne mySQL.
( http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm indique "par défaut, toutes les tables temporaires sont supprimées par MySQL lorsque votre connexion à la base de données est interrompue")

Cependant, il existe souvent des moyens de modifier ces comportements. Par exemple, dans MS SQL Server, vous pouvez créer une table temporaire visible par toutes les connexions au lieu de la seule en cours en lui donnant un nom commençant par ##.

Je laisse toujours tomber les tables temporaires dès qu'elles ne sont plus nécessaires pour éviter toute confusion possible. J'ai été mordu auparavant lorsque le regroupement de connexions a entraîné la création de tables temporaires provoquant des erreurs car une table temporaire du même nom avait été créée mais pas détruite lors d'une action précédente qui utilisait la connexion actuelle.

2
David Spillett