楼主: Younth_0701

[SQL] OCI 线程安全

[复制链接]
论坛徽章:
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
21#
发表于 2021-1-18 04:54 来自手机 | 只看该作者
我忽然想起一个技术之外的事情。利润的分成难道不是按照股份,或投资比例来分吗?要不然谁愿意运营冷门的路段?

使用道具 举报

回复
论坛徽章:
0
22#
 楼主| 发表于 2021-1-18 12:17 | 只看该作者
yulihua49 发表于 2021-1-14 11:11
http://www.itpub.net/forum.php?m ... orid=8804348&page=215楼。OCI比proc快。看2楼的OCI包装器程序,只 ...

老哥,我觉得你能救我,我的要求都没有你的万分之一的苛刻,纯粹是对API理解上的:
我想整个程序使用一个连接,每个查询重新定义一个结果集,使用这个连接。我的是单行fetch,慢得一批。
大概几十到一百多个字段,约50万行记录,我尝试加载约1万行记录,都得要5~6秒,我去掉了界面,单走数据fetch的循环,时间也差不多。这是第一个问题,我希望是能在1秒内加载完,我觉得batch_fetch 应该会有用,就是你说的 select bulk,这个当年在pro*c中我深有体会。但是我还不知道怎么做成动态的通用查询,问题在于那个定义绑定变量的函数,看了你的回帖,还没来得及研究。我后面会试一下,然后将结果反馈出来。
第二个问题就是你说的线程安全,我这里比如两个相同的查询,在两个线程中同时执行,就会出问题,分开依次就没事,两个查询业务逻辑上没有什么涉及互斥的东西,我不知道问题在哪里。我觉得oracle oci 提供的线程支持是对操作系统多线程在oci上的进一步封装,在我测试的windows系统上(客户端),我是直接使用windows的线程函数来处理的,应该也能正常OCI,不知道这个理解是否正确。

使用道具 举报

回复
论坛徽章:
0
23#
 楼主| 发表于 2021-1-18 12:35 | 只看该作者
本帖最后由 Younth_0701 于 2021-1-18 12:56 编辑
yulihua49 发表于 2021-1-15 15:16
确实如此。在外边是全并行计算,用了3台服务器,96个线程。数据库是2台RAC。从文件--发送--多路并行计算--- ...

你们这里讨论的是插入数据的问题,插入数据在我经历的业务环境中是接口数据(数据来源端的初级数据),确实是文件的,用sqlldr我觉得已经不错了,写控制文件,编造整理格式化的数据文件等那一套,几个文件同时往数据库里头插入,删掉索引,处理下空值,基本上能达到要求了,文件太多了可以合并临时文件(让他不超过100万行,超过了分成几个数据文件)。我觉得在使用中已经很nice了。
我还是想多看看OCI对数据库的多线程操作(单连接,多数据集类似那种包装,主要原因是单练接方便程序的数据库管理,还据说会快),我对这个连接的定义不是特别明确,比如里面的环境句柄,服务句柄,session 句柄 context句柄,语句句柄 错误句柄,他们哪个归哪个比较合适,还没有清醒的认识,写出来的能运行,但是不稳定不效率。关于多线程的OCI,其接口函数倒是都能理解,但对于他的这个几个传参(那几个mode) 还是很纠结,而且他的互斥,到底是使用多线程,本身就得互斥(他句柄所绑定的背后资源的互斥),还是说我们完全不用管他句柄所绑定的背后资源的互斥,我们用只需要管我们使用资源的互斥?原帖

使用道具 举报

回复
论坛徽章:
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
24#
发表于 2021-1-19 11:11 | 只看该作者
本帖最后由 yulihua49 于 2021-1-19 11:16 编辑
Younth_0701 发表于 2021-1-18 12:35
你们这里讨论的是插入数据的问题,插入数据在我经历的业务环境中是接口数据(数据来源端的初级数据),确实 ...

