一句话让 SharePoint 罢工

首先将问题呈现在大家面前。 注意:请在开发环境或者测试环境中进行下面的实验。 打开 SharePoint 内容数据库所在的 SQL Server 管理工具。 在你希望做测试的内容数据库中运行下面的SQL语句:...... ​

一句话让 SharePoint 罢工

注意,题目不是标题党,绝非吸引眼球,这是一个事实描述。

制造问题

首先将问题呈现在大家面前。
注意:请在开发环境或者测试环境中进行下面的实验。

  • 打开 SharePoint 内容数据库所在的 SQL Server 管理工具。
  • 在你希望做测试的内容数据库中运行下面的SQL语句:
DBCC CHECKIDENT(SiteQuota, Reseed, 2147483647)
  • 用浏览器打开 SharePoint任意的界面,一切都挺好不是?接下来随便找到一个列表,新建一条列表项数据试试。一定不会成功,且有如下的错误:

spe1

  • 查看系统日志,会得到下面的异常:

    • 中文:将 IDENTITY 转换为数据类型 int 时出现算术溢出错误。发生算术溢出。
    • 英文:Msg 8115, Arithmetic overflow error converting IDENTITY to data type int. Arithmetic overflow occurred.
  • 进而你会发现,整个 SharePoint 系统除了可以查看数据,增删修数据都不行。类似于将内容数据库设置为只读的状态。

究竟发生了什么?为什么会产生这样的情况?

发现问题

当然,问题产生并不是我们真的去SQL Server 中运行这样一句话,而是在日积月累的使用中沉淀下来的。
首先看看SiteQuota表,这是一个记录网站集使用量的表,具体的工作方式不在这里详细介绍,只说一个关键的点,当我们在 SharePoint 中新增 修改 删除一条列表项数据时,这个表的 Identity 会自增长2。表的 Identity 数据类型是INT,4个字节,也就是说 Identity 的最大值为2^31-1,也就是2147483647,简短点翻译就是二十一亿。当然,针对 SharePoint 不只是列表项操作会触发这个 Identity 的增加(比如新建一个列表会增加14),但我们可以这样简单计算,一个 SharePoint 的内容数据库最多允许大约十亿次左右的数据操作。 这个问题在 SharePoint 2013 以及还未发布的 SharePoint 2016上均存在。

以 SharePoint 2013为例:

  • 单个内容数据库建议的列表项上限为六千万条。如果在满载的情况下,平均一条列表项数据允许进行20次左右的操作。
  • 从时间序列上来看,如果每秒进行31次左右的数据操作,一年时间也能达到这个上限。

当然,对于 SharePoint 系统来讲这算是一个很大的数字,但并非不是一个不可触及的数字高度。而且这个数字并非SharePoint 系统软硬阈值之类的设置,这是 SharePoint 一个深层次的问题。

这个问题已经提交给 SharePoint 产品组,产品组进行了几天的确认,确定有这个问题,但属于超出产品的使用范畴(小声嘀咕一下,一个企业级产品,十亿次以上操作应该可以支持吧?)。所以我正在据理力争,希望他们能解决这个问题或者给出合理的用户提示(一个很困扰的数据库层级的异常,查找问题用了大半天时间)。否则到达这个上限后,整个 SharePoint 网站集只是一个能提供莫名异常的只读站点,不能进行任何操作。

在平常生产环境使用中,我们不会手动去设置 Identity,那究竟怎么样使用,需要多长时间,什么样的业务场景才会遇到这个问题?简短概括一下就是:

只有一个高效使用的 SharePoint 系统才配得上这个问题

高效使用

上面的问题是在水杉工作流平台(基于 SharePoint 列表打造的工作流及表单平台)使用过程中呈现出来的。我相信 SharePoint 产品组在全球范围也是第一次接到这个问题,从这个角度说,水杉工作流平台在高效使用 SharePoint 方面已经走到了世界前列。

我们可以看以下一组水杉工作流平台上的实际生产环境数据:

  • 软件环境:Windows Server 2012, SharePoint 2013, Sql Server 2014。
  • 硬件环境:两台 SharePoint 服务器(前端兼应用程序),一台数据库服务器,配置参考微软官方推荐。
  • 服务设置:单台 SP 前端单个应用程序池设置5个独立进程。IIS 的 TCP 连接数设置为500。每台 SharePoint 服务器上有十个 timerjob 实例在支撑水杉工作流调度。
  • 用户使用环境:PC 端,Android 客户端,iOS 客户端。
  • 用户数: 5,000
  • 流程类型数:120
  • 共有流程节点: 2,000
  • 一个月产生的业务数据 (基于 SPList)
    • 总共流程实例: 25,000
    • 运行中的流程实例:7,000
    • 已分配任务数:187,000
    • 已分配任务处理人次:100,000

用户访问系统,比如下面这样一个中等程度的表单(太长,只截取了一半),通过水杉工作流平台对象模型从大约十个左右的 SPList 中获取数据。在日常使用情况下,用户访问表单首次响应时间控制在1,000毫秒内。

spe2
she3

那么在这样一个 SharePoint 系统中,一个月能让SiteQuota表的 Identity 增加多少?1.5亿。也就是说维持这样一个量级的业务系统,一个月需要进行七千万次数据操作。达到这个天花板所需要的时间也就是一年半。

解决问题

天花板总有达到的一天,那么遇到这个问题该怎么解决呢?
目前找到最直白的办法就是重新 reset identity。

DBCC CHECKIDENT(SiteQuota, Reseed, 0)

注意:这不是微软官方推荐的解决办法(目前没有其他解决办法),如果你有遇到,请联系微软提供支持。这个问题我也会继续和 SharePoint 产品组沟通下去,一旦有有效的解决办法,我会更新状态。

你的 SharePoint 在被高效使用吗?