dbSlice ou MySQL Workbench?
O MySQL Workbench tem um assistente de migração gratuito que lê o SQL Server, e para uma migração única vale testar. O dbSlice é para equipes que precisam de execuções repetidas (Upsert ou só linhas novas toda noite até a virada), de uma diferença chave a chave e conferências na tela antes de gravar, de mascaramento para cópias de teste, e da mesma ferramenta para outros pares. Nenhum dos dois converte procedures ou triggers em T-SQL para MySQL; planeje essa parte à parte.
Comparando ferramentas? Veja as melhores ferramentas para migrar SQL Server para MySQL →

O que o dbSlice faz
- Lê o SQL Server em lotes pequenos, para o banco em uso continuar atendendo os usuários.
- Grava no MySQL e no MariaDB. As cargas iniciais e completas ficam mais rápidas quando o seu DBA liga o
local_infileno servidor e você o permite na conexão; sem isso elas funcionam do mesmo jeito, só mais devagar. - Mostra o DDL do destino. Se a tabela não existe no MySQL, o dbSlice para antes de gravar e mostra um
CREATE TABLEtraduzido do SQL Server para o seu DBA revisar e rodar. Ele não cria objetos nos seus bancos por conta própria. - Mantém os seus ids. As linhas chegam com os valores originais de
IDENTITY. O InnoDB do MySQL avança oAUTO_INCREMENTda tabela para depois do maior id inserido, então as linhas novas criadas pela aplicação depois da cópia não colidem.
Detalhes do SQL Server para planejar
| SQL Server | Sugerido no MySQL | Confira |
|---|---|---|
datetimeoffset | DATETIME(6) | O offset não é mantido. Converta para UTC num SELECT de origem se o fuso importa |
datetime2(7) | DATETIME(6) | O MySQL guarda microssegundos; o 7º dígito é descartado |
uniqueidentifier | CHAR(36) | Guardado como texto; serve para joins, ocupa mais que BINARY(16) |
nvarchar(max), varchar acima de 16.383 | LONGTEXT | Esperado; indexe só um prefixo se precisar |
bit | TINYINT(1) | O booleano usual do MySQL |
varbinary, image | LONGBLOB | Esperado |
tinyint, smallint, int, bigint | SMALLINT, SMALLINT, INT, BIGINT | Mesmas faixas; o tinyint ganha um tipo maior |
decimal(p,s), money, smallmoney | DECIMAL(p,s) | money chega como DECIMAL(19,4) |
float, real | DOUBLE | — |
char(n), nchar(n) | VARCHAR(n) | O preenchimento com espaços no fim não é mantido |
time(7) | TIME | O TIME do MySQL guarda segundos inteiros; troque para TIME(6) se precisar das frações |
text, ntext, xml | LONGTEXT | O XML chega como texto simples |
timestamp / rowversion | LONGBLOB | Copiado como bytes. São as versões de linha do SQL Server, e a maioria dos destinos não precisa delas: você pode deixar a coluna fora da cópia |
sql_variant, hierarchyid, geography, geometry | LONGTEXT | Converta num SELECT de origem (por exemplo .ToString() ou CAST) se precisar do valor |
Duas configurações do lado do MySQL:
- Conjunto de caracteres. Crie o banco do MySQL (ou as tabelas) com
utf8mb4. Com um padrãolatin1antigo, os caracteres fora dele falham ou viram?. - Maiúsculas nos nomes de tabela. No Linux, os nomes de tabela do MySQL diferenciam maiúsculas por padrão. Escolha uma convenção (normalmente minúsculas) no
CREATE TABLEe mantenha; o dbSlice casa as colunas pelo nome sem diferenciar maiúsculas.
Migrar procedures e triggers em T-SQL para MySQL
O dbSlice move os dados; o código é uma frente à parte. A maioria das reescritas de T-SQL se resume à mesma lista:
| T-SQL (SQL Server) | MySQL |
|---|---|
SELECT TOP 10 … | SELECT … LIMIT 10 |
ISNULL(a, b) | IFNULL(a, b) ou COALESCE(a, b) |
GETDATE(), SYSDATETIME() | NOW(), NOW(6) |
IDENTITY(1,1) | AUTO_INCREMENT |
@variable declarada com DECLARE | DECLARE dentro da procedure, ou @user_variable |
Tabelas #temp | CREATE TEMPORARY TABLE |
TRY … CATCH | DECLARE … HANDLER FOR SQLEXCEPTION |
+ para juntar strings | CONCAT(a, b) |
[colchetes] em volta dos nomes | `crases` |
Parâmetros OUTPUT | Parâmetros OUT |
Triggers com as tabelas inserted / deleted | Triggers de linha com NEW / OLD, um por evento |
MERGE | INSERT … ON DUPLICATE KEY UPDATE |
Reescreva e teste o código contra uma cópia dos dados primeiro: carregue as tabelas com o dbSlice, rode as novas procedures no MySQL e compare os resultados com o SQL Server antes da virada.
Erros comuns e o que significam
Incorrect string value: '\xF0\x9F…' for column …— a tabela do MySQL não está emutf8mb4. Recrie a tabela (ou o banco) comutf8mb4, como acima.Data too long for column …— a coluna de destino é menor que os dados, muitas vezes umVARCHARdeclarado à mão. Aumente o tamanho ou troque paraLONGTEXT.Row size too large (> 8126)— muitas colunasVARCHARlargas numa linha InnoDB. Transforme as maiores emTEXTouLONGTEXTnoCREATE TABLE.Loading local data is disabled— olocal_infileestá desligado no servidor ou na conexão. A carga roda sem ele, só mais devagar; fale com o seu DBA se quiser o caminho mais rápido.Duplicate entry … for key 'PRIMARY'— a linha já está no MySQL. Use Upsert ou Insert new em vez de Initial load nas execuções repetidas.
Passo a passo
Antes de começar
- Liste o que vai mudar de lugar: tabelas, contagens de linhas e as maiores tabelas primeiro. Tabelas muito grandes ou legadas têm opções próprias: veja copying huge legacy tables (em inglês).
- Decida o padrão: uma cópia num fim de semana, ou uma carga inicial mais uma sincronia toda noite até a virada. Veja initial load + scheduled catch-up or CDC? (em inglês)
- Combine as conferências que liberam a troca: six layers of migration evidence (em inglês).
- Conecte no SQL Server e no MySQL ou MariaDB.
- Escolha a tabela de origem ou um SELECT, e a tabela de destino.
- Escolha a coluna-chave usada para casar as linhas.
- Escolha o modo: Initial load na primeira vez, depois Upsert ou Insert new.
- Confira antes de gravar: o Record Diff compara as chaves dos dois lados.
- Rode, ou salve como job e agende pela CLI. O Replicador copia uma lista de tabelas numa execução, as pais antes das filhas.
Mantenha os dois sincronizados até a virada
Agende um job Upsert toda noite. Com uma coluna que só cresce (um updated_at ou o id IDENTITY), cada execução lê só as linhas acima do último valor visto. Exclusões no SQL Server não são detectadas pelas execuções incrementais; por isso, planeje uma comparação completa ou uma recarga antes da troca.
Perguntas frequentes
O dbSlice converte stored procedures ou triggers em T-SQL?
Não. Ele move dados. Reescreva procedures e triggers para o MySQL à parte, e use o dbSlice para os dados e a sincronia até a virada.
O SQL Server pode continuar rodando durante a migração?
Sim. O dbSlice lê em lotes pequenos, e execuções noturnas Upsert ou só de linhas novas mantêm o MySQL perto do SQL Server até você trocar.
Ele cria as tabelas no MySQL?
Não por padrão. Ele para antes de gravar e mostra um CREATE TABLE para o seu DBA revisar e rodar.
MySQL ou MariaDB?
Os dois. O dbSlice conecta em qualquer um deles sem nada extra para instalar.
Posso testar antes de comprar?
Sim. A versão gratuita da Microsoft Store não precisa de chave de licença; gravar num banco de destino exige uma licença Desktop ou Server.
Existe ferramenta gratuita para migrar SQL Server para MySQL?
O assistente de migração do MySQL Workbench é gratuito e faz uma cópia única de esquema e dados. A versão gratuita do dbSlice na Microsoft Store não precisa de chave de licença; gravar no MySQL exige uma licença Desktop ou Server.
Quanto tempo leva uma migração de SQL Server para MySQL?
Depende das linhas, da largura das linhas, da rede e do servidor MySQL. Meça uma tabela grande num ensaio e dimensione o resto a partir dela; veja how to read a sync speed number (em inglês).
Também serve para
SQL Server para PostgreSQL (guia de sincronia), Oracle, Firebird, SQLite ou InterSystems IRIS, e MySQL de volta para o SQL Server.
Vai mover dados no outro sentido? MySQL para SQL Server.