Xử lý phạm vi nhận dạng để nhân rộng giao dịch


9

Tôi đã nhận thấy rằng khi bạn thiết lập sao chép giao dịch, SQL Server sẽ đặt quản lý phạm vi nhận dạng thành thủ công. Điều này có nghĩa là trong cơ sở dữ liệu đăng ký của tôi, khi tôi cố gắng chèn một bản ghi mới vào một bảng có PK là một cột định danh, nó sẽ báo lỗi và nói rằng nó đã cố gắng chèn PK là "1", "2 "," 3 ", v.v ... Điều này là do giá trị nhận dạng hiện tại cho tất cả các cột nhận dạng trên thuê bao được đặt lại về giá trị hạt giống (thường là 1) thay vì giữ nguyên giá trị của nhà xuất bản.

Tôi hiểu lý do tại sao SQL Server thực hiện việc này - bạn phải rời khỏi bảng thuê bao dưới dạng chỉ đọc. Tuy nhiên, kịch bản của tôi hơi không chính thống - thỉnh thoảng tôi cập nhật thuê bao của mình thông qua sao chép, tạo bản sao lưu ngay lập tức của DB đó, sau đó tôi muốn thực hiện một số cập nhật cho thuê bao mà KHÔNG bị đẩy trở lại nhà xuất bản, sau đó Khi tôi cập nhật lại thuê bao, tôi khôi phục cơ sở dữ liệu từ bản sao lưu trước đó và lấy các bản cập nhật mới nhất. Vì tôi muốn thực hiện cập nhật cho người đăng ký ở giữa những cập nhật này ('tạm thời' nếu bạn muốn), tôi cần cột nhận dạng để hoạt động và không đặt lại thành 1 khi được sao chép.

Tôi đã thử bật quản lý phạm vi nhận dạng tự động khi thiết lập ấn phẩm của mình, nhưng điều đó chỉ gây ra lỗi sau khi tôi cố thêm bảng vào ấn phẩm:

Msg 21231, Cấp 16, Trạng thái 1, Quy trình sp_MSrepl_addarticle, Dòng 2243
Hỗ trợ phạm vi nhận dạng tự động chỉ hữu ích cho các ấn phẩm cho phép cập nhật người đăng ký.

Có cách nào tôi có thể giải quyết vấn đề này không? Tôi muốn trình bày bản sao này cho SQL Server như thể nó chỉ đọc ở cuối thuê bao vì tôi không có kế hoạch thực hiện các bản cập nhật sẽ được gửi lại cho nhà xuất bản , nhưng tôi muốn thực hiện các cập nhật tạm thời sẽ bị xóa trước khi nhân rộng tiếp theo.

Tôi cũng đã xem xét rằng sao chép ảnh chụp nhanh có thể là một phương pháp phù hợp hơn so với sao chép giao dịch cho mẫu sử dụng của tôi, nhưng rắc rối là sao chép ảnh chụp nhanh yêu cầu gửi toàn bộ DB mỗi lần cập nhật; bởi vì tôi đang lên kế hoạch sao lưu DB ngay lập tức sau lần sao chép mới nhất, tôi không cần phải thực hiện toàn bộ chuyển khoản đó mỗi lần; chỉ là những thay đổi kể từ lần trước.


Phiên bản SQL Server nào bạn đang sử dụng? Bạn có thể xác định lại bảng?

2008 r2. Tôi không thấy việc xác định lại bảng sẽ giải quyết vấn đề này như thế nào ...
Jez

Tôi đã nghĩ đến một giải pháp bằng cách sử dụng SEQUENCE, nhưng đó chỉ là dành cho SQL 2012.

2
Is there any way I can get round this problem?Bạn phải đặt cột định danh là KHÔNG ĐƯỢC THAY ĐỔI bằng cách sử dụng sys.sp_identitycolumnforreplication cho máy chủ sql 2005 trở lên. Bạn thậm chí không phải đánh giá lại các bài viết của mình khi bạn thay đổi cột nhận dạng là không sao chép. Chỉ không làm điều đó bằng GUI.
Kin Shah

Nó đã được đánh dấu là không sao chép. Về cơ bản đó là vấn đề - SQL Server không sao chép thông tin nhận dạng nên trên thuê bao, nó bắt đầu từ 1.
Jez

Câu trả lời:


3

Giả sử Nhà xuất bản của bạn đang sử dụng danh tính int bắt đầu từ 1, bạn có thể phát hành DBCC CHECKIDENT('dbo.mytable', RESEED, -2147483648) tại thuê bao. Sau đó, bạn có thể sử dụng phạm vi từ -2147483648 đến 0 để giữ "đồng bằng tạm thời" của mình.


Đây là giải pháp tôi đã đưa ra, nhưng nó vẫn có nghĩa là mã của tôi kết nối với nhà xuất bản và người đăng ký và đồng bộ hóa các danh tính theo cách thủ công. Tôi đã hy vọng có một cách tự động hơn để làm điều đó.
Jez

Tại sao bạn cần phải đồng bộ hóa danh tính bằng tay? Chỉ cần viết một thủ tục được lưu trữ tại thuê bao chạy checkident cho mỗi bảng mà bạn đang lưu trữ delta tạm thời và chạy nó sau khi ảnh chụp nhanh kết thúc. Tác nhân phân phối sẽ chèn các thay đổi khi chúng xảy ra trong phạm vi nhận dạng "thực" và các thay đổi được thực hiện trực tiếp cho thuê bao sẽ nằm trong phạm vi phủ định.
Liam Confrey

