Bagikan melalui


Mengonfigurasi deteksi konflik penulis terakhir & resolusi

Dimulai dengan SQL Server 2019 (15.x) CU 13, Anda dapat mengonfigurasi replikasi peer-to-peer untuk menyelesaikan konflik secara otomatis dengan memungkinkan sisipan atau pembaruan terbaru untuk memenangkan konflik. Jika salah satu tulis menghapus baris, SQL Server memungkinkan penghapusan untuk memenangkan konflik. Metode ini dikenal sebagai kemenangan tulisan terakhir.

Gunakan prosedur tersimpan untuk mengonfigurasi kemenangan tulis terakhir. Jangan gunakan Wizard Topologi Peer-to-Peer untuk menambahkan atau menghapus simpul saat Anda menggunakan penulis terakhir.

Pertimbangan konfigurasi penting

Catatan

Setelah memperbarui ke SQL Server 2019 (15.x) CU13 atau lebih tinggi, ketika Anda mengonfigurasi publikasi dengan resolusi konflik yang diatur ke kemenangan tulis terakhir, metadata tambahan disertakan dalam publikasi. Jika Nanti Anda menghapus instalasi/menurunkan tingkat ke rilis di bawah SQL Server 2019 (15.x) CU13, metadata tambahan ini akan menyebabkan masalah. Disarankan untuk menghilangkan publikasi tersebut sebelum menurunkan tingkat, lalu membuatnya kembali pada versi yang lebih rendah.

Saat Anda mengonfigurasi replikasi peer-to-peer dengan penemuan dan resolusi konflik otomatis untuk diselesaikan saat penulisan terakhir menang, sertakan konfigurasi dan pengaturan berikut:

  • Buat publikasi dengan parameter berikut,

    • Atur @p2p_conflictdetection_policy = 'lastwriter' untuk menentukan kemenangan tulis terakhir. Lihat sp_addpublication (Transact-SQL). Parameter ini diperkenalkan di SQL Server 2019 (15.x) CU 13. Nilai originatorid default menyelesaikan konflik berdasarkan ID asal dan sama dengan resolusi konflik sebelum SQL Server 2019 (15.x) CU 13.
    • Atur @p2p_continue_onconflict = 'true' untuk mengizinkan agen distribusi mengatasi konflik.
  • Saat Anda menambahkan artikel (sp_addarticle), konfirmasi perilaku jenis perintah untuk perintah pembaruan (@upd_cmd). Opsi meliputi:

    • CALL (Default)
    • SCALL

    Lihat detail di sp_addarticle (Transact-SQL).

  • Saat Anda menambahkan artikel (sp_addarticle) dalam publikasi dengan kebijakan deteksi konflik penulis terakhir, GUNAKAN CALL atau SCALL sebagai jenis perintah untuk @upd_cmd parameter, CALL adalah default.

    Catatan

    SQL Server mendukung SCALL untuk @upd_cmd. Dengan SCALL, ketika transaksi memperbarui nilai ke nilai yang sama, transaksi tidak dianggap sebagai perubahan dan SCALL format tidak menyediakan nilai untuk kolom yang tidak diperbarui atau dimodifikasi. Harap tinjau hal berikut untuk detail tentang format panggilan SCALL - Sintaks panggilan untuk prosedur tersimpan.

  • Anda dapat menggunakan publikasi peer-to-peer dengan deteksi konflik penulis terakhir dan resolusi dalam grup ketersediaan. Lihat:

  • Anda dapat melihat konflik dan resolusinya.

    • Di SQL Server Management Studio, klik kanan publikasi dan pilih Lihat Konflik.

    Atau

  • Konflik sisipkan dan perbarui diselesaikan berdasarkan penulis terakhir, tetapi hapus selalu berlaku. Misalnya, jika Anda memiliki konflik penghapusan-pembaruan dan pembaruan dilakukan di lain waktu, penghapusan masih menang.

  • Deteksi dan resolusi konflik penulis terakhir ditentukan berdasarkan kolom $sys_mw_cd_idtersembunyi . Jenis data kolom ini adalah datetime2.

