はじめに
Oracle Databaseへの疎通確認でよく遭遇する「Connection reset by peer」エラーの原因と対処法について、実際のトラブルシューティング経験を基にまとめました。
最近のAIは本当に優秀なのでコーディングのほとんどは生成したもので事足りました。自分で確認する必要があったのは接続情報の確認くらいでした
よくあるエラーパターン
1. Connection reset by peer
java.sql.SQLRecoverableException: IO Error: Connection reset by peer, connect lapse 10 ms., Authentication lapse 0 ms.
原因: ネットワーク接続は成功しているが、JDBC接続URLのサービス名/SIDが正しくない
2. Connection timed out
java.sql.SQLRecoverableException: IO Error: The Network Adapter could not establish the connection
原因: ネットワーク接続の問題(IPアドレス、ポート、ファイアウォール)
3. ORA-01017: ユーザー名/パスワードが無効
原因: 認証情報が正しくない
疎通確認に必要な情報
必須情報
- IPアドレス: データベースサーバのIPアドレス
- ポート番号: 通常は1521(デフォルト)または1522
- サービス名: (SERVICE_NAME)またはSID
- ユーザー名: 接続するスキーマ名
- パスワード: 接続するスキーマのパスワード
接続情報の確認方法
1. サーバ上でリスナーの状態を確認
lsnrctl status
出力例:
Service "ORCL" has 1 instance(s).
Service "ORCLPDB1" has 1 instance(s).
2. tnsnames.oraを確認
cat $ORACLE_HOME/network/admin/tnsnames.ora
出力例:
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCL)
)
)
3. SQLPlusで確認
-- インスタンス名を確認
SELECT INSTANCE_NAME FROM V$INSTANCE;
-- データベース名を確認
SELECT NAME FROM V$DATABASE;
-- サービス名を確認
SELECT NAME FROM V$SERVICES;
JDBC接続URLの形式
サービス名形式
jdbc:oracle:thin:@IPアドレス:ポート/サービス名
例: jdbc:oracle:thin:@192.168.1.100:1522/ORCL
SID形式
jdbc:oracle:thin:@IPアドレス:ポート:SID
例: jdbc:oracle:thin:@192.168.1.100:1522:ORCL
疎通確認用Javaツールの作成
基本的な疎通確認ツール
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class OracleConnectionChecker {
// 接続情報(実際の値に変更)
private static final String IP = "xxx.xxx.xxx.xxx";
private static final String PORT = "1522";
private static final String SERVICE_NAME = "ORCL";
private static final String USERNAME = "your_schema";
private static final String PASSWORD = "your_password";
// 疎通確認用SQL
private static final String TEST_SQL =
"SELECT 'Connection OK' as status FROM DUAL";
public static void main(String[] args) {
String jdbcUrl = String.format("jdbc:oracle:thin:@%s:%s/%s",
IP, PORT, SERVICE_NAME);
System.out.println("接続先: " + jdbcUrl);
try (Connection conn = DriverManager.getConnection(jdbcUrl, USERNAME, PASSWORD);
PreparedStatement pstmt = conn.prepareStatement(TEST_SQL);
ResultSet rs = pstmt.executeQuery()) {
System.out.println("✓ 接続成功!");
if (rs.next()) {
System.out.println("結果: " + rs.getString("status"));
}
} catch (SQLException e) {
System.err.println("✗ 接続失敗");
System.err.println("エラー: " + e.getMessage());
}
}
}
複数パターンを自動試行するツール
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
public class OracleConnectionTester {
private static final String IP = "xxx.xxx.xxx.xxx";
private static final String PORT = "1522";
private static final String USERNAME = "your_schema";
private static final String PASSWORD = "your_password";
// よくあるサービス名/SIDのパターン
private static final List<String> SERVICE_PATTERNS = Arrays.asList(
"ORCL", "orcl",
"XE", "xe",
"ORCLPDB1", "ORCLCDB",
"your_schema", // スキーマ名と同じ場合もある
"PROD", "DEV", "TEST"
);
public static void main(String[] args) {
System.out.println("複数の接続パターンを試行します...");
// サービス名形式を試行
for (String serviceName : SERVICE_PATTERNS) {
String jdbcUrl = String.format("jdbc:oracle:thin:@%s:%s/%s",
IP, PORT, serviceName);
if (testConnection(jdbcUrl, USERNAME, PASSWORD)) {
System.out.println("✓ 接続成功!");
System.out.println("正しいサービス名: " + serviceName);
System.out.println("JDBC URL: " + jdbcUrl);
return;
}
}
// SID形式を試行
for (String sid : SERVICE_PATTERNS) {
String jdbcUrl = String.format("jdbc:oracle:thin:@%s:%s:%s",
IP, PORT, sid);
if (testConnection(jdbcUrl, USERNAME, PASSWORD)) {
System.out.println("✓ 接続成功!");
System.out.println("正しいSID: " + sid);
System.out.println("JDBC URL: " + jdbcUrl);
return;
}
}
System.out.println("✗ すべてのパターンで接続失敗");
}
private static boolean testConnection(String jdbcUrl, String username, String password) {
System.out.print("試行: " + jdbcUrl + " ... ");
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
System.out.println("成功");
return true;
} catch (SQLException e) {
System.out.println("失敗");
return false;
}
}
}
Maven設定(pom.xml)
<dependencies>
<!-- Oracle JDBC Driver -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>21.9.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 実行可能JARを作成 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>OracleConnectionChecker</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
トラブルシューティングの手順
1. ネットワーク疎通の確認
# pingで疎通確認
ping xxx.xxx.xxx.xxx
# ポートの疎通確認
telnet xxx.xxx.xxx.xxx 1522
2. ファイアウォール設定の確認
- サーバ側のファイアウォールでOracleポートが開放されているか
- クライアント側のファイアウォールでアウトバウンド接続が許可されているか
3. Oracleリスナーの状態確認
# リスナーの状態確認
lsnrctl status
# リスナーの起動(必要に応じて)
lsnrctl start
4. 接続文字列の検証
- サービス名/SIDが正しいか
- 接続形式(サービス名形式 vs SID形式)が適切か
- 大文字小文字が正しいか
よくあるサービス名のパターン
デフォルトパターン
-
ORCL- 一般的なOracle Database -
XE- Oracle Express Edition -
ORCLPDB1- Pluggable Database(デフォルト) -
ORCLCDB- Container Database
カスタムパターン
- プロジェクト名や環境名(例:
MYAPP_PROD,DEV_DB) - スキーマ名と同じ名前
- 会社名やシステム名を含む名前
まとめ
- ネットワーク疎通 → ping、telnetで確認
- サービス名/SID → lsnrctl status、tnsnames.oraで確認
- 接続文字列 → サービス名形式またはSID形式で試行
- 認証情報 → ユーザー名/パスワードの確認