nhibernate - 如何将主键生成从 "increment"迁移到 "hi-lo"?

标签 nhibernate migration primary-key

我正在使用一个中等大小的 SQL Server 2008 数据库(大约 120 个表,备份压缩后大约 4GB),其中所有表主键都声明为简单的 int 列。

目前,主键值是由 NHibernate 使用增量身份生成器生成的,到目前为止效果良好,但妨碍了迁移到多处理环境。

系统上的负载不断增加,因此我正在评估允许使用多个服务器访问公共(public)数据库后端所需的工作。

过渡到 hi-lo 生成器似乎是最好的前进方式,但我找不到有关此类迁移如何工作的详细信息。

NHibernate 会自动为我在 hi-lo 表中创建行,还是需要我手动编写这些行?

如果 NHibernate 确实自动插入行,它是否正确考虑了现有的键值?

如果 NHibernate 确实能自动处理事情,那就太好了。如果没有,有什么工具可以提供帮助吗?

更新

NHibernate 的增量标识符生成器完全在内存中工作。它通过从表中选择已用标识符的最大值来播种,但从那时起,通过简单的增量分配新值,而不引用回底层数据库表。如果任何其他进程向表中添加行,最终会出现主键冲突。您可以在一个进程中运行多个线程,但不能运行多个进程。

作为比较,NHibernate identity 生成器的工作原理是使用标识列配置数据库表,将主键生成的控制权交给数据库。这很有效,但会损害工作单元模式。

hi-lo算法介于这两者之间 - 主键的生成通过数据库进行协调,允许多重处理,但实际分配可以完全发生在内存中,避免工作单元模式的问题.

最佳答案

要使用 hi-lo 生成器,您需要创建查找表来存储生成的键的“Hi”部分的下一个值。您可以选择为每个实体表创建一个单独的列、将由所有实体使用的单个列或这两个选项的组合。

如果使用共享列,则每个生成的键将仅由单个实体使用。如果有很多实体表,这可能是更好的选择,但它会减少可以生成的 Id 总数。

例如,我们的项目使用包含三列的 HiLoLookup 表:

NextEntityId BIGINT NOT NULL,
NextAuthenticationLogId BIGINT NOT NULL,
NextConfigurationLogId BIGINT NOT NULL

日志表有大量插入,因此被赋予了一个单独的 Hi 值池。我们的常规实体表的主键列使用 64 位 BIGINT 数据类型,因此即使 id 序列中存在较大间隙,也不会有溢出的危险。使用 ID 共享池来减少管理开销。

高低生成器没有内置支持使用与现有键不冲突的起始值来初始化自身 - 因此这需要手动执行。 用作起始“hi”值的值取决于几个考虑因素:

  • 现有最大 ID 值 - 生成的 ID 需要高于此值以避免重复
  • 在从数据库请求新的“hi”值之前应生成多少个 id (max_lo) - 较大的值可以提高并发性,但会增加 id 浪费的可能性,特别是在服务频繁重启

在确定起始“hi”值时,实体映射中提供的 max_lo 值至关重要。例如,考虑一个表的最大现有 id 值为 12345。返回数据库之前应生成的 id 数量为 1000。在这种情况下,起始 hi 值应为 (12345/1000) + 1 = 13,第一个生成的 id 将为 13000。由于 HiLoGenerator 实现中的一个怪癖,实体配置中提供的 max_lo 值需要为 999,<强>不是1000

如果使用 .hbm 映射:

<generator class="hilo">
    <param name="table">dbo.HiLoLookup</param>
    <param name="column">NextEntityId</param>
    <param name="max_lo">999</param>
</generator>

关于nhibernate - 如何将主键生成从 "increment"迁移到 "hi-lo"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10827054/

相关文章:

c# - 最小起订量:不可覆盖成员的无效设置:x => x.GetByTitle ("asdf")

.net - 流利的 NHibernate : multiple one-to-many relationships between the same entities

database - 合并具有相同主键的 SQLite3 表

sql-server - 创建有唯一索引但没有主键的表有什么影响?

mysql - 为什么auto_increment id不逐一递增,怎么设置?

nhibernate - 一级缓存可以与 ICriteria 或其他 API 一起使用吗?

c# - 如何使用 "not in"执行 NHibernate QueryOver?

c# - Entity Framework 创建的主键不会自动递增

django - 在 django 中使用 makemigration 时出错

mysql - 将 .sql 文件从 MSSQL 导入 MySQL