Perbandingan deteksi konflik

Tabel berikut membandingkan bagaimana konflik terdeteksi dan diselesaikan dengan replikasi peer-to-peer tradisional, dan ketika resolusi konflik penulis terakhir diaktifkan:

Jenis konflik Detail konflik Peer-to-peer Penulis terakhir
Sisipkan-Sisipkan Semua baris dalam setiap tabel yang berpartisipasi dalam replikasi peer-to-peer diidentifikasi secara unik dengan menggunakan nilai kunci primer. Konflik sisipan-sisipkan terjadi ketika baris dengan nilai kunci yang sama disisipkan di lebih dari satu simpul. Jika baris masuk adalah pemenang, maka kami memperbarui baris tujuan. Dalam kedua kasus, kami merekam informasi. Jika baris masuk adalah pemenang, maka kami memperbarui baris tujuan. Dalam kedua kasus, kami merekam informasi.
Pembaruan-Pembaruan Terjadi ketika baris yang sama diperbarui pada lebih dari satu simpul. Jika baris masuk adalah pemenang, maka kami hanya memodifikasi kolom yang diubah. Jika baris masuk adalah pemenang, maka kami memodifikasi semua kolom di tujuan (jika @upd_cmd diatur ke default – PANGGILAN).
Perbarui-Sisipkan Terjadi jika baris diperbarui pada satu simpul, tetapi baris yang sama dihapus dan kemudian diinserksi ulang pada simpul lain. Jika baris masuk adalah pemenang, maka kami hanya memodifikasi kolom yang diubah. Ini terjadi ketika baris diperbarui pada peer1 dan baris yang sama dihapus dan disisipkan kembali pada peer2. Ketika sinkronisasi terjadi, baris pada peer1 dihapus karena penghapusan selalu menang dan kemudian baris yang sama disisipkan, sedangkan baris diperbarui pada peer2 seperti yang diperbarui terjadi di lain waktu. Ini akan menyebabkan nonkonvergensi.
Sisipkan- Perbarui Terjadi jika baris dihapus lalu diinserksi ulang pada satu simpul dan baris yang sama diperbarui pada simpul lain. Jika baris masuk adalah pemenang, maka kita memperbarui semua kolom. Ini terjadi ketika baris dihapus dan disisipkan ulang pada peer1 dan baris yang sama diperbarui pada peer2. Ketika sinkronisasi terjadi, baris dihapus pada peer2 karena penghapusan selalu menang dan kemudian disisipkan lagi. Pada peer1, pembaruan dilewati.
Hapus-Sisipkan

Sisipkan-Hapus
Terjadi jika baris dihapus pada satu simpul, tetapi baris yang sama dihapus dan kemudian diinserksi ulang pada simpul lain. Saat ini kami menganggap ini sebagai konflik D-U dan jika baris masuk kemudian menjadi pemenang maka kami menghapus baris dari tujuan. Ini terjadi ketika baris dihapus pada peer1 dan baris yang sama dihapus + disisipkan ulang pada peer2. Saat sinkronisasi terjadi, baris pada peer2 dihapus, sedangkan baris disisipkan pada peer1. Ini terjadi karena kami tidak menyimpan informasi tentang baris yang dihapus, jadi kami tidak tahu apakah baris dihapus atau tidak ada di peer. Ini akan menyebabkan nonkonvergensi.
Hapus-Perbarui Terjadi jika baris dihapus pada satu simpul, tetapi baris yang sama diperbarui pada simpul lain. Saat ini kami menganggap ini sebagai konflik D-U dan jika baris masuk adalah pemenang maka kami menghapus baris dari tujuan. Ini adalah konflik D-U. Karena penghapusan selalu menang, penghapusan masuk akan menjadi pemenang dan kami menghapus baris dari tujuan.
Perbarui-Hapus Terjadi jika baris diperbarui pada satu simpul, tetapi baris yang sama dihapus di simpul lain. Dalam prosedur tersimpan Pembaruan peer-to-peer, jika ada konflik U-D, maka kami mencetak pesan berikut dan tidak mengatasinya.

