楼主: yulihua49

[PRO*C] 看我做的数据库包装器

[复制链接]
论坛徽章:
2
生肖徽章2007版:马
日期:2008-12-25 19:45:382009新春纪念徽章
日期:2009-01-04 14:52:28
171#
发表于 2009-1-13 00:52 | 只看该作者

回复 #177 newkid 的帖子

1“你的程序可以杀掉,数据库连接也可以杀掉的。”
我说的是程序能杀掉,你能把你正在调用的存储过程的session都杀掉吗(其实主要是禁止新的调用,不是杀dblink),有人调用存储过程的时候,存储过程应该是不能编译的吧。
2.“如果是做数据库应用,我还没发现有例外的。如果你有的例子的话举一个出来。”
举个例子:不知道你接触过移动BOSS吗,像移动boss这样的系统,有3000万用户,月底的出帐你能用存储过程在6个小时内解决吗(机器32U的,内存不清楚应该>=100G了)。

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
172#
发表于 2009-1-13 01:11 | 只看该作者
原帖由 stillwalking 于 2009-1-13 00:52 发表
1“你的程序可以杀掉,数据库连接也可以杀掉的。”
我说的是程序能杀掉,你能把你正在调用的存储过程的session都杀掉吗(其实主要是禁止新的调用,不是杀dblink),有人调用存储过程的时候,存储过程应该是不能编译的吧。
2.“如果是做数据库应用,我还没发现有例外的。如果你有的例子的话举一个出来。”
举个例子:不知道你接触过移动BOSS吗,像移动boss这样的系统,有3000万用户,月底的出帐你能用存储过程在6个小时内解决吗(机器32U的,内存不清楚应该>=100G了)。


禁止新SESSION的产生是可以的,但这样系统就动弹不得了。更新程序的正确做法就是停机。

不知道BOSS出帐是在做什么动作?是不是为每个用户产生一条应收帐?就是INSERT ... SELECT SUM(...) WHERE 日期=当月 AND USERS_ID ... GROUP BY... 这样的吧?这是典型的高负荷SQL, 有多少计算量可以移出数据库的?不用存储过程你用什么?

[ 本帖最后由 newkid 于 2009-1-13 04:34 编辑 ]

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
173#
发表于 2009-1-13 04:16 | 只看该作者
原帖由 gzluma 于 2009-1-12 12:52 发表
很想向您请教具体的做法,希望不用ISCSI或NAC等


非常抱歉我对你说的ISCSI或NAC一无所知,我只是个写应用的,数据库环境都是靠别人搭起来的。

使用道具 举报

回复
论坛徽章:
2
生肖徽章2007版:马
日期:2008-12-25 19:45:382009新春纪念徽章
日期:2009-01-04 14:52:28
174#
发表于 2009-1-13 11:26 | 只看该作者
原帖由 newkid 于 2009-1-13 01:11 发表


禁止新SESSION的产生是可以的,但这样系统就动弹不得了。更新程序的正确做法就是停机。

不知道BOSS出帐是在做什么动作?是不是为每个用户产生一条应收帐?就是INSERT ... SELECT SUM(...) WHERE 日期=当月 AND USERS_ID ... GROUP BY... 这样的吧?这是典型的高负荷SQL, 有多少计算量可以移出数据库的?不用存储过程你用什么?


首先承认个错误,给的例子有点问题,这3000万用户不是在一台主机上的,每台主机计算自己的用户就可以了(多的一台可能有700-800万用户)

“禁止新SESSION的产生是可以的,但这样系统就动弹不得了。更新程序的正确做法就是停机。”
如果是程序,只要不是超大程序(编译都要10分钟那种的,其实这种程序也有快速更新办法),就可以1-2分钟内把程序应急更新上去,而且不会影响其他的业务,比停机损失要小的多(当然我的举例有点极端),其实日常更新程序如果是程序都是不需要停机,限制接入的。


