Bacpac e dacpac: semelhanças e diferenças
Bacpac e dacpac são dois formatos de pacote do SQL Server que geram muita confusão entre desenvolvedores e administradores de banco de dados. A explicação mais repetida em fóruns diz que o bacpac contém dados e o dacpac não contém.
Essa afirmação, porém, é incompleta e leva a decisões erradas de arquitetura. Neste artigo, você vai ver o que cada formato realmente é, o que carrega internamente, quais restrições impõe e em que cenários deve ser adotado.
Data-tier application, a base de bacpac e dacpac
Antes de comparar bacpac e dacpac, é necessário entender o conceito que dá origem aos dois. Uma data-tier application, ou DAC, é uma entidade lógica que define todos os objetos de SQL Server associados ao banco de dados de um usuário.
Esses objetos incluem tabelas, views e também objetos de instância, como logins. Assim, a DAC funciona como uma unidade autocontida que representa o modelo inteiro do banco.
Além disso, a DAC é portável tanto em pacotes .dacpac quanto em pacotes .bacpac. Os dois formatos seguem a especificação Open Packaging Conventions.
Na prática, ambos são arquivos compactados com uma estrutura interna de partes XML. O formato .bacpac estende o formato .dacpac para incluir todos os dados das tabelas além do esquema.
É justamente aí que mora a raiz técnica da confusão entre bacpac e dacpac. Afinal, se um estende o outro, a fronteira entre eles não está apenas na presença de dados.
Bacpac e a portabilidade orientada ao Azure SQL Database
A maioria dos profissionais conhece o bacpac pelas operações de exportação e importação. Elas permitem mover objetos de banco de dados e seus dados entre diferentes versões do SQL.
Esse movimento inclui inclusive o caminho de volta. Ou seja, é possível sair do Azure para o SQL Server ou migrar para versões mais antigas do SQL Server.
Esse comportamento contrasta com os backups nativos, os arquivos BAK. Eles só podem ser restaurados em versões iguais ou superiores à versão de origem.
A funcionalidade de importação e exportação está disponível em várias ferramentas. Você encontra essas operações no SQL Server Management Studio, no Visual Studio Code, no Portal do Azure e na linha de comando com o SqlPackage.
O que existe dentro de um bacpac
Um arquivo bacpac contém a definição dos objetos do banco de dados e uma cópia de todos os dados presentes nas tabelas. Se você trocar a extensão do arquivo para .zip e extrair o conteúdo, poderá inspecionar a estrutura interna diretamente.
O conteúdo inclui um arquivo model.xml, que define a estrutura dos objetos. Também traz uma pasta de dados com arquivos no formato BCP.
A exportação grava esses arquivos BCP. Em seguida, na importação, uma operação de bulk insert popula o banco de destino com esse conteúdo.
Vale ainda um alerta de segurança relevante. Os dados contidos em arquivos .bacpac e .dacpac ficam compactados, mas não criptografados.
Por isso, a proteção do artefato é responsabilidade de quem o armazena e transporta. Trate bacpac e dacpac com dados como você trataria uma cópia do próprio banco.
O custo de desempenho da portabilidade
O bacpac é um formato flexível para mover dados. Contudo, existe um custo claro de velocidade para alcançar esse nível de portabilidade.
Uma exportação ou importação de bacpac costuma ser mais lenta do que um backup ou restore nativo do SQL Server. A razão é conceitual.
As operações de bacpac extraem e recriam logicamente o esquema e os dados das tabelas. Enquanto isso, backup e restore nativos copiam páginas de banco e registros de log no formato otimizado do SQL Server.
Existe também uma diferença de responsabilidade operacional. No Azure SQL Database, o próprio serviço gerencia os backups em nível de arquivo, enquanto no SQL Server essa gestão continua com você ou com o seu DBA.
Por essa razão, a documentação é explícita ao afirmar que arquivos BACPAC não se destinam a operações de backup e restore.
A restrição de superfície que separa bacpac e dacpac
Este é o ponto mais determinante do formato e o que realmente separa bacpac e dacpac. A portabilidade de dados via bacpac existe para garantir que o arquivo possa ser importado no Azure SQL Database.
Como consequência direta, um bacpac só pode conter objetos utilizáveis no Azure SQL Database. Logo, você não consegue criar um bacpac a partir de um banco que contenha objetos sem suporte nessa plataforma.
Entre esses objetos estão logins do Windows, colunas com FILESTREAM e elementos de SQL CLR. Nesse caso, a exportação falha na validação.
Ainda assim, nem tudo está perdido quando um banco não exporta para bacpac. Uma alternativa é criar uma cópia do banco e remover os objetos sem suporte antes da exportação.
No entanto, se o destino não é o Azure SQL Database, essas limitações podem ser irrelevantes ou até indesejadas. É exatamente nesse ponto que o dacpac se torna a resposta correta.
Dacpac como artefato de implantação
A maioria dos profissionais associa o dacpac exclusivamente a implantações de banco de dados, e essa associação faz sentido. Quando você compila um SQL project, o resultado da compilação é um arquivo dacpac.
Esse artefato é a base de uma estratégia de gerenciamento do ciclo de vida do banco e de DevOps. Por outro lado, muita gente desconhece que um dacpac também pode ser extraído diretamente de um banco existente.
Um dacpac contém a definição de esquema, ou modelo, do banco de dados. A partir dele, a ferramenta que o consome gera um plano de implantação.
Esse plano pode virar um script T-SQL, por meio da ação script. Também pode ser aplicado diretamente no destino, por meio da ação publish.
Para um banco novo, o plano cria todos os objetos do zero. Já para um banco existente, o plano determina como modificar os objetos atuais para que correspondam à definição do dacpac.
Propriedades que moldam o plano de implantação
As operações de publish e script expõem um conjunto grande de propriedades. Com elas, você customiza e analisa o plano gerado.
Por exemplo, a propriedade GenerateSmartDefaults customiza o plano. Ela fornece automaticamente um valor padrão ao adicionar uma coluna que não aceita nulos em uma tabela que já tem registros.
Já a propriedade AllowTableRecreation analisa o plano. Ela verifica se a implantação vai recriar a tabela e copiar os dados para um novo local antes de permitir ou cancelar a execução.
Vale destacar que a recriação de tabela preserva os dados. Mesmo assim, ela pode ter impacto significativo de desempenho em tabelas grandes.
Outra propriedade essencial em produção é BlockOnPossibleDataLoss, que por padrão vale verdadeiro. Ela encerra a operação na validação de esquema caso as mudanças possam provocar perda de dados.
Essa proteção cobre inclusive redução de precisão e mudanças de tipo que exijam conversão. Graças a esse dinamismo, o mesmo dacpac atende desde aplicações simples até cenários de SaaS multi-tenant com milhares de bancos.
As opções de extração
A criação de um dacpac pela operação de extract inclui, por padrão, todas as definições de objeto do banco. Esses objetos podem ser específicos de qualquer plataforma suportada, como SQL Server, Azure SQL Database ou SQL database no Fabric.
Além disso, você pode modificar a extração de três formas relevantes. Primeiro, é possível excluir do pacote os elementos de escopo de servidor.
Em segundo lugar, você pode incluir os dados das tabelas diretamente dentro do dacpac, de forma parecida com o que um bacpac faz. Por fim, é possível extrair os dados para o Azure Blob Storage no formato Parquet, mantendo apenas o esquema no arquivo local.
Com isso, você consegue portabilidade em cenários nos quais a exigência de compatibilidade com o Azure SQL Database seria um impedimento. Na prática, aproveitar essas capacidades mais avançadas geralmente exige a CLI do SqlPackage.
Portabilidade com dacpac quando o bacpac não serve
O roteiro a seguir move uma cópia de banco entre servidores com os comandos extract e publish do SqlPackage. O processo é análogo ao par export e import do bacpac, com uma diferença importante.
Nesse caso, não há garantia de que o conteúdo gerado esteja pronto para importação no Azure SQL Database. Em compensação, o pacote aceita objetos que o bacpac rejeitaria.
Na etapa de extração, adicione a propriedade ExtractAllTableData. Opcionalmente, use também ExtractReferencedServerScopedElements com valor falso para gerar um dacpac com a cópia dos dados de origem.
# Extrai esquema e dados para um dacpac
sqlpackage /action:extract \
/sourceconnectionstring:"<source-connection-string>" \
/targetfile:"C:\extracted.dacpac" \
/p:ExtractAllTableData=true \
/p:ExtractReferencedServerScopedElements=false
Na publicação, o SqlPackage popula por padrão o banco de destino com os dados contidos no dacpac. Ainda assim, algumas propriedades podem ser necessárias para ajustar o comportamento.
A propriedade AllowIncompatiblePlatform com valor verdadeiro permite a implantação entre tipos diferentes de banco. Já ExcludeObjectTypes com o valor Logins;Users ignora os logins do Windows quando o destino é o Azure SQL Database.
# Publica o dacpac no servidor de destino
sqlpackage /action:publish \
/sourcefile:"C:\extracted.dacpac" \
/targetconnectionstring:"<target-connection-string>" \
/p:AllowIncompatiblePlatform=true \
/p:ExcludeObjectTypes=Logins;Users
Se você ainda não tem um servidor de testes, vale subir um SQL Server local seguindo o guia de SQL Server no Docker. Assim, você pratica extract e publish sem tocar em produção.
Autenticação no SqlPackage
O SqlPackage funciona com autenticação integrada, autenticação SQL e métodos do Microsoft Entra ID. Dessa forma, a string de conexão pode incluir Authentication=Active Directory Interactive para autenticar pelo navegador.
Também é possível usar Authentication=Active Directory Default. Nesse caso, a ferramenta aproveita a sessão do terminal depois da execução prévia do comando az login.
Para entender melhor cada parte dessas strings, consulte o artigo que descomplica as connection strings do SQL Server.
Considerações operacionais sobre bacpac e dacpac
Existem detalhes de execução que não aparecem na comparação conceitual entre bacpac e dacpac. Mesmo assim, são eles que definem o sucesso de uma migração real.
Para que uma exportação seja transacionalmente consistente, garanta que não haja escrita durante o processo. Outra opção é exportar a partir de uma cópia transacionalmente consistente do banco.
Ao exportar para blob storage, o tamanho máximo de um arquivo BACPAC é de 200 GB. Para arquivar um volume maior, exporte para armazenamento local com o SqlPackage.
Além disso, o serviço pode cancelar uma exportação que ultrapasse vinte horas. Por isso, existem três medidas diretas para melhorar o desempenho.
A primeira é aumentar temporariamente o tamanho de computação. Em seguida, interrompa toda atividade de leitura e escrita durante a operação.
Por último, e talvez a medida mais negligenciada, use um índice clusterizado com valores não nulos em todas as tabelas grandes. Sem ele, uma exportação pode falhar se passar de seis a doze horas, porque o serviço precisa varrer a tabela inteira.
Em bancos hospedados no Azure, extract e publish com arquivos Parquet costumam superar import e export com .bacpac em muitos cenários. Portanto, vale testar essa alternativa em bancos grandes.
Recapitulando as operações com bacpac e dacpac
A leitura correta das quatro operações do SqlPackage resolve praticamente toda a confusão sobre bacpac e dacpac. Na tabela abaixo, você vê um resumo de cada uma.
| Operação | Gera ou consome | Conteúdo | Uso principal |
|---|---|---|---|
| Export | Gera bacpac | Esquema e dados | Mover ou arquivar quando há interação com o Azure SQL Database |
| Extract | Gera dacpac | Esquema | Implantação, comparação e versionamento |
| Extract com dados | Gera dacpac | Esquema e dados | Mover ou arquivar sem a restrição de superfície do Azure |
| Publish | Consome dacpac | Atualização incremental | Atualizar ou criar o banco de destino |
A operação de export cria um bacpac com o modelo de esquema e os dados. Ela serve principalmente para mover ou arquivar o conteúdo lógico de um banco quando existe interação com o Azure SQL Database.
Já a operação de extract cria um dacpac com o modelo de esquema, incluindo tabelas, views, procedures e demais objetos. Ela serve para implantação, comparação e versionamento.
A operação de extract com dados de tabela cria um dacpac com esquema e dados. Ou seja, ela move ou arquiva o conteúdo lógico sem a restrição de superfície do Azure SQL Database.
Por fim, a operação de publish consome um dacpac e atualiza incrementalmente o esquema de destino. Se o banco não existir no servidor, o publish o cria.
Os arquivos bacpac são fortemente integrados ao Azure SQL Database, com importação e exportação no Portal do Azure, na CLI do Azure e no Azure PowerShell. Enquanto isso, bacpac e dacpac têm suporte no SSMS, no Visual Studio Code e na CLI do SqlPackage.
Quando usar bacpac e dacpac
A descrição popular de que o bacpac carrega dados e o dacpac não carrega descreve apenas o comportamento padrão de cada formato. Ela não descreve a natureza de cada um.
A diferença estruturante entre bacpac e dacpac é outra. Por padrão, o bacpac contém dados e exige objetos compatíveis com o Azure SQL Database, enquanto o dacpac é otimizado para implantações e tem a opção de incluir dados.
Assim, a decisão prática decorre disso de forma quase automática. Quando o destino é o Azure SQL Database e o objetivo é mover ou arquivar o conteúdo lógico completo, o bacpac é o caminho natural.
Por outro lado, o dacpac é a escolha correta em outros objetivos. Entre eles estão versionar esquema, comparar modelos, integrar o banco a um pipeline de entrega contínua ou mover um banco com objetos fora da superfície do Azure.
Conclusão
Entender a diferença entre bacpac e dacpac deixa de ser trivialidade acadêmica no momento em que uma migração de produção falha. Basta um login do Windows ou um tipo CLR para a validação de esquema barrar todo o processo.
Portanto, escolha o formato pelo destino e pelo objetivo, e não pela ideia simplificada de que só um deles carrega dados. Com essa clareza, bacpac e dacpac passam a ser ferramentas complementares no seu dia a dia.
FAQ
O dacpac realmente pode conter dados?
Sim. Por padrão ele não contém, mas você pode incluir dados de tabelas de usuário na extração com as propriedades ExtractAllTableData ou TableData.
Posso usar bacpac como estratégia de backup?
Não é a finalidade do formato. A documentação afirma que arquivos BACPAC não se destinam a backup e restore, e o Azure já cria backups automáticos para cada banco de usuário.
Por que meu banco não exporta para bacpac?
Provavelmente ele contém objetos fora da superfície do Azure SQL Database. Logins do Windows, colunas FILESTREAM e elementos SQL CLR são os casos mais comuns.
Como mover um banco que não pode virar bacpac?
Use extract com ExtractAllTableData=true para gerar um dacpac com dados. Depois, publique com AllowIncompatiblePlatform=true quando houver mudança de plataforma.
Os arquivos bacpac e dacpac são criptografados?
Não. Os dados ficam compactados, mas não criptografados, então o arquivo precisa de proteção no armazenamento e no transporte.
Como inspecionar o conteúdo de um dacpac ou bacpac?
Basta trocar a extensão para .zip e descompactar. O resultado inclui arquivos como DacMetadata.xml, Origin.xml e model.xml, além da pasta de dados no caso do bacpac.
Existe alternativa mais rápida para bancos grandes no Azure?
Sim. Extract e publish com dados em Parquet no Azure Blob Storage costumam superar import e export em muitos cenários.