Java informix jdbc 卡住连接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21572185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:25:55  来源:igfitidea点击:

informix jdbc stuck connecting

javajdbcinformix

提问by xacy

I'm trying to connect to a Informix database server with jdbc using the standard way :

我正在尝试使用标准方式使用 jdbc 连接到 Informix 数据库服务器:

connection = DriverManager.getConnection("jdbc:informix-sqli://"+ip+
/"+sid+":INFORMIXSERVER="+server+";user="+user+";password="+pass+"");

But it keeps trying to connect and does not throw a error message (I suppose it tries to connect because it does not show anything). I'm using IBM Informix driver 4.10.00.1534 and Java 1.7. I have been using this method to connect to Informix servers until now, in fact it only fails with one server. I can connect to this server through Informix clients with odbc but it keeps failing with jdbc with no error message.

但它不断尝试连接并且不会抛出错误消息(我想它尝试连接是因为它没有显示任何内容)。我使用的是 IBM Informix 驱动程序 4.10.00.1534 和 Java 1.7。到目前为止,我一直使用这种方法连接到 Informix 服务器,实际上它只在一台服务器上失败。我可以使用 odbc 通过 Informix 客户端连接到该服务器,但使用 jdbc 一直失败,没有错误消息。

Is there any method to verbose the jdbc connection? Any suggestion about why it fails?

有什么方法可以详细说明 jdbc 连接吗?关于它为什么失败的任何建议?

UPDATE: The sqlidebug trace:

更新: sqlidebug 跟踪:

C->S (4)            
    SQ_VERSION
    SQ_EOT

S->C (14)           
    SQ_VERSION
        "7.31.TD6" [8]
    SQ_EOT

C->S (66)           
    SQ_INFO
        INFO_ENV
            Name Length = 12
            Value Length = 8
            "DBTIME"="%d/%M/%Y"
            "DBTEMP"="/tmp"
            "SUBQCACHESZ"="10"
        INFO_DONE
    SQ_EOT

S->C (2)            
    SQ_EOT

C->S (16)           
    SQ_DBOPEN
         "database" [8]
        NOT EXCLUSIVE
    SQ_EOT

S->C (28)           
    SQ_DONE
        Warning..: 0x15
        # rows...: 0
        rowid....: 0
    serial id: 0
SQ_COST
    estimated #rows: 1
    estimated I/O..: 1
SQ_EOT

C->S (78)           
    SQ_PREPARE
        # values: 0
        CMD.....: "select site from informix.systables where tabname = '   GL_COLLATE'" [65]
    SQ_NDESCRIBE
    SQ_WANTDONE
    SQ_EOT

And the jdbctrace.log says:

jdbctrace.log 说:

 trying com.informix.jdbc.IfxDriver
    SQLWarning: reason(Database selected) SQLState(01I04)
    SQLWarning: reason(Float to decimal conversion has been used) SQLState(01I05)
    SQLWarning: reason(Database has transactions) SQLState(01I01)
    SQLWarning: reason(Database selected) SQLState(01I04)
    SQLWarning: reason(Database has transactions) SQLState(01I01)
    SQLWarning: reason(Database selected) SQLState(01I04)

采纳答案by Micha? Niklas

Try to run code that connects do Informix database but also shows full exception info and create trace files. One trace file is for JDBC, one is for Informix. Change URL to database, username and password, and run it. You will probably see the problem on screen or in trace file:

尝试运行连接到 Informix 数据库但也显示完整异常信息并创建跟踪文件的代码。一个跟踪文件用于 JDBC,一个用于 Informix。将 URL 更改为数据库、用户名和密码,并运行它。您可能会在屏幕或跟踪文件中看到问题:

import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

class informix_trace
    {
    public static void main(String[] args)
        {
        try
            {
            Class.forName("com.informix.jdbc.IfxDriver");
            FileWriter fwTrace = new FileWriter("c:\JDBCTrace.log");
            PrintWriter pwTrace = new PrintWriter(fwTrace);
            DriverManager.setLogWriter(pwTrace);
            String debug_url = "SQLIDEBUG=C:\sqlidebug.trace";
            String url = "jdbc:informix-sqli://1.2.3.4:9088/test_db:informixserver=ol_testifx;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250;" + debug_url
            Connection connection = DriverManager.getConnection(url, "user", "passwd");
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery("SELECT FIRST 1 DBINFO('version','full') FROM systables;");
            while (resultSet.next())
                System.out.println(resultSet.getObject(1));
            }
        catch (Exception e)
            {
            e.printStackTrace();
            }
        }

    } // class informix_trace

Informix trace file will be with some postfix (timestamp or similar info) and in my case it was something like sqlidebug.trace1391758523500.0. It is binary but you can analyze it using sqliprtutility.

Informix 跟踪文件将带有一些后缀(时间戳或类似信息),就我而言,它类似于sqlidebug.trace1391758523500.0. 它是二进制的,但您可以使用sqliprt实用程序对其进行分析。

Example of my session with wrong database name:

我使用错误数据库名称的会话示例:

c:\>sqliprt  sqlidebug.trace1391758523500.0
SQLIDBG Version 1
    ...
S->C (12)
                SQ_ERR
                                SQL error..........: -329
                                ISAM/RSAM error....: -111
                                Offset in statement: 0
                                Error message......: "" [0]
                SQ_EOT

In JDBCTrace.logI can found more interesting info (I see it also on my screen):

JDBCTrace.log我可以找到更多有趣的信息(我也在我的屏幕上看到它):

SQLState(IX000) vendor code(-111)
java.sql.SQLException: ISAM error: no record found.
    at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:413)
    at com.informix.jdbc.IfxSqli.E(IfxSqli.java:3412)
    at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2324)
    ....
    at java.sql.DriverManager.getConnection(Unknown Source)
    at informix_trace.main(informix_trace.java:20)
