[Windows] DBへの接続/切断を頻繁に繰り返すプログラムが途中でこける | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

Windows 2000 や XP 上でJDBCドライバを使用してSQL Serverに接続し、大量にデータを登録・更新する Javaプログラムを実行していると、途中で以下のようなエラーが発生しました。

ホスト に TCP/IP 接続できませんでした。 java.net.BindException: Address already in use: connect

Windows 2000 や XP では、TCP/IP 接続を確立すると空いている TCP/IP ポート番号が順次割り当てられます。

割り当てられる TCP/IP ポート番号の範囲はレジストリパラメータ MaxUserPortで設定されており、デフォルトでは 1024番 ~ 5000番となっています。


使用されたポート番号は TCP/IP 接続が解除されると解放されますが、すぐに解放されるわけではなく、一定時間 TIME_WAIT状態を維持した後、解放されるようです。

TIME_WAIT状態が維持される時間はレジストリパラメータ TcpTimedWaitDelay で設定されており、デフォルトでは 60秒と設定されています。


ここにワナが潜んでいるわけです。

つまり、短時間に JDBC で DB への接続と切断を繰り返した場合、TIME_WAIT状態の TCP/IPポート番号が大量に発生することにより、使用可能な TCP/IPポート番号がなくなり上記のようなエラーが発生するというわけです。


確かにプログラムの実行中に netstatコマンドでネットワーク接続状況を確認してみると TIME_WAITの接続が大量に出現していました。


C:\>netstat

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    mypc:microsoft-ds   localhost:3046         ESTABLISHED
  TCP    mypc:2883           localhost:microsoft-ds  TIME_WAIT
  TCP    mypc:3046           localhost:microsoft-ds  ESTABLISHED
  TCP    mypc:2884           mypc:netbios-ssn    TIME_WAIT
  TCP    mypc:2885           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2886           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2887           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2888           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2889           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2890           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2891           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2892           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2893           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2894           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2895           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2896           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2897           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2898           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2899           mypc:ms-sql-s       TIME_WAIT
  TCP    mypc:2900           mypc:ms-sql-s       TIME_WAIT
  .
  .
  .

このエラーは、MaxUserPort(5000~65534)または TcpTimedWaitDelay(30秒~300秒)の設定を調整することで回避することも可能です。

ただ、そもそも DBへの接続と切断を頻繁に繰り返すようなプログラムの作りのほうが悪いので、そちらを改善するのが本筋でしょう。

DBへの接続と切断の回数を減らすことによってパフォーマンスも向上します。



参考:5000 を超える番号の TCP ポートから接続しようとすると 'WSAENOBUFS (10055)' エラーが表示される