簡體   English   中英

SQL Server Transaction Replication error Online index operations can only be performed in Enterprise edition of SQL 服務器從Ent到Standard

[英]SQL Server Transaction Replication error Online index operations can only be performed in Enterprise edition of SQL Server from Ent to Standard

我正在為 SQL 服務器中的多個數據庫設置事務復制,其中發布者位於 SQL Server 2014 Enterprise Edition 上,目標是 SQL Server 2017 Standard。 除了 2 個數據庫外,所有數據庫都運行良好,我遇到的錯誤就在將快照應用到這 2 個數據庫的訂閱者的最后。

"Online index operations can only be performed in Enterprise edition of SQL Server"

我假設這意味着這兩個數據庫在某一時刻應用了索引或更改了 ONLINE=ON? 我試圖在沒有聚簇索引和非聚簇索引的情況下創建快照,並且也不斷遇到錯誤。

如果這是真的,有沒有辦法告訴數據庫中的哪些文章已經編寫了 ONLINE=ON 的腳本來導致彈出這個錯誤?

我計划在較小的源數據庫上使用 ONLINE=OFF 重建完整索引,希望這是解決方法,但我很好奇是否有人知道解決方案。 不想因為這個錯誤而被迫獲得企業版!

更新:索引重建並沒有讓我擺脫錯誤。 有沒有一種方法可以在不應用主鍵索引的情況下進行事務復制?

更新#2:所以報告回來,我切換了數據庫類型並截斷了日志,然后重新創建了發布並且它不會在沒有相同錯誤的情況下拍攝快照。 然后,我確定了有問題的文章將其從出版物中刪除以創建新快照,但錯誤仍然存在。 之后,我進行了日志截斷和索引重建,並創建了一個全新的發布以及訂閱者和目標數據庫,但在將快照傳遞給訂閱者時,該數據庫仍然出現錯誤。 (有或沒有文章)

所以最后,看起來一旦您在數據庫的架構更改、索引等上使用 ONLINE=ON 功能,您就會陷入只能從企業版到企業版的事務復制,除非您開始編輯二進制文件在處理大量事務性生產環境時,不推薦、不支持事務日志,實際上弊大於利。

驚人的! 我喜歡這個問題

我們終於有理由深入挖掘內部結構

我假設這意味着這兩個數據庫在某一時刻應用了索引或更改了 ONLINE=ON?

這有道理...

但請記住,“在線索引操作”可以包括多個任務,如 CREATE/ALTER/DROP INDEX; ALTER TABLE(使用 CLUSTERED 索引選項和更改列添加或刪除 UNIQUE 或 PRIMARY KEY 約束)。

很好奇是否有人知道解決方案

第一步,我們需要找到導致此問題的在線執行和使用任務的人員/方式/任務 這意味着我們需要找到在線使用的任務並阻止您使用非企業版。

筆記! 為了便於討論,我將討論CREATE INDEX ,但同樣的過程可以應用於記錄在事務日志中的其他 ONLINE 任務。

這可能有點復雜和先進,因為關於我們如何創建索引的信息並沒有像我們記得的那樣存儲在數據庫表(元數據)中,因為一旦創建它就沒有價值/用途(通常,因為我們現在發現它可能在這個問題中有價值)。

因此,我們需要從事務復制從中提取信息的相同位置,從事務日志中提取信息

對於此任務,我們將使用未記錄的 function fn_dblog

問:有沒有辦法判斷數據庫中的哪些文章已使用 ONLINE=ON 編寫腳本

答案是肯定的:-)

讓我們從頭到尾演示一下

CREATE DATABASE Test
GO
USE Test
GO

DROP TABLE IF EXISTS fyi_links_indexed
GO

Create table fyi_links_indexed(url char(100))
GO -- No index yet

-- Let's find the last LSN from the log file. 
-- This will help us to filter the log file in our sample instead of read the entire log file each time.
SELECT TOP 1 [Current LSN] 
FROM fn_dblog(null,null)
ORDER BY [Current LSN] DESC
GO -- remember this value for next step. In my test Db I got 00000025:00000a18:0024

