繁体   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