An update-delete conflict was detected and unresolved. The row could not be updated since the row does not exist.
Ini adalah konflik U-D. Karena penghapusan selalu menang, pembaruan masuk dilewati.
Hapus-Hapus Terjadi ketika baris dihapus pada lebih dari satu simpul. Dalam prosedur Hapus peer-to-peer tersimpan, jika ada konflik D-D maka kami tidak memproses perubahan apa pun, cukup rekam. Jika ada konflik D-D maka kami tidak memproses perubahan apa pun, catat saja.

Catatan

Dalam implementasi kebijakan deteksi konflik penulis terakhir saat ini, penghapusan selalu menang ketika ada konflik insert-delete, delete-insert, atau update-delete.

Contoh

Membuat publikasi pada peer pertama (Node1)

Dalam contoh ini, skrip:

  • Menerbitkan database yang disebut MWPubDB.
  • Menamai publikasi PublMW.
  • Mengonfigurasi deteksi konflik dan kebijakan resolusi saat penulisan terakhir menang:
    , @p2p_continue_onconflict= 'true'
    , @p2p_conflictdetection_policy = 'lastwriter'
USE [MWPubDB]
EXEC sp_replicationdboption @dbname = N'MWPubDB'
  , @optname = N'publish'
  , @value = N'true'
GO
-- Adding the transactional publication
USE [MWPubDB]
EXEC sp_addpublication @publication = N'PublMW'
  , @description = N'Peer-to-Peer publication of database ''MWPubDB'' from Publisher ''Node1''.'
  , @sync_method = N'native'
  , @retention = 0
  , @allow_push = N'true'
  , @allow_pull = N'true'
  , @allow_anonymous = N'false'
  , @enabled_for_internet = N'false'
  , @snapshot_in_defaultfolder = N'true'
  , @compress_snapshot = N'false'
  , @ftp_port = 21
  , @allow_subscription_copy = N'false'
  , @add_to_active_directory = N'false'
  , @repl_freq = N'continuous'
  , @status = N'active'
  , @independent_agent = N'true'
  , @immediate_sync = N'true'
  , @allow_sync_tran = N'false'
  , @allow_queued_tran = N'false'
  , @allow_dts = N'false'
  , @replicate_ddl = 1, @allow_initialize_from_backup = N'true'
  , @enabled_for_p2p = N'true'
  , @enabled_for_het_sub = N'false'
  , @p2p_conflictdetection = N'true'
  , @p2p_originator_id = 100
  , @p2p_continue_onconflict= 'true'
  , @p2p_conflictdetection_policy = 'lastwriter'
GO

USE [MWPubDB]
EXEC sp_addarticle @publication = N'PublMW'
  , @article = N'tab1'
  , @source_owner = N'dbo'
  , @source_object = N'tab1'
  , @type = N'logbased'
  , @description = null
  , @creation_script = null
  , @pre_creation_cmd = N'drop'
  , @schema_option = 0x0000000008035DDB
  , @identityrangemanagementoption = N'manual'
  , @destination_table = N'tab1'
  , @destination_owner = N'dbo'
  , @status = 16
  , @vertical_partition = N'false'
  , @ins_cmd = N'CALL sp_MSins_dbotab1'
  , @del_cmd = N'CALL sp_MSdel_dbotab1'
  , @upd_cmd = N'CALL sp_MSupd_dbotab1'
GO

Membuat publikasi pada peer kedua (Node2)

Skrip di bawah ini membuat publikasi pada peer kedua (Node 2).

USE [MWPubDB]
EXEC sp_replicationdboption @dbname = N'MWPubDB'
 , @optname = N'publish'
 , @value = N'true'
