2013-11-01 17 views
7

Bản thân ứng dụng được mô tả trong question trước đó của tôi. Về phía Dal tôi sử dụngODP .NET hoạt động lạ

Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342 

Đây là chuỗi kết nối:

User id=usr;Password=pwd;Data Source=database1;Validate connection=True;Connection timeout=8;Pooling=false 

Các starange là đôi khi ODP tăng ra ngoại lệ sau đây:

Oracle.ManagedDataAccess.Client.OracleException (0xFFFFFC18): Connection request timed out 
    in OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, String instanceName) 
    in OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch) 
    in OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch) 
    in OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword) 
    in Oracle.ManagedDataAccess.Client.OracleConnection.Open() 
    in MySyncApp.DBRepository.GetChangedDataDB(DateTime startPeriod) in D:\MySyncApp\MySyncApp\DB.cs:line 23 
    in MySyncApp.Program.<>c__DisplayClass30.<>c__DisplayClass32.<Synchronize>b__2f(ID id) in D:\MySyncApp\MySyncApp\Program.cs:line 441 

Nhưng sau khi ngoại lệ này, khi tôi nhìn vào các phiên trong Oracle, tôi thấy rằng thực sự kết nối đang hoạt động và chỉ được đánh dấu là INACTIVE! Vì vậy, các kết nối như vậy sẽ tiếp tục treo ở phía máy chủ, dần dần loại bỏ một số phiên có sẵn.

Có gì đặc biệt trong mã của tôi là, chỉ

public List<DataObj> GetChangedDataDB(DateTime startPeriod) 
{ 
    List<DataObj> list = new List<DataObj>(); 
    using (OracleConnection conn = new OracleConnection(this._connstr)) 
    { 
     conn.Open(); 

     using (OracleCommand comm = new OracleCommand("select data from table(usr.syncpackage.GetChanged(:pStart))", conn)) 
     { 
      comm.CommandTimeout = 10; 
      comm.Parameters.Add(":pStart", startPeriod); 

      using (OracleDataReader reader = comm.ExecuteReader()) 
      { 
       // ..omitted 
      } 
     } 

    } 
    return list; 
} 

Mã này chạy trong Parallel.ForEach vòng lặp cho kéo ra dữ liệu từ rất nhiều cơ sở dữ liệu cùng một lúc. Thậm chí có thể có ba kết nối song song với cùng một cơ sở dữ liệu (ví dụ, lấy ra dữ liệu từ các phần khác nhau của lược đồ, từ ba bộ phận khác nhau của doanh nghiệp).

Các Oracle là

Oracle Database 11g Enterprise Edition phiên bản 11.2.0.3.0 - 64bit Sản

Quá trình đồng bộ hóa tự bắn vào hẹn giờ trong khoảng thời gian 10 giây. Nếu có đã được runnning nhiệm vụ thì công việc tiếp theo đã được dừng lại:

public static void Synchronize(object obj) 
    {    
     // ... omitted 
     log.Info("ITERATION_COMMON_START"); 

     if (Program.State == "Running") 
     { 
      log.Info("ITERATION_COMMON_END_BY_EXISTING"); 
      return; 
     } 

     lock (Program.StateLock) 
     { 
      Program.State = "Running"; 
     }     

     Parallel.ForEach(Global.config.dbs, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (l) => 
     { 
      Console.WriteLine("Started synchronization for {0}", l.key); 
      DBRepository db = new DBRepository(l.connectionString); 

      Parallel.ForEach(l.departments, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (department) => 
      {      
       DateTime ChangesFromTS = GetPreviousIterationTS; 
       List<DataObj> cdata = db.GetChangedDataDB(ChangesFromTS); 
       // ... doing the work here 
      } 

     } 

     // Finishing work 

     GC.Collect();    

     lock (Program.StateLock) 
     { 
      Program.State = ""; 
     } 

    } 

Đây là bộ đếm thời gian cho cách gọi đồng bộ hóa các nhiệm vụ theo định kỳ:

Program.getModifiedDataTimer = new Timer(Program.Synchronize, null, (int)Global.config.syncModifiedInterval * 1000, (int)Global.config.syncModifiedInterval * 1000); 

Global.config.syncModifiedInterval là trong vài giây

ODP cư xử thân theo cùng một cách khi tôi bật tính năng tổng hợp. Nó tạo ra nhiều kết nối hơn được cho phép bởi chỉ thị Max pool size trong các chuỗi kết nối với cùng một ngoại lệ.

Hãy cho tôi biết suy nghĩ và kinh nghiệm của bạn về nội dung đó.


CẬP NHẬT

Dưới đây là một phần của Oracle dấu vết khi ngoại lệ xảy ra:

(PUB) (ERR) OracleConnection.Open() (txnid=n/a) Oracle.ManagedDataAccess.Client.OracleException (0xFFFFFC18): Connection request timed out 
    in OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, String instanceName) 
    in OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch) 
    in OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch) 
    in OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword) 
    in Oracle.ManagedDataAccess.Client.OracleConnection.Open() 

CẬP NHẬT # 2

