在以前的jaybird(2.2(版本中,我能够对Firebird服务器执行服务API以获得活动的事务标记:OIT,OAT,Next等。
在 3.0 版中,我找不到如何正确执行此操作。只有ISC常量(如isc_info_oldest_snapshot(,但没有方法。
所以,我看到了一种方法:通过StatisticsManager
获取数据库头的查询。但这并不容易,因为它会返回需要解析的文本:
StatisticsManager SM = new FBStatisticsManager(); //"PURE_JAVA", "NATIVE", "EMBEDDED"
SM.setHost("localhost");
SM.setUser("sysdba");
SM.setPort(3053);
SM.setPassword("masterkey");
SM.setDatabase("c:\Firebird\3.0.2\examples\empbuild\EMPLOYEE.FDB");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SM.setLogger(baos);
SM.getHeaderPage();
String outputstr2 = new String( baos.toByteArray(), java.nio.charset.StandardCharsets.UTF_8 );
现在我需要解析文本:
Database "C:FIREBIRD3.0.2EXAMPLESEMPBUILDEMPLOYEE.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
);
}
}
);
}
够吗?
我已经将功能添加到 Jaybird 3.0.0,请参阅此提交。
我添加了两种方法来获取此信息:
-
使用
StatisticsManager
:StatisticsManager statsMan = new FBStatisticsManager(); statsMan.setHost("localhost"); statsMan.setDatabase("/path/to/your.fdb"); statsMan.setUser("youruser"); statsMan.setPassword("yourpassword"); DatabaseTransactionInfo info = statsMan.getDatabaseTransactionInfo();
-
使用现有
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>
否则,您可以使用以下方法下载快照:
- Jaybird-JDK17 3.0.0-SNAPSHOT
- Jaybird-JDK18 3.0.0-快照
对于将来的版本,我将考虑是否可以以更通用的方式公开数据库信息查询工具,因此不必使用内部FbDatabase
接口。
select * from MON$DATABASE
会查询"OIT, OAT, Next">
或者,您可以通过select * from MON$TRANSACTIONS
获取更多详细信息
在c:Program FilesFirebirdFirebird_2_1docREADME.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:这些表中的某些数据仅在通过SYSDBA
或RDB$ADMIN
或数据库所有者用户连接时可用。示例:附件(连接(表将使其他用户的连接不可见,并为非管理员用户的请求跳过。
注意 2:从监视表中读取可能相对较慢,尤其是从包含连接相关(AKA 附件相关(信息的表中读取。慢,阻塞。因此,不建议过于频繁地读取监视表。