我是用开源的sqlora8的包装器,它有一个多线程模式,按这个初始化即可。
它就是把OCI的好多步操作合成一步,比较简单,效率也高。
具体,你去SDBC群,下载源码,看看sqlora是怎么做的。
你下载源码,安装编译,,里边有demo,把demo/ldasc下的程序编译一下,配置,运行就可以高速下载你的各个表的数据。
我可以指导你怎么弄。

使用道具 举报

回复
论坛徽章:
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
25#
发表于 2021-1-19 11:20 | 只看该作者
Younth_0701 发表于 2021-1-18 12:17
老哥,我觉得你能救我,我的要求都没有你的万分之一的苛刻,纯粹是对API理解上的:我想整个程序使用一个连 ...

当年,我做这个东西,就是为了通用。
这些工具程序是通用的,做成库,供你引用。

使用道具 举报

回复
论坛徽章:
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
26#
发表于 2021-1-19 11:21 | 只看该作者
本帖最后由 yulihua49 于 2021-1-19 12:06 编辑
Younth_0701 发表于 2021-1-18 12:17
老哥,我觉得你能救我,我的要求都没有你的万分之一的苛刻,纯粹是对API理解上的:我想整个程序使用一个连 ...

PROC多线程非常困难,OCI多线程相对容易。
还有一个可能是你自己的环境没弄好,不是OCI的问题。
必须每个线程使用自己的context。


  1. /*---------------------------------------------------------------------------
  2. * sqlo_server_attach
  3. *--------------------------------------------------------------------------*/
  4. int
  5. DEFUN(sqlo_server_attach, (dbhp, tnsname),
  6.       sqlo_db_handle_t *   dbhp      AND
  7.       const char *         tnsname )
  8. {
  9.   sqlo_db_struct_ptr_t  dbp;
  10.   
  11.   if (dbhp)
  12.     *dbhp = -1;
  13.   TRACE(2, fprintf(_get_trace_fp(NULL), "sqlo_server_attach starts\n" ););
  14.   if (!(dbp = _db_add())) {
  15.     TRACE(3, fprintf(_get_trace_fp(NULL),
  16.                      "sqlo_server_attach: Could not alloacte a dbp\n"); );
  17.     return SQLO_ERROR;
  18.   }
  19.   TRACE(3, fprintf(_get_trace_fp(dbp), "sqlo_server_attach: allocated dbh=%u\n",
  20.                    dbp->dbh); );
  21.   /* if tnsname contains a connect string we split it */
  22.   if (strchr(tnsname, [url=mailto:]'@'[/url]) || strchr(tnsname, '/') ) {
  23.     enum {MAX_BUFLEN = 1023};
  24.     char uid[MAX_BUFLEN + 1];
  25.     char pwd[MAX_BUFLEN + 1];
  26.     char dbname[MAX_BUFLEN + 1];
  27.     if (SQLO_SUCCESS != sqlo_split_cstring(tnsname, uid, pwd, dbname, MAX_BUFLEN))
  28.       return SQLO_ERROR;
  29.     dbp->tnsname = strdup(dbname);
  30.    
  31.   } else {
  32.     dbp->tnsname = strdup(tnsname);
  33.   }
  34.   dbp->status = SQLO_SUCCESS;
  35.   dbp->exec_flags = OCI_DEFAULT;
  36.   dbp->errmsg[0] = '\0';
  37.   /* We return the handle even on error, so sql_geterror can return
  38.    * the stored message
  39.    */
  40.   if (dbhp)
  41.     *dbhp = (int) dbp->dbh;
  42.   /*
  43.     We must use OCIEnvCreate instead of OCIInitialize / OCIEnvInit (see Oracle OCI
  44.     Programmer's Guide 8.1.6 pg 15-91 - 15-93). If during the first call to OCIEnvCreate
  45.     an OCI_THREADED parameter is specified then this parameter will apply all along.
  46.     CAFL says fb doesn't have the earlier manual...which says to use
  47.     ocienvinit to create the handle.  The real question is whether to pass
  48.     OCI_NO_MUTEX to it, which would probably be right here where there is one
  49.     environment handle per connection, or OCI_DEFAULT.  I have no guts.
  50.   */
  51.   /* There are roumors that OCIEnvCreate is not thread safe. I'm not sure that this
  52.    * is true, but to be on the safe side, I protect it by a lock
  53.    */
  54.   EXEC_WHEN_THREADING(_env_lock(););
  55. #ifdef HAVE_OCIENVCREATE
  56.   dbp->status = OCIEnvCreate( &dbp->envhp,
  57.          _oci_init_mode,
  58.          NULL, NULL, NULL, NULL, 0, NULL
  59.          ) ;
  60.   CHECK_OCI_STATUS(dbp, dbp->status, "sqlo_server_attach", "OCIEnvCreate" );
  61. #else
  62.   dbp->status = OCIEnvInit( (dvoid *)&dbp->envhp,
  63.        _oci_init_mode,
  64.        0, (dvoid **)0
  65.        );
  66.   CHECK_OCI_STATUS(dbp, dbp->status, "sqlo_server_attach", "OCIEnvInit" );
  67. #endif
  68.   EXEC_WHEN_THREADING( _env_unlock(); );
  69.   /* release allocated resources */
  70.   if (OCI_SUCCESS != dbp->status) {
  71.     _db_release( dbp );
  72.     return ( dbp->status );
  73.   }
  74.   /* Alloc the service context handle */
  75.   dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
  76.     (dvoid **)&dbp->svchp,
  77.     OCI_HTYPE_SVCCTX,
  78.     0,
  79.     (dvoid **) 0
  80.     );
  81.   CHECK_OCI_STATUS(dbp, dbp->status,
  82.      "sqlo_server_attach", "OCIEnvHandleAlloc(svchp)" );
  83.   /* release allocated resources */
  84.   if (OCI_SUCCESS != dbp->status) {
  85.     _db_release( dbp );
  86.     return (dbp->status);
  87.   }
  88.   /* Alloc the error handle */
  89.   dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
  90.     (dvoid **)&dbp->errhp,
  91.     OCI_HTYPE_ERROR,
  92.     0, (dvoid **) 0
  93.     );
  94.   CHECK_OCI_STATUS(dbp, dbp->status, "sqlo_server_attach",
  95.      "OCIHandleAlloc(errhp)" );
  96.   
  97.   /* release allocated resources */
  98.   if (OCI_SUCCESS != dbp->status) {
  99.     _db_release( dbp );
  100.     return ( dbp->status );
  101.   }
  102.   /* Alloc the server handle */
  103.   dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
  104.     (dvoid **)&dbp->srvhp,
  105.     OCI_HTYPE_SERVER,
  106.     0,
  107.     (dvoid **) 0
  108.     );
  109.   
  110.   CHECK_OCI_STATUS(dbp, dbp->status,
  111.      "sqlo_server_attach", "OCIHandleAlloc(srvhp)" );
  112.   /* release allocated resources */
  113.   if (OCI_SUCCESS != dbp->status) {
  114.     _db_release(dbp);
  115.     return (dbp->status);
  116.   }
  117.   /* Create a server context */
  118.   dbp->status = OCIServerAttach( dbp->srvhp,
  119.      dbp->errhp,
  120.      (text *)dbp->tnsname,
  121.      strlen(dbp->tnsname),
  122.      OCI_DEFAULT
  123.      );
  124.   CHECK_OCI_STATUS(dbp, dbp->status,
  125.      "sqlo_server_attach", "OCISeverAttach(tnsname)");
  126.   /* release allocated resources */
  127.   if (OCI_SUCCESS != dbp->status) {
  128.     _db_release( dbp );
  129.     return ( dbp->status );
  130.   }
  131.   /* Set the server context in the service context */
  132.   dbp->status = OCIAttrSet( (dvoid *)dbp->svchp,
  133.        OCI_HTYPE_SVCCTX,
  134.        (dvoid *)dbp->srvhp,
  135.        (ub4) 0,
  136.        OCI_ATTR_SERVER,
  137.        dbp->errhp
  138.        );
  139.   CHECK_OCI_STATUS(dbp, dbp->status,
  140.      "sqlo_server_attach", "OCIAttrSet(server->service)" );
  141.   
  142.   /* release allocated resources */
  143.   if (OCI_SUCCESS != dbp->status) {
  144.     _db_release( dbp );
  145.     return ( dbp->status );
  146.   }
  147.   /* Allocate a authentication handle */
  148.   dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
  149.     (dvoid **)&dbp->authp,
  150.     OCI_HTYPE_SESSION,
  151.     0,
  152.     (dvoid **) 0
  153.     );
  154.   CHECK_OCI_STATUS( dbp, dbp->status,
  155.      "sqlo_server_attach", "OCIHandleAlloc(authp)" );
  156.   if (SQLO_SUCCESS == dbp->status) {
  157.     TRACE(2,fprintf( _get_trace_fp(dbp), "sqlo_server_attach[%d]: attached\n", *dbhp); );
  158.   } else {
  159.     /* release allocated resources */
  160.     TRACE(2,fprintf( _get_trace_fp(dbp), "sqlo_server_attach[%d]: failed\n", *dbhp); );
  161.     _db_release( dbp );
  162.     return ( dbp->status );
  163.   }
  164.   
  165.   dbp->used   = TRUE;
  166.   dbp->attached = TRUE;           
  167.   return ( dbp->status );
  168. }
