postgresql 生成无间隙的序列

2024-03-21

我必须/必须为发票创建唯一的 ID。我有一个表 ID 和这个唯一编号的另一列。我使用序列化隔离级别。使用

  var seq = @"SELECT invoice_serial + 1 FROM  invoice WHERE ""type""=@type ORDER BY invoice_serial DESC LIMIT 1";

没有帮助,因为即使使用 FOR UPDATE 它也不会读取序列化级别中的正确值。

唯一的解决方案似乎是放置一些重试代码。


序列不会生成无间隙的数字集,并且实际上没有办法让它们这样做,因为回滚或错误将“使用”序列号。

我不久前写过一篇关于此的文章。它是针对 Oracle 的,但实际上是关于无间隙数字的基本原则,我认为这同样适用于这里。

好吧,又发生了。有人有如何实现生成一系列无间隙数字的要求,一群反对者突然降临到他们身上说(这里我稍微解释一下)这会降低系统性能,这很少是一个有效的要求,无论谁写的要求是白痴等等等等。

正如我在帖子中指出的那样,有时生成无间隙数字系列是真正的法律要求。英国超过 2,000,000 家注册增值税(销售税)的组织的发票号码都有这样的要求,其原因相当明显:这使得向税务机关隐瞒收入的产生变得更加困难。我看到评论说这是西班牙和葡萄牙的要求,如果其他许多国家没有要求,我也不会感到惊讶。

那么,如果我们承认这是一个有效的要求,那么在什么情况下无间隙系列*的数字会成为问题呢?群体思维常常会让你相信它总是如此,但事实上它只是在非常特殊的情况下的一个潜在问题。

  1. 这一系列数字必须没有间隙。
  2. 多个进程创建与该号码关联的实体(例如发票)。
  3. 这些数字必须在创建实体时生成。

如果必须满足所有这些要求,那么您的应用程序中就有一个序列化点,我们稍后将讨论它。

首先让我们讨论一下实现一系列数字要求的方法(如果您可以放弃其中任何一个要求)。

如果您的数字序列可能有间隙(并且您有多个进程需要立即生成数字),那么请使用 Oracle Sequence 对象。它们的性能非常高,并且已经对可能出现差距的情况进行了很好的讨论。如果很重要的话,通过设计努力最大限度地减少生成数字和提交事务之间流程失败的机会来最小化跳过的数字量并不是太有挑战性。

如果您没有创建实体的多个流程(并且您需要必须立即生成的无间隙数字系列),就像批量生成发票的情况一样,那么您已经有了序列化点。这本身可能不是问题,并且可能是执行所需操作的有效方式。在这种情况下,生成无间隙数字相当简单。您可以读取当前的最大值,并使用多种技术将递增值应用于每个实体。例如,如果您要将一批新发票从临时工作表插入到发票表中,您可以:

insert into
  invoices
    (
    invoice#,
    ...)
