并发像同一张ORACLE插入会锁表吧,有向数据库缓存并发插入,=这种方式吗?

designerchen 2017-12-02 08:38:25
我现在为提高效率多线程向同一张表插入,会出现超时的问题,可以并发插入数据库缓存,然后让他自己再插入吗?MySQL有这种方式,不知道ORACLE该如何实现?
...全文
1866 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingysh 2019-10-21
  • 打赏
  • 举报
回复
采用分表模式,一个线程操作一个表。
minsic78 2017-12-04
  • 打赏
  • 举报
回复
另外,默认情况下,Oracle的绝大多数操作都是通过buffer cache,数据缓存区的。
minsic78 2017-12-04
  • 打赏
  • 举报
回复
高并发插入最常见的问题: 主键递增,主键索引分裂争用——将主键索引调整为分区hash全局索引,具体分区数可参考最高并发数,如果主键上不存在范围扫描,可以将该索引进一步调整为反向索引;递增主键因为可能由sequence提供,所以序列上可能也会发生争用,调整sequence cache可以一定程度上缓减这种争用。 当然还有很多其他原因会导致并发插入的性能问题,需要更多信息,比如插入时候的等待事件,甚至是插入时间段的AWR报告,以作进一步诊断。
designerchen 2017-12-04
  • 打赏
  • 举报
回复
就是我多线线程批量读取,然后每一个读取的线程读到,就立刻开一个写的线程去写
引用 13 楼 minsic78 的回复:
多线程当然可以,但是线程数肯定不是可以无限上涨的,也许你得找找这个拐点,看来报资源正忙不是一下子就报的,而是执行时间长了之后再报的,那么可能还是一些非高级队列锁的争用,如果想找找是否还有优化的余地,最好能有精确的问题时段的AWR报告
好的,那我试试吧,谢谢啦
minsic78 2017-12-04
  • 打赏
  • 举报
回复
引用 13 楼 minsic78 的回复:
多线程当然可以,但是线程数肯定不是可以无限上涨的,也许你得找找这个拐点,看来报资源正忙不是一下子就报的,而是执行时间长了之后再报的,那么可能还是一些非高级队列锁的争用,如果想找找是否还有优化的余地,最好能有精确的问题时段的AWR报告
如果获取AWR报告有困难,那么可以在程序执行的时候,查下v$session.event字段,看看插入的那些线程都在经历一些什么等待,多次查询,看看会不会有什么变化
minsic78 2017-12-04
  • 打赏
  • 举报
回复
多线程当然可以,但是线程数肯定不是可以无限上涨的,也许你得找找这个拐点,看来报资源正忙不是一下子就报的,而是执行时间长了之后再报的,那么可能还是一些非高级队列锁的争用,如果想找找是否还有优化的余地,最好能有精确的问题时段的AWR报告
designerchen 2017-12-04
  • 打赏
  • 举报
