Java 每日重置顺序订单号的安全生成
我需要生成YYYYMMDDXXXXX格式的订单号,其中xxxxxx是自午夜以来的订单数 例如20120821000004是2012年8月21日的第四份订单。每秒最多可以创建5个订单,因此这是一个性能考虑因素 一个显而易见的解决方案是执行以下操作,以查找要增加的最新订单:Java 每日重置顺序订单号的安全生成,java,oracle,hibernate,Java,Oracle,Hibernate,我需要生成YYYYMMDDXXXXX格式的订单号,其中xxxxxx是自午夜以来的订单数 例如20120821000004是2012年8月21日的第四份订单。每秒最多可以创建5个订单,因此这是一个性能考虑因素 一个显而易见的解决方案是执行以下操作,以查找要增加的最新订单: SELECT MAX (id) FROM table_name WHERE id LIKE '2012-08-21%' 但这可能会遇到性能问题 我探索的另一个选项是创建一个序列,用于驱动数字组件并使用插入触发器。这种方法的问题
SELECT MAX (id) FROM table_name WHERE id LIKE '2012-08-21%'
但这可能会遇到性能问题
我探索的另一个选项是创建一个序列,用于驱动数字组件并使用插入触发器。这种方法的问题是,你需要一些安全的方法在一天开始时将序列滚动到零,如果序列没有在午夜完全重置,这可能会导致冲突/竞争条件
在这里,我可以使用Oracle的一些技巧使其不透气,但也能发挥性能吗?这不是一个专门的Oracle解决方案,但我正在考虑使用一个订单号表,该表有三列:日期、xxxxxx(作为整数)和订单号 在(日期xxxxxxx)上保存索引。现在,按照以下步骤执行查询:
select max(id) from OrderNumbers where date = <date>
从日期=
这将使用索引,并应加快操作
另一个想法是保留一个类似的表,但只针对当前日期。在此版本中,您将有一个序列/自动增量列自动生成xxxxxx。然后,您可以使用触发器计算订单号,并取回最后插入的值以创建新订单号。这可能是最快的方法,尤其是在考虑锁定数据的问题时。 您可以为每一个新的一天生成新的序列。 给他们一个有意义的名字,比如“order\u seq\u 20120821”
- 检查今天的序列是否存在
- 如果不创建它(在这里处理并发性,另一个线程可能已经创建了它)
- 然后使用它
在这里,这不是一个真正的java问题,客户机无法处理数据库并发性如果只在SQL中执行此操作,而没有任何外部实用程序,我可能会保留两个表:
- 绝对订单ID
- 日期/订单抵销
您可以考虑使用整数绝对订单ID跟踪DB中的订单,并且只使用日期/偏移数据来生成日期和每日订单号的友好信息,或者作为交叉引用。< / P> < P>您可以从下一个订单ID/P>开始创建SEQ。
CREATE SEQUENCE orders_seq
START WITH 201208210000001
INCREMENT BY 1
NOCACHE
;
并通过作业增加午夜到第二天第一个id的序列:
declare
v_curr_id NUMBER;
v_inc NUMBER;
v_next_val NUMBER;
begin
select orders_seq.nextval into v_curr_id from dual;
v_next_val := to_number(to_char(SYSDATE+1, 'yyyymmdd') || '000000');
v_inc := v_next_val - v_curr_id;
execute immediate ' alter sequence orders_seq increment by ' || v_inc ;
select orders_seq.nextval into v_curr_id from dual;
execute immediate ' alter sequence orders_seq increment by 1';
end;
/
为一周中的每一天创建Oracle序列,即 创建序列序号
从1开始
增加1
秩序
创建顺序序列
从1开始
增加1
秩序
ETC至SEQ_SUN 创建返回以下内容的Oracle存储过程:
1.日期时间
2.与上述日期时间相对应的一周中某一天的序列号
逻辑如下:
-将当前日期和时间存储在变量中
-获取变量中日期对应的星期几。
注意:使用独立于NLS_TERRITORY设置的公式。您可以使用:1+TRUNC(DT)-TRUNC(DT,'IW')为Mon获取1。
-从一周中上述日期对应的序列中获取下一个序列
-返回变量中的日期时间和上面获得的新序列号。
计划作业:
创建每天凌晨1点(不是午夜)运行的计划作业,以重置前一天的顺序 使用上述方法,您可以安全地进行全天候操作 重要提示:
返回的datetime应用于为传入请求添加时间戳,以便请求的时间戳与分配给它的序列号匹配。这对于午夜前到达的请求很重要。最大(id)是否将成为同步订单的竞争条件?相反,您可以在
OrderNumbers
表中插入,然后获取最后一次插入的ID(SCOPE\u IDENTITY
在SQL Server中,不确定它在Oracle中是什么)。这样你就知道你总是有一个唯一的ID。所以你想使用一个唯一的序列吗?可能您可以保存前一天的序列最后一个值。使用此选项可以重新计算id的顺序。但是注释仍然有效:客户端无法处理数据库并发!它必须在数据库端处理。您是否打算生成一个无间隙序列?如果是这样的话,这将强制对订单进行序列化--如果您试图每秒处理5个订单,这可能会有问题。此外,除了序列化带来的性能问题外,不可能有无间隙的序列,因为可能会出现倒退。如果我处在你的位置,我会回去质疑要求。为什么他们需要这种格式的订单号?为什么他们需要无间隙呢?他们需要按顺序订购吗?换句话说,我建议只使用一个简单的序列来生成一个简单的唯一订单ID,并为订单日期设置一个单独的列。严格来说,这些数字不是无间隙的要求。我的工作方式与pizen的方法非常相似,没有无间隙数字。如果作业无法运行会发生什么?作业运行并将序列设置回0后,可能会发生冲突。@anger:我们的想法不是将序列设置回0,而是