with curr as (
  select Coalesce(Max(invoice#)) max_invoice#
  from   invoices)
select
  curr.max_invoice#+rownum,
  ...
from
  tmp_invoice
  ...

当然,您会保护您的进程,以便一次只能运行一个实例(如果您使用的是 Oracle,则可能使用 DBMS_Lock),并使用唯一的键约束保护发票#,并且可能使用单独的代码检查缺失值,如果你真的真的很在乎。

如果您不需要即时生成数字(但需要它们无间隙并且多个进程生成实体),那么您可以允许生成实体并提交事务,然后将数字的生成留给单个批次工作。对实体表的更新,或插入到单独的表中。

那么,我们是否需要通过多个进程即时生成一系列无间隙数字的三重奏呢?我们能做的就是尽量减少连载过程中的时间,我提供以下建议,并欢迎任何额外的建议(当然也包括反建议)。

  1. 将当前值存储在专用表中。不要使用序列。
  2. 通过将其封装在函数或过程中,确保所有进程使用相同的代码来生成新数字。
  3. 使用 DBMS_Lock 串行化对数字生成器的访问,确保每个系列都有自己的专用锁。
  4. 持有系列生成器中的锁,直到通过在提交时释放锁来完成实体创建事务
  5. 将数字的生成延迟到最后可能的时刻。
  6. 考虑生成数字之后和提交完成之前意外错误的影响 - 应用程序会正常回滚并释放锁,还是会保持序列生成器上的锁直到会话稍后断开连接?无论使用哪种方法,如果交易失败,则序列号必须“返回到池中”。
  7. 您可以将整个事情封装在实体表上的触发器中吗?您能否将其封装在表或其他插入行并自动提交插入的 API 调用中?

来源文章 http://oraclesponge.wordpress.com/2010/09/24/generating-a-gap-free-series-of-numbers-not-always-a-problem/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

postgresql 生成无间隙的序列 的相关文章

随机推荐

  • 如何在 CoffeeScript 中传递两个匿名函数作为参数?

    我想传递两个匿名函数作为 jQuery 悬停的参数 如下所示 element hover function do stuff on mouseover function do stuff on mouseout 只需一个就很容易 hover
  • git 错误; RPC失败;结果=22,HTTP 代码=401

    我正在尝试将一些颠覆代码和历史记录放入 TFS 中 通过 GIT 似乎是一个快速的胜利 并按照以下网址中的步骤进行操作 http www incyclesoftware com 2013 08 how easy its to migrate
  • 使用参数添加和删除事件监听器

    我正在写一个普通 JavaScript工具 启用后将事件侦听器添加到传递给它的每个元素 我想做这样的事情 var do something function obj do something for var i 0 i lt arr len
  • 如何将变量从 PHP 传递到 Python?

    我可以从 a 传递一个变量吗 php脚本到Python反之亦然 例如 myPHPScript php hello hello myPythonScript py print get the result from hello variabl
  • Android Studio 错误:增量输出目录应设置为输出目录

    我导入了一个github项目 https github com caarmen poet assistant https github com caarmen poet assistant到我的 Android Studio 当我单击 Ma
  • 如何更改菜单栏的字体颜色?

    如何更改 QML 菜单项的文本颜色MenuBar import QtQuick 2 4 import QtQuick Controls 1 3 import QtQuick Window 2 2 import QtQuick Dialogs
  • 在查询中使用变量表名

    有时我需要运行相同的 SQL Server 脚本 每次将每个表名称中的一两个字母更改为每次运行脚本时都不同的值 如何在脚本开头设置一次 这样我就不需要更改每个表名 这是该脚本的一个简化示例 实际上它包含更多的表 SELECT FROM T
  • Python:从url获取shoutcast/网络广播电台的名称

    我一直在尝试根据 python 中的 url 获取网络广播电台的名称 标题 但到目前为止还没有运气 网络广播电台似乎使用 HTTP 之外的其他协议 但如果我错了 请纠正我 例如 http 89 238 146 142 7030 http 8
  • CodeIgniter、模型、ORM,怎么处理?

    我从 CodeIgniter 开始 在 Google 中潜入几个小时后 我有点困惑 让我们尝试用一个简单的例子来解释我的问题 我有一个表 car 其中包含字段 name 和 color 因此我想要一个 php 类 Car 这样我的代码最终看
  • AWS Elastic Beanstalk:在运行 PHP 的 EC2 实例上终止 HTTPS

    我想在我的单实例 EBS 环境上允许 https 连接 我按照以下链接中的步骤操作 http docs aws amazon com elasticbeanstalk latest dg https singleinstance php h
  • 字符串作为决策树/随机森林中的特征

    我是机器学习新手 现在我正在做一些关于决策树 随机森林应用的问题 我正在尝试解决一个以数字和字符串 例如国家 地区名称 为特征的问题 现在 scikit learn 库仅接受数字作为参数 但我想注入字符串以及它们携带大量知识 我该如何处理这
  • ipython笔记本单元格的背景颜色

    如何更改 iPython Notebook 中特定单元格的背景颜色 例如 我正在编写一本手册 我想在灰色文本框中添加一些终端命令 如下所示http ipython org ipython doc 1 interactive nbconver
  • React Native - 如何像 iOS 或 Instagram 一样进行模糊视图?

    模糊背景透明度 是否可以在不使用背景图像的情况下模糊视图 我想展示家长内容在上面背景模糊视图 in modal 类似这样的 尝试过反应本机模糊 https github com react native community react na
  • Linq lambda 表达式 - 查找一周中距离当前日期(现在)最近的一天

    例如 我将星期一 星期四和星期日作为抽奖日期 使用 Linq Lambda 查找与 Datetime Now 最接近的 dayOfWeek 的方法是什么 我使用正常功能完成了此操作 但我想知道如何使用 Linq Lambda 来完成此操作
  • 在 webapp 中优雅地关闭 ExecutorService?

    在我的网络应用程序中 我创建了一个使用ExecutorService具有固定大小的线程池 我重复使用相同的ExecutorService在整个应用程序生命周期内 private static ExecutorService pool Exe
  • 如何创建一个内容为表达式结果的有限迭代器?

    我想创建一个Iterator通过 重复 评估表达式来获取下一个元素 并且我希望表达式能够返回某个值来终止它 我唯一发现的就是这样迭代器 continually http www scala lang org api current inde
  • Python有限差分函数?

    我一直在 Numpy Scipy 中寻找包含有限差分函数的模块 然而 我发现的最接近的是numpy gradient 这对于二阶精度的一阶有限差分很有用 但如果您想要更高阶的导数或更准确的方法 则效果不太好 我什至还没有找到很多专门用于此类
  • 如何在客户端读取excel文件内容?

    在 JSP 页面中 我需要浏览 excel 文件 在系统上选择文件后 我需要读取该 excel 文件内容并填写表格 目前我已经尝试使用下面的代码 但它只能在 IE 中工作 并对 ActiveXObject 的 IE Internet 选项进
  • 使用 java poi 从 Office 2007+ 文档中读取属性集

    我尝试从 Office 2007 文档 docx xlsx 读取属性集 找到了惊人的解决方案http poi apache org hpsf how to html http poi apache org hpsf how to html
  • postgresql 生成无间隙的序列

    我必须 必须为发票创建唯一的 ID 我有一个表 ID 和这个唯一编号的另一列 我使用序列化隔离级别 使用 var seq SELECT invoice serial 1 FROM invoice WHERE type type ORDER