我现在为提高效率多线程向同一张表插入,会出现超时的问题,可以并发插入数据库缓存,然后让他自己再插入吗?MySQL有这种方式,不知道ORACLE该如何实现?

解决方案 »

  1.   

    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;   
      

  2.   

    高并发插入最常见的问题:
    主键递增,主键索引分裂争用——将主键索引调整为分区hash全局索引,具体分区数可参考最高并发数,如果主键上不存在范围扫描,可以将该索引进一步调整为反向索引;递增主键因为可能由sequence提供,所以序列上可能也会发生争用,调整sequence cache可以一定程度上缓减这种争用。
    当然还有很多其他原因会导致并发插入的性能问题,需要更多信息,比如插入时候的等待事件,甚至是插入时间段的AWR报告,以作进一步诊断。
      

  3.   

    另外,默认情况下,Oracle的绝大多数操作都是通过buffer cache,数据缓存区的。
      

  4.   

    你好,我在多线程向同一张表插入时,每条线程批量插入40万条数据,会出现锁表的现象啊。会导致有的线程操作不执行啊。
    错误提示:ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效  。
    想请教您一下。
      

  5.   

    你好,我在多线程向同一张表插入时,每条线程批量插入40万条数据,会出现锁表的现象啊。会导致有的线程操作不执行啊。
    错误提示:ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效  。
    想请教您一下。也是插入的时候报资源正忙?而不是插入的时候做其他DDL操作,比如创建索引、修改表结构什么的?另外insert语句是怎么写的?本身有没有打开并行DML,使用append提示等等?但即使是这样,照理说也应该是等待,或者报出其他错误,而不是资源正忙才对。
      

  6.   

    另外,查下表一级是否打开了parallel属性,表上是否有位图索引,咱们来玩猜猜猜吧 
      

  7.   

     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的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢
      

  8.   

     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的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢我本来想看的是SQL……
    比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。另外,说资源正忙报错的是啥情况下报的?
      

  9.   

     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的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢我本来想看的是SQL……
    比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。另外,说资源正忙报错的是啥情况下报的?
    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
      

  10.   

     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的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢我本来想看的是SQL……
    比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。另外,说资源正忙报错的是啥情况下报的?
    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
    我们公司现在就是单线程顺序插入嘛,一次插入10万左右,现在想要插入更快,我就想着多线程一起插入可不可以
      

  11.   

     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的批量插入方法。多线程调用他,你看,我上面要是加锁让线程排队就没事,不过就会线程争夺资源,比单线程还慢我本来想看的是SQL……
    比单线程慢是正常的,无论什么样的系统,并发总是有拐点的,而且你每批次插入几十万数据,争用会更明显,但总体是要比单条插入效率高的,你少开几个并发试试。另外,说资源正忙报错的是啥情况下报的?
    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
    我们公司现在就是单线程顺序插入嘛,一次插入10万左右,现在想要插入更快,我就想着多线程一起插入可不可以
    我是从数据源多线程批量导出,这样读取快,然后想着多线程批量导入
      

  12.   

    多线程当然可以,但是线程数肯定不是可以无限上涨的,也许你得找找这个拐点,看来报资源正忙不是一下子就报的,而是执行时间长了之后再报的,那么可能还是一些非高级队列锁的争用,如果想找找是否还有优化的余地,最好能有精确的问题时段的AWR报告
      

  13.   


    如果获取AWR报告有困难,那么可以在程序执行的时候,查下v$session.event字段,看看插入的那些线程都在经历一些什么等待,多次查询,看看会不会有什么变化