1

Điều cuối cùng tôi đã làm là gắn bó với một bản sao giao dịch dựa trên kéo và để chương trình của tôi cập nhật các giá trị nhận dạng người đăng ký giống như trên cơ sở dữ liệu xuất bản ngay sau khi đồng bộ hóa (loại điều tôi ước là đại lý phân phối đã làm theo ý mình ). Trong mã giả, nó trông hơi giống thế này:

synchronize databases with TransSynchronizationAgent

equivalentTablesNotFound is a list of strings
for each table in publisher tables:
    try:
        check table identity value (this is via functionality provided by .NET's Microsoft.SqlServer.Management.Smo.Server class)
        parse identity value as integer to newIdentity
        if the table's identity value was NULL, skip to next loop iteration
        (HACK) increment newIdentity value by 1
        if there is no subscriber table with the same name as this one:
            record its name in equivalentTablesNotFound and skip to next loop iteration
        set subscriber table with same name's identity value to newIdentity using TSQL: DBCC CHECKIDENT ("tableName", newIdentity)
    catch:
        if exception shows that the error was because the table doesn't have an identity column, drop the exception

if equivalentTablesNotFound has more than zero entries, warn about tables on publisher without an equivalent name on subscriber

Có vẻ hoạt động tốt. Bit HACK là bởi vì, mặc dù theo mặc định và với tất cả các bảng của tôi, giá trị nhận dạng chỉ tăng một, nó có thể được cấu hình khác nhau, vì vậy về mặt kỹ thuật, bạn nên tìm hiểu cách tăng giá trị nhận dạng trên bảng nhà xuất bản và tăng nó cùng một cách


0

Phương pháp ưa thích của tôi để xử lý việc này là làm như sau:

a. Trước tiên hãy dừng tác nhân sao chép của bạn (để bạn không nhận được bất kỳ dữ liệu mới nào vào DB thuê bao của mình)

b. Thứ hai đổi tên bảng hiện có của bạn

exec sp_rename '[CurrentTable]', '[BackupTableName]'

c. Tạo lại bảng của bạn với bộ IDENTITY

CREATE TABLE [CurrentTable]
(
   ID INT NOT NULL IDENTITY(1,1), 
   OtherField VARCHAR(10) NULL,
   ....
)

d. Chèn lấp bảng của bạn (từ [BackupTableName]) với SET IDENTITY_INSERT

SET IDENTITY_INSERT [CurrentTable] ON
INSERT INTO [CurrentTable] (ID, OtherField, ...)
SELECT ID, OtherField, ....
FROM [BackupTableName]
SET IDENTITY_INSERT [CurrentTable] OFF

Khi bạn có ràng buộc IDENTITY trên DB của mình, thì bạn có thể thực hiện sao chép tùy chỉnh (nghĩa là: thay đổi chèn thay thế của bạn thành SET IDENTITY_INSERT [TableName] ON hoặc bạn có thể đặt cờ KHÔNG CHO TRẢ LẠI trên bảng (thông báo cho máy chủ SQL biết nếu người dùng kết nối là tác nhân sao chép, hãy hy vọng giá trị IDENTITY sẽ được cung cấp) ( Tôi thích cách tiếp cận sao chép tùy chỉnh, vì nó giúp tôi linh hoạt hơn )

e. Sửa đổi thủ tục lưu trữ sao chép chèn của bạn (thường được đặt tên là sp_MSins_CiverseTable) để cũng chèn bằng cách sử dụngSET IDENTITY INSERT

ALTER procedure [dbo].[sp_MSins_CurrentTable]
    @c1 int, @c2 varchar(50), ...
as
begin
    /* allow replication to insert values for IDENTITY */
    SET IDENTITY_INSERT [CurrentTable] ON
    insert into [CurrentTable]
        ([ID], [OtherField], ...)
    values
        (@c1, @c2, ...)
    /* now turn off Identity insert */
    SET IDENTITY_INSERT [CurrentTable] OFF
end

f. Bây giờ bạn có thể khởi động lại đại lý nhân rộng của bạn.


1
lol, so với việc sử dụng DBCC CHECKIDENT, phương pháp này là một khối lượng công việc lớn.
Jez

@Jez bạn sẽ cần tạo lại bảng (với IDENTITY) để chạy DBCC CHECKIDENT ... Ảnh chụp nhanh sao chép sẽ tạo bảng với ràng buộc IDENTITY (dựa trên q của bạn Tôi muốn nói DBCC CHECKIDENT đã thắng 't work)
Andrew Bickerton

FYI nó đã hoạt động và việc nhân rộng sẽ tạo ra bảng với ràng buộc IDENTITY ...
Jez

@Jez bạn đã thiết lập kiểu sao chép nào? (nếu bạn thiết lập nó là MERGE sẽ xảy ra, đối với GIAO DỊCH thì điều đó thường không xảy ra, mặc dù sao chép có thể tùy chỉnh cao nếu bạn không sử dụng GUI)
Andrew Bickerton

Giao dịch. Như tôi đã nói IDENTITY ở đó, nhưng giá trị nhận dạng hiện tại được đặt lại thành giá trị hạt giống (1).
Jez
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.