getConnection failed: java.sql.SQLException: No database found or wrong system privileges.

(I have translated it from Polish so it can be little different)

(我是从波兰语翻译过来的,所以可能有点不同)

回答by Micha? Niklas

My suggestion is to:

我的建议是:

  1. build ConnectString and show us its full content, this way we will see if in ipthere is only IP address or if it is with port number
  2. instead of adding username and password to ConnectString use 3 parameter version of getConnection()just like:

    getConnection("jdbc:informix-sqli://169.0.5.10:9088/test_db:informixserver=ol_test;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250", username, password)
    
  1. 构建 ConnectString 并向我们展示其完整内容,这样我们将看到ip其中是否只有 IP 地址或是否带有端口号
  2. 而不是将用户名和密码添加到 ConnectString 使用 3 参数版本,getConnection()就像:

    getConnection("jdbc:informix-sqli://169.0.5.10:9088/test_db:informixserver=ol_test;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250", username, password)
    

(of course set your own locale instead of my Polish locale)

(当然设置您自己的语言环境而不是我的波兰语语言环境)

To spy network traffic use tools like Wireshark. Start capturing ip traffic to your Informix database. In my case Wireshark rule is:

要监视网络流量,请使用 Wireshark 等工具。开始捕获到 Informix 数据库的 ip 流量。就我而言,Wireshark 规则是:

ip.addr == 169.0.5.10

If I set up wrong IP Wireshark will display "Destination unreachable".

如果我设置了错误的 IP Wireshark 将显示“目标无法访问”。

You can also see someting using netstat:

您还可以使用 netstat 查看某些内容:

c:\>netstat -an | grep 9088
    TCP    169.0.1.126:4295       169.0.5.10:9088        TIME_WAIT

It was when my application stopped working.

那是我的应用程序停止工作的时候。

In case of error (wrong IP port) I see:

如果出现错误(错误的 IP 端口),我会看到:

c:\>netstat -an | grep 9089
    TCP    169.0.1.126:4398       169.0.5.10:9089        SYN_SENT

回答by hd1

IBM says that: From version 3.00.JC1 of IBM? Informix? JDBC Driver onwards, debug drivers are no longer shipped. Informix JDBC Driver now supports SQLIDEBUG. You no longer need to set values for TRACE, TRACEFILE or PROTOCOLTRACE, PROTOCOLTRACEFILE. You only need to set SQLIDEBUG.and the page goes on to outline the steps you need to create a trace. Copying:

IBMFrom version 3.00.JC1 of IBM? Informix? JDBC Driver onwards, debug drivers are no longer shipped. Informix JDBC Driver now supports SQLIDEBUG. You no longer need to set values for TRACE, TRACEFILE or PROTOCOLTRACE, PROTOCOLTRACEFILE. You only need to set SQLIDEBUG.并且该页面继续概述创建跟踪所需的步骤。复制:

  1. Set the CLASSPATH to the Informix JDBC Driver package.

    c:\Infx\Java>set CLASSPATH=C:\infx\JDBC3.00JC3\lib\ifxjdbc.jar;C:\infx\JDBC3.00JC3\lib\ifxjdbcx.jar;.

  2. Compile simple.java

    c:\Infx\Java>javac simple.java

  3. Ensure that SQLIDEBUG is set correctly

    c:\Infx\Java>grep SQLIDEBUG simple.java
    conn=DriverManager.getConnection("jdbc:informix-sqli://irk:1526/sysmaster:INFORMIXSERVER=irk940;USER=informix; PASSWORD=ximrofni;SQLIDEBUG=C:\infx\java\trace");

    Note: SQLIDEBUG is set in the connection string. It points to where the trace file will be found with a certain format i.e. trace.xxxxxxx

  4. Remove or move all other trace files

    c:\Infx\Java>del trace*

  5. Run java.simple

    c:\Infx\Java>java simple systables syscolumns ... ... oledbordinals

  6. Then locate the trace file

    c:\Infx\Java>dir trace* Volume in drive C has no label. Volume Serial Number is B823-46D8

    Directory of c:\Infx\Java

    04/04/2006 14:12 20,560 trace1144156355642.0 1 File(s) 20,560 bytes 0 Dir(s) 4,067,995,648 bytes free

    c:\Infx\Java>

    You will be able to see that a trace file has been created however you will not be able to read the file.

  7. Send the trace file to your local technical support office for analysis.

  1. 将 CLASSPATH 设置为 Informix JDBC 驱动程序包。

    c:\Infx\Java>set CLASSPATH=C:\infx\JDBC3.00JC3\lib\ifxjdbc.jar;C:\infx\JDBC3.00JC3\lib\ifxjdbcx.jar;。

  2. 编译 simple.java

    c:\Infx\Java>javac simple.java

  3. 确保 SQLIDEBUG 设置正确

    c:\Infx\Java>grep SQLIDEBUG simple.java
    conn=DriverManager.getConnection("jdbc:informix-sqli://irk:1526/sysmaster:INFORMIXSERVER=irk940;USER=informix;PASSWORD=ximrofni;SQLIDEBUG=C:\ infx\java\trace");

    注意:SQLIDEBUG 在连接字符串中设置。它指向可以找到特定格式的跟踪文件的位置,即 trace.xxxxxxx

  4. 删除或移动所有其他跟踪文件

    c:\Infx\Java>del 跟踪*

  5. 运行 java.simple

    c:\Infx\Java>java simple systables syscolumns ... ... oledbordinals

  6. 然后找到跟踪文件

    c:\Infx\Java>dir trace* 驱动器 C 中的卷没有标签。卷序列号为 B823-46D8

    c:\Infx\Java 目录

    04/04/2006 14:12 20,560 trace1144156355642.0 1 File(s) 20,560 bytes 0 Dir(s) 4,067,995,648 bytes free

    c:\Infx\Java>

    您将能够看到已创建跟踪文件,但您将无法读取该文件。

  7. 将跟踪文件发送到您当地的技术支持办公室进行分析。

Of course, if you're not using Version 3.00.JC1 of the Informix drivers, ignore the above and follow a different set of instructions; again duplicated for your convenience:

当然,如果您不使用版本 3.00.JC1 的 Informix 驱动程序,请忽略以上内容并遵循不同的说明;为了您的方便再次复制:

To turn on tracing, specify the environment variables TRACE, TRACEFILE, PROTOCOLTRACE, and PROTOCOLTRACEFILE in the database URL or the property list when you establish a connection to an Informix database or database server. TRACE can be set to one of the following levels:

  1. Tracing not enabled. This is the default value.
  2. Traces the entry and exit points of methods.
  3. Same as Level 1, plus generic error messages are also traced.
  4. Same as Level 2, plus data variables are also traced. TRACEFILE Specifies the full pathname of the operating system file on the client computer to which the TRACE messages are written.

PROTOCOLTRACE traces the SQLI protocol messages sent between your Java program and the Informix database server.

Can be set to the following levels:

  1. Protocol tracing not enabled. This is the default value.
  2. Traces message IDs.
  3. Same as Level 1, plus the data in the message packets are also traced. PROTOCOLTRACFILE specifies the full pathname of the operating system file on the client computer to which the PROTOCOLTRACE messages are written.

要打开跟踪,请在建立与 Informix 数据库或数据库服务器的连接时在数据库 URL 或属性列表中指定环境变量 TRACE、TRACEFILE、PROTOCOLTRACE 和 PROTOCOLTRACEFILE。TRACE 可以设置为以下级别之一:

  1. 未启用跟踪。这是默认值。
  2. 跟踪方法的入口和出口点。
  3. 与级别 1 相同,此外还会跟踪一般错误消息。
  4. 与级别 2 相同,还跟踪数据变量。TRACEFILE 指定客户端计算机上写入 TRACE 消息的操作系统文件的完整路径名。

PROTOCOLTRACE 跟踪在 Java 程序和 Informix 数据库服务器之间发送的 SQLI 协议消息。

