首页 > 其他 > 详细

防跳号的两种方式

时间:2015-01-21 02:05:08      阅读:308      评论:0      收藏:0      [点我收藏+]

在财务上有一种需求,就是单据号必须连续不能中断.
这种需求用Oracle的序列不能实现,MySQL的auto_increment也不能实现.
因为事务回滚,或者实例重启,都可能造成单据号不连续的情况,就是跳号.

防止跳号有两种方式,但是前提都是不能删除数据.
第一种方式,用锁限制并发.
一个表有两个字段,一个是模块名称,一个是当前模块的序列值
create table tab_lock
(
?? ?module_name varchar(10) primary key,
?? ?current_value int
)engine=innodb;

insert into tab_lock values(‘HR‘,1),(‘IT‘,1);
commit;

使用的时候,用悲观锁锁住这行数据,然后使用这个值填充主键,最后让这个序列自增.
select * from tab_lock
where module_name=‘IT‘ for update;

update tab_lock
set current_value=current_value+1
where module_name=‘IT‘;

commit;

这种方式限制了并发.
一旦回滚,这个号码没有任何变化.这样可以保证单号的连续性.


-------------------------------------------------------------------------

还有一种方式,就是使用一个伪列作为单号.
主键不连续,而伪列单号可以连续.
create table order_log
(
?? ?id int primary key
)engine=innodb;

insert into order_log
values
(1),(2),(4),(5),(7),(10),(13),(17),(20);
commit;

虽然主键不连续,但是可以通过下面的方式使单据号连续.

延迟关联实现分页,每页5条
第一页
select
concat(‘TX‘,lpad(b.rn,10,‘0‘)),a.*
from
order_log a
,
(
?? ?select * from
?? ?(
?? ??? ?select
?? ??? ?id,
?? ??? ?@a := @a + 1 AS rn
?? ??? ?from order_log,
?? ??? ?(SELECT @a := 0) t order by id limit 5
?? ?) c? where rn>0
) b
where a.id=b.id;
bubuko.com,布布扣

第二页
select
concat(‘TX‘,lpad(b.rn,10,‘0‘)),a.*
from
order_log a
,
(
?? ?select * from
?? ?(
?? ??? ?select
?? ??? ?id,
?? ??? ?@a := @a + 1 AS rn
?? ??? ?from order_log,
?? ??? ?(SELECT @a := 0) t order by id limit 10
?? ?) c? where rn>5
) b
where a.id=b.id;
bubuko.com,布布扣

第二种方式显然更好.
两种方式的前提都是不能删除表中数据.

第二种方式其实是
select
concat(‘TX‘,lpad(b.rn,10,‘0‘)),a.*
from
order_log a
,
(
?? ?select * from
?? ?(
?? ??? ?select
?? ??? ?id,
?? ??? ?@a := @a + 1 AS rn
?? ??? ?from order_log,
?? ??? ?(SELECT @a := 0) t order by id limit ${pageSize}*${pageNum}
?? ?) c? where rn>${pageSize}*(${pageNum}-1)
) b
where a.id=b.id;

?

SpringMVC+mybatis HTML5 全新高大尚后台框架_集成代码生成器

防跳号的两种方式

原文:http://qq-23269693.iteye.com/blog/2177793

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!