复制代码


这是他的打开环境函数,可以看到里边线程加锁的动作。
  • /* There are roumors that OCIEnvCreate is not thread safe. I'm not sure that this
  •    * is true, but to be on the safe side, I protect it by a lock
  •    */
这东西是线程独享,就是说,每个线程一个或多个,不能一个连接各线程用。
多线程时,我是建立连接池,每个线程各自从池里取连接。

程序发不了,说是有不良信息。QQ讨论吧。


使用道具 举报

回复
论坛徽章:
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
27#
发表于 2021-1-19 12:22 | 只看该作者
本帖最后由 yulihua49 于 2021-1-19 18:46 编辑
yulihua49 发表于 2021-1-19 11:21
PROC多线程非常困难,OCI多线程相对容易。还有一个可能是你自己的环境没弄好,不是OCI的问题。必须每个线程 ...

https://blog.csdn.net/cjxrmobq704396/article/details/100466586
这家伙绝对是抄我的贴,用SDBC打开数据库,用SDBC的handle操作sqlora .

使用道具 举报

回复
论坛徽章:
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
28#
发表于 2021-1-19 12:29 | 只看该作者
yulihua49 发表于 2021-1-19 11:21
PROC多线程非常困难,OCI多线程相对容易。还有一个可能是你自己的环境没弄好,不是OCI的问题。必须每个线程 ...

https://www.dssz.com/19442.html
sqlora8这里有下载,2.2.4版的,比较老,看文档和例子吧。
SDBC里有3.3的

使用道具 举报

回复
论坛徽章:
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
29#
发表于 2021-1-19 18:58 | 只看该作者
Younth_0701 发表于 2021-1-18 12:17
老哥,我觉得你能救我,我的要求都没有你的万分之一的苛刻,纯粹是对API理解上的:我想整个程序使用一个连 ...

每个线程各自使用自己的handle。

使用道具 举报

回复
论坛徽章:
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
30#
发表于 2021-1-19 19:25 | 只看该作者
本帖最后由 yulihua49 于 2021-1-19 19:31 编辑
Younth_0701 发表于 2021-1-18 12:35
你们这里讨论的是插入数据的问题,插入数据在我经历的业务环境中是接口数据(数据来源端的初级数据),确实 ...

libsqlora8-2.3.4.tar.gz.zip (1.83 MB, 下载次数: 3)
2.3.4,可以在windows进行configure:
./configure  --enable-64bit  

在每个线程中进行sqlo_connect();
可以把文件名的.zip去掉,这是我加的,.gz不让上传。
里边有文档和例子。




使用道具 举报

回复

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

本版积分规则 发表回复

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