SQL Server CE @threshold和标识范围真正发生了什么?

时间:2016-09-16 00:42:25

标签: sql sql-server-ce

Folks,因为这个问题与IDENTITY列和合并复制有关,如果我可能会要求你不要回答#34;而是使用GUID代替"。我非常清楚两者的优点和局限性,并且自SQL Server 2000以来一直在使用SQL复制。我偶尔会感到惊讶。就是这种情况。

这是对问题的复杂描述,请耐心等待。

以下是https://msdn.microsoft.com/en-us/library/ms152543.aspx的摘录,是我在身份范围和阈值方面一直都能理解的内容。

  

"运行SQL Server Compact或以前版本的SQL Server的订户只分配了主要范围;新范围的分配由@threshold参数控制。此外,重新发布订阅服务器仅具有@identity_range参数中指定的范围;它必须将此范围用于本地更改以及与重新发布订阅服务器同步的订阅服务器的更改。例如,您可以为@pub_identity_range指定10000,为@identity_range指定500000,为@threshold指定80%。在订阅服务器上插入8000次(10000的80%)后,将为发布服务器分配一个新范围。分配新范围时,表中的标识范围值将存在间隙。指定较高的阈值会导致较小的间隙,但系统的容错性较低:如果合并代理由于某种原因无法运行,则订阅者可能更容易耗尽身份。"

如果假设这是真的,那么我们就会开始解决问题。

为了帮助用户使用我们的应用程序,我们一直在使用以下查询的变体,让客户知道如果他们继续使用并启动同步以获得新范围,他们可能会用尽身份。

SELECT 
    AUTOINC_MAX, AUTOINC_NEXT, AUTOINC_MAX-AUTOINC_NEXT 
FROM 
    INFORMATION_SCHEMA.COLUMNS 
WHERE 
    TABLE_NAME = N'Asset'

AUTOINC_MAX | AUTOINC_NEXT | AUTOINC_MAX-AUTOINC_NEXT
------------+--------------+-------------------------
3081898     |   3080899    |        999

通过评估AUTOINC_MAX - AUTOINC_NEXT(= 999),我们可以看到我们何时会降低ID

在代码中,我们正在查看AUTOINC_MAX - AUTOINC_MIN,它给出了分配的范围。使用默认阈值80%和剩余范围,我们可以建议客户端同步,如果他们看起来已经用完了。

然而,这是我所认为的真实在实践中失败的地方。参考上面的Microsoft详细信息,这句话突出显示"当指定新范围时,表格中的标识范围值将存在差距。"

我认为这意味着以下

如果我们的用户具有0-1000个ID的标识范围并且使用最多801的ID。在下一次同步时,将为用户分配下一个1001-2000的范围(我们假设一个订户用于说明)。作为同步的结果,下一个使用的ID将是1001,与802-1000之间留下间隙。

首先请告诉我,如果我的理解是错误的。

其次,这不是我们在实践中看到的。

实际上,我们所看到的,基于上面的例子,后同步和后续插入,是在我们完全消耗原始范围之前使用的ID的平衡。然后,在扩展AUTOINC-MIN范围时,-MAX和-NEXT都更新到新范围。没有发生其他同步。

以下是一个例子。

在目标表中,使用的最后一个ID是3080899

为了模拟用法,使用了以下查询

INSERT INTO Asset (lInstID, lTypeID, sUsrName, lUsrID, dCreated, dAudit,  sStatus)
    SELECT 
        lInstID, lTypeID, sUsrName, lusrID, dCreated, dAudit, sStatus
    FROM 
        Asset 
    WHERE 
        lAssetID = 3080899

插入后,使用的下一个ID值为3080900(如预期的那样,例如AUTOINC_NEXT = 3080899,+ 1 = 3080900)

我们重复此插入,直到达到分配的标识范围的80%。

SELECT 
    AUTOINC_MAX, AUTOINC_NEXT, AUTOINC_MAX-AUTOINC_NEXT 
