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 / 59117
Accepted
Aasim Abdullah
Aasim Abdullah
Asked: 2014-02-19 06:02:39 +0800 CST2014-02-19 06:02:39 +0800 CST 2014-02-19 06:02:39 +0800 CST

SQL Server 2014 na memória OLTP - coleta de lixo na reversão da transação

  • 772

No SQL Server 2014, na memória OLTP, o que acontece se uma transação for revertida e a versão recém-criada da linha não for mais necessária. É dever do coletor de lixo remover até mesmo esse tipo de linha ou esse lixo será coletado em tempo de execução na reversão da transação?

sql-server in-memory-database
  • 1 1 respostas
  • 962 Views

1 respostas

  • Voted
  1. Best Answer
    Martin Smith
    2014-02-19T11:50:01+08:002014-02-19T11:50:01+08:00

    Meu entendimento do artigo SIGMOD Hekaton: SQL Server's Memory-Optimized OLTP Engine é que ele é tratado da mesma forma que outros tipos de lixo.

    Algumas seções relevantes são

    6.2.3 Reversão de Transação

    As transações podem ser revertidas a pedido do usuário ou devido a falhas no processamento de confirmação. A reversão é obtida invalidando todas as versões criadas pela transação e limpando o campo de registro de data e hora final de todas as versões excluídas pela transação. Se houver outras transações dependentes do resultado da transação revertida, elas serão notificadas. Novamente, o conjunto de gravação da transação é usado para executar essa operação com muita eficiência.

    Observe que diz invalidado , não coletado como lixo.

    Veja também a seção Coleta de Lixo (grifo meu)

    8.1.1 Correção do GC

    Primeiro, deve-se tomar cuidado para identificar quais versões podem ser lixo. Versões de lixo potenciais podem ser criadas por um dos dois processos. Primeiro, uma versão torna-se lixo se a) foi excluída (por meio de DELETE explícito ou por meio de uma operação UPDATE) por uma transação confirmada e b) a versão não pode ser lida ou de outra forma executada por qualquer transação no sistema. Uma segunda maneira, menos comum, de as versões se tornarem lixo é se elas foram criadas por uma transação que subsequentemente reverte. A primeira e mais importante propriedade do GC é que ele determina corretamente quais versões são realmente lixo. A visibilidade de uma versão é determinada por seus timestamps de início e término. Qualquer versão cujo timestamp final seja menor que a transação ativa mais antiga atual no sistema não é visível para nenhuma transação e pode ser descartada com segurança. Um encadeamento GC verifica periodicamente o mapa de transação global para determinar o carimbo de data/hora inicial da transação ativa mais antiga no sistema. Quando o processo de GC é notificado de que deve iniciar a coleta, as transações confirmadas ou abortadas desde o último ciclo de GC são ordenadas por seus timestamps finais.

    Mas, na prática, parece que o lixo das reversões é dispensado mais rapidamente do que dos commits, então talvez o encadeamento abortado limpe seu próprio lixo pelo menos algumas vezes.

    Para ver isso, criei o seguinte proc (em um banco de dados com otimização de memória)

    CREATE PROC GetStats
    AS
    SELECT *
    FROM   sys.dm_db_xtp_table_memory_stats
    WHERE  object_id = object_id('dbo.Test')
    
    SELECT name AS 'index_name',
           s.*
    FROM   sys.dm_db_xtp_hash_index_stats s
           JOIN sys.indexes i
             ON s.object_id = i.object_id
                AND s.index_id = i.index_id
    WHERE  i.object_id = object_id('dbo.Test')
    
    SELECT name AS 'index_name',
           s.index_id,
           scans_started,
           rows_returned,
           rows_expired,
           rows_expired_removed
    FROM   sys.dm_db_xtp_index_stats s
           JOIN sys.indexes i
             ON s.object_id = i.object_id
                AND s.index_id = i.index_id
    WHERE  object_id('dbo.Test') = s.object_id;
    

    E, em seguida, executei o seguinte, experimentando alternar os ROLLBACKeCOMMIT

    CREATE TABLE [dbo].[Test]
      (
         [Id]     [INT] NOT NULL CONSTRAINT PK PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 8),
         [String] CHAR(900) COLLATE Latin1_General_100_BIN2 NOT NULL INDEX IX NONCLUSTERED HASH WITH (BUCKET_COUNT = 8)
      ) WITH ( MEMORY_OPTIMIZED = ON )
    
    INSERT INTO [dbo].[Test]
    VALUES
        (1,REPLICATE('A',900)),
        (2,REPLICATE('A',900)),
        (3,REPLICATE('A',900)),
        (4,REPLICATE('A',900)),
        (5,REPLICATE('A',900)),
        (6,REPLICATE('A',900)),
        (7,REPLICATE('A',900)),
        (8,REPLICATE('A',900))
    
    /*Get initial position*/
    EXEC GetStats
    
    BEGIN TRAN
        UPDATE [dbo].[Test]
        SET    [String] = REPLICATE('B', 900)
    
    /*Mid Transaction*/
    EXEC GetStats
    
    COMMIT    
    
    /*Force a scan of both indexes*/
    SELECT COUNT(*)
    FROM   dbo.Test WITH (INDEX=IX)
    EXCEPT
    SELECT COUNT(*)
    FROM   dbo.Test WITH (INDEX = PK)
    
    EXEC GetStats
    
    DROP TABLE [dbo].[Test]
    

    Eu consistentemente obtive resultados resumidos da seguinte forma.

    O efeito do UPDATEfoi o mesmo para transações confirmadas e revertidas memory_allocated_for_table_kb(aumentou de 7 KB para 15 KB)

    Estatísticas do intervalo

    As estatísticas iniciais do intervalo para ambos os testes foram as mesmas com

    +------------+--------------------+--------------------+------------------+------------------+
    | index_name | total_bucket_count | empty_bucket_count | avg_chain_length | max_chain_length |
    +------------+--------------------+--------------------+------------------+------------------+
    | IX         |                  8 |                  7 |                8 |                8 |
    | PK         |                  8 |                  7 |                8 |                8 |
    +------------+--------------------+--------------------+------------------+------------------+
    

    No meio da transação (antes da reversão ou confirmação), as contagens de balde são

    +------------+--------------------+--------------------+------------------+------------------+
    | index_name | total_bucket_count | empty_bucket_count | avg_chain_length | max_chain_length |
    +------------+--------------------+--------------------+------------------+------------------+
    | IX         |                  8 |                  6 |                8 |                8 |
    | PK         |                  8 |                  7 |               16 |               16 |
    +------------+--------------------+--------------------+------------------+------------------+
    

    Em seguida rollback, eles revertem instantaneamente para a contagem inicial, mas depois commitpermanecem como na segunda tabela, mostrando que o lixo agora está presente.

    O único balde que aparentemente todos os valores de PK fazem hash agora tem 16 linhas vinculadas em vez das 8 anteriores.

    E agora o índice de hash na outra coluna tem dois baldes em uso com 8 linhas vinculadas em cada (para os valores de string "antes" e "depois" de AAA...e BBB...)

    Linhas expiradas

    Depois de Confirmar

    +------------+----------+---------------+---------------+--------------+----------------------+
    | index_name | index_id | scans_started | rows_returned | rows_expired | rows_expired_removed |
    +------------+----------+---------------+---------------+--------------+----------------------+
    | IX         |        2 |             1 |             8 |            8 |                    0 |
    | PK         |        3 |            10 |            16 |            8 |                    0 |
    +------------+----------+---------------+---------------+--------------+----------------------+
    

    Após a reversão

    +------------+----------+---------------+---------------+--------------+----------------------+
    | index_name | index_id | scans_started | rows_returned | rows_expired | rows_expired_removed |
    +------------+----------+---------------+---------------+--------------+----------------------+
    | IX         |        2 |             1 |             8 |            8 |                    8 |
    | PK         |        3 |            10 |            16 |            8 |                    8 |
    +------------+----------+---------------+---------------+--------------+----------------------+
    

    O rows_expiredestá 8em ambos os casos, mas rows_expired_removedestá 0seguindo a confirmação da transação, enquanto todos eles foram removidos após a reversão.

    • 7

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

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

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

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

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 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

    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
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • 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
    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