Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Отстраняване на проблеми с репликацията на транзакции на SQL Server

Транзакционната репликация на SQL Server е една от най-често срещаните техники за репликация, използвани за копиране или разпространение на данни в множество дестинации.

В предишните статии обсъдихме репликацията на SQL Server, как тя работи вътрешно и как да конфигурирате репликация чрез съветника за репликация или T-SQL подхода. Сега се фокусираме върху проблемите с репликацията на SQL и правилното им отстраняване на неизправности.

Проблеми с репликацията на SQL

По-голямата част от клиентите, които използват транзакционна репликация на SQL Server, основно се фокусират върху постигането на данни в почти реално време, налични в екземплярите на базата данни на абонатите. Следователно DBA, който управлява репликацията, трябва да е наясно с различни възможни проблеми, свързани с репликацията на SQL, които могат да възникнат. Освен това DBA трябва да може да реши тези проблеми за кратко време.

Можем да категоризираме всички проблеми с репликацията на SQL в категориите по-долу (въз основа на моя опит):

Проблеми с конфигурацията

  • Максимален размер за репликация на текст
  • SQL Server Agent Service не е настроен да стартира автоматичен режим
  • Ненаблюдаваните копия на репликация влизат в състояние на неинициализирани абонаменти
  • Известни проблеми в SQL Server

Проблеми с разрешенията

  • Проблеми с разрешението за работа на агент на SQL Server
  • Идентификационните данни за работа на агента за моментни снимки нямат достъп до пътя на папката за моментна снимка
  • Идентификационните данни на агента за четене на журнали не могат да се свържат с базата данни на издател/разпространение
  • Идентификационните данни за работа на агента за разпространение не могат да се свържат с базата данни за разпространение/абонат

Проблеми със свързването

  • Сървърът на издателя не беше намерен или не беше достъпен
  • Сървърът за разпространение не беше намерен или не беше достъпен
  • Сървърът за абонати не беше намерен или не беше достъпен

Проблеми с целостта на данните

  • Грешки при нарушаване на първичния или уникалния ключ
  • Грешки в ред не е намерен
  • Грешки при нарушаване на външния ключ или други ограничения

Проблеми с производителността

  • Дългосрочни активни транзакции в базата данни на издателя
  • Групови операции INSERT/UPDATE/DELETE върху статии
  • Огромни промени в данните в рамките на една транзакция
  • Блокиране в базата данни за разпространение

Проблеми, свързани с корупцията

  • Повреда на базата данни на издателя
  • Повреда на регистрационния файл на транзакциите на издателя
  • Повреда на базата данни за разпространение
  • Повреда на базата данни на абонатите

Подготовка на ДЕМО среда

Преди да се потопим в подробности относно проблемите с репликацията на SQL, трябва да подготвим средата си за демонстрацията. Както беше обсъдено в предишните ми статии, всякакви промени в данните, които се случват в базата данни на абонатите в транзакционната репликация, няма да се виждат директно в базата данни на издателя. По този начин ще направим определени модификации директно в базата данни на абонатите за учебни цели.

Моля, бъдете изключително внимателни и не променяйте нищо в производствените бази данни. Това ще повлияе на целостта на данните на базите данни на абонатите. Ще взема резервните скриптове за всяка извършена промяна и ще използвам тези скриптове, за да коригирам проблемите с репликацията на SQL.

Промяна 1 – Вмъкване на записи в таблицата Person.ContactType

Преди да вмъкнете записи в Person.ContacType таблица, нека да разгледаме тази структура на таблицата, няколко ограничения по подразбиране и разширени свойства, редактирани в скрипта по-долу:

CREATE TABLE [Person].[ContactType](
	[ContactTypeID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
	[Name] [dbo].[Name] NOT NULL,
	[ModifiedDate] [datetime] NOT NULL,
 CONSTRAINT [PK_ContactType_ContactTypeID] PRIMARY KEY CLUSTERED 
(
	[ContactTypeID] ASC
) ON [PRIMARY]
) ON [PRIMARY]
GO

Избрах тази таблица, тъй като има по-малко колони. По-удобно е за тестови цели. Сега, нека проверим какво имаме за неговата структура:

  • ContactTypeId се дефинира като КОЛОНА ЗА ИДЕНТИЧНОСТ – тя ще генерира автоматично стойностите на първичния ключ и НЕ ЗА РЕПЛИКАЦИЯ.
  • NOT FOR REPLICATION е специално свойство, което може да се използва за различни типове обекти като таблици, ограничения като ограничения на външния ключ, ограничения за проверка, тригери и колони за идентичност на издател или абонат, докато се използва само някоя от методологиите за репликация. Той позволява на DBA да планира или прилага репликация, за да гарантира, че определени функционалности се държат различно в Publisher/Subscriber, докато използват репликация.
  • В нашия случай ние инструктираме SQL Server да използва стойностите на IDENTITY, генерирани само в базата данни на Publisher. Свойството IDENTITY не трябва да се използва за Person.ContactType таблица в базата данни за абонати. По подобен начин можем да модифицираме ограниченията или тригерите, за да ги накараме да се държат различно, докато репликацията е конфигурирана с помощта на тази опция.
  • 2 други колони NOT NULL са налични в таблицата.
  • Таблицата има първичен ключ, дефиниран в ContactTypeId . Само да припомня, че първичният ключ е задължително изискване за репликация. Без него на маса не бихме могли да копираме статия от таблица.

Сега, нека ВМЕСТИМ примерен запис към Лице .ContactType таблица в AdventureWorks_REPL база данни:

Директното INSERT в таблицата ще се провали в базата данни на абонатите, тъй като свойството за самоличност е деактивирано само за репликация чрез опцията НЕ ЗА РЕПЛИКАЦИЯ. Всеки път, когато изпълняваме операцията INSERT ръчно, все още трябва да използваме опцията SET IDENTITY_INSERT по следния начин:

 SET IDENTITY_INSERT AdventureWorks_REPL.Person.ContactType ON;

 INSERT INTO AdventureWorks_REPL.Person.ContactType(ContactTypeID, Name, ModifiedDate)
 VALUES (21, 'Test Position', GETDATE())
SET IDENTITY_INSERT AdventureWorks_REPL.Person.ContactType OFF;

След като добавим опцията SET IDENTITY_INSERT, можем успешно да INSERT запис в Person.ContactType таблица.

Изпълнението на SELECT върху таблицата показва нововмъкнатия запис:

Добавихме нов запис само към базата данни за абонати, която не е налична в базата данни на издателя на Person.ContactType таблица.

Изпълнението на SELECT върху същата таблица на базата данни на издателя не показва никакви записи. По този начин всички промени, направени в базата данни за абонати, не се репликират в базата данни на издателя.

Промяна 2 – Изтриване на 2 записа от таблицата Person.ContactType

Придържаме се към познатия ни Person.ContactType маса. Преди да изтрием записи от базата данни на абонатите, трябва да проверим дали тези записи съществуват както в издателя, така и в абоната. Вижте по-долу:

Сега можем да изтрием тези 2 ContactTypeId използвайки следното изявление:

DELETE FROM AdventureWorks_REPL.Person.ContactType
WHERE ContactTypeID IN (19,20)

Горният скрипт ни позволява да изтрием 2 записа от Person.ContactType таблица в базата данни за абонати:

Имаме препратка към външния ключ, която предотвратява изтриването на тези 2 записа от Person.ContactType маса. Можем да се справим с този сценарий, като деактивираме временно ограничението за външния ключ на дъщерната таблица. Скриптът е по-долу:

ALTER TABLE [Person].[BusinessEntityContact] NOCHECK CONSTRAINT [FK_BusinessEntityContact_ContactType_ContactTypeID];

След като външните ключове бъдат деактивирани, можем да изтрием успешно записи от Person.ContactType таблица:

Това също промени ограничението за препратка към външния ключ в двете таблици. Можем да опитаме да симулираме проблеми с репликацията на SQL въз основа на този сценарий.

В настоящия ни сценарий знаем, че Person.ContactType таблицата нямаше синхронизирани данни за издателя и абоната.

Повярвайте ми, в няколко производствени среди разработчиците или администраторите на база данни правят някои корекции на данни в базата данни на абонатите. както всички промени, които извършихме по-рано, причиниха проблеми с целостта на данните в базите данни на издателя и абоната в една и съща таблица. Като DBA имам нужда от по-опростен механизъм за проверка на тези видове несъответствия. В противен случай това би направило живота на DBA жалък.

Тук идва решението от Microsoft, което ни позволява да проверим несъответствията на данните в таблиците в издателя и абоната. Да, познахте правилно. Това е помощната програма TableDiff, която обсъждахме в предишни статии.

Помощна програма TableDiff

Помощната програма TableDiff се използва основно в среди за репликация. Можем да го използваме и за други случаи, когато трябва да сравним 2 таблици на SQL Server за несближаване. Можем да ги сравним и да идентифицираме разликите между тези 2 таблици. След това помощната програма помага да се синхронизира Дестинацията маса към Източник маса чрез генериране на необходимите скриптове INSERT/UPDATE/DELETE.

TableDiff е самостоятелна програма tablediff.exe, инсталирана по подразбиране в C:\Program Files\Microsoft SQL Server\130\COM, след като сме инсталирали компонентите за репликация. Моля, имайте предвид, че пътят по подразбиране може да варира в зависимост от параметрите за инсталиране на SQL Server. Числото 130 в пътя показва версията на SQL Server (SQL Server 2016). Следователно тя ще варира за всяка различна версия на инсталацията на SQL Server.

Можете да получите достъп до помощната програма TableDiff чрез командния ред или само от пакетни файлове. Помощната програма няма изискан съветник или графичен интерфейс за използване. Подробният синтаксис на помощната програма TableDiff е в статията на MSDN. Нашата текуща статия се фокусира само върху някои необходими опции.

За да сравним 2 таблици с помощта на помощната програма TableDiff, трябва да предоставим задължителни подробности за таблиците източник и дестинация, като име на изходния сървър, име на изходна база данни, име на схема на източник, име на таблица на източника, име на целеви сървър, име на базата данни на местоназначение, дестинация Име на схемата и име на целевата таблица.

Нека опитаме да тестваме TableDiff с Person.ContactType таблица с разлики между издателя и абоната.

Отворете командния ред и се придвижете до пътя на помощната програма TableDiff (ако този път не е добавен към променливите на средата).

За да видите списъка с всички налични параметри, въведете командата “tablediff-?” за да изброите всички налични опции и параметри. Резултатите са по-долу:

Нека проверим лицето.ContactType таблица в нашите бази данни за издатели и абонати, като изпълните командата по-долу:

tablediff -sourceserver RRJ -sourcedatabase AdventureWorks -sourceschema Person -sourcetable ContactType -destinationserver RRJ -destinationdatabase AdventureWorks_REPL -destinationschema Person -destinationtable ContactType

Имайте предвид, че не съм предоставил sourceuser , sourcepassword , destinationuser и парола за дестинация тъй като моето влизане в Windows има достъп до таблиците. Ако искате да използвате SQL Credentials вместо Windows Authentication, горните параметри са задължителни за достъп до таблиците за сравнение . В противен случай ще получите грешки.

Резултатите от правилното изпълнение на командата:

Показва, че имаме 3 несъответствия. Единият е нов запис в базата данни на местоназначението, а два записа не са налични в базата данни на местоназначението.

Сега нека да разгледаме набързо Разни налични опции за помощната програма TableDiff.

  • – регистрира обобщението на резултатите в таблицата на местоназначението
  • -dt – премахва таблицата за дестинация на резултата, ако вече съществува
  • -f – генерира T-SQL DML скрипт с изрази INSERT/UPDATE/DELETE, за да доведе таблицата Destination до конвергенция с таблицата Source.
  • -o – име на изходния файл, ако опцията -f се използва за генериране на файла за конвергенция.

Ще създадем файл за конвергенция с -f и -o опции към нашата по-ранна команда:

tablediff -sourceserver RRJ -sourcedatabase AdventureWorks -sourceschema Person -sourcetable ContactType -destinationserver RRJ -destinationdatabase AdventureWorks_REPL -destinationschema Person -destinationtable ContactType -f -o C:\PersonContactType.sql

Файлът за конвергенция е създаден успешно:

Както можете да видите, създаването на нов файл в главната папка на C:устройството не е разрешено от съображения за сигурност. Следователно той показва съобщение за грешка и създава изходния файл DIFFIX.*.sql файл в папката на помощната програма TableDiff. Когато отворим този файл, можем да видим следните подробности:

Скриптовете INSERT бяха създадени за 2-те изтрити записа, а скриптовете DELETE бяха създадени за записите, нововмъкнати в базата данни на абоната. Инструментът също се грижи за използването на опциите IDENTITY_INSERT, както се изисква за Дестинация маса. Следователно този инструмент ще бъде от голяма полза, когато DBA трябва да синхронизира две таблици.

В нашия случай няма да изпълнявам скриптовете, тъй като имаме нужда от тези отклонения, за да симулираме нашите проблеми с репликацията на SQL.

Предимства на помощната програма TableDiff

  • TableDiff е безплатна помощна програма, която идва като част от инсталацията на компонентите за репликация на SQL Server, за да се използва за сравнение или конвергенция на таблици.
  • Скриптовете за създаване на конвергенция могат да бъдат създадени без ръчна намеса.

Ограничения на помощната програма TableDiff

  • Помощната програма TableDiff може да се изпълнява само от командния ред или пакетния файл.
  • От командния ред можете да извършвате само едно сравнение на таблици в даден момент, освен ако нямате паралелно отворени няколко командни подкана, за да сравните няколко таблици.
  • Изходната таблица, която трябва да сравните с помощта на помощната програма TableDiff, изисква дефиниран първичен ключ или колона за идентичност, или наличната колона ROWGUID за извършване на сравнението ред по ред. Ако е-строго се използва опцията, таблицата Destination също изисква първичен ключ, или колона за самоличност, или налична колона ROWGUID.
  • Ако таблицата източник или местоназначение съдържа sql_variant колона тип данни, не можете да използвате помощната програма TableDiff, за да я сравните.
  • Могат да бъдат забелязани проблеми с производителността при изпълнение на помощната програма TableDiff върху таблици, съдържащи огромни записи, тъй като тя ще извърши сравнението ред по ред на тези таблици.
  • Скриптовете за конвергенция, създадени от помощната програма TableDiff, не включват колоните с тип данни за BLOB символи, като varchar(max) , nvarchar(max) , varbinary(max) , текст , ntext , или изображение колони и xml или клеймо за време колони. Следователно имате нужда от алтернативни подходи за обработка на таблиците с тези колони от тип данни.

Въпреки това, дори и с тези ограничения, помощната програма TableDiff може да се използва във всяка таблица на SQL Server за бърза проверка на данни или проверка на конвергенцията. Можете обаче да закупите и добър инструмент на трета страна.

Сега нека разгледаме подробно различните проблеми с репликацията на SQL.

Проблеми с конфигурацията

От моя опит категоризирах често пропусканите опции за конфигуриране на репликация, които могат да доведат до критични проблеми с репликацията на SQL като Конфигурация проблеми. Някои от тях са по-долу.

Максимален размер на репликация на текст

Максимален размер на отговор на текст се отнася до максималния размер на репликация на текст в байтове . Прилага се за всички типове данни като char(max), nvarchar(max), varbinary(max), text, ntext, varbinary, xml, и изображение .

SQL Server има опция по подразбиране за ограничаване на максималната дължина на колоната на низовия тип данни (в байтове), която да бъде репликирана като 65536 байтове.

Трябва внимателно да оценим максималния размер на репликиране на текст винаги, когато репликацията е конфигурирана за база данни. За това трябва да проверим всички по-горе колони с тип данни и да идентифицираме максималните възможни байтове, които ще бъдат прехвърлени чрез репликация.

Промяната на стойността на -1 показва, че няма ограничения. Въпреки това ви препоръчваме да оцените максималната дължина на низа и да конфигурирате тази стойност.

Можем да конфигурираме максимален размер на републикан текст с помощта на SSMS или T-SQL.

В SSMS щракнете с десния бутон върху името на сървъра> Свойства > Разширени :

Просто кликнете върху 65536 за да го модифицирате. За тестове промених 65536 на 1000000 и щракнах OK :

За да конфигурирате опцията Max Text Repl Size чрез T-SQL, отворете нов прозорец за заявка и изпълнете скрипта по-долу срещу главната база данни:

EXEC sys.sp_configure N'max text repl size (B)', N'-1'
GO
RECONFIGURE WITH OVERRIDE
GO

Тази заявка ще позволи на репликацията да не ограничава размера на колоните от горните типове данни.

За да проверим, можем да извършим SELECT на sys.configurations DMV и проверете value_in_use колона, както е по-долу:

Услугата за агент на SQL Server не е настроена да стартира автоматичен режим

Репликацията разчита на агенти за репликация, които се изпълняват като задачи на агент на SQL Server. Следователно всеки проблем с някои SQL Server Agent Service ще има пряко въздействие върху функционалността на репликацията.

Трябва да се уверим, че стартовият режим на SQL Server и SQL Server Agent Services е настроен на Автоматично. Ако е зададено Ръчно, трябва да конфигурираме някои сигнали. Те ще уведомят администраторите на администратора на база данни или сървъра да стартират услугата за агент на SQL Server, когато сървърът рестартира планирано или непланирано.

Ако не е направено, репликацията може да не се изпълнява дълго време, което засяга и други задачи на SQL Server Agent.

Ненаблюдавани екземпляри на репликация влизат в състояние на неинициализиран абонамент

Подобно на наблюдението на SQL Server Agent Service, конфигурирането на Database Mail Service във всеки екземпляр на SQL Server играе жизненоважна роля за навременното предупреждаване на DBA или лицето, конфигурирано. За всякакви неизправности или проблеми, задания на агент на SQL Server, като агент за четене на журнали или агент за разпространение, могат да бъдат конфигурирани да изпращат сигнали до DBA или съответния член на екипа по имейл. Неуспехът на изпълнението на заданието на агента за репликация може да доведе до следните сценарии:

Неизпълнение на задачата на агент за четене на журнали . Регистрационният файл на транзакциите на базата данни на издателя ще бъде използван повторно само след командата маркирана за репликация се чете от агента за четене на журнали и се изпраща успешно към базата данни за разпространение. В противен случай log_reuse_wait_desc колона sys.databases ще покаже стойността като репликация, което показва, че регистрационният файл на базата данни не може да бъде използван повторно, докато не прехвърли успешно промените в базата данни за разпространение. Следователно, неизпълнението на агента Log Reader ще продължи да увеличава размера на регистрационния файл на транзакциите на базата данни на Publisher и ще срещнем проблеми с производителността по време на пълното архивиране или проблеми с дисковото пространство в екземпляра на базата данни Publisher.

Неизпълнение на задание за дистрибутор. Заданието Агент за разпространение чете данните от базата данни за разпространение и ги изпраща до базата данни на абонатите. След това маркира тези записи за изтриване в базата данни за разпространение. Ако заданието на агента за разпространение не се изпълнява, това ще увеличи размера на базата данни за разпространение, което ще доведе до проблеми с производителността на цялостната производителност на репликацията. По подразбиране базата данни за разпространение е конфигурирана да съхранява записи за максимум 0-72 часа, както е показано в свойството Задържане на транзакции по-долу. Ако репликацията е неуспешна за повече от 72 часа, съответният абонамент ще бъде маркиран като неинициализиран, което ни принуждава или да преконфигурираме абонамента, или да генерираме нова моментна снимка, за да може репликацията да работи отново.

Неизпълнение на почистване на разпространението:задача за разпространение . Задачата за почистване на разпространението е отговорна за изтриването на всички репликирани записи от базата данни за разпространение, за да поддържа размера на базата данни за разпространение под контрол. Неизпълнението на това задание води до увеличен размер на базата данни за разпространение, което води до проблеми с производителността на репликацията.

За да гарантираме, че няма да се сблъскаме с някой от тези ненаблюдавани проблеми, пощата на базата данни трябва да бъде конфигурирана да докладва всички неуспехи или повторни опити на съответните членове на екипа за бързи действия.

Известни проблеми в SQL Server

Някои версии на SQL Server са имали известни проблеми с репликацията във версията RTM или по-ранните версии. Тези проблеми бяха отстранени в следващите сервизни пакети или CU пакети. Ето защо се препоръчва да приложите най-новите сервизни пакети или CU пакети, веднъж налични за всички SQL Server, след като ги тествате в QA средата. Въпреки че това е обща препоръка за сървъри, работещи с SQL Server, тя е приложима и за репликация.

Проблеми с разрешенията

В среда с конфигурирана транзакционна репликация на SQL Server, можем често да наблюдаваме проблемите с разрешенията. Може да се сблъскаме с тях по време на конфигуриране на репликация или всякакви дейности по поддръжка на екземпляри от базата данни на издателя, дистрибутора или абонатите. Това води до загуба на идентификационни данни или разрешения. Нека сега да видим някои чести проблеми с разрешенията, свързани с репликацията.

Проблеми с разрешението за работа на агент на SQL сървър

Всички агенти за репликация използват задачи на SQL Server Agent. Всяко задание на агент на SQL Server, свързано с моментната снимка или агента за четене на журнали, или разпространението, се изпълнява под някои идентификационни данни за Windows или SQL, както е показано по-долу:

За да стартирате задача на агент на SQL Server, трябва да притежавате или SQLAgentOperatorRole за да стартирате всички задания или SQLAgentUserRole или SQLAgentReaderRole да започнете работа, която притежавате. Ако някоя задача не може да започне правилно, проверете дали собственикът на заданието има необходимите права за изпълнение на това задание.

Идентификационните данни за работа на агента за моментна снимка нямат достъп до пътя на папката за моментна снимка

В предишните ни статии забелязахме, че изпълнението на агента за моментна снимка ще създаде моментна снимка на статиите в локална или споделена папка, която да бъде разпространена в базата данни на абонатите чрез агента за разпространение. Местоположението на пътя на моментната снимка може да бъде идентифицирано под Свойства на публикация > Моментна снимка :

Ако агентът за моментни снимки няма достъп до това местоположение на файловете за моментни снимки, може да получим грешката:

Достъпът до пътя „C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\repldata\unc\XXXX\YYYYMMDDHHMISS\“ е отказан.

За да разрешите проблема, по-добре е да предоставите пълен достъп до пътя на папката C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\repldata\unc\ за акаунта, под който се изпълнява Snapshot Agent. В нашата конфигурация ние използваме акаунта на агент на SQL Server, а услугата за агент на SQL Server се изпълнява под акаунта RRJ\RRJ.

Идентификационните данни на агента за четене на журнали не могат да се свържат с базата данни на издател/разпространение

Агентът за четене на журнали се свързва с базата данни на издателя, за да изпълни sp_replcmds процедура за сканиране за транзакциите, маркирани за репликация, от регистрационните файлове на транзакциите на базата данни на издателя.

Ако собственикът на базата данни на базата данни Publisher не е зададен правилно, може да получим следните грешки:

Процесът не можа да изпълни „sp_replcmds“ на „RRJ“.

Или

Не може да се изпълни като принципал на базата данни, тъй като принципалът „dbo“ не съществува, този тип принципал не може да бъде имитиран или нямате разрешение.

За да разрешите този проблем, уверете се, че свойството собственик на базата данни на базата данни Publisher е настроено на sa или друг валиден акаунт (вижте по-долу).

Щракнете с десния бутон върху Издател база данни (AdventureWorks )> Свойства > Файлове . Уверете се, че Собственикът полето е зададено на sa или всяко валидно влизане и не празно .

Ако възникнат проблеми с разрешенията, когато се свързваме с базата данни на издателя или разпространението, проверете идентификационните данни, използвани за агента за четене на журнали, и им дайте разрешения за достъп до тези бази данни.

Идентификационните данни за работа на агента за разпространение не могат да се свържат с базата данни за разпространение/абонат

Агентът за разпространение може да има проблеми с разрешенията, ако на акаунта не е разрешен достъп до базата данни за разпространение или да се свърже с базата данни на абонатите. В този случай може да получим следните грешки:

Не може да се стартира изпълнението на стъпка 2 (причина:Грешка при удостоверяване на прокси RRJ\RRJ, системна грешка:Потребителското име или паролата са неправилни.)

Процесът не можа да се свърже с абонат „RRJ.

Неуспешно влизане за потребител „RRJ\RRJ“.

За да го разрешите, проверете акаунта, използван в свойствата на абонамента, и се уверете, че има необходимите разрешения за свързване с базата данни за разпространение или абонати.

Проблеми със свързването

Обикновено конфигурираме транзакционната репликация между сървъри в рамките на една и съща мрежа или в географски разпределени местоположения. Ако базата данни за разпространение се намира на специален сървър с изключение на издателя или абоната, тя става податлива на загуба на мрежови пакети – проблеми със свързаността.

В случай на такива проблеми, агентите за репликация (Log Reader или Distribution Agent) могат да докладват следните грешки:

Сървърът на издателя не беше намерен или не беше достъпен

Сървърът за разпространение не беше намерен или не беше достъпен

Абонатният сървър не беше намерен или не беше достъпен

За да отстраним тези проблеми, може да опитаме да се свържем с базата данни на издателя, дистрибутора или абоната в SSMS, за да проверим дали можем да се свържем с тези екземпляри на SQL Server без проблеми или не.

Ако проблемите със свързването се случват често, можем да опитаме да пингуваме непрекъснато на сървъра, за да идентифицираме загубите на пакети. Освен това трябва да работим с необходимите членове на екипа, за да разрешим тези проблеми и да задействаме сървъра за репликация, за да възобнови прехвърлянето на данни.

Проблеми с целостта на данните

Тъй като репликацията на транзакции е еднопосочен механизъм, всякакви промени в данните, които се случват на абоната (ръчно или от приложението), няма да бъдат отразени на издателя. Това може да доведе до различия в данните между издателя и абоната.

Нека разгледаме тези проблеми, свързани с целостта на данните, и да видим как да ги разрешим. Имайте предвид, че вмъкнахме запис в Person.ContactType таблица и изтри 2 записа от Person.ContactType таблица в базата данни за абонати. Ще използваме тези 3 записа, за да открием грешки.

Грешки при нарушаване на първичния ключ или уникален ключ

Ще тествам записа INSERT в Person.ContactType маса. Нека вмъкнем този запис в базата данни на издателя и да видим какво се случва:

Стартирайте монитора за репликация, за да видите как върви. Получаваме грешката:

Разгъващ се Издател и Публикация , получаваме следните подробности:

Ако сме конфигурирали сигналите за репликация и сме назначили съответните лица да получават техните известия по пощата, ще получим подходящи имейл известия със съобщението за грешка:Не може да се вмъкне дублиран ключов ред в обект 'Person.ContactType' с уникален индекс 'AK_ContactType_Name ' . Дублираната стойност на ключа е (Тестова позиция). (Източник:MSSQLServer, номер на грешка:2601)

За да разрешим проблема, свързан с уникални ключови нарушения или проблеми с първичен ключ, имаме няколко опции:

  • Анализирайте защо се е случила тази грешка, как записът е бил наличен в базата данни за абонати и кой по какви причини го е вмъкнал. Определете дали е било необходимо или не.
  • Добавете skiperrors параметър към профила на Distribution Agent, за да пропуснете Номер на грешка 2601 или Номер на грешка 2627 в случай на нарушение на първичния ключ.

В нашия случай ние целенасочено вмъкнахме данни, за да получим тази грешка. За да се справите с този проблем, изтрийте този ръчно вмъкнат запис, за да продължите да репликирате промените, получени от издателя.

DELETE from Person.ContactType
where ContactTypeID = 21

За да проуча други опции и да сравня разликите между тези два подхода, пропускам първата опция (която е ефективна и препоръчителна) и преминавам към втората опция, като добавя -skiperrors параметър към заданието на агента за разпространение.

Можем да го внедрим, като редактираме Работа на агента за разпространение > Стъпки > щракнете върху 2 Job Step с име Run Agent > щракнете върху Редактиране за да видите наличната команда:

Сега добавете -SkipErrors 2601 ключова дума накрая (2601 е номерът на грешката – можем да пропуснем всеки номер на грешка, получен като част от репликацията) и щракнете върху OK .

To make sure that the Distribution job is aware of this configuration change, we need to restart the Distribution agent job. For that, stop it and start again from Step 1 as shown below:

The Replication Monitor displays that one of the error records is skipped from the Replication, that started working fine.

Since the Replication issue is resolved successfully, we’d recommend removing the -SkipErrors parameter from the Distribution Agent job. Then, restart the job to get the changes reflected.

Thus, we’ve fixed the replication issue, but let’s compare the data across the same Person.ContactType in the Publisher and Subscriber databases. The results show the data variance, or the data integrity issue :

ModifiedDate is different across the Publisher and Subscriber databases. It happens because the data in the Subscriber database was inserted earlier (when we were preparing the test data), and the data in the Publisher database has just been inserted.

If we deleted the record from the Subscriber database, the record from the Publisher would have been inserted to match the data across the Publisher and the Subscriber databases.

Most of the newbie DBAs simply add the -SkipErrors option to get the replication working immediately without detailed investigations of the issue. Hence, it is recommended not to use the -SkipErrors option as a primary solution without proper examination of the problem. The Person.ContactType table had only 3 columns. Assume that the table has over 20 columns. Then, we have just screwed up the Data integrity of this table with that -SkipErrors команда.

We used this approach just to illustrate the usage of that option. The best way is to examine and clarify the reason for variance and then perform the appropriate DELETE statements on the Subscriber database to maintain the Data Integrity across the Publisher and Subscriber databases.

Row Not Found Errors

Let’s try to perform an UPDATE on one of the records that were deleted from the Subscriber database:

Let’s check the Replication Monitor to see the performance. We have the following error:

The row was not found at the Subscriber when applying the replicated UPDATE command for Table ‘[Person].[ContactType]’ with Primary Key(s):[ContactTypeID] =19 (Source:MSSQLServer, Error number:20598).

There are two ways to resolve this error. First, we can use -SkipErrors for Error Number 20598 . Or, we can INSERT the record with ContactTypeID =19 (shown in the error message) to get the data changes reflected.

If we skip this error, we’ll lose the record with ContactTypeId =19 from the Subscriber database permanently. It can cause data inconsistency issues. Hence, we aren’t going to use the -SkipErrors опция. Instead, we’ll apply the INSERT approach.

The Replication resumes correctly by sending the UPDATE to the Subscriber database.

It is the same when we try to delete the ContactTypeId =20 from the Publisher database and see the error popping up in the Replication Monitor.

The Replication Monitor shows us a message similar to the one we already noticed:

The row was not found at the Subscriber when applying the replicated DELETE command for Table ‘[Person].[ContactType]’ with Primary Key(s):[ContactTypeID] =20 (Source:MSSQLServer, Error number:20598)

Similar to the previous error, we need to identify the missing record and insert it back to the Subscriber database for the DELETE statement to get replicated properly. For DELETE scenario, using -SkipErrors doesn’t have any issues but can’t be considered as a safe option, as both missing UPDATE or missing DELETE record are captured with the same error number 20598 and adding -SkipErrors 20598 will skip applying all records from the Subscriber database.

We can also get more details about the problematic command by using the sp_browsereplcmds stored procedure which we have discussed earlier as well. Let’s try to use sp_browsereplcmds stored procedure for the previous error we have received out as shown below.

exec sp_browsereplcmds @xact_seqno_start = '0x000000A500001160000600000000'
			, @xact_seqno_end = '0x000000A500001160000600000000'
			, @publisher_database_id = 1
			, @command_id = 1

@xact_seqno_start and @xact_seqno_end will be the same value. We can fetch that value from the Transaction Sequence number in the Replication Monitor along with Command ID.

@publisher_database_id can be fetched from the id column of the distribution..MSPublisher_databases DMV.

select * from MSpublisher_databases 

Foreign Key or Other Constraint Violation Errors

The error messages related to Foreign keys or any other data issues are slightly different. Microsoft has made these error messages detailed and self-explanatory for anyone to understand what the issue is about.

To identify the exact command that was executed on the Publisher and resolve it efficiently, we can use the sp_browsereplcmds procedure explained above and identify the root cause of the issue.

Once the commands are identified as INSERT/UPDATE/DELETE which caused the errors, we can take corresponding actions to resolve the problems correctly which is more efficient compared to simply adding -SkipErrors approach. Once corrective measures are taken, Replication will start resuming fine immediately.

Word of Caution Using -SkipErrors Option

Those who are comfortable using -SkipErrors option to resolve error quickly should remember that -SkipErrors option is added at the Distribution agent level and applies to all Published articles in that Publication. Command -SkipErrors will result in skipping any number of commands related to that particular error across all published articles any number of times resulting in discrepancies we have seen in demo resulting in data discrepancies across Publisher and Subscriber without knowing how many tables are having discrepancies and would require efforts to compare the tables and fix it out.

Заключение

Thanks for going through another robust article. I hope it was helpful for you to understand the SQL Server Transactional Replication issues and methods of troubleshooting them. In our next article, we’ll continue the discussion about the SQL Transaction Replication issues, examine other types, such as Corruption-related issues, and learn the best methods of handling them.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да намерите най-бавните заявки

  2. Подреждане на опашка в OneWay WCF съобщения с помощта на Windows Service и SQL Server

  3. Разбиране на анализатора на работното натоварване за картографиране на тесните места в производителността

  4. Грешка на SQL Server 110:Има по-малко колони в израза INSERT от стойностите, посочени в клаузата VALUES.

  5. Представяме ви нова функция - репликация в облака на Spotlight