查看: 11129|回复: 19

业务流水号的唯一连续性,如何实现?

[复制链接]
论坛徽章:
7
奥运会纪念徽章:水球
日期:2008-08-04 09:14:15CTO参与奖
日期:2009-01-15 11:42:46生肖徽章2007版:鼠
日期:2009-03-10 21:12:512010广州亚运会纪念徽章:皮划艇
日期:2010-11-11 17:57:242010广州亚运会纪念徽章:板球
日期:2010-11-11 17:57:32鲜花蛋
日期:2011-12-09 20:17:34ITPUB社区OCM联盟徽章
日期:2015-08-14 09:45:11
跳转到指定楼层
1#
发表于 2008-7-24 16:50 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
业务流水号=当前日期(YYYYMMDD)+顺序号
我目前的实现方法如下:
每增加一条业务流水前,先到库表中查询当天的最大业务流水号,然后当前最大业务流水号=当天最大业务流水号+1

这样做存在一个问题,并发增加业务流水时,会报违反主键约束的错误

如何才能保证业务流水号的唯一性且连续性啊???
论坛徽章:
3
2009新春纪念徽章
日期:2009-01-04 14:52:28ITPUB9周年纪念徽章
日期:2010-10-08 09:28:51蜘蛛蛋
日期:2011-09-13 10:35:40
20#
发表于 2008-7-25 10:27 | 只看该作者
我们系统有个业务表也通过序列的,而且还有一个删除标志,如果业务不成功也会占了序列号,但把删除标志置了1.

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
19#
发表于 2008-7-25 09:41 | 只看该作者
原帖由 jvkojvko 于 2008-7-25 07:49 发表


是的,直接取最大值+1就可以了,在程序最后保存数据的时候生成ID号



哪怕是“最后保存”,也可能是两个并发事务,它们同时SELECT MAX(), 同时取到同样的一个数字,再 INSERT 就有一个会出错。

所以你非得用行锁不可,最简单易行的就是我那个办法。

使用道具 举报

回复
论坛徽章:
27
设计板块每日发贴之星
日期:2007-08-24 01:05:17奥运会纪念徽章:拳击
日期:2012-06-25 14:17:112012新春纪念徽章
日期:2012-01-04 11:49:54生肖徽章2007版:龙
日期:2009-04-07 18:18:35生肖徽章2007版:鸡
日期:2008-10-14 14:14:30生肖徽章2007版:龙
日期:2008-10-08 21:22:20铁扇公主
日期:2008-09-28 11:20:58授权会员
日期:2008-09-05 13:30:44ITPUB元老
日期:2008-09-05 13:30:31奥运会纪念徽章:摔跤
日期:2008-07-26 08:05:05
18#
发表于 2008-7-25 09:12 | 只看该作者
原帖由 gtlions 于 2008-7-25 08:58 发表
就是 序列好啊

太绝对了,呵,用序列主要是进行断号的处理,看了上面老狐狸的分析有所启发,继续关注

使用道具 举报

回复
论坛徽章:
6
BLOG每日发帖之星
日期:2008-10-16 01:03:282010新春纪念徽章
日期:2010-03-01 11:07:242011新春纪念徽章
日期:2011-02-18 11:42:47迷宫蛋
日期:2011-08-02 09:46:45ITPUB十周年纪念徽章
日期:2011-11-01 16:24:042012新春纪念徽章
日期:2012-01-04 11:53:54
17#
发表于 2008-7-25 08:58 | 只看该作者
就是 序列好啊

使用道具 举报

回复
论坛徽章:
9607
土豪章
日期:2013-12-31 14:11:39土豪章
日期:2013-12-31 14:11:39阿森纳
日期:2013-06-03 17:00:31阿森纳
日期:2013-10-11 09:27:58法拉利
日期:2013-12-27 15:20:30林肯
日期:2013-12-27 15:19:09法拉利
日期:2013-12-27 15:20:30法拉利
日期:2013-12-27 15:20:30法拉利
日期:2013-12-27 15:20:30法拉利
日期:2013-12-27 15:20:30
16#
发表于 2008-7-25 07:49 | 只看该作者
原帖由 kdkd 于 2008-7-24 23:23 发表
要保证绝对的连续就不能用sequence了,原因是sequence可能丢失序号,原因有以下几个:
1、取到的序号应用失败,如insert、update后被回滚
2、数据库崩溃,丢失cache的序号
3、取到的序号用于其他地方,如sequence被其他程序调用nextval


是的,直接取最大值+1就可以了,在程序最后保存数据的时候生成ID号

使用道具 举报

回复
论坛徽章:
10
授权会员
日期:2008-03-13 10:32:44生肖徽章2007版:鸡
日期:2008-04-03 18:55:51数据库板块每日发贴之星
日期:2008-04-21 01:01:58奥运会纪念徽章:拳击
日期:2008-06-14 10:29:372014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11
15#
发表于 2008-7-24 23:23 | 只看该作者
要保证绝对的连续就不能用sequence了,原因是sequence可能丢失序号,原因有以下几个:
1、取到的序号应用失败,如insert、update后被回滚
2、数据库崩溃,丢失cache的序号
3、取到的序号用于其他地方,如sequence被其他程序调用nextval

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
14#
发表于 2008-7-24 23:00 | 只看该作者
看他程序怎么写了,如果插入之前调用再提交,中间没有人机交互的过程是可以这么用的。
和SEQUENCE的区别就是假设中间出错回滚了号码也随之回滚。

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
13#
发表于 2008-7-24 22:28 | 只看该作者
如果一定不能断号的话,用这种办法:

CREATE TABLE seq (next_id NUMBER(11));

INSERT INTO SEQ VALUES (TO_CHAR(SYSDATE,'YYYYMMDD')||'001');

CREATE OR REPLACE FUNCTION f_next_id RETURN NUMBER
IS
   lv_ret NUMBER(11);
BEGIN
   UPDATE seq
      SET next_id = (CASE WHEN SUBSTR(next_id,1,8)<>TO_CHAR(SYSDATE,'YYYYMMDD') THEN TO_CHAR(SYSDATE,'YYYYMMDD')||'001'
                          ELSE next_id+1
                     END)
   RETURNING next_id
   INTO lv_ret;
   
   RETURN lv_ret;
   
END f_next_id;
/

在需要取号的地方,调一下f_next_id取号。

在大系统中是不推荐这么用的,因为所有并行的事务都将串行化。考虑到你的业务规模不大,每日只有三位数,用这种解决办法也是可以的。

使用道具 举报

回复
论坛徽章:
9
六级虎吧徽章
日期:2009-01-03 20:00:34
12#
发表于 2008-7-24 22:09 | 只看该作者
如果是mysql就好办了!

使用道具 举报

回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表