我提前为一篇长篇文章道歉,但我真的想确保在向社区寻求帮助之前我做了尽职调查,所以就这样了。
我正在研究概念证明,目的是使用事务复制来维护我们数据库的“报告”副本。该设置将包括一个“发布者”服务器和一个单独的“订阅者”服务器。复制将是一个“拉”事务复制,分发服务器运行在订阅服务器上。再次:发布者 => 拉取 =>(分发者 + 订阅者)
我们希望在我们的每台服务器上都有很多数据库,因此,为了模拟这种情况,我在发布者上恢复了 100 个数据库(每个大约 1 GB)。所有数据库都是相同的。
我编写了一个脚本,它使我能够以自动方式设置复制(因为显然我不想手动进行数十次)。该脚本执行以下步骤:
为数据库启用复制(如果尚未启用):
为数据库创建日志读取器代理
为数据库创建发布(如果不存在)
为数据库创建快照代理(先不要运行它)
将文章添加到出版物
运行快照代理作业(并等待它完成)
创建订阅数据库(如果不存在)
在订阅数据库中添加订阅(如果不存在)
创建分销代理
我能够成功地为大约 52 个数据库设置复制,并且一切运行良好. 当我到达数据库#53 时,事情开始出错。快照创建成功,但日志读取器和分发代理失败。转到数据库#54 现在一切都完全坏了。不会创建快照并且没有任何代理正在运行。我仔细查看了复制监视器和 SQL 代理作业以查找错误消息,但没有发现任何有用的信息。复制监视器只是说:“代理关闭。有关更多信息,请参阅作业'……'的 SQL Server 代理作业历史记录”。在详细信息部分,它说:“复制代理遇到故障。有关详细信息,请参阅上一个作业步骤历史消息或复制监视器”。接下来,我转到 SQL 代理作业并查看输出。在作业历史记录中,失败的步骤显示:“消息:复制代理遇到故障。有关更多信息,请参阅上一个作业步骤历史消息或复制监视器”。反过来,上一步根本没有任何信息。只有“消息”这个词,后面什么也没有。我还查看了 Windows 应用程序日志,以查找任何错误, 但它只是重复我在复制监视器和代理作业历史记录中看到的相同消息。我在代理命令中添加了“–output”参数(在 SQL 代理作业步骤属性中),希望输出文件能为我提供更多信息,但没有创建输出文件,这让我相信代理甚至没有启动。只是“消息”这个词,之后什么都没有。我还查看了 Windows 应用程序日志以查找任何错误,但它只是重复了我在复制监视器和代理作业历史记录中看到的相同消息。我在代理命令中添加了“–output”参数(在 SQL 代理作业步骤属性中),希望输出文件能为我提供更多信息,但没有创建输出文件,这让我相信代理没有甚至开始。只是“消息”这个词,之后什么都没有。我还查看了 windows 应用程序日志以查找任何错误,但它只是重复了我在复制监视器和代理作业历史记录中看到的相同消息。我在代理命令中添加了“–output”参数(在 SQL 代理作业步骤属性中),希望输出文件能为我提供更多信息,但没有创建输出文件,这让我相信代理没有甚至开始。
我在想我可能已经达到了一些硬件限制,所以我检查了磁盘空间并且有很多可用空间。我还检查了 RAM,它甚至没有使用 50%。
最后,真正让我受益的是我能够从命令行手动运行所有代理。例如,我可以从 SQL 代理快照作业复制粘贴参数,并使用这些参数从命令行运行 snapshot.exe - 快照已成功创建。logreader 和分发代理也是如此。
我在这里完全感到困惑,并感谢任何指向正确方向的指示。
最后一点(也许是唯一的一线希望):这个问题是完全可以重现的。我可以成功设置我的 50 多个订阅,然后问题将始终围绕订阅号 52-53 开始。
谢谢!
replication sql-server sql-server-2012 transactional-replication
我有一个表,我需要在其中填充值,这些值使用给定的步长递增。此外,我还有一个range的概念,因此一定数量的步长将适合范围内(不一定均匀)。一旦到达范围的末端,就需要进行循环过程。扭曲的是,我还需要计算我执行循环的次数,一旦达到给定的最大循环,我需要重置循环的计数。由于这令人困惑,这里有一个插图。
让我们创建并填充一个简单的表:
IF OBJECT_ID('tempdb..#mytable') IS NOT NULL DROP TABLE
tempdb.dbo.#mytable
CREATE TABLE #mytable (
id INT IDENTITY(1,1),
iteration INT,
step INT
)
INSERT #mytable
DEFAULT VALUES
GO 20
Run Code Online (Sandbox Code Playgroud)
现在让我们声明一些变量并使用它们来更新表中的数据(请注意,未使用 @max_iterations 变量,因为我不知道如何利用它以及为什么要问我的问题):
DECLARE @step_size INT = 7,
@max_iteration_range INT = 40,
@max_iterations INT = 2
UPDATE #mytable
SET iteration = (id*@step_size)/@max_iteration_range,
step = (id*@step_size)%@max_iteration_range
SELECT * FROM #mytable
Run Code Online (Sandbox Code Playgroud)
这是结果输出:
id iteration step
----------- ----------- -----------
1 0 7
2 0 14
3 0 …Run Code Online (Sandbox Code Playgroud) 我们有多个 SQL Server,每个 SQL Server 拥有数十个数据库 - 每个客户端一个(在这种情况下,客户端意味着一个客户组织)。这些数据库是通过应用程序访问的,但该应用程序当前使用单个 Windows 登录。因此,这会产生安全风险,即如果存在某些应用程序漏洞,理论上可以访问“其他”客户端的数据库。
处理这种情况的最佳方法是什么?
我们是否应该为每个客户端创建单独的登录名并让应用程序使用单独的登录凭据进行连接?这将降低安全风险,但会产生大量的管理开销(这可能是值得的)。
后续问题是:在这种情况下我们应该使用 Windows AD 安全性还是 SQL Server 身份验证。
我很感激任何建议!
我计划将数据库复制从 SQL Server 2012(发布者)运行到 SQL Server 2014(分发者和订阅者)——拉复制。
有没有人做过这种类型的跨版本复制并知道它是否有任何问题?
谢谢!
我想寻求帮助提出一个查询,它可以识别非重叠记录上的组。这是一个示例场景(无可否认是人为的)。假设我有一些员工被分配从事各种项目。虽然一名员工可以被分配到多个项目,但他/她在任何给定时间只能从事一个项目(你不希望我们都拥有这种奢侈吗:)。我需要找出哪些项目可以安排并行工作,因为它们不共享任何员工。这是设置示例表和数据的一些代码。
--1. Create #Projects table
IF OBJECT_ID('tempdb..#Projects') IS NOT NULL
DROP TABLE #Projects
CREATE TABLE #Projects (
ProjectId INT,
ProjectName VARCHAR(16)
)
INSERT INTO #Projects ( ProjectId, ProjectName )
VALUES ( 1, 'Project 1'), ( 2, 'Project 2'), ( 3, 'Project 3'), ( 4, 'Project 4'), ( 5, 'Project 5'),
( 6, 'Project 6'), ( 7, 'Project 7')
--2. Create #Employees table
IF OBJECT_ID('tempdb..#Employees') IS NOT NULL
DROP TABLE #Employees
CREATE TABLE #Employees (
EmployeeId INT,
EmployeeName VARCHAR(16)
)
INSERT …Run Code Online (Sandbox Code Playgroud) 下面是一个脚本,可用于重现我面临的问题。基本上问题是这样的:为什么(ID1 = 6,ID2 = 7)的记录没有填充到最终的#tt2表中?我可以手动插入它,所以它不会违反 UNIQUE 约束,但它不会作为 INSERT/SELECT 的一部分进行填充。
USE [tempdb]
GO
IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1
CREATE TABLE [#t1] ([ID] INT , [V] VARCHAR(10))
INSERT INTO #t1 (ID, V)
VALUES
(1,'A'),
(2,'B'),
(3,'B'),
(4,'C'),
(5,'E'),
(6,'E')
IF OBJECT_ID('tempdb..#t2') IS NOT NULL DROP TABLE #t2
CREATE TABLE [#t2] ([ID] INT , [V] VARCHAR(10))
INSERT INTO #t2 (ID, V)
VALUES
(1,'A'),
(2,'B'),
(3,'C'),
(4,'C'),
(5,'D'),
(6,'E'),
(7,'E')
IF OBJECT_ID('tempdb..#tt') IS NOT NULL DROP TABLE #tt
SELECT t1.ID AS …Run Code Online (Sandbox Code Playgroud) 我在两台服务器之间进行了事务复制设置,我注意到如果运行类似于以下的语句:
更新 mytable SET mycolumn = mycolumn
复制不知何故知道忽略此事务,并且它不会应用于订阅者。我已经通过运行 SQL Profiler 以及将 TIMESTAMP 列添加到我的订阅者表(它不会改变)来确认它。我怀疑有某种机制可以实现这种“智能”行为,我想知道是否有人可以对此有所了解。
谢谢!