GO
-- Adding the transactional publication
USE [MWPubDB]
EXEC sp_addpublication @publication = N'PublMW'
 , @description = N'Peer-to-Peer publication of database ''MWPubDB'' from Publisher ''Node2''.'
 ,@sync_method = N'native'
 , @retention = 0, @allow_push = N'true'
 , @allow_pull = N'true'
 , @allow_anonymous = N'false'
 , @enabled_for_internet = N'false'
 , @snapshot_in_defaultfolder = N'true'
 , @compress_snapshot = N'false'
 , @ftp_port = 21, @allow_subscription_copy = N'false'
 , @add_to_active_directory = N'false'
 , @repl_freq = N'continuous'
 , @status = N'active'
 , @independent_agent = N'true'
 , @immediate_sync = N'true'
 , @allow_sync_tran = N'false'
 , @allow_queued_tran = N'false'
 , @allow_dts = N'false'
 , @replicate_ddl = 1, @allow_initialize_from_backup = N'true'
 , @enabled_for_p2p = N'true'
 , @enabled_for_het_sub = N'false'
 , @p2p_conflictdetection = N'true'
 , @p2p_originator_id = 1
 , @p2p_continue_onconflict= 'true'
,  @p2p_conflictdetection_policy = 'lastwriter'
GO

USE [MWPubDB]
EXEC sp_addarticle @publication = N'PublMW'
 , @article = N'tab1'
 , @source_owner = N'dbo'
 , @source_object = N'tab1'
 , @type = N'logbased'
 , @description = null
 , @creation_script = null
 , @pre_creation_cmd = N'drop'
 , @schema_option = 0x0000000008035DDB
 , @identityrangemanagementoption = N'manual'
 , @destination_table = N'tab1'
 , @destination_owner = N'dbo'
 , @status = 16, @vertical_partition = N'false'
 , @ins_cmd = N'CALL sp_MSins_dbotab1'
 , @del_cmd = N'CALL sp_MSdel_dbotab1'
 , @upd_cmd = N'CALL sp_MSupd_dbotab1'
GO

Membuat langganan dari Node1 ke Node2

USE [MWPubDB]
EXEC sp_addsubscription @publication = N'PublMW'
 , @subscriber = N'Node2'
 , @destination_db = N'MWPubDB'
 , @subscription_type = N'Push'
 , @sync_type = N'replication support only'
 , @article = N'all'
 , @update_mode = N'read only'
 , @subscriber_type = 0
GO
EXEC sp_addpushsubscription_agent @publication = N'PublMW'
 , @subscriber = N'Node2'
 , @subscriber_db = N'MWPubDB'
 , @job_login = null
 , @job_password = null
 , @subscriber_security_mode = 1
 , @frequency_type = 64
 , @frequency_interval = 1
 , @frequency_relative_interval = 1
 , @frequency_recurrence_factor = 0
 , @frequency_subday = 4
 , @frequency_subday_interval = 5
 , @active_start_time_of_day = 0
 , @active_end_time_of_day = 235959
 , @active_start_date = 0 
 , @active_end_date = 0
 , @dts_package_location = N'Distributor'
GO

Membuat langganan dari Node2 ke Node1

USE [MWPubDB]
EXEC sp_addsubscription @publication = N'PublMW'
 , @subscriber = N'Node1'
 , @destination_db = N'MWPubDB'
 , @subscription_type = N'Push',
@sync_type = N'replication support only'
 , @article = N'all'
 , @update_mode = N'read only'
 , @subscriber_type = 0
go
EXEC sp_addpushsubscription_agent @publication = N'PublMW'
 , @subscriber = N'Node1'
 , @subscriber_db = N'MWPubDB'
 , @job_login = null
 , @job_password = null
 , @subscriber_security_mode = 1
 , @frequency_type = 64
 , @frequency_interval = 1
 , @frequency_relative_interval = 1
 , @frequency_recurrence_factor = 0
 , @frequency_subday = 4
 , @frequency_subday_interval = 5
 , @active_start_time_of_day = 0
 , @active_end_time_of_day = 235959
 , @active_start_date = 0
 , @active_end_date = 0
 , @dts_package_location = N'Distributor'
GO

Baca juga