Menangkap datetime perubahan dalam SQL Server CDC

8

Jadi kami telah mulai mengeksplorasi dengan menggunakan perubahan data pada salah satu database produksi kami. Kami ingin mengetahui waktu dari setiap perubahan. Membaca melalui tutorial dan tutorial dll. Tampaknya pendekatan standar adalah menggunakan LSN untuk berhubungan dengan cdc.lsn_time_mappingtabel sistem. Pendekatan ini bekerja tetapi tidak terlalu mudah atau berkinerja ketika berbicara tentang 100-an dari ribuan perubahan sehari.

Dalam lingkungan pengujian saya membuat penyesuaian berikut ke tabel trek perubahan. Saya mengeluarkan ALTER TABLEpernyataan untuk menambahkan kolom ke ujung yang dipanggil [__ChangeDateTime]dan menjadikannya nilai default GetDate(). Pendekatannya tampaknya bekerja, pelacakan perubahan masih berfungsi secara normal, datetime sedang ditangkap. Tapi bermain-main dengan tabel sistem membuat saya sedikit gugup.

Jika ini bukan bidang sistem yang Microsoft tambahkan sejak awal, mereka pasti memiliki alasan. Karena mereka malah memilih untuk LSN ke pendekatan cdc.lsn_time_mapping apakah saya mengatur diri saya untuk masalah dengan membuat hack saya sendiri dengan cara ini?

MEMPERBARUI:

Ditemukan selama pengujian yang GetDate () pada waktu tidak cukup tepat untuk kebutuhan kita - beberapa perubahan berbagi waktu yang sama. Rekomendasikan menggunakan sysdatetime () dan datetime2 untuk memindahkan nilai ke nanosecond. Opsi untuk 2008+ hanya jelas.

RThomas
sumber

Jawaban:

8

Ingat bahwa CDC menggunakan agen pembaca log untuk mengisi tabel perubahan. Mengapa itu penting? Dengan mekanisme itu, baris muncul di tabel perubahan secara serempak dengan perubahan yang dibuat di tabel dasar.

Sebenarnya ada 3 titik waktu berbeda yang dapat direkam, dalam urutan kronologis terbalik:

  1. Waktu perubahan dikirimkan ke tabel perubahan (yang Anda rekam).
  2. Waktu transaksi yang mengandung perubahan yang dilakukan (menggunakan cdc.lsn_time_mapping).
  3. Waktu yang Anda gunakan untuk mengisi kolom di tabel dasar secara manual (menggunakan batasan default, pemicu, dll.).

Jadi, hal pertama adalah memperjelas apa yang ingin Anda rekam. Biasanya kita akan peduli dengan # 2 atau # 3.

Jika mekanisme pemetaan LSN (# 2) tidak berkinerja cukup baik untuk Anda, satu-satunya alternatif yang didukung adalah menambahkan kolom ke tabel dasar dan mengisinya sendiri (# 3).

Berkenaan dengan mengubah tabel internal, sebagai masalah kebijakan, saya pikir yang terbaik adalah menghindari peretasan dengan internal ketika ada alternatif yang didukung. Hal terakhir yang Anda inginkan adalah sistem produksi penting turun, perlu memanggil Dukungan Produk, dan ditolak layanan karena sesuatu seperti ini. Jangankan masalah itu berpotensi melanggar hal-hal (upgrade), atau sedang rusak karena itu tidak terduga (matikan CDC, lalu nyalakan lagi, seperti yang disebutkan dalam jawaban lain).

Jon Seigel
sumber
3

Contoh praktis:

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');
Gareth Orrill
sumber
Jawaban ini akan mendapat manfaat dari beberapa komentar yang menjelaskan apa yang Anda lakukan, dan mengapa itu relevan.
Erik
2

Satu-satunya peringatan yang akan saya berikan adalah bahwa tabel-tabel itu dijatuhkan secara otomatis ketika CDC dinonaktifkan. Kolom tidak dibuat ulang secara otomatis saat Anda mengaktifkannya kembali

Liam Confrey
sumber