Suite à un peu de troubleshoot ces derniers jours je suis tombé sur un problème MySQL difficile à comprendre lors d’un requêtage sur mes vues lors de la création d’une instance dupliquée d’une base de production destinée à des tests de charge. L’erreur lors du requêtage sur la vue avec un utilisateur non privilégiée était la suivante:
Access denied for user 'read_user'@'172.1.7.125'
A première vue, il semblerait que notre utilisateur mysql applicatif n’aie pas accès à la base de données avec son mot de passe habituel. Pourtant lorsque l’application requête une table InnoDB sur la même base cela fonctionne. Regardons maintenant les droits de notre utilisateur:
GRANT USAGE ON *.* TO 'read_user'@'172.1.7.125' IDENTIFIED BY PASSWORD '*32F1789A74AA440B2FC136AF791B5C2B8BC7DE2F'
GRANT ALL PRIVILEGES ON `financialdb`.* TO 'read_user'@'172.1.7.125'
D’après ces droits, notre utilisateur a bien le droit de se connecter et possède les droits sur la base financialdb (notre base importée). Si on teste rapidement via un prompt mysql
mysql -u read_user -h localhost -p financialdb
select count(*) from history_records;
+----------+
| count(*) |
+----------+
| 11332692 |
+----------+
select count(*) from view_history_records_filtered;
Access denied for user 'read_user'@'172.1.7.125'
Etrange, nous sommes connectés mais impossible de lire la vue.
show create table view_history_records_filtered
| view_history_records_filtered | CREATE ALGORITHM=UNDEFINED DEFINER=`gildas`@`localhost` SQL SECURITY DEFINER VIEW `view_history_records_filtered` AS select `id` from view_history_records WHERE `p`='134' |
La vue appartient à l’utilisateur ‘gildas’@’localhost’, il ne s’agit pas de notre utilisateur applicatif. Verifions les droits de cet utilisateur:
show grants for 'gildas'@'localhost';
ERROR 1141 (42000): There is no such grant defined for user 'gildas' on host 'localhost'
Notre utilisateur n’existe pas ou plus, c’est là l’erreur. On recréée la vue avec un utilisateur qui existe, le nôtre par exemple, et on retente la requête
select count(*) from history_records;
+----------+
| count(*) |
+----------+
| 715 |
+----------+
Cela fonctionne ! MySQL parle de droits pour votre utilisateur, alors qu’en fait c’est le definer de la vue qui n’existe pas, le message d’erreur est obscur et dans les logs nous n’avons pas d’entrée évoquant ce problème. Ceci s’explique par le fait que l’utilisateur définissant la vue est une sorte d’utilisateur proxy lisant les données (donc attention à ne pas mettre root !)