回复
引用 11 楼 dashenyyy 的回复:
[quote=引用 10 楼 dashenyyy 的回复:] [quote=引用 9 楼 minsic78 的回复:] [quote=引用 7 楼 dashenyyy 的回复:] [quote=引用 6 楼 minsic78 的回复:] 另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
public void BulkToDB(DataTable dt, string targetTable) { // lock (syncRoot) { string err = "大批量插入时产生错误"; OracleConnection conn = Connect("test", "test"); if (conn.State != ConnectionState.Open) { conn.Open(); } OracleBulkCopy bulkCopy = new OracleBulkCopy(conn, OracleBulkCopyOptions.Default); bulkCopy.BatchSize = pageSize; bulkCopy.BulkCopyTimeout = 260;//260 bulkCopy.DestinationTableName = targetTable; try { if (conn.State != ConnectionState.Open) { conn.Open(); } // conn.Open(); if (dt != null && dt.Rows.Count != 0) { bulkCopy.WriteToServer(dt); // m_OraTrans.Commit(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); // BulkToDB(dtt,targetTablee); } finally { conn.Close(); if (bulkCopy != null) bulkCopy.Close(); } } 就是用的这个ONP.NET ORACLE的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢[/quote] 我本来想看的是SQL…… 比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。 另外,说资源正忙报错的是啥情况下报的?[/quote] Oracle.DataAccess.Client.OracleException ORA-00604: 递归 SQL 级别 1 出现错误 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 在 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck) 在 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src) 在 Oracle.DataAccess.Client.OracleBulkCopy.PerformBulkCopy() 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteDataSourceToServer() 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table, DataRowState rowState) 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table) 在 ConsoleApp7.CopyDataUtil.BulkToDB(DataTable dt, String targetTable) 位置 D:\WPF\ConsoleApp7\ConsoleApp7\CopyDataUtil.cs:行号 207[/quote] 我们公司现在就是单线程顺序插入嘛,一次插入10万左右,现在想要插入更快,我就想着多线程一起插入可不可以[/quote] 我是从数据源多线程批量导出,这样读取快,然后想着多线程批量导入
designerchen 2017-12-04
  • 打赏
  • 举报
回复
引用 10 楼 dashenyyy 的回复:
[quote=引用 9 楼 minsic78 的回复:] [quote=引用 7 楼 dashenyyy 的回复:] [quote=引用 6 楼 minsic78 的回复:] 另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
public void BulkToDB(DataTable dt, string targetTable) { // lock (syncRoot) { string err = "大批量插入时产生错误"; OracleConnection conn = Connect("test", "test"); if (conn.State != ConnectionState.Open) { conn.Open(); } OracleBulkCopy bulkCopy = new OracleBulkCopy(conn, OracleBulkCopyOptions.Default); bulkCopy.BatchSize = pageSize; bulkCopy.BulkCopyTimeout = 260;//260 bulkCopy.DestinationTableName = targetTable; try { if (conn.State != ConnectionState.Open) { conn.Open(); } // conn.Open(); if (dt != null && dt.Rows.Count != 0) { bulkCopy.WriteToServer(dt); // m_OraTrans.Commit(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); // BulkToDB(dtt,targetTablee); } finally { conn.Close(); if (bulkCopy != null) bulkCopy.Close(); } } 就是用的这个ONP.NET ORACLE的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢[/quote] 我本来想看的是SQL…… 比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。 另外,说资源正忙报错的是啥情况下报的?[/quote] Oracle.DataAccess.Client.OracleException ORA-00604: 递归 SQL 级别 1 出现错误 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 在 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck) 在 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src) 在 Oracle.DataAccess.Client.OracleBulkCopy.PerformBulkCopy() 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteDataSourceToServer() 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table, DataRowState rowState) 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table) 在 ConsoleApp7.CopyDataUtil.BulkToDB(DataTable dt, String targetTable) 位置 D:\WPF\ConsoleApp7\ConsoleApp7\CopyDataUtil.cs:行号 207[/quote] 我们公司现在就是单线程顺序插入嘛,一次插入10万左右,现在想要插入更快,我就想着多线程一起插入可不可以
designerchen 2017-12-04
  • 打赏
  • 举报
回复
引用 9 楼 minsic78 的回复:
[quote=引用 7 楼 dashenyyy 的回复:] [quote=引用 6 楼 minsic78 的回复:] 另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
public void BulkToDB(DataTable dt, string targetTable) { // lock (syncRoot) { string err = "大批量插入时产生错误"; OracleConnection conn = Connect("test", "test"); if (conn.State != ConnectionState.Open) { conn.Open(); } OracleBulkCopy bulkCopy = new OracleBulkCopy(conn, OracleBulkCopyOptions.Default); bulkCopy.BatchSize = pageSize; bulkCopy.BulkCopyTimeout = 260;//260 bulkCopy.DestinationTableName = targetTable; try { if (conn.State != ConnectionState.Open) { conn.Open(); } // conn.Open(); if (dt != null && dt.Rows.Count != 0) { bulkCopy.WriteToServer(dt); // m_OraTrans.Commit(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); // BulkToDB(dtt,targetTablee); } finally { conn.Close(); if (bulkCopy != null) bulkCopy.Close(); } } 就是用的这个ONP.NET ORACLE的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢[/quote] 我本来想看的是SQL…… 比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。 另外,说资源正忙报错的是啥情况下报的?[/quote] Oracle.DataAccess.Client.OracleException ORA-00604: 递归 SQL 级别 1 出现错误 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 在 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck) 在 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src) 在 Oracle.DataAccess.Client.OracleBulkCopy.PerformBulkCopy() 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteDataSourceToServer() 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table, DataRowState rowState) 在 Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table) 在 ConsoleApp7.CopyDataUtil.BulkToDB(DataTable dt, String targetTable) 位置 D:\WPF\ConsoleApp7\ConsoleApp7\CopyDataUtil.cs:行号 207
minsic78 2017-12-04
  • 打赏
  • 举报
回复
引用 7 楼 dashenyyy 的回复:
[quote=引用 6 楼 minsic78 的回复:] 另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
public void BulkToDB(DataTable dt, string targetTable) { // lock (syncRoot) { string err = "大批量插入时产生错误"; OracleConnection conn = Connect("test", "test"); if (conn.State != ConnectionState.Open) { conn.Open(); } OracleBulkCopy bulkCopy = new OracleBulkCopy(conn, OracleBulkCopyOptions.Default); bulkCopy.BatchSize = pageSize; bulkCopy.BulkCopyTimeout = 260;//260 bulkCopy.DestinationTableName = targetTable; try { if (conn.State != ConnectionState.Open) { conn.Open(); } // conn.Open(); if (dt != null && dt.Rows.Count != 0) { bulkCopy.WriteToServer(dt); // m_OraTrans.Commit(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); // BulkToDB(dtt,targetTablee); } finally { conn.Close(); if (bulkCopy != null) bulkCopy.Close(); } } 就是用的这个ONP.NET ORACLE的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢[/quote] 我本来想看的是SQL…… 比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。 另外,说资源正忙报错的是啥情况下报的?
designerchen 2017-12-04
  • 打赏
  • 举报
回复
引用 6 楼 minsic78 的回复:
另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
我问了一下别人说同时往一张表里差,因为有事务隔离等级,肯定会锁表的,是不是只能单线程插入啊?
designerchen 2017-12-04
  • 打赏
  • 举报
回复
引用 6 楼 minsic78 的回复:
另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
public void BulkToDB(DataTable dt, string targetTable) { // lock (syncRoot) { string err = "大批量插入时产生错误"; OracleConnection conn = Connect("test", "test"); if (conn.State != ConnectionState.Open) { conn.Open(); } OracleBulkCopy bulkCopy = new OracleBulkCopy(conn, OracleBulkCopyOptions.Default); bulkCopy.BatchSize = pageSize; bulkCopy.BulkCopyTimeout = 260;//260 bulkCopy.DestinationTableName = targetTable; try { if (conn.State != ConnectionState.Open) { conn.Open(); } // conn.Open(); if (dt != null && dt.Rows.Count != 0) { bulkCopy.WriteToServer(dt); // m_OraTrans.Commit(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); // BulkToDB(dtt,targetTablee); } finally { conn.Close(); if (bulkCopy != null) bulkCopy.Close(); } } 就是用的这个ONP.NET ORACLE的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢
minsic78 2017-12-04
  • 打赏
  • 举报
回复
另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧
minsic78 2017-12-04
  • 打赏
  • 举报
回复
引用 4 楼 dashenyyy 的回复:
[quote=引用 3 楼 minsic78 的回复:] 另外,默认情况下,Oracle的绝大多数操作都是通过buffer cache,数据缓存区的。
你好,我在多线程向同一张表插入时,每条线程批量插入40万条数据,会出现锁表的现象啊。会导致有的线程操作不执行啊。 错误提示:ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 。 想请教您一下。[/quote] 也是插入的时候报资源正忙?而不是插入的时候做其他DDL操作,比如创建索引、修改表结构什么的?另外insert语句是怎么写的?本身有没有打开并行DML,使用append提示等等?但即使是这样,照理说也应该是等待,或者报出其他错误,而不是资源正忙才对。
designerchen 2017-12-04
  • 打赏
  • 举报
回复
引用 3 楼 minsic78 的回复:
另外,默认情况下,Oracle的绝大多数操作都是通过buffer cache,数据缓存区的。
你好,我在多线程向同一张表插入时,每条线程批量插入40万条数据,会出现锁表的现象啊。会导致有的线程操作不执行啊。 错误提示:ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 。 想请教您一下。
碧水幽幽泉 2017-12-02
  • 打赏
  • 举报
回复
Oracle从oracle7i开始就支持并行,即多线程,具体的使用方法有:

--1.修改表并行
alter table 表名称 parallel;

--2.查询设置并行度(即:线程数)
select /*+ parallel(table_name) */* from table_name ;
select /*+ parallel(t,8) */ * from table_name t;  
select /*+ parallel(8) */ * from table_name t;  
select /*+ parallel */ * from table_name t;   

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