-- For each query now we will use: where [Current LSN] > '00000025:00000a18:0024'

-- Let's CREATE INDEX ONLINE and check what was added in the transaction log

CREATE INDEX fyi_links_url ON fyi_links_indexed (url)
   WITH (ONLINE = ON);
GO

-- just for understanding let's see waht added to the transaction log:
SELECT * FROM fn_dblog(null,null)
where [Current LSN] > '00000025:00000a18:0024'
GO
-- Notice that creating the index online writes multiple rows in the transaction log


-- just for understanding let's confirm that this index was created ONLINe,
-- which is what the replication see as well
-- and what failed in the standards edidion
SELECT [Current LSN], [Transaction ID], [Transaction Name] FROM fn_dblog(null,null)
where [Current LSN] > '00000025:00000a18:0024' and [Transaction Name] in('CREATE INDEX','ONLINE_INDEX_DDL')
GO


-- our next task is to find the transaction ID
-- search for Transaction name "CREATE INDEX"
SELECT [Transaction ID], [Transaction Name] FROM fn_dblog(null,null)
where [Current LSN] > '00000025:00000a18:0024' and Operation = 'LOP_BEGIN_XACT' and [Transaction Name] = 'CREATE INDEX'
GO -- 0000:0000042d



-- Now we have the transaction ID so we can get the object ID if the entitiy which was used ONLINE (in our case the INDEX)
select [Lock Information]
FROM fn_dblog(null,null) where [Transaction ID] = '0000:0000042d' and [Lock Information] like '%object_id = %'
GO 
-- result should be like:
-- HoBt 0:ACQUIRE_LOCK_SCH_M METADATA: database_id = 9 INDEXSTATS(object_id = 901578250, index_id or stats_id = 2), lockPartitionId = 0
-- Notice the object Id (in my case 901578250)

就這些!

我們找到了使用 ONLINE 創建的有問題實體的 ID


接下來是什么?

問題是從事務日志中清除信息以便繼續復制,這可能是非常先進和復雜的(理論上可以完成)

所以在這一點上我們知道要修復什么但下一個問題是如何修復......

最簡單的方法是在已經創建有問題的實體之后從這一點開始復制,因為如果我們使用當前的事務日志,那么即使我們現在刪除索引,問題也會出現,因為復制是逐個日志完成的,一旦我們將使用包含CREATE INDEX ONLINE的日志,然后問題將再次出現。

創建復制后,我們需要避免將來出現相關問題

例如,在生產中,索引重建(可以使用 ONLINE)的執行通常是通過在 Jobs 中執行的手動執行或維護任務來完成的(不幸的是,它可能來自其他觸發器,如果您不熟悉系統)。

此時您必須確認,如果您從源服務器復制了相同的作業,那么您應該修復所有這些作業和其他使用 ONLINE 的任務。

這是一個單獨的任務

找到包括世界在線的工作

SELECT 
    s.step_id as 'Step ID',
    j.[name] as 'SQL Agent Job Name',
    s.database_name as 'DB Name',
    s.command as 'Command'
FROM   msdb.dbo.sysjobsteps AS s
INNER JOIN msdb.dbo.sysjobs AS j ON  s.job_id = j.job_id
WHERE  s.command LIKE '%ONLINE%'

我們在這里遇到的最后一個問題

有沒有一種方法可以在不應用主鍵索引的情況下進行事務復制?

否。事務復制需要對每個已發布的表進行主鍵約束。

https://learn.microsoft.com/en-us/sql/relational-databases/replication/administration/frequently-asked-questions-for-replication-administrators?view=sql-server-ver15#how-do-i-管理對已發布表的約束---


信用

答案首發於此(原作者復制於此): https://ariely.info/Blog/tabid/83/EntryId/302/SQL-Server-Transaction-Replication-from-Enterprise-to-Standard-error -在線索引操作只能在企業版中執行.aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM