我们有两个应用服务器与同一个DB通信。一个是TCP服务器,另一个是HTTP服务器(我们希望用新的HTTP服务器替换旧的TCP服务器......但是需要它们一起工作一段时间。)
两台服务器都以相同的方式与DB通信。 Spring-JDBC具有完全相同的代码。
在测试环境中运行此设置时,一切正常,但在云服务器上进行生产部署时,会出现一种非常奇怪的现象。
似乎(只是一个猜测,我可能完全错误)数据库连接以某种方式"阻止"或者"锁定"来自 特定行 的彼此。虽然没有一个MySQL查询使用锁。
例如,此查询会发生什么:HTTP服务器上的SELECT * FROM users WHERE uid = '?'
为?= x返回一个空的ResultSet,当从TCP服务器运行x时,相同的完全查询返回正确的行。该行确实在数据库中,不应返回空。
在两台服务器上运行此查询的代码如下:
public UserDBO getUserRecord(String uid) throws SQLException {
UserDBO result = null;
try {
JdbcOperations jdbcOperations = new JdbcTemplate(dataSource);
String query = "SELECT *" + " FROM " + TABLE_USERS + " WHERE " + COL_UID + "=" + quote(uid);
logger.config("Executing SQL query:[" + query + "]");
result = jdbcOperations.queryForObject(query, new UserDboRowMapper());
} catch(EmptyResultDataAccessException ignored) {}
return result;
}
两个服务器DAO都使用相同的用户帐户连接到数据库。检查服务器配置表明它不应该是一个问题(每个帐户最大并发连接数和所有其他相关配置不受限制)。
我们知道问题不在代码中,因为如上所述它在测试环境中完美运行。所以我们认为它必须是数据库服务器配置。 但它有什么用呢?
我知道这个问题的特殊性,但我很绝望,别无选择,只能向StackOverFlow社区寻求帮助。
提前致谢。
更新1 :
添加quote()
方法代码:
private String quote(String str) {
return "\"" + str + "\"";
}
更新2 :
重要的是要澄清,一旦我关闭HTTP服务器,重新启动服务器计算机并启动只有TCP服务器它可以正常对MySQL DB。
这导致我们相信这里有一些阻塞/锁定机制,因为似乎服务器以某种方式打断了彼此对数据库的访问,即使它们使用相同的DAO代码与之通信。
另外,为了澄清,所有组件(TCP,HTTP和DB)都在同一台机器上。
更新3 :
添加UserDBO
目标代码:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class UserDBO {
private String uid;
private String token;
private Date registered_date;
private UserStatus userStatus;
private Date unregistered_date;
private int unregistered_count;
private String deviceModel;
private String androidVersion;
}
UserDboRowMapper
代码:
public class UserDboRowMapper implements org.springframework.jdbc.core.RowMapper<UserDBO> {
@Override
public UserDBO mapRow(ResultSet resultSet, int i) throws SQLException {
return new UserDBO(resultSet.getString(COL_UID),
resultSet.getString(COL_TOKEN),
resultSet.getDate(COL_REGISTERED_DATE),
UserStatus.valueOf(resultSet.getString(COL_USER_STATUS)),
resultSet.getDate(COL_UNREGISTERED_DATE),
resultSet.getInt(COL_UNREGISTERED_COUNT),
resultSet.getString(COL_DEVICE_MODEL),
resultSet.getString(COL_ANDROID_VERSION));
}
}