Crie um usuário no MySQL 8 ou no MariaDB com CREATE USER, conceda só as permissões necessárias com GRANT, confira com SHOW GRANTS e revogue o resto.
Dar acesso a um banco de dados é sempre um trabalho em duas etapas: primeiro você cria a conta com CREATE USER, depois diz o que ela pode fazer com GRANT. No MySQL 8 essa separação é obrigatória: o GRANT não cria mais usuário. Usar a conta root na aplicação é o erro mais comum e o mais perigoso; cada sistema deve ter o seu usuário, com acesso só ao próprio banco.
Antes de começar
- Acesso administrativo ao banco. No Ubuntu e no Debian o root entra pelo socket do sistema, sem senha:
sudo mysql(ousudo mariadb). Em outras instalações, usemysql -u root -p. - Hospedagem cPanel? Não crie usuários pelo terminal. Use a tela de bancos do cPanel, que aplica o prefixo da conta e mantém tudo registrado. Veja como criar um banco de dados MySQL no cPanel.
- Saiba de onde a aplicação vai conectar: do próprio servidor (
localhost) ou de outra máquina (IP).
Como criar o usuário no MySQL e no MariaDB
No MySQL, uma conta é sempre o par usuário + origem. O comando é o mesmo nos dois bancos:
CREATE USER 'app_loja'@'localhost' IDENTIFIED BY 'Troque-Esta-Senha-2026';
A parte depois do @ define de onde o usuário pode entrar:
| Origem | Significa |
|---|---|
'localhost' | Só do próprio servidor (pelo socket local). |
'10.0.0.25' | Só daquele IP. |
'10.0.0.%' | Qualquer IP da rede 10.0.0.x. |
'%' | De qualquer lugar. Evite em servidor exposto à internet. |
'app_loja'@'localhost' e 'app_loja'@'%' são duas contas diferentes, com senhas e permissões próprias. Quando as duas existem, a conexão local cai na mais específica (localhost).Como conceder permissões com GRANT
Para uma aplicação comum (site, loja, sistema), dê acesso total só ao banco dela:
GRANT ALL PRIVILEGES ON loja.* TO 'app_loja'@'localhost';
Para um usuário que só lê (relatórios, BI, integração):
GRANT SELECT ON loja.* TO 'relatorio'@'10.0.0.%';
Para restringir ainda mais, liste as permissões e, se quiser, uma tabela específica:
GRANT SELECT, INSERT, UPDATE ON loja.pedidos TO 'integracao'@'10.0.0.25';
O alvo do ON define o alcance: *.* é o servidor inteiro, loja.* é um banco e loja.pedidos é uma tabela. As permissões mais usadas:
| Permissão | O que libera |
|---|---|
SELECT, INSERT, UPDATE, DELETE | Ler, inserir, alterar e apagar linhas. |
CREATE, ALTER, DROP, INDEX | Criar, alterar e apagar tabelas e índices (instaladores e atualizações de sistemas precisam). |
CREATE TEMPORARY TABLES, LOCK TABLES | Tabelas temporárias e travas, usadas por muitos sistemas e pelo backup com mysqldump. |
EXECUTE, CREATE ROUTINE, TRIGGER, EVENT | Procedures, funções, gatilhos e eventos agendados. |
ALL PRIVILEGES | Tudo no alvo indicado, menos repassar permissões. |
GRANT OPTION | Permite que o usuário dê as próprias permissões a outros. Raramente necessário. |
FLUSH PRIVILEGES depois de CREATE USER, GRANT, REVOKE ou ALTER USER: o servidor aplica na hora. O FLUSH PRIVILEGES só é necessário quando alguém altera as tabelas internas do banco mysql diretamente com INSERT ou UPDATE.Como conferir, trocar a senha e remover acesso
- Veja as permissões de uma conta:
SHOW GRANTS FOR 'app_loja'@'localhost'; - Liste as contas existentes:
SELECT user, host FROM mysql.user ORDER BY user; - Teste o login saindo do root e entrando com o usuário novo:
mysql -u app_loja -p loja - Retire uma permissão:
REVOKE DELETE ON loja.* FROM 'app_loja'@'localhost'; - Troque a senha:
ALTER USER 'app_loja'@'localhost' IDENTIFIED BY 'Nova-Senha-Forte'; - Apague a conta:
DROP USER 'app_loja'@'localhost';
Diferenças entre MySQL 8 e MariaDB que geram erro
GRANT com IDENTIFIED BY não funciona no MySQL 8
Tutoriais antigos usam GRANT ... TO 'user'@'host' IDENTIFIED BY 'senha'. No MySQL 8 isso dá ERROR 1064 (erro de sintaxe). Crie a conta com CREATE USER e depois rode o GRANT sem a senha.
ERROR 1410: You are not allowed to create a user with GRANT
No MySQL 8 o GRANT para uma conta que não existe é recusado. Confira o par usuário e origem com SELECT user, host FROM mysql.user: muitas vezes a conta existe como @'%' e o comando foi para @'localhost'.
No MariaDB, um GRANT a mais pode criar um usuário sem senha
O MariaDB ainda cria a conta no GRANT quando o sql_mode não tem NO_AUTO_CREATE_USER, o que acontece em servidores onde alguém zerou o sql_mode. Um caso real que atendemos: a aplicação usava 'app'@'%', alguém rodou um GRANT extra "por garantia" para 'app'@'localhost' e o MariaDB criou essa conta sem senha. Como a conexão local prefere a conta mais específica, o sistema inteiro passou a receber Access denied na hora. A correção foi DROP USER 'app'@'localhost';. Antes de qualquer GRANT, confira quais contas existem.
The server requested authentication method unknown to the client
Desde o MySQL 8.0, contas novas usam o método caching_sha2_password. Clientes antigos (PHP anterior ao 7.4, conectores velhos) não o reconhecem. A solução certa é atualizar o cliente. Trocar a conta para mysql_native_password é paliativo: no MySQL 8.4 esse método vem desligado (só funciona com mysql_native_password=ON no [mysqld]) e a série 9.x o removeu.
Problemas comuns
ERROR 1045 (28000): Access denied for user
Senha errada ou origem diferente da cadastrada. Atenção: conectar em 127.0.0.1 usa TCP e conectar em localhost usa o socket; dependendo das contas existentes, cada um casa com uma linha diferente da tabela de usuários.
ERROR 1130: Host '203.0.113.50' is not allowed to connect
Não existe conta para aquele IP. Crie 'usuario'@'203.0.113.50', dê o GRANT e confira se o servidor escuta na rede (bind-address) e se o firewall libera a porta 3306 só para esse IP. Em hospedagem cPanel, use o acesso remoto ao MySQL pelo painel.
ERROR 1044: Access denied for user to database
O usuário entrou, mas não tem permissão naquele banco. Confira com SHOW GRANTS se o nome do banco no GRANT está certo (no cPanel, ele tem o prefixo da conta).