Entenda o strict mode do MySQL e MariaDB, como mudar o sql_mode no my.cnf ou só na sessão, e por que desligar tudo deve ser solução temporária.
O sql_mode é uma lista de regras que diz ao MySQL e ao MariaDB quão rigorosos eles devem ser com os dados. O "strict mode" é a regra STRICT_TRANS_TABLES (ou a STRICT_ALL_TABLES): com ela ligada, um valor inválido gera erro e a gravação é desfeita. Com ela desligada, o banco ajusta o valor por conta própria e só emite um aviso que quase ninguém lê.
O que muda com o strict mode ligado ou desligado
| Situação | Strict ligado | Strict desligado |
|---|---|---|
Texto em coluna numérica ('' ou 'abc') | Erro 1366 | Grava 0 |
| Texto maior que a coluna | Erro 1406 | Corta o texto |
| Coluna NOT NULL sem valor e sem padrão | Erro 1364 | Grava o valor "vazio" do tipo |
Data inválida ou 0000-00-00 | Erro 1292 | Grava data zerada |
O padrão de fábrica é estrito nos dois bancos:
- MySQL 8.4:
ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION - MariaDB (10.2.4 em diante):
STRICT_TRANS_TABLES, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION
Sistemas antigos, escritos para o MySQL 5.5 ou anterior, costumam quebrar com essas regras. O WHMCS, por exemplo, pede na documentação oficial que o strict mode esteja desligado.
Como ver o sql_mode atual
mysql -e "SELECT @@GLOBAL.sql_mode AS global, @@SESSION.sql_mode AS sessao\G"
O valor global vale para as conexões novas; o de sessão é o da sua conexão. Uma aplicação pode trocar o próprio modo ao conectar, então os dois podem ser diferentes.
Opção 1: mudar só na sessão da aplicação
É a forma mais segura de contornar um sistema antigo, porque o resto do servidor continua protegido. Logo depois de conectar, a aplicação roda:
SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION';
Em PHP com PDO, por exemplo:
$pdo->exec("SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'");
Muitos frameworks já têm uma opção para isso. No Laravel, por exemplo, é o item 'strict' da conexão em config/database.php.
Opção 2: mudar no servidor inteiro, de forma permanente
- Ache o arquivo de configuração certo.
Sistema Arquivo Ubuntu e Debian com MySQL /etc/mysql/mysql.conf.d/mysqld.cnfUbuntu e Debian com MariaDB /etc/mysql/mariadb.conf.d/50-server.cnfAlmaLinux, Rocky e servidores cPanel /etc/my.cnf(ou um arquivo em/etc/my.cnf.d/) - Faça uma cópia antes de editar:
cp -a /etc/my.cnf /etc/my.cnf.bak-$(date +%F) - Na seção
[mysqld], defina o modo. Se já existir uma linhasql_mode, altere-a em vez de criar outra. Para tirar só o strict e manter o resto do comportamento normal:
Para o WHMCS, a documentação oficial dele pede o valor vazio:[mysqld] sql_mode = "NO_ENGINE_SUBSTITUTION"sql_mode = "". - Reinicie o serviço:
systemctl restart mysql(MySQL no Ubuntu e Debian),systemctl restart mariadb(MariaDB) ou/scripts/restartsrv_mysqlem servidor cPanel. - Confira com o comando
SELECT @@GLOBAL.sql_modeda seção anterior.
Em servidor cPanel, o mesmo ajuste pode ser feito pelo WHM em SQL Services » Edit SQL Configuration, que tem o campo sql_mode e reinicia o serviço ao salvar.
SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION';. Vale para as conexões novas e se perde quando o serviço reinicia. No MySQL 8 ou mais novo, SET PERSIST faz a mesma coisa e grava o valor para sobreviver ao reinício; o MariaDB não tem SET PERSIST.Por que desligar o strict mode é só um paliativo
Sem o strict, o banco aceita o dado errado e "conserta" do jeito dele: um preço vazio vira 0, uma descrição longa é cortada no meio, uma data inválida vira 0000-00-00. Ninguém fica sabendo, porque o aviso não aparece para o usuário do sistema. O erro some, mas o dado ruim fica gravado e aparece meses depois, em relatório ou nota fiscal.
A correção de verdade fica na aplicação: enviar valores do tipo certo, dar valor padrão (DEFAULT) às colunas opcionais, usar NULL em vez de data zerada e escrever GROUP BY completo. Se puder, deixe o strict ligado no ambiente de desenvolvimento para encontrar esses pontos e desligue só na sessão do sistema que ainda não foi corrigido.
sql_mode inteiro também remove o NO_AUTO_CREATE_USER. A partir daí, um GRANT para uma conta que não existe cria essa conta sem senha, sem avisar. Se precisar desligar o strict no MariaDB, prefira manter essa regra: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION".Problemas comuns
O MySQL não inicia depois que mudei o sql_mode
Algum valor da lista não existe na sua versão. O caso clássico é copiar um my.cnf do MySQL 5.7 com NO_AUTO_CREATE_USER: esse modo foi removido no MySQL 8.0 e impede o servidor de subir. Veja o motivo no log de erros, remova o valor inválido e reinicie.
Mudei o arquivo, mas o valor continua o mesmo
Outro arquivo lido depois está sobrescrevendo o seu. Para ver o que o servidor realmente recebe de todos os arquivos, rode my_print_defaults mysqld (no MariaDB, my_print_defaults --mysqld). No MySQL 8, confira também se alguém usou SET PERSIST: SELECT * FROM performance_schema.persisted_variables;
Expression #1 of SELECT list is not in GROUP BY clause ... sql_mode=only_full_group_by
Esse erro (1055) não é do strict mode, é do ONLY_FULL_GROUP_BY, ativo por padrão no MySQL 8. Se for preciso contornar, tire só esse item da lista em vez de zerar o sql_mode.