2017-03-22 45 views
2

在以前的版本jaybird(2.2),我是能夠執行服務API來火鳥服務器,以獲得活動事務標記:OIT,燕麥,下一首等Jaybird 3和Firebird交易信息

在3.0版本中,我無法找到如何正確地做到這一點。只有ISC常量(如isc_info_oldest_snapshot),但沒有方法。

所以,我看到了一種方法:通過StatisticsManager獲取數據庫頭的查詢。但它不是那麼容易,因爲它會返回一個需要解析的文本:

​​

,現在我需要解析的文字:

Database "C:\FIREBIRD\3.0.2\EXAMPLES\EMPBUILD\EMPLOYEE.FDB" 
Database header page information: 
    Flags   0 
    Generation  806 
    System Change Number 12 
    Page size  8192 
    ODS version  12.0 
    Oldest transaction 520 
    Oldest active  521 
    Oldest snapshot  521 
    Next transaction 521 
    Sequence number  0 
    Next attachment ID 857 
    Implementation  HW=AMD/Intel/x64 little-endian OS=Windows CC=MSVC 
    Shadow count  0 
    Page buffers  0 
    Next header page 0 
    Database dialect 3 
    Creation date  Apr 15, 2016 17:38:34 
    Attributes   

    Variable header data: 
    Database backup GUID: {6F41E937-76D5-4C67-6CAE-F8556AD27BEE} 
    Database GUID: {EE5B2713-7B17-43B0-0CB3-0616B4B8A63D} 
    *END* 

可能就可以得到直接值?

UPD:代碼舊版本是:

/** [ActiveCount, OAT, OST, OIT, Next] */ 
public static int[] getTxInfo(final GDS gds, 
           final String host, 
           final int port, 
           final String databasePath, 
           final String user, 
           final String password) throws Exception { 
    final byte[] queryItems = { 
      ISCConstants.isc_info_oldest_transaction, 
      ISCConstants.isc_info_oldest_active, 
      ISCConstants.isc_info_oldest_snapshot, 
      ISCConstants.isc_info_next_transaction, 
      ISCConstants.isc_info_active_transactions, 
      ISCConstants.isc_info_end 
    }; 
    byte[] response = queryDB(
      gds, host, port, databasePath, user, password, 
      queryItems, DEFAULT_BUFFER_SIZE 
    ); 
    int i = 0; 
    final int[] result = new int[5]; 
    while (response[i] != ISCConstants.isc_info_end) { 
     final byte code = response[i++]; 
     switch (code) { 
      case ISCConstants.isc_info_active_transactions: { 
       //здесь идет столько блоков isc_info_active_transactions, сколько 
       //реально активных транзакций в данный момент 
       final int valueLen = gds.iscVaxInteger(response, i, LENGTH_LEN); 
       i += LENGTH_LEN; 
       //final int res = gds.iscVaxInteger(response, i, valueLen); 
       i += valueLen; 
       result[0]++; 
       break; 
      } 
      case ISCConstants.isc_info_oldest_active: { 
       final int valueLen = gds.iscVaxInteger(response, i, LENGTH_LEN); 
       i += LENGTH_LEN; 
       final int res = gds.iscVaxInteger(response, i, valueLen); 
       i += valueLen; 
       result[1] = res; 
       break; 
      } 
      case ISCConstants.isc_info_oldest_snapshot: { 
       final int valueLen = gds.iscVaxInteger(response, i, LENGTH_LEN); 
       i += LENGTH_LEN; 
       final int res = gds.iscVaxInteger(response, i, valueLen); 
       i += valueLen; 
       result[2] = res; 
       break; 
      } 
      case ISCConstants.isc_info_oldest_transaction: { 
       final int valueLen = gds.iscVaxInteger(response, i, LENGTH_LEN); 
       i += LENGTH_LEN; 
       final int res = gds.iscVaxInteger(response, i, valueLen); 
       i += valueLen; 
       result[3] = res; 
       break; 
      } 
      case ISCConstants.isc_info_next_transaction: { 
       final int valueLen = gds.iscVaxInteger(response, i, LENGTH_LEN); 
       i += LENGTH_LEN; 
       final int res = gds.iscVaxInteger(response, i, valueLen); 
       i += valueLen; 
       result[4] = res; 
       break; 
      } 
      case ISCConstants.isc_info_truncated: { 
       //этот код означает "буфер слишком маленький, дайте больше" 
       //обычно это бывает когда слишком много активных транзакций 

       //сначала пробуем увеличить буфер 
       if (response.length == DEFAULT_BUFFER_SIZE) { 
        response = queryDB(
          gds, host, port, databasePath, user, password, 
          queryItems, 32 * DEFAULT_BUFFER_SIZE 
        ); 
        result[0] = 0;//на всякий случай 
        //начинаем разбор заново 
        i = 0; 
       } else { 
        //32Кб буфера оказалось тоже недостаточно -- пичалька. Но 
        //делать нечего -- просто обойдемся без числа активных транзакций 
        response = queryDB(
          gds, host, port, databasePath, user, password, 
          new byte[]{ 
            ISCConstants.isc_info_oldest_transaction, 
            ISCConstants.isc_info_oldest_active, 
            ISCConstants.isc_info_oldest_snapshot, 
            ISCConstants.isc_info_next_transaction, 
            ISCConstants.isc_info_end 
          }, DEFAULT_BUFFER_SIZE 
        ); 
        result[0] = -1; 
        //начинаем разбор заново 
        i = 0; 
       } 
       break; 
      } 

      default: 
       throw new FBSQLException("Unrecognized response code: " + code + " (response=" + Arrays.toString(result) + ")"); 
     } 
    } 
    return result; 
} 

其中

public static byte[] queryDB(final GDS gds, 
           final String host, 
           final int port, 
           final String databasePath, 
           final String user,  
           final String password, 
           final byte[] queryItems, 
           final int bufferLength) throws Exception { 
    return doWithDB(
      gds, host, port, databasePath, user, password, 
      new DBOperation<byte[]>() { 
       public byte[] doWithDB(final GDS gds, 
             final IscDbHandle db) throws GDSException { 
        return gds.iscDatabaseInfo(
          db, 
          queryItems, 
          bufferLength 
        ); 
       } 
      } 
    ); 
} 

是否足夠?

+0

您可以繼承'FBServiceManager'並自己獲取信息。我會看看我是否可以將它添加到'FBStatisticsManager'(或者如果我像上次一樣忽略它)。 –

+0

它會很好!我需要事務標記來檢查一些間隙和掃描... –

+0

我爲此創建了[JDBC-485](http://tracker.firebirdsql.org/browse/JDBC-485)。根據當前的時間表,我會在可用時更新,可能會在一兩週內更新。 –

回答

1

我已將功能添加到Jaybird 3.0.0,請參閱this commit

我已經添加了兩種方式來獲得這樣的信息:

  1. 使用StatisticsManager

    StatisticsManager statsMan = new FBStatisticsManager(); 
    statsMan.setHost("localhost"); 
    statsMan.setDatabase("/path/to/your.fdb"); 
    statsMan.setUser("youruser"); 
    statsMan.setPassword("yourpassword"); 
    DatabaseTransactionInfo info = statsMan.getDatabaseTransactionInfo(); 
    
  2. 使用現有Connection得到這個信息的簡便方法:

    try (Connection connection = dataSource.getConnection()) { 
        DatabaseTransactionInfo info = FBStatisticsManager 
          .getDatabaseTransactionInfo(connection); 
    } 
    

    唯一的要求是連接實例展開到接口FirebirdConnection

如果您正在使用Maven,你可以嘗試從Sonatype的OSS快照庫中的最新Jaybird快照:https://oss.sonatype.org/content/repositories/snapshots(你需要這個快照庫添加到您的Maven的配置)。

<dependency> 
    <groupId>org.firebirdsql.jdbc</groupId> 
    <artifactId>jaybird-jdk18</artifactId> 
    <version>3.0.0-SNAPSHOT</version> 
</dependency> 

否則,您可以使用下載快照:

對於未來的版本,我會考慮,如果我能在一個公開的數據庫中的信息查詢功能更通用的方式,所以沒有必要使用內部FbDatabase接口。

0

select * from MON$DATABASE將查詢 「OIT,燕麥,下一步」

或者您也可以通過select * from MON$TRANSACTIONS

見多c:\Program Files\Firebird\Firebird_2_1\doc\README.monitoring_tables.txt獲得更多細節

MON$DATABASE (connected database) 
    - MON$DATABASE_NAME (database pathname or alias) 
    - MON$PAGE_SIZE (page size) 
    - MON$ODS_MAJOR (major ODS version) 
    - MON$ODS_MINOR (minor ODS version) 
    - MON$OLDEST_TRANSACTION (OIT number) 
    - MON$OLDEST_ACTIVE (OAT number) 
    - MON$OLDEST_SNAPSHOT (OST number) 
    - MON$NEXT_TRANSACTION (next transaction number) 
    - MON$PAGE_BUFFERS (number of pages allocated in the cache) 
    - MON$SQL_DIALECT (SQL dialect of the database) 
    - MON$SHUTDOWN_MODE (current shutdown mode) 
     0: online 
     1: multi-user shutdown 
     2: single-user shutdown 
     3: full shutdown 
    - MON$SWEEP_INTERVAL (sweep interval) 
    - MON$READ_ONLY (read-only flag) 
    - MON$FORCED_WRITES (sync writes flag) 
    - MON$RESERVE_SPACE (reserve space flag) 
    - MON$CREATION_DATE (creation date/time) 
    - MON$PAGES (number of pages allocated on disk) 
    - MON$BACKUP_STATE (current physical backup state) 
     0: normal 
     1: stalled 
     2: merge 
    - MON$STAT_ID (statistics ID) 

MON$TRANSACTIONS (started transactions) 
    - MON$TRANSACTION_ID (transaction ID) 
    - MON$ATTACHMENT_ID (attachment ID) 
    - MON$STATE (transaction state) 
     0: idle 
     1: active 
    - MON$TIMESTAMP (transaction start date/time) 
    - MON$TOP_TRANSACTION (top transaction) 
    - MON$OLDEST_TRANSACTION (local OIT number) 
    - MON$OLDEST_ACTIVE (local OAT number) 
    - MON$ISOLATION_MODE (isolation mode) 
     0: consistency 
     1: concurrency 
     2: read committed record version 
     3: read committed no record version 
    - MON$LOCK_TIMEOUT (lock timeout) 
     -1: infinite wait 
     0: no wait 
     N: timeout N 
    - MON$READ_ONLY (read-only flag) 
    - MON$AUTO_COMMIT (auto-commit flag) 
    - MON$AUTO_UNDO (auto-undo flag) 
    - MON$STAT_ID (statistics ID) 

注1:本表中的一些數據僅當通過SYSDBARDB$ADMIN或數據庫所有者用戶連接時纔可用。示例:附件(連接)表將使其他用戶連接不可見,並跳過非管理員用戶的請求。注2:從監控表中讀取可能相對較慢,尤其是從包含與連接有關的(與AKA附件相關的)信息的表中。在那緩慢和阻塞。所以不建議經常閱讀監控表。

+0

編號$ MON表是最糟糕的方法,因爲它的速度放緩...最好解碼數據庫頭結構以從數據庫文件中獲取這些值(我可以訪問它),但我不確定 - 如果FB引擎+ OS在所有系統上正確更新它們 –

+0

它們會在他們想要更新時正確更新它。它正在讀取它們而沒有先刷新服務器和操作系統緩存,這是不正確的。無論如何,閱讀MON $ DATABASSE中的單行不應該是一個大的放緩。 FB3也試圖加速周表和棄用服務API,所以你必須有備份計劃。此外,您可以與Firebird開發人員自己討論它在sql.ru/forum/interbase –

+0

然後減速是一個非常相對的術語,如果你這樣做,每秒檢查1000次 - 這是一種情況,如果你每隔千秒做一次 - 另一個。 –