16.1: 当我尝试使用MySQL Connector / J连接到数据库时,出现以下异常:
SQLException: Server configuration denies access to data source
SQLState: 08001
VendorError: 0
到底是怎么回事?我可以很好地与MySQL命令行客户端连接。
Connector / J通常使用TCP / IP套接字连接到MySQL(有关例外情况,请参见第6.8节“使用Unix域套接字连接”和 第6.9节“使用命名管道连接”)。MySQL服务器上的安全管理器使用其授权表来确定是否允许TCP / IP连接。因此,您必须通过向MySQL服务器发布一条GRANT语句,为连接添加必要的安全凭证。有关更多信息,请参见GRANT语句。
警告
在MySQL上不正确地更改特权和权限可能会导致您的服务器安装具有非最佳的安全属性。
注意
除非您添加 标志,并且使用主机以外的其他功能, 否则无法 使用mysql命令行客户端测试连接性 。如果使用特殊的主机名,则 mysql命令行客户端将尝试使用Unix域套接字 。如果要测试与的TCP / IP连接,请改用 作为主机名。 --hostlocalhostlocalhostlocalhost127.0.0.1
16.2: 我的应用程序抛出一个SQLException'没有合适的驱动程序'。为什么会这样呢?
有三种可能的原因导致此错误:
Connector / J驱动程序不在您的范围内 CLASSPATH,请参阅 第4章,Connector / J安装。
连接URL的格式不正确,或者您引用了错误的JDBC驱动程序。
使用DriverManager时, jdbc.drivers尚未使用Connector / J驱动程序的位置填充系统属性。
16.3: 我试图在小程序或应用程序中使用MySQL Connector / J,但出现类似于以下的异常:
SQLException: Cannot connect to MySQL server on host:3306.
Is there a MySQL server running on the machine/port you
are trying to connect to?
(java.security.AccessControlException)
SQLState: 08S01
VendorError: 0
您正在运行Applet,安装了 skip_networking启用系统变量的MySQL服务器,或者您的MySQL服务器前面都有防火墙。
小程序只能通过网络连接到运行为该小程序提供.class文件的Web服务器的计算机。这意味着MySQL必须在同一台计算机上运行(或者您必须具有某种类型的端口重定向)才能起作用。这也意味着您将无法从本地文件系统测试applet,但必须始终将它们部署到Web服务器。
Connector / J通常使用TCP / IP套接字连接到MySQL(有关例外情况,请参见第6.8节“使用Unix域套接字连接”和 第6.9节“使用命名管道连接”)。与MySQL的TCP / IP通信可能会受到 skip_networking系统变量或服务器防火墙的影响。如果已skip_networking 启用MySQL 启动,则需要在文件中注释掉它, /etc/mysql/my.cnf或 /etc/my.cnf使TCP / IP连接正常工作。(请注意,您的服务器配置文件也可能存在于dataMySQL服务器的目录或其他位置,具体取决于MySQL的编译方式;由Oracle创建的二进制文件总是寻找 /etc/my.cnf和 datadir/my.cnf; 有关详细信息,请参见使用选项文件。)如果您的MySQL服务器已经过防火墙保护,则需要配置防火墙以允许从运行Java代码的主机到MySQL正在侦听的端口上的MySQL服务器进行TCP / IP连接。到(默认为3306)。
16.4: 我有一个servlet /应用程序,可以正常工作一天,然后在一夜之间停止工作
MySQL闲置8个小时后关闭连接。您要么需要使用处理过时的连接的连接池,要么使用autoReconnect 参数(请参见 第6.3节“配置属性”)。
另外,捕获SQLExceptions您的应用程序并处理它们,而不是一直传播它们直到您的应用程序退出。这只是良好的编程习惯。MySQL Connector / J会将 SQLState(java.sql.SQLException.getSQLState()在API文档中参见 )设置为08S01在查询处理期间遇到网络连接问题时。此时尝试重新连接到MySQL。
以下(简单的)示例显示了可以处理这些异常的代码如下所示:
例16.1连接器/ J:具有重试逻辑的事务示例
public void doBusinessOp() throws SQLException{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//
// How many times do you want to retry the transaction
// (or at least _getting_ a connection)?
//
int retryCount = 5;
boolean transactionCompleted = false;
do {
try {
conn = getConnection(); // assume getting this from a
// javax.sql.DataSource, or the
// java.sql.DriverManager
conn.setAutoCommit(false);
//
// Okay, at this point, the 'retry-ability' of the
// transaction really depends on your application logic,
// whether or not you're using autocommit (in this case
// not), and whether you're using transactional storage
// engines
//
// For this example, we'll assume that it's _not_ safe
// to retry the entire transaction, so we set retry
// count to 0 at this point
//
// If you were using exclusively transaction-safe tables,
// or your application could recover from a connection going
// bad in the middle of an operation, then you would not
// touch 'retryCount' here, and just let the loop repeat
// until retryCount == 0.
//
retryCount = 0;
stmt = conn.createStatement();
String query = "SELECT foo FROM bar ORDER BY baz";
rs = stmt.executeQuery(query);
while (rs.next()) {
}
rs.close();
rs = null;
stmt.close();
stmt = null;
conn.commit();
conn.close();
conn = null;
transactionCompleted = true;
} catch (SQLException sqlEx) {
//
// The two SQL states that are 'retry-able' are 08S01
// for a communications error, and 40001 for deadlock.
//
// Only retry if the error was due to a stale connection,
// communications problem or deadlock
//
String sqlState = sqlEx.getSQLState();
if ("08S01".equals(sqlState) || "40001".equals(sqlState)) {
retryCount -= 1;
} else {
retryCount = 0;
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
// You'd probably want to log this...
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
// You'd probably want to log this as well...
}
}
if (conn != null) {
try {
//
// If we got here, and conn is not null, the
// transaction should be rolled back, as not
// all work has been done
try {
conn.rollback();
} finally {
conn.close();
}
} catch (SQLException sqlEx) {
//
// If we got an exception here, something
// pretty serious is going on, so we better
// pass it up the stack, rather than just
// logging it...
throw sqlEx;
}
}
}
} while (!transactionCompleted && (retryCount > 0));
}
注意
autoReconnect不建议 使用该选项,因为没有安全的方法可以重新连接到MySQL服务器,而不会冒连接状态或数据库状态信息损坏的风险。而是使用连接池,这将使您的应用程序可以使用池中的可用连接连接到MySQL服务器。该 autoReconnect功能已弃用,在将来的版本中可能会删除。
16.5: 我无法使用Connector / J连接到MySQL服务器,并且我确定连接参数正确。
确保 skip_networking尚未在服务器上启用系统变量。Connector / J必须能够通过TCP / IP与服务器通信;不支持命名套接字。另外,请确保您没有通过防火墙或其他网络安全系统过滤连接。有关更多信息,请参见 无法连接到[本地] MySQL服务器。