AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 33987
Accepted
RThomas
RThomas
Asked: 2013-02-02 10:08:55 +0800 CST2013-02-02 10:08:55 +0800 CST 2013-02-02 10:08:55 +0800 CST

Capturando data e hora de alteração no CDC do SQL Server

  • 772

Então, começamos a explorar o uso da captura de dados alterados em um de nossos bancos de dados de produção. Gostaríamos de saber a data e hora de cada alteração. Lendo passo a passo e tutoriais , etc., parece que a abordagem padrão é usar o LSN para se relacionar com a cdc.lsn_time_mappingtabela do sistema. Essa abordagem funciona, mas não é muito direta nem eficiente quando falamos de centenas de milhares de alterações por dia.

Em um ambiente de teste, fiz o seguinte ajuste nas tabelas de controle de alterações. Emiti uma ALTER TABLEinstrução para adicionar uma coluna ao final chamado [__ChangeDateTime]e tornei seu valor padrão GetDate(). A abordagem parece funcionar, o controle de alterações ainda funciona normalmente, as datas e horas estão sendo capturadas. Mas mexer nas tabelas do sistema me deixa um pouco nervoso.

Se este não é um campo do sistema que a Microsoft adicionou desde o início , eles devem ter seus motivos. Como eles optaram pela abordagem LSN para cdc.lsn_time_mapping, estou me preparando para problemas ao criar meu próprio hack dessa maneira?

ATUALIZAR:

Descoberto durante o teste que GetDate() às vezes não é preciso o suficiente para nossas necessidades - várias alterações compartilhando o mesmo tempo. Recomende o uso de sysdatetime() e datetime2 para mover o valor para o nanossegundo. Opção para 2008+ apenas obviamente.

sql-server-2008 change-data-capture
  • 5 5 respostas
  • 8953 Views

5 respostas

  • Voted
  1. Best Answer
    Jon Seigel
    2013-02-05T10:54:41+08:002013-02-05T10:54:41+08:00

    Lembre-se de que o CDC usa um agente de leitura de log para preencher a tabela de alterações. Por que isso é importante? Por esse mecanismo, as linhas aparecem nas tabelas de alteração de forma assíncrona com as alterações feitas nas tabelas base.

    Na verdade, existem 3 pontos de tempo diferentes que podem ser registrados, em ordem cronológica inversa:

    1. A hora em que a alteração foi entregue na mesa de alteração (que é o que você está registrando).
    2. A hora em que a transação que continha a alteração foi confirmada (usando cdc.lsn_time_mapping).
    3. A hora com a qual você preenche manualmente uma coluna na tabela base (usando uma restrição padrão, um acionador, etc.).

    Portanto, a primeira coisa é ter claro o que você deseja gravar. Normalmente, nos importaríamos com o número 2 ou com o número 3.

    Se o mecanismo de mapeamento LSN (nº 2) não estiver funcionando bem o suficiente para você, a única alternativa compatível é adicionar uma coluna à tabela base e preenchê-la você mesmo (nº 3).

    No que diz respeito à alteração das tabelas internas, por uma questão de política, acho melhor evitar hackear com as internas quando houver alternativas suportadas. A última coisa que você deseja é um importante sistema de produção caindo, precisando ligar para o suporte ao produto e ter o serviço negado por causa de algo assim. Não importa os problemas de potencialmente quebrar coisas (atualizações) ou ser quebrado porque foi inesperado (desligue o CDC e ligue-o novamente, conforme mencionado na outra resposta).

    • 8
  2. Gareth Orrill
    2016-03-10T14:17:10+08:002016-03-10T14:17:10+08:00

    Um exemplo prático:

    USE Database;
    GO
    
    DECLARE @from_lsn binary(10), @to_lsn binary(10)
    SET @from_lsn = sys.fn_cdc_get_min_lsn('schema_tablename')
    SET @to_lsn = sys.fn_cdc_get_max_lsn()
    
    SELECT
        sys.fn_cdc_map_lsn_to_time(__$start_lsn) AS 'Time'
        ,[Field1]
        ,[Field2]
        ,[Field3]
    FROM [cdc].[fn_cdc_get_all_changes_schema_tablename]
      (@from_lsn, @to_lsn, N'all');
    
    • 3
  3. Liam Confrey
    2013-02-02T12:31:35+08:002013-02-02T12:31:35+08:00

    A única ressalva que eu daria é que essas tabelas são descartadas automaticamente quando o CDC é desabilitado. A coluna não é recriada automaticamente quando você a reativa

    • 2
  4. bobt
    2022-09-21T12:59:22+08:002022-09-21T12:59:22+08:00

    Inspirado na resposta de Gareth, aqui está uma versão mais curta. Isso não usa, o DECLAREque é ótimo se você precisar criar um VIEW( DECLAREnão é permitido entrar VIEW)

    SELECT
        sys.fn_cdc_map_lsn_to_time(__$start_lsn) AS 'Time'
        , *
    FROM [cdc].[fn_cdc_get_all_changes_dbo_yourtablename
        (sys.fn_cdc_get_min_lsn('dbo_yourtablename')
        , sys.fn_cdc_get_max_lsn(), N'all')
    
    • 0
  5. Alberto Guerrero
    2022-10-12T12:35:55+08:002022-10-12T12:35:55+08:00

    Com base nas respostas anteriores, criei este script que examinará todas as tabelas CDC e exibirá o nome da tabela e a última atualização:

    DECLARE @tableName varchar(max)
    DECLARE @from_lsn binary(10)
    DECLARE @to_lsn binary(10) = sys.fn_cdc_get_max_lsn()
    DECLARE @results TABLE
    (
        [Table] varchar(max),
        [LastUpdated] datetime
    )
    
    -- Get list of change tables
    DECLARE cdc_tables_cursor CURSOR
    FOR SELECT
            [capture_instance]
        FROM cdc.change_tables;
    
    OPEN cdc_tables_cursor
    FETCH NEXT FROM cdc_tables_cursor INTO @tableName;
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Get Table Name / Last Updated
        SET @from_lsn = sys.fn_cdc_get_min_lsn(@tableName)
        DECLARE @sql nvarchar(max) = '
        SELECT
            top 1
            REPLACE(@tableName,''dbo_'','''') as [Table],
            sys.fn_cdc_map_lsn_to_time(__$start_lsn) AS ''Time''
        FROM [cdc].[fn_cdc_get_all_changes_'+@tableName+'](@from_lsn, @to_lsn, N''all update old'')
        order by 2 desc'
    
        -- Insert results of dynamic sql
        INSERT @results
        EXECUTE sp_executesql   
            @sql,  
            N'@tableName varchar(max), @from_lsn binary(10), @to_lsn binary(10)',  
            @tableName, @from_lsn, @to_lsn;
    
        FETCH NEXT FROM cdc_tables_cursor INTO @tableName
    END
    
    CLOSE cdc_tables_cursor;
    
    DEALLOCATE cdc_tables_cursor;
    
    -- List Tables/Last Updated
    SELECT 
        * 
    FROM @results
    order by 1
    
    • 0

relate perguntas

  • Melhores práticas para conectar bancos de dados que estão em diferentes regiões geográficas

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Quanto "Padding" coloco em meus índices?

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

  • Downgrade do SQL Server 2008 para 2005

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve