我正在尝试创建一个JDBC
连接池组件,但我遇到了一个问题。那就是:如何检测java.sql.SQLException
的错误状态。
据说,州应遵循SQL2003
约定中的XOPEN SQL
约定和JDK
约定。但我找不到关于这两个约定的任何文件。有人可以为我提供吗?
我想知道每个州代表什么,所以我可以决定何时完全关闭连接或重新连接。
我已提到BoneCP
的源代码。以下是在发生SQLException时将激活的部分:
ImmutableSet<String> sqlStateDBFailureCodes = ImmutableSet.of("08001", "08007", "08S01", "57P01", "HY000");
String state = e.getSQLState();
ConnectionState connectionState = this.getConnectionHook() != null ? this.getConnectionHook().onMarkPossiblyBroken(this, state, e) : ConnectionState.NOP;
if (state == null){ // safety;
state = "08999";
}
if (((sqlStateDBFailureCodes.contains(state) || connectionState.equals(ConnectionState.TERMINATE_ALL_CONNECTIONS)) && this.pool != null) && this.pool.getDbIsDown().compareAndSet(false, true) ){
logger.error("Database access problem. Killing off all remaining connections in the connection pool. SQL State = " + state);
this.pool.connectionStrategy.terminateAllConnections();
this.pool.poisonAndRepopulatePartitions();
}
char firstChar = state.charAt(0);
if (connectionState.equals(ConnectionState.CONNECTION_POSSIBLY_BROKEN) || state.equals("40001") ||
state.startsWith("08") || (firstChar >= '5' && firstChar <='9') /*|| (firstChar >='I' && firstChar <= 'Z')*/){
this.possiblyBroken = true;
}
// Notify anyone who's interested
if (this.possiblyBroken && (this.getConnectionHook() != null)){
this.possiblyBroken = this.getConnectionHook().onConnectionException(this, state, e);
}
根据这些代码,当{SQLException>的状态等于“08001”,“08007”,“08S01”,“57P01”,“HY000”之一时,boneCP
将其视为数据库服务器崩溃。
但为什么,这些州代表什么呢?
答案 0 :(得分:5)
前{2}个字符在SQL92 specification的“Table_23-SQLSTATE_class_and_subclass_values”中指定。
以下是相关摘录:
00 success completion
01 warning
02 no data
07 dynamic SQL error
08 connection exception
0A feature not supported
21 cardinality violation
22 data exception
23 integrity constraint violation
24 invalid cursor state
25 invalid transaction state
26 invalid SQL statement name
27 triggered data change violation
28 invalid authorization specification
2A direct SQL syntax error or access rule violation
2B dependent privilege descriptors still exist
2C invalid character set name
2D invalid transaction termination
2E invalid connection name
33 invalid SQL descriptor name
34 invalid cursor name
35 invalid condition number
37 dynamic SQL syntax error or access rule violation
3C ambiguous cursor name
3D invalid catalog name
3F invalid schema name
40 transaction rollback
42 syntax error or access rule violation
44 with check option violation
HZ remote database access
其余字符与数据库供应商有关。因此,通常建议只执行startsWith()
检查。
答案 1 :(得分:2)
SQL标准(ISO / IEC-9075),特别是书2基础定义SQL状态。它们是一个2个字符的类值,后跟一个3个字符的子类值。
以“0”,“1”,“2”,“3”或“4”之一或简单的拉丁大写字母“A”,“B”之一开头的类值C','D','E','F','G'或'H'仅在ISO / IEC 9075或任何其他国际标准中定义的条件下返回。 [...]仅与ISO / IEC 9075或其他国际标准中定义的条件一起返回与这些类别相关的子类值,这些类别也以这13个字符之一开头。 [...]与这些类相关联的子类值,以数字“5”,“6”,“7”,“8”或“9”之一或简单的拉丁大写字母“I”之一开头,'J','K','L','M','N','O','P','Q','R','S','T','U',' V','W','X','Y'或'Z'保留用于实现定义的条件,并称为实现定义的子类。
以数字'5','6','7','8'或'9'之一开头的类值或其中一个简单的拉丁大写字母'I','J',' K','L','M','N','O','P','Q','R','S','T','U','V','W' ,'X','Y'或'Z'保留用于实现定义的异常条件,并称为实现定义的类。除了'000'之外的所有子类值(这意味着没有子类)与这些类相关联,都是为实现定义的条件保留的,并且被称为实现定义的子类。
(来自SQL:2011第2册)
这些标准类(和标准定义的子类)列在第2册(基础),3(CLI),4(PSM),9(MED),10(OLB),13(JRT)和14(XML)中。它还列出了某些内容是异常,警告,成功完成条件还是无数据完成条件(并非所有SQL状态都是错误!)
例如,您问题中列出的sqlstates是:
08001
:class:连接异常,子类:SQL-client无法建立SQL连接08007
:class:连接异常,子类:事务解析未知08S01
:class:连接异常,子类:以S开头,因此是实现定义的子类(在ODBC中定义为通信链接失败)57P01
:class:从5开始,实现定义类也是如此,它似乎是ADMIN SHUTDOWN的PostgreSQL sqlstate HY000
:class:特定于CLI的条件(在第3册中定义,CLI),子类:(无子类) HY000
是一个非常通用的错误,因为某些数据库或驱动程序会为没有特定sqlstate的任何错误返回它,因此它通常被视为致命错误。我认为BoneCP的行为将其视为杀死整个连接池的一个原因有点过分,因为HY000
也可能因为相对良性的错误而被抛出。其他sqlstates通常表示连接到数据库(08001
,08S01
)或数据库不可用(57P01
)或数据库本身存在问题({{ 1}})。
答案 2 :(得分:0)