FROM
    INFORMATION_SCHEMA.COLUMNS 
WHERE 
    TABLE_NAME = N'Asset'

AUTOINC_MAX | AUTOINC_NEXT | AUTOINC_MAX-AUTOINC_NEXT
------------+--------------+-------------------------
3081898     |   3081699    |           199

我们同步。我们注意到800个订阅者更改。我们查询,这就是我们所看到的。预先同步没有变化。

AUTOINC_MAX | AUTOINC_NEXT | AUTOINC_MAX-AUTOINC_NEXT
------------+--------------+-------------------------
3081898     |    3081699   |         199

我们继续插入,直到剩余零ID

AUTOINC_MAX | AUTOINC_NEXT | AUTOINC_MAX-AUTOINC_NEXT
------------+--------------+-------------------------
3081898     |   3081898    |            0

再插入一次,结果就是这个

AUTOINC_MAX | AUTOINC_NEXT | AUTOINC_MAX-AUTOINC_NEXT
------------+--------------+-------------------------
3082898     |    3081899   |           999

这是完全出乎意料的,与相反,当指定新范围时,表格中的标识范围值会有间隙。实际上IDENTITY RANGE是连续的。这有点令人满意,因为我们不会浪费ID。

我找不到存储下一个分配范围的.SDF

我假设来自next_range_start服务器表的next_range_endsysmergearticles但是找不到在.SDF中公开这些值的文档}。

如果有人知道这里会发生什么,我会非常感激。

要注意的是,如果你完全花费这个"下一个范围"没有同步,数据库会按预期返回错误。

同步发布错误显示订阅者上传了1200条新记录(200条来自之前的范围加上来自"下一个范围的#300;")

AUTOINC_MAX | AUTOINC_NEXT | AUTOINC_MAX-AUTOINC_NEXT
------------+--------------+-------------------------
3083898     |    3082898   |          999

亲切的问候

安德鲁

1 个答案:

答案 0 :(得分:0)

对于那些感兴趣的人,我从微软的一个小伙伴那里得到了这个答案。

  

嗨,安德鲁,

     

根据测试,我认为这应该是一个文档错误。 CE   同步应该使用运行SQL Server的相同方法订阅者   2005年或更高版本。也就是说,

     

订阅者将收到两个身份范围。次要范围是   大小与主要范围相等;当主要范围是   耗尽,使用辅助范围,合并代理程序分配   订阅者的新范围。新范围成为次要范围   范围,并且当订阅者使用标识时,该过程继续   值。

     

所以,让我们说,你将用户标识范围设置为10.然后   发布者从1到11开始主要范围,11到21开始   次要范围。订阅者从21岁开始为31岁   范围和次要范围31到41。如果没有   消耗所有用户范围之前的同步,您将点击   错误,这意味着你可以插入双号记录   在您点击之前设置为订阅者数据库的订阅者范围   错误信息。

     

对于发布商结束,如果您消耗所有范围但不包含在一个批次中,   插入触发器将帮助您重新分配新范围。例如,   在同步之前,如果发布者结束达到21并且下一次插入   将从42开始,因为22到41属于订户。

     

如果您还在,多个订阅者的机制相同   在订户的主要范围内,不会分配新范围。如果   你已经在二级范围内,将分配新的范围   并使你的二级范围成为新的主要范围和新范围   新的中学范围。

     

您可以跳过重新发布方案,因为CE用户无法采取行动   作为出版商。

     

致以最诚挚的问候,

     

彼得https://social.msdn.microsoft.com/profile/sql%20team%20-%20msft/?ws=usercard-mini

这确切地证实了我们在测试中看到的内容。因此,要明确SQL CE 3.1+在首次同步时确实会收到主要和次要范围。在扩展第一个范围后,辅助设备成为主设备,下一个同步设备将应用新的辅助范围。

只需要查询来识别SQL CE中的辅助范围...