本节解释的症状和决议的最常见的问题与应用程序使用MySQL连接器/ J。
问题
15.1:当我试图连接到数据库和MySQL连接器/ J,我得到以下异常:
SQLException异常:服务器配置数据源SQLState拒绝访问:08001 VendorError: 0
什么是怎么回事?我可以连接MySQL命令行客户端就可以了。
15.2:我的应用程序抛出SQLException没有合适的驱动程序。为什么会这样?
15.3:我想在applet或者应用程序中使用MySQL连接器/ J,我得到一个类似于异常:
SQLException异常:无法连接到MySQL服务器主机:3306。有在这台机器上运行的MySQL服务器/端口你试图连接到吗?(java.security.AccessControlException) SQLState: 08年s01 VendorError: 0
15.4:我有一个servlet /应用程序工作正常一天,一夜之间,然后停止工作
15.5:我不能连接到MySQL服务器使用连接器/ J,我相信连接参数是正确的。
15.7:我得到一个
ER_NET_PACKET_TOO_LARGE
例外,即使二进制斑点大小我想插入下面安全使用JDBCmax_allowed_packet
大小。15.8:我该怎么办如果我收到错误消息类似如下:”通信链路失败——最后一个数据包发送到服务器前女士是X”吗?
15.9:为什么连接器/ J不连接到MySQL和重新发出声明后通信失败而不是抛出异常,即使我使用吗
autoReconnect
连接字符串的选择吗?15.10:我怎么能使用3字节UTF8连接器/ J ?
15.11:我怎么能使用4字节UTF8 (
utf8mb4
与连接器/ J) ?15.12:使用
useServerPrepStmts = false
和某些字符编码插入blob时可能导致腐败。该如何避免呢?
问题和答案
15.1:当我试图连接到数据库和MySQL连接器/ J,我得到以下异常:
SQLException异常:服务器配置数据源SQLState拒绝访问:08001 VendorError: 0
什么是怎么回事?我可以连接MySQL命令行客户端就可以了。
连接器/ J通常使用TCP / IP套接字连接到MySQL(见6.9节,“使用Unix域套接字连接”和6.10节,“使用命名管道连接”例外)。MySQL服务器上的安全管理器使用其授权表来确定是否允许一个TCP / IP连接。你必须添加必要的安全凭据的MySQL服务器发出的连接格兰特
声明你的MySQL服务器。看到GRANT语句为更多的信息。
改变特权和权限在MySQL不当可能会导致您的服务器安装好不安全属性。
测试你的连接mysql命令行客户端将不会工作,除非你添加——主机
国旗,并使用之外的东西本地主机
的主机。的mysql命令行客户端将尝试使用Unix域套接字如果你使用特殊的主机名本地主机
。如果你正在测试的TCP / IP连接本地主机
,使用127.0.0.1
的主机名。
15.2:我的应用程序抛出SQLException没有合适的驱动程序。为什么会这样?
这个错误可能有三个原因:
连接器/ J司机不是在你
类路径
,请参阅第四章,连接器/ J安装。你的连接URL的格式不正确,或者你引用错误的JDBC驱动程序。
当使用DriverManager,
jdbc.drivers
系统属性没有被填充的位置连接器/ J司机。
15.3:我想在applet或者应用程序中使用MySQL连接器/ J,我得到一个类似于异常:
SQLException异常:无法连接到MySQL服务器主机:3306。有在这台机器上运行的MySQL服务器/端口你试图连接到吗?(java.security.AccessControlException) SQLState: 08年s01 VendorError: 0
要么你运行Applet, MySQL服务器已经安装的skip_networking
启用系统变量,或您的MySQL服务器防火墙坐在它前面。
applet只能使网络连接回机器运行的web服务器,applet的. class文件。这意味着MySQL必须运行在同一台机器上(或者你必须有某种端口重定向)工作。这也意味着你将不能测试applet从您的本地文件系统,但必须将它们部署到web服务器。
连接器/ J通常使用TCP / IP套接字连接到MySQL(见6.9节,“使用Unix域套接字连接”和6.10节,“使用命名管道连接”例外)。TCP / IP通信与MySQL可以影响skip_networking
系统变量或服务器防火墙。如果MySQL已经开始skip_networking
启用时,你需要在文件置评/etc/mysql/my.cnf
或/etc/my.cnf
对于TCP / IP连接工作。(注意,也可能存在于您的服务器配置文件数据
您的MySQL服务器的目录,或者其他地方,这取决于MySQL是编译;二进制文件创建的Oracle总是寻找/etc/my.cnf
和
;看到使用选项文件详情)。如果您的MySQL服务器防火墙,防火墙需要配置为允许TCP / IP连接的主机在Java代码运行的MySQL服务器端口,MySQL是听(默认情况下,3306)。datadir
/ my.cnf
15.4:我有一个servlet /应用程序工作正常一天,一夜之间,然后停止工作
MySQL关闭连接后8小时不活动的。你需要使用连接池处理过期连接或使用autoReconnect
参数(见6.3节,“配置属性”)。
同时,抓住异常
在您的应用程序和处理它们,而不是传播他们直到应用程序退出。这是良好的编程实践。MySQL连接器/ J将设置SQLState
(见java.sql.SQLException.getSQLState ()
在你的API文档)08年s01
当遇到网络连接问题在处理一个查询。尝试重新连接MySQL。
下面的例子(简单的)显示了什么代码可以处理这些异常的样子:
示例15.1连接器/ J:事务和重试逻辑的例子
公共空间doBusinessOp()抛出SQLException{连接康涅狄格州=零;声明支撑=零;ResultSet rs =零;/ / / /你想重试多少次事务/ /(或者至少_getting_连接)?/ / int retryCount = 5;布尔transactionCompleted = false;做的{{康涅狄格州= getConnection ();/ / / / javax.sql假设得到这个。/ / java.sql数据源,或者。DriverManager conn.setAutoCommit(假);/ / / /好吧,在这一点上,/ /事务的“retry-ability”实际上取决于您的应用程序逻辑,/ /你是否正在使用自动提交(在本例中是/ /不),以及你是否使用事务性存储引擎/ / / / / /在这个例子中,我们假设它是安全/ /重试整个事务,所以我们设置重试/ /数到0此时/ / / /如果你是使用专门transaction-safe表,/ /或者您的应用程序可以从连接恢复/ /坏在中间的一个操作,那么你不会/ /触摸“retryCount”,并让循环重复/ /直到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
设施是弃用,可能在将来的版本中被删除。
15.5:我不能连接到MySQL服务器使用连接器/ J,我相信连接参数是正确的。
确保skip_networking
系统变量没有在服务器上启用。连接器/ J必须能够通过TCP / IP与服务器通信;不支持指定套接字。也确保你不是过滤连接通过防火墙或其他网络安全系统。有关更多信息,请参见不能连接到MySQL服务器(本地)。
15.6:更新一个表,其中包含一个主键,要么是浮动
或复合主键使用浮动
未能更新表,提出了一个例外。
连接器/ J添加条件在哪里
条款在更新
检查旧的主键值。如果没有匹配,那么连接器/ J认为这失败的条件,提出了一个例外。
问题是,舍入差异提供价值和数据库中存储的值可能意味着值不匹配,因此更新失败。这个问题将会影响所有查询,不仅仅是那些从连接器/ J。
为了防止这个问题,使用不使用一个主键浮动
。如果你必须使用浮点列在你的主键,使用双
或小数
类型的地方浮动
。
15.7:我得到一个ER_NET_PACKET_TOO_LARGE
例外,即使二进制斑点大小我想插入下面安全使用JDBCmax_allowed_packet
大小。
这是因为hexEscapeBlock ()
方法com.mysql.cj.AbstractPreparedQuery.streamToBytes ()
可能几乎两倍大小的数据。
15.8:我该怎么办如果我收到错误消息类似如下:”通信链路失败——最后一个数据包发送到服务器前女士是X”吗?
一般来说,这个错误表明网络连接已经关闭。可以有多个根源:
防火墙或路由器可能打击空闲连接(MySQL客户端/服务器协议不平)。
MySQL服务器可能关闭空闲连接超过
wait_timeout
或interactive_timeout
阈值。
虽然网络连接不稳定,可以有助于避免以下问题:
确保从连接池连接使用时是有效的。使用查询开始
/ * * /
执行一个轻量级的平而不是完整的查询。注意,萍的语法需要完全按照指定的。减少持续时间一个连接对象执行闲置,而其他应用程序逻辑。
显式验证连接在使用前如果连接已经闲置了一段时间。
确保
wait_timeout
和interactive_timeout
设置足够高。确保
tcpKeepalive
启用。确保任何可配置防火墙或路由器超时设置允许的最大预期连接空闲时间。
不要指望能够重用连接没有问题如果被闲置一段时间。如果一个连接重用被闲置了一段时间后,确保你明确在重用之前对其进行测试。
15.9:为什么连接器/ J不连接到MySQL和重新发出声明后通信失败而不是抛出异常,即使我使用吗autoReconnect
连接字符串的选择吗?
这有几个原因。第一个是事务完整性。MySQL参考手册的州”没有安全的方法重新连接到MySQL服务器不冒着一些腐败的状态或数据库的连接状态信息”。考虑下面的一系列声明,例如:
conn.createStatement ()。执行(“更新checking_account设置余额=资产- 1000.00客户=“史密斯”);conn.createStatement ()。执行(“更新savings_account设置余额=资产+ 1000.00客户=“史密斯”);conn.commit ();
考虑到服务器的连接失败后更新
来checking_account
。如果没有异常,应用程序不了解这个问题,它将继续执行。然而,服务器没有提交第一个事务在这种情况下,这将回滚。但继续执行下一个事务,并增加了savings_account
在1000年的平衡。应用程序没有收到一个异常,所以继续不管,最终提交第二个事务,提交的更改只适用于新的连接。而不是发生转移,存款在这个例子。
注意,使用自动提交
启用并不能解决这个问题。当连接器/ J遇到沟通问题,没有办法确定服务器处理当前执行语句。以下理论状态同样是可能的:
服务器没有收到声明,因此没有相关的处理发生在服务器上。
服务器收到该语句,执行它,但没有收到客户的响应。
如果您正在运行自动提交
启用,不可能保证数据在服务器上的状态当遇到一个通信异常时。声明可能到达服务器,也可能不会。你只知道通信失败在某种程度上,在客户端从服务器收到的确认(或数据)。这不仅影响自动提交
语句。如果发生在通信问题Connection.commit ()
的问题是否服务器上的事务是提交之前沟通失败,或者服务器收到提交请求。
第二代的异常的原因是,以事务上下文数据可能是脆弱的,例如:
临时表。
用户定义的变量。
服务器端准备好的语句。
这些物品丢失连接失败时,如果连接默默地重新连接时没有产生一个异常,这可能损害应用程序的正确执行。
总之,沟通错误生成条件,很可能是不安全的连接器/ J默默地重新简单地忽略。有必要应用程序通知。然后对应用程序开发人员决定如何进行连接错误和失败的事件。
早些时候8.0.12和:使用3字节UTF8连接器/ J集characterEncoding = utf8
并设置useUnicode = true
在连接字符串。
8.0.13和后:因为没有java风格的字符集名称utfmb3
连接选项,您可以使用charaterEncoding
,使用的唯一方法utf8mb3
当你连接字符集是使用utf8mb3
排序(例如,utf8_general_ci
)的连接选项connectionCollation
,这力量utf8mb3
要使用字符集。看到6.7节,“使用字符集和Unicode”获取详细信息。
15.11:我怎么能使用4字节UTF8 (utf8mb4
与连接器/ J) ?
使用4字节UTF8连接器/ J配置MySQL服务器character_set_server = utf8mb4
。连接器/ J将使用该设置,如果characterEncoding
和connectionCollation
没有设置在连接字符串。自动识别出字符集。这相当于看到6.7节,“使用字符集和Unicode”获取详细信息。8.0.13和后:您可以使用characterEncoding = utf - 8
使用utf8mb4
,即使character_set_server
在服务器上已设置为别的东西。
15.12:使用useServerPrepStmts = false
和某些字符编码插入blob时可能导致腐败。该如何避免呢?
当使用特定的字符编码,如SJIS CP932,繁体,BLOB数据可能包含字符,可以解释为控制字符,例如,反斜杠“\”。这可能导致损坏时插入blob数据到数据库中。有两件事需要做,以避免:
设置连接字符串的选择
useServerPrepStmts
来真正的
。集
SQL_MODE
来NO_BACKSLASH_ESCAPES
。