可以设置为以下级别:

  1. 未启用协议跟踪。这是默认值。
  2. 跟踪消息 ID。
  3. 与Level 1 相同,另外还跟踪消息包中的数据。PROTOCOLTRACFILE 指定客户端计算机上写入 PROTOCOLTRACE 消息的操作系统文件的完整路径名。

Hope that helps

希望有帮助

回答by Bartek

  1. try different jdbc version
  2. check NETTYPEconfiguration parameter and compare it with current number of informix sessions
  3. dump java thread states (kill -3 ) when jdbc connection hangs
  1. 尝试不同的 jdbc 版本
  2. 检查NETTYPE配置参数并将其与当前的 informix 会话数进行比较
  3. 当 jdbc 连接挂起时转储 java 线程状态(kill -3)

回答by Vishwanath Hiremath

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.informix.*;
public class DBConnect {
    static String url="jdbc:informix-sqli://host_name:port/database_name:INFORMIXSERVER=server;user=username;password=password";

    public static void main(String [] args){
        try {
            Class.forName("com.informix.jdbc.IfxDriver");
        }catch (Exception e){
            System.out.println("ERROR: failed to load Informix JDBC driver.");
            e.printStackTrace();
            return;
        }
        try{

            DriverManager.registerDriver((com.informix.jdbc.IfxDriver)Class.forName("com.informix.jdbc.IfxDriver").newInstance());

        }catch(Exception ex){
            System.out.println("Driver is not Registered");
        }
        try{

            Connection conn = DriverManager.getConnection(url);
            System.out.println("Connection Successful");
        }catch (SQLException e){
            System.out.println("ERROR: failed to connect!");
            System.out.println("ERROR: " + e.getMessage());
            e.printStackTrace();
            return;
        }
        }
}

For more info go through [this book] (http://www.cursor-distribution.de/aktuell.11.70.xC6/documentation/ids_jdbc_bookmap.pdf)

有关更多信息,请阅读 [本书] ( http://www.cursor-distribution.de/aktuell.11.70.xC6/documentation/ids_jdbc_bookmap.pdf)

回答by ron190

The problem I encountered was that Informix was listening on local IPv6 address on port 7360, command netstat -awas displaying this format :

我遇到的问题是 Informix 正在侦听端口 7360 上的本地 IPv6 地址,命令netstat -a显示以下格式:

TCP    [feab::11ab:78ab:efab:8aab%17]:7360  myhostname:0      LISTENING

Therefore my jdbc connection was always failing until I figured out I should have use the IPv6 address in the URL :

因此,我的 jdbc 连接总是失败,直到我发现我应该在 URL 中使用 IPv6 地址:

jdbc:informix-sqli://fe80::1125:78c0:ef17:8ab5%17:7360:user=informix;password=test;INFORMIXSERVER=ol_informix1210_2

jdbc:informix-sqli://fe80::1125:78c0:ef17:8ab5%17:7360:user=informix;password=test;INFORMIXSERVER=ol_informix1210_2

You can test that the connection is working with this simple script :

您可以使用这个简单的脚本测试连接是否正常工作:

/***************************************************************************
 *
 *  Title:         SimpleConnection.java
 *
 *  Description:    Demo a connection to a server (no database specified)
 *      
 *  An example of running the program: 
 *      
 *   java SimpleConnection 
 *      'jdbc:informix-sqli://myhost:1533:user=<username>;password=<password>'
 *      
 *   Expected result:
 * 
 * >>>Simple Connection test.
 * URL = "jdbc:informix-sqli://myhost:1533:user=<username>;password=<password>"
 * >>>End of Simple Connection test.
 * 
 ***************************************************************************
 */

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class SimpleConnection {

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("FAILED: connection URL must be provided in order to run the demo!");
            return;
        }

        String url = args[0];

        String testName = "Simple Connection";

        Connection conn = null;

        System.out.println(">>>" + testName + " test.");
        System.out.println("URL = \"" + url + "\"");

        try {
            Class.forName("com.informix.jdbc.IfxDriver");
        } catch (Exception e) {
            System.out.println("FAILED: failed to load Informix JDBC driver.");
        }

        try {
            PrintWriter out = new PrintWriter(System.out, true);
            DriverManager.setLogWriter(out);
            conn = DriverManager.getConnection(url);
        } catch (SQLException e) {
            System.out.println("FAILED: failed to connect!");
        }

        try {
            conn.close();
        } catch (SQLException e) {
            System.out.println("FAILED: failed to close the connection!");
        }

        System.out.println(">>>End of " + testName + " test.");
    }
}