MySQL gerenciado
O MySQL gerenciado é um banco MySQL 8.4 LTS que a plataforma cria, atualiza, monitora e copia para você. Ele é um nó do grafo do ambiente, como uma aplicação ou um volume: você o adiciona no canvas (ou no coda.yaml), liga as aplicações a ele e usa as variáveis que ele publica.
O banco usa replicação síncrona: com 3 nós, toda transação confirmada já está nos três. Isso traz algumas restrições que valem desde o primeiro nó, para que a passagem de 1 para 3 nós nunca quebre sua aplicação. Leia a seção Restrições antes de migrar uma aplicação existente.
Criar o banco
No canvas do ambiente, adicione um MySQL e escolha:
| Campo | Descrição |
|---|---|
| Versão | 8 (MySQL 8.4 LTS). Não muda depois de aplicada. |
| Tamanho | CPU, memória e disco padrão (db-s1 a db-l1). |
| Instâncias | 1 ou 3. Com 3, o banco tem alta disponibilidade e um endereço de leitura. Dois nós não são aceitos. O máximo depende do plano. |
| Disco (GiB) | Só aumenta. |
| PITR | Recuperação a um instante (ligada por padrão). |
| Janela de manutenção | Quando as atualizações de versão menor podem ser aplicadas. |
| Agenda e retenção de backup | Horário do backup diário e por quantos dias guardá-lo (o teto depende do plano). |
O mesmo banco no coda.yaml:
services:
db:
kind: mysql
config:
engineMajor: "8"
size: db-s2
instances: 3
storageGiB: 20
pitr: true
api:
type: web
port: 8080
connects:
- db
variables:
DATABASE_URL: ${{ db.DATABASE_URL }}
O painel do nó mostra a pegada do banco: o tamanho escolhido vezes o número de instâncias e, separados, os componentes da plataforma (proxy, coleta de métricas e de logs binários). A pegada é o que conta nas quotas de serviços de dados do plano; veja Planos, recursos e limites.
Conectar a aplicação
Ligue a aplicação ao banco com uma aresta de rede (porta 3306) e use as variáveis do nó. O banco só é alcançável pelas aplicações ligadas a ele, dentro do ambiente.
| Variável | Conteúdo |
|---|---|
DATABASE_URL, MYSQL_URL | mysql://app:<senha>@<nó>:3306/app?ssl-mode=REQUIRED (segredo) |
DATABASE_READONLY_URL | Mesmo formato, apontando para as réplicas de leitura. Só existe com 3 instâncias. (segredo) |
HOST, PORT | Nome do nó e 3306 |
DATABASE, USER | app |
PASSWORD | Senha do usuário app (segredo) |
- TLS é obrigatório. O servidor recusa conexão sem TLS. Use
ssl-mode=REQUIRED(ou o equivalente do seu driver:sslmode,ssl: true,MYSQL_ATTR_SSL_CA). - A senha é gerada pela plataforma e guardada no cofre da organização. Para trocá-la, use Rotacionar credencial no painel do nó: a rotação entra no rascunho, e as aplicações que usam as variáveis são reiniciadas ao aplicar.
- O usuário
apptem todos os privilégios no bancoapp, mas nenhum privilégio global. Crie quantas tabelas, views, procedures e triggers quiser dentro deapp.
Restrições
Valem com 1 ou 3 instâncias, porque o servidor roda em modo estrito (pxc_strict_mode=ENFORCING) desde o primeiro nó.
| Restrição | O que acontece | O que fazer |
|---|---|---|
| Só InnoDB | Tabelas MyISAM, MEMORY ou ARCHIVE não são replicadas e a escrita nelas é recusada. | Crie tabelas com ENGINE=InnoDB (o padrão) e converta as antigas com ALTER TABLE t ENGINE=InnoDB. |
| Chave primária obrigatória para escrever | INSERT, UPDATE ou DELETE numa tabela sem chave primária falha (erro 3750). | Toda tabela precisa de PRIMARY KEY. Numa tabela sem chave natural, acrescente id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY. |
Sem LOCK TABLES e GET_LOCK entre nós | Travas explícitas valem só no nó em que foram pedidas; com 3 nós, não protegem nada. | Use transações com SELECT ... FOR UPDATE ou uma coluna de versão (bloqueio otimista). |
| Transações grandes limitadas | Uma transação que altera mais dados que o limite de replicação (wsrep_max_ws_size) é recusada. | Divida cargas e DELETE/UPDATE em massa em lotes (por exemplo, 1.000 a 10.000 linhas por transação). |
| Sem transações XA | XA START/XA COMMIT não são suportados. | Use transações locais ou um padrão de saga na aplicação. |
| Sem privilégios globais | FILE, SUPER, LOAD DATA LOCAL INFILE e SELECT ... INTO OUTFILE não estão disponíveis. | Importe e exporte pela conexão normal (INSERT em lotes, mysqldump/mysql pela aplicação). |
Com 3 instâncias, um conflito de escrita entre nós aparece como deadlock (erro 1213) no COMMIT. Trate-o como qualquer deadlock: repita a transação.
WordPress
-
O núcleo do WordPress cria as tabelas
wp_*em InnoDB e com chave primária; ele funciona como está. -
Plugins antigos às vezes criam tabelas sem chave primária ou em MyISAM. O sintoma é um erro de escrita só nas telas do plugin. Para achar essas tabelas:
SELECT t.table_name, t.engineFROM information_schema.tables tLEFT JOIN information_schema.table_constraints cON c.table_schema = t.table_schema AND c.table_name = t.table_name AND c.constraint_type = 'PRIMARY KEY'WHERE t.table_schema = 'app' AND (c.constraint_name IS NULL OR t.engine <> 'InnoDB');Corrija com
ALTER TABLE wp_plugin_x ENGINE=InnoDB;eALTER TABLE wp_plugin_x ADD COLUMN id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY FIRST;, ou troque o plugin. -
Plugins de backup que usam
SELECT ... INTO OUTFILEouLOCK TABLESnão funcionam. Use os backups da plataforma. -
Em
wp-config.php, definaDB_NAME,DB_USER,DB_PASSWORDeDB_HOSTa partir das variáveis do nó e ligue o TLS comdefine('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL);.
Laravel
-
Use sempre
$table->id();(ou outra chave primária) nas migrations, inclusive nas tabelas pivô e nas tabelas de pacotes que você publica. Uma tabela pivô só com duas chaves estrangeiras precisa de$table->primary(['a_id', 'b_id']);. -
Não defina
$table->engine = 'MyISAM';. Deixe o padrão (InnoDB) ou declare'engine' => 'InnoDB'emconfig/database.php. -
Troque
DB::unprepared('LOCK TABLES ...')eDB::select('SELECT GET_LOCK(...)')por transações comlockForUpdate():DB::transaction(function () use ($id) {$conta = Conta::whereKey($id)->lockForUpdate()->first();$conta->saldo -= 100;$conta->save();}, attempts: 3); // repete em caso de deadlock -
Use
chunkById()em atualizações em massa, para não estourar o limite de tamanho de transação. -
Em
config/database.php, passe o TLS com'options' => [PDO::MYSQL_ATTR_SSL_CA => ...]ou useDB_URLcomssl-mode=REQUIRED.
Backups, PITR e clone
- Backup diário automático na agenda do nó, guardado fora do cluster, no armazenamento da sua organização (nenhuma outra organização o alcança), pelo número de dias do nó. Você também pode pedir um backup sob demanda na aba Backups.
- PITR: com o campo PITR ligado, os logs binários são enviados a cada minuto. Você pode restaurar o banco a qualquer instante entre o backup mais antigo retido e o último envio.
- Restaurar (de um backup ou de um instante) e clonar sempre criam um nó novo ao lado do original, pelo rascunho do ambiente; o original nunca é sobrescrito. O nó novo recebe credenciais novas. Depois de conferir os dados, aponte as aplicações para ele e remova o antigo.
- O clone de MySQL não tem mascaramento de dados nesta versão.
- Remover o banco exige o papel Admin e confirmação. A plataforma faz um backup final antes de apagar e o guarda pelo prazo do plano.
A plataforma também restaura uma cópia dos backups toda semana, num ambiente isolado, para verificar que eles funcionam.
O que ainda não está disponível
- Importar um dump (
.sql) pelo portal chega com a fase 65 do roadmap. Até lá, importe pela própria aplicação (um job que rodamysqlcontraDATABASE_URL), respeitando as restrições. - Acesso ao banco de fora do ambiente (o acesso público TCP ainda não cobre o MySQL) e console de dados no portal.
- Outras versões do MySQL (só 8.4 LTS) e upgrade de versão maior.