(3000万BOSS系统的规模,同时连入的终端有上万个,同时有业务动作的终端能达到几百个)
出帐真的不简单:(这个过程绝对不是一条,几条sql就能解决问题的,至少有大量的逻辑判断,会产生大量中间数据,大概说说,我了解的也不深入,你可以了解一下,就当关心3G动态了
每个人都定有不同的产品(市话,长途,短信,来电显示....)每个产品都有自己的单价,要判断你的使用时间,是否参加了什么优惠活动(多个优惠那个先适用),或者移动自有的一些优惠活动,应该交多少,或者应该给你返还多少,是否已经欠费(更新你的用户状态),每个用户的参与计算的数据保守估计30条,数据量就N亿了。
虽然出帐最初的时候包括用户信息,产品信息等数据都是在数据库里的,但是这个任务用存储过程不太可能解决。
(我们的争论就到这里吧,也许你哪天你接触到我说的你就能有些感觉。不过争论挺好,至少我要再看看那本《9i&10g编程艺术》了)。

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
175#
发表于 2009-1-14 00:20 | 只看该作者
如果存储过程组织得好,合理地分散在多个PACKAGE,编译的影响就更小。你的C程序如果有很多人在用,那么直接把它杀掉也是很不好的用户体验,跟停机差不多。

BOSS的东西由于没有具体需求,这里只能纸上谈兵地说说。首先你提到的很多规则,数据都在库里,计算结果也要写回去,正如我前面所说,用C来解决也会有大量SQL. 你要是CACHE住部分数据,那么就有不一致风险,况且数据库的CACHE也不差。
要是我来做,会往这两个方向努力:1.尽量不用显式游标遍历数据,尽量用SQL批量计算批量修改。2.争取把月底的计算量分散到每天,比如累计值之类的。
你说的“这个任务用存储过程不太可能解决”,做过对比实验吗?

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
176#
 楼主| 发表于 2009-1-16 16:07 | 只看该作者
原帖由 stillwalking 于 2009-1-12 12:36 发表


dblink这个东东不好说,是挺方便,但是,如果我有几千万数据要快速处理完,dblink肯定不如proc同时建立多个长连接快。

dblink是什么?不懂,需要学习。
最近没闲着,程序已经包装到DAU里了,程序员可以透明的使用bind了。只是,如果数据有问题,看不出来,给调试造成一定麻烦。
见一个申请席位的事务记录:
2 SP0102002:21778 01/16 10:51'36 getctx:1232074293 called!
5 SP0102002:21778 01/16 10:51'36 bind_update:bind=19,sth=0,stmt=UPDATE TICKET.TUXCONTEX SET(clid,devid,userid,username,stat_date,shift_code,devtype,unit,perm,purpose1,purpose2,purpose3,purpose4,purpose5,purpose6,purpose7,purpose8,last_oper)=(SELECT  :1, :2, :3, :4,to_date(:5,'YYYY-MM-DD'), :6, :7, :8, :9, :10, :11, :12, :13, :14, :15, :16, :17,to_date(:18,'YYYY-MM-DD HH24:MI:SS') FROM DUAL) where clid=:19,
2 SP0102002:21778 01/16 10:51'36 seatapply:2009-01-17|H6|BHHP|SJHP|20|0|10|
5 SP0102002:21778 01/16 10:51'36 to getxw:2009-01-16|H6B|BHHP|6|20|0|10|
5 SP0102002:21778 01/16 10:51'36 bind_prepare:cursor=0,SELECT /* +rule */ to_char(start_date,'YYYY-MM-DD') start_date,beg_station,train_no,run_train,to_char(on_date,'YYYY-MM-DD HH24:MI') on_date,carno,seat_type,seat_no,end_station,shortest_station,purpose,gride,pro,flag,used_dev,used_uid,to_char(used_time,'YYYY-MM-DD HH24:MI:SS') used_time,ROWID FROM TICKET.SEAT WHERE start_date=to_date(:1,'YYYY-MM-DD')  AND beg_station=:2 AND train_no=:3 AND SEAT_TYPE > :4 AND (SEAT_TYPE <= :5+9) AND end_station>=:6 AND purpose=:7 AND FLAG=0 AND ROWNUM <= :8 ORDER BY END_STATION,CARNO,SEAT_NO,SEAT_TYPE FOR UPDATE WAIT 10 SKIP LOCKED
5 SP0102002:21778 01/16 10:51'36 seat_DAOAU_prepare ret=0,err=0,
5 SP0102002:21778 01/16 10:51'36 bind_update:bind=5,sth=1,stmt=UPDATE TICKET.SEAT SET(flag,used_dev,used_uid,used_time)=(SELECT  :1, :2, :3,to_date(:4,'YYYY-MM-DD HH24:MI:SS') FROM DUAL) WHERE ROWID=:5 ,
2 SP0102002:21778 01/16 10:51'36 seatapply:成功申请票 10 !
DAO如下:
int getSeat_for_sell(DAU *DP,int quantity,char *stmt)
{
int ret;
char tmp[1024],*p;
char xb;
        p=(char *)DAU_getP_by_key(DP,"ROWID";  //借用,bind变量
        sprintf(p,"%d",quantity);
        xb=*(char *)DAU_getP_by_key(DP,"seat_type";
        p=stmt;
        p=mk_where1(DP,"start_date",p);
        p+=sprintf(p," AND beg_station=:beg_station AND train_no=:train_no AND ";
        if(xb%10) {
                p+=sprintf(p,"SEAT_TYPE=:seat_type ";
        } else {
                p+=sprintf(p,"SEAT_TYPE > :seat_type AND (SEAT_TYPE <= :seat_type+9) AND ";
        }
        p+=sprintf(p,"end_station>=:end_station AND purpose=urpose AND FLAG=0 AND ROWNUM <= :ROWID "
                "ORDER BY END_STATION,CARNO,SEAT_NO";
        if(!(xb%10)) {
                p+=sprintf(p, ",SEAT_TYPE";
                if(xb==0) p+=sprintf(p," DESC ";//无号优先给硬座
        }
        p+=sprintf(p," FOR UPDATE WAIT 10 SKIP LOCKED";

        DP->srm.selectExtra="/* +rule */";
        ret=DAU_prepare(DP,stmt);
        if(ret) {
                ShowLog(1,"seat_DAOAU_prepare ret=%d,err=%d,%s",ret,
                        DP->SQL_Connect->Errno,
                        DP->SQL_Connect->ErrMsg);
        }
        return ret;
}

可以看出,用户使用:名 进行bind,DAU内部进行了一个变换成数字。

进行了100个进程的并行测试,运行时间基本是线性的。

既然DAU系统性能已经接近系统极限,提供了近乎线性的并行负载,那么,在大多数情况下,调用存储过程是不必要的。毕竟,存储过程对C结构的映射很困难。
在本坛看到大量高深的问题和神秘莫测的sql语句。这些问题对于我们而言,其实很简单,用简单的sql存取数据,用C语言处理复杂逻辑,一切都不是问题。

[ 本帖最后由 yulihua49 于 2009-1-16 17:10 编辑 ]

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
177#
发表于 2009-1-16 23:38 | 只看该作者
  1. "dblink是什么?"
  2. 搜索"DATABASE LINK"

  3. "最近没闲着,程序已经包装到DAU里了,程序员可以透明的使用bind了。只是,如果数据有问题,看不出来,给调试造成一定麻烦。"
  4. 你可以设计一个较大的字符串,每绑定一个就往里面拼一截,最后看起来就像这样: 1:ABC|2:DEF|.....
  5. 执行SQL后如果有异常就把它写入日志。执行结束把它清空。

  6. "既然DAU系统性能已经接近系统极限,提供了近乎线性的并行负载,那么,在大多数情况下,调用存储过程是不必要的。毕竟,存储过程对C结构的映射很困难。"
  7. 呵呵,存储过程的好处前面说很多了。任何情况下,如果你觉得你的C代码比存储过程好,欢迎拿出来比试。

  8. "在本坛看到大量高深的问题和神秘莫测的sql语句。这些问题对于我们而言,其实很简单,用简单的sql存取数据,用C语言处理复杂逻辑,一切都不是问题。"
  9. 这是因为SQL本身极为强劲,能用一个SQL写出的代码往往比一段PLSQL或C代码要高效很多。有本书叫 THINKING IN JAVA, 哪天你学会了THINKING IN SQL就不会觉得高深莫测了。
复制代码

使用道具 举报

回复
论坛徽章:
211
国际米兰
日期:2010-01-11 10:26:28ITPUB评论家
日期:2007-11-04 01:35:51季节之章:春
日期:2011-04-03 16:30:30热刺
日期:2009-09-21 10:54:48天枰座
日期:2015-11-05 16:32:03月度论坛发贴之星
日期:2010-05-01 02:15:42生肖徽章:狗
日期:2006-10-01 00:29:23BLOG每周发帖之星
日期:2009-08-30 01:35:31BLOG每日发帖之星
日期:2009-08-28 01:01:02妮可·罗宾
日期:2016-10-19 10:45:04
178#
发表于 2009-1-17 00:08 | 只看该作者
深夜学习

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
179#
发表于 2009-1-17 00:50 | 只看该作者
再有一个问题是我一早就提出来的,希望楼主解答:
用你这个包装器对于程序员来说基本上就是单表访问。按你的说法程序员不需要知道表名表结构。那么表间的JOIN是怎么实现的呢?难道都是从一个表取得数据,再访问另一个表?即类似NESTED LOOPS的方式?
做数据库应用而不用JOIN, 这是不可思议的事。

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
180#
 楼主| 发表于 2009-1-19 10:54 | 只看该作者

回复 #186 newkid 的帖子

JOIN有时用,你看前边那个生成模板的程序就用了多表,那是一个很特殊的例子,一般的,
多表采用:
DAU_getm(int n,DAU *DP,stmt);
n: DAU的个数,就是表的个数。
DP,DAU数组,每个表一个DAU。其中表名可以设别名。生成的每个列名都冠以 表别名. ,目前多表不支持bind。

DAU_nextm(int n,DAU *DP);
把结果集分别提取到各表的记录中。
DAU_freem(int n,DAU *DP);
释放所有DAU。

[ 本帖最后由 yulihua49 于 2009-1-19 11:03 编辑 ]

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

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