Có vẻ như thế này kết nối các chương trình lên b ecause của lag kết nối, như yêu cầu để thiết lập kết nối oracle được gửi nhưng phản ứng của nó bị bỏ qua. Hoặc dữ liệu được truyền đến/từ máy chủ đang bị hỏng trong khi nó đến đích.

Kết nối tiếp tục treo trong danh sách phiên của máy chủ ngay cả khi tôi tắt ứng dụng. Khi tôi giết một phiên, nó đang treo trong danh sách với nhãn "KILLED".


CẬP NHẬT # 3

Here là ứng dụng demo mà làm cho cùng một vấn đề. Như tôi đã nói trước đây, nó xuất hiện trên kết nối kém, bạn có thể mô phỏng kết nối như vậy bằng cách sử dụng bộ mô phỏng WANem. Here là cùng một thành phần tôi sử dụng để kết nối cơ sở dữ liệu. Hy vọng giúp đỡ của bạn.

+0

Bạn có thể cung cấp kết xuất đơn khi điều đó xảy ra không? – Olivier

+0

@Olivier Vui lòng xem cập nhật câu hỏi thứ ba của tôi. Hy vọng nó làm cho bạn dễ dàng hơn để tái tạo vấn đề. Nhưng có, chắc chắn, tôi có thể làm một bãi chứa. – kseen

+0

Bạn có bao giờ giải quyết được không? –

Trả lời

4

Thời gian chờ kết nối của bạn cực kỳ thấp, 8 giây nói chung và 10 giây đối với các lệnh bạn đang phát hành, hãy thử tăng nó lên một phút để xem điều gì xảy ra. Tôi không biết các thuật toán của bạn nặng bao nhiêu, nhưng chỉ đủ một luồng ở đâu đó với một truy vấn trong vòng chưa đầy 8 giây và bạn sẽ nhận được ngoại lệ đó.

Ngoài ra, tôi không thể tìm thấy tài liệu nói rằng ODP.net không phải là thread-an toàn, nhưng tôi không thể tìm thấy bất kỳ tài liệu nói rằng nó là một trong hai, vì vậy nếu không có gì khác giúp thử thay đổi này:

Parallel.ForEach(Global.config.dbs, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (l) => 
    { 
     Console.WriteLine("Started synchronization for {0}", l.key); 

     Parallel.ForEach(l.departments, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (department) => 
     {      
      // Now local to the executing thread. 
      DBRepository db = new DBRepository(l.connectionString); 

      DateTime ChangesFromTS = GetPreviousIterationTS; 
      List<DataObj> cdata = db.GetChangedDataDB(ChangesFromTS); 
      // ... doing the work here 
     } 

    } 
0

Bạn có cố gắng incraese thời gian chờ lệnh (dòng mã trong phương pháp GetChangedDataDB)? Một cái gì đó như thế này

comm.CommandTimeout = 360; 

tôi đã tạo ra dự án quản lý dữ liệu khổng lồ và tôi cũng nhận được thông báo lỗi như bạn, vì vậy tôi thêm ngày càng nhiều giá trị CommandTimeout, sau đó nó hoạt động, nhưng tôi không chắc chắn nếu bạn đã gặp trường hợp tương tự như tôi.

Nói cách khác, tôi thấy bạn có phạm vi Parallel.ForEach trong phạm vi Parallel.ForEach và tôi nghĩ bạn có thể thử sửa đổi phạm vi thứ hai bằng cách sử dụng Thư viện công việc song song. bạn có thể tìm hiểu nó ở đây hơn http://msdn.microsoft.com/en-us/library/dd537609.aspx

Sau đó, phạm vi Parallel.ForEach thứ hai của bạn nên được như thế này

Task task = new Task(() => 
Parallel.ForEach(l.departments, new ParallelOptions { MaxDegreeOfParallelism = -1 }, (department) => 
{ 
    // Now local to the executing thread. 
    DBRepository db = new DBRepository(l.connectionString); 

    DateTime ChangesFromTS = GetPreviousIterationTS; 
    List<DataObj> cdata = db.GetChangedDataDB(ChangesFromTS); 
    // ... doing the work here 
} 
)); //close lambda expression 

task.Start(); 
1

tôi đã cùng một vấn đề với F # mã của tôi. Nó sinh ra nhiều kết nối cùng một lúc và không sử dụng thư viện Task Parallel. Tôi đồng ý với flindeberg, Motomoto Pink và kết luận của riêng bạn rằng vấn đề là kết nối xác nhận phản hồi từ Oracle đến sau khi ngoại lệ hết thời gian chờ kết nối.

Như những người khác, tôi khuyên bạn nên tăng thời gian chờ yêu cầu kết nối. Nhưng bổ sung bạn có thể xem xét sử dụng hồ bơi kết nối với thông số Min Pool Size được đặt thành số chuỗi được tạo song song sẽ mở các kết nối. Việc sử dụng pool kết nối có thể làm tăng đáng kể hiệu suất cả ở phía máy khách và phía máy chủ khi số lượng các phòng ban lớn.

Các vấn đề liên quan