|
虽然你提供的信息不多,我还是把你15楼的代码改写成了存储过程。这个过程完成了取空白票、打上占用标记的功能,绝对是密集型事务的最佳选择。你尽可以用各种手段去测试并和你自己的程序对比。
我也很想看到你怎么证明这个存储过程会造成系统“堵车”。
关于数据格式的转换,例如输入、输出的日期格式,toJSON,我一向是主张不在数据库中完成的,但实在要这么做也未尝不可。你可以取完结果集再toJSON,这时模板就排上用场了,至于是静态模板还是动态模板随你选择。
结果集结构按你原来要求,虽然我认为没有必要字段所有都返回,特别是ROWID。
我不知道准确的表结构所以全部采用了VARCHAR2(20)。
刚刚模拟100个终端各自买100张票再转JSON格式,效果很好,1.5秒所有的JOB都结束了。明天我再进一步测试。
CREATE OR REPLACE TYPE tp_seat2 AS OBJECT (
start_date varchar2(20)
,beg_station varchar2(20)
,train_no varchar2(20)
,run_train varchar2(20)
,on_date varchar2(20)
,carno varchar2(20)
,seat_type varchar2(20)
,seat_no varchar2(20)
,end_station varchar2(20)
,shortest_station varchar2(20)
,purpose varchar2(20)
,gride varchar2(20)
,pro varchar2(20)
,flag varchar2(20)
,used_dev varchar2(20)
,used_uid varchar2(20)
,used_time varchar2(20)
,row_id VARCHAR2(20)
)
/
CREATE OR REPLACE TYPE tp_seat_table2 AS TABLE OF tp_seat2
/
CREATE OR REPLACE PROCEDURE getseat_for_sell (
p_result OUT SYS_REFCURSOR ---- 结果集
,p_count OUT NUMBER ---- 获得的票数。假如没有足够的票, 可能<p_quantity
,p_start_date IN DATE
,p_train_no IN VARCHAR2
,p_beg_station IN VARCHAR2
,p_arrive IN NUMBER
,p_xb IN NUMBER
,p_purpose IN NUMBER
,p_quantity IN NUMBER
,p_userid IN VARCHAR2
,p_devid IN VARCHAR2
)
AS
lv_flag NUMBER;
e_locked EXCEPTION;
PRAGMA EXCEPTION_INIT (e_locked, -54);
lv_result tp_seat_table2 := tp_seat_table2();
BEGIN
p_count := 0;
FOR lv_rec IN (SELECT rowid AS row_id,seat.*
FROM seat
WHERE start_date = p_start_date
AND beg_station = p_beg_station
AND train_no = p_train_no
AND (MOD(p_xb,10) = 0 AND seat_type > p_xb AND seat_type <= p_xb+9
OR MOD(p_xb,10) <> 0 AND seat_type = p_xb
)
AND end_station >= p_arrive
AND purpose = p_purpose
AND flag = 0
ORDER BY end_station,carno,seat_no,seat_type*DECODE(p_xb,0,-1,1)
)
LOOP
lv_flag := NULL;
BEGIN
SELECT flag
INTO lv_flag
FROM seat
WHERE rowid = lv_rec.row_id
FOR UPDATE NOWAIT;
EXCEPTION
WHEN e_locked THEN
lv_flag := NULL;
END;
IF lv_flag = 0 THEN
UPDATE seat
SET flag =1
,used_time = SYSDATE
,used_uid = p_userid
,used_dev = p_devid
WHERE rowid = lv_rec.row_id;
p_count := p_count+1;
lv_result.EXTEND;
lv_result(p_count) := tp_seat2(TO_CHAR(lv_rec.start_date,'YYYY-MM-DD')
,lv_rec.beg_station
,lv_rec.train_no
,lv_rec.run_train
,TO_CHAR(lv_rec.on_date,'YYYY-MM-DD HH24:MI')
,lv_rec.carno
,lv_rec.seat_type
,lv_rec.seat_no
,lv_rec.end_station
,lv_rec.shortest_station
,lv_rec.purpose
,lv_rec.gride
,lv_rec.pro
,lv_rec.flag
,lv_rec.used_dev
,lv_rec.used_uid
,TO_CHAR(lv_rec.used_time,'YYYY-MM-DD HH24:MI:SS')
,ROWIDTOCHAR(lv_rec.row_id)
);
IF p_count >= p_quantity THEN
EXIT;
END IF;
END IF;
END LOOP;
OPEN p_result FOR
SELECT *
FROM TABLE(CAST(lv_result AS tp_seat_table2)) r
ORDER BY end_station,carno,seat_no,seat_type*DECODE(p_xb,0,-1,1);
END getseat_for_sell;
/
在看你的程序时我发现了一个问题。DTO_update生成UPDATE语句是怎么一个过程?假如我只修改其中一两个字段,你是UPDATE所有字段还是被修改的字段?如何处理“丢失更新”的问题?(即多用户环境中,某个修改被其他修改所覆盖)
[ 本帖最后由 newkid 于 2008-12-10 07:49 编辑 ] |
|