"A Connection" is nothing but details of a Socket
, with extra details (like username, password, etc.). Each connection have a different socket connection.
For example:
Connection 1:
Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]
Connection 2:
Socket[addr=localhost/127.0.0.1,port=1030,localport=51246]
I have created two connection in a single JVM process to demonstrate how the server knows in which Socket
the reply is to be sent. A socket, if I define in terms of UNIX is a special file that is used for inter-process communication:
srwxr-xr-x. 1 root root 0 Mar 3 19:30 /tmp/somesocket
When a socket is created (i.e., when this special socket file is created; how to create a socket? and this) operating system creates a file descriptor that points to that file. Server distinguishes the Socket with following attributes:
Ref.
{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}
PROTOCOL
: I have used postgres
as an example, the socket connection in postgres
driver is done with SocksSocketImpl
which is a TCP socket implementation (RFC 1928)
Coming back the two connections I have created, if you look closely the localport
for both the connections are different, so the server clearly understands where it has to send the reply back.
Now there are limitations on the number of files (or file descriptors) that you can open in an operating system, thus it's recommended not to keep your connections dangling (called connection leak)
Does it load the database schema with every connection?
Answer: No, it's the ResultSet that takes care of it.
What happens to a connection when the database schema changes
Answer: Connection and database schema are two different things. Connection just defines how to communicate with another process. Database schema is a contract between application and database, an application might throw errors that the contract is broken, or it may simply ignore it.
If you are interested in digging more, you should add a breakpoint to a connection object and below is how it looks like (see FileDescriptor)
connection = {Jdbc4Connection@777}
args = {String[0]@776}
connection = {Jdbc4Connection@777}
_clientInfo = null
rsHoldability = 2
savepointId = 0
logger = {Logger@778}
creatingURL = "dbc:postgresql://localhost:1030/postgres"
value = {char[40]@795}
hash = 0
openStackTrace = null
protoConnection = {ProtocolConnectionImpl@780}
serverVersion = "10.7"
cancelPid = 19672
cancelKey = 1633313435
standardConformingStrings = true
transactionState = 0
warnings = null
closed = false
notifications = {ArrayList@796} size = 0
pgStream = {PGStream@797}
host = "localhost"
port = 1030
_int4buf = {byte[4]@802}
_int2buf = {byte[2]@803}
connection = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
created = true
bound = true
connected = true
closed = false
closeLock = {Object@811}
shutIn = false
shutOut = false
impl = {SocksSocketImpl@812} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
server = null
serverPort = 1080
external_address = null
useV4 = false
cmdsock = null
cmdIn = null
cmdOut = null
applicationSetProxy = false
impl = {DualStackPlainSocketImpl@814} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
exclusiveBind = true
isReuseAddress = false
timeout = 0
trafficClass = 0
shut_rd = false
shut_wr = false
socketInputStream = {SocketInputStream@819}
eof = false
impl = {DualStackPlainSocketImpl@814} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
temp = null
socket = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
created = true
bound = true
connected = true
closed = false
closeLock = {Object@811}
shutIn = false
shutOut = false
impl = {SocksSocketImpl@812} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
server = null
serverPort = 1080
external_address = null
useV4 = false
cmdsock = null
cmdIn = null
cmdOut = null
applicationSetProxy = false
impl = {DualStackPlainSocketImpl@814} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
timeout = 0
trafficClass = 0
shut_rd = false
shut_wr = false
socketInputStream = null
socketOutputStream = null
fdUseCount = 0
fdLock = {Object@815}
closePending = false
CONNECTION_NOT_RESET = 0
CONNECTION_RESET_PENDING = 1
CONNECTION_RESET = 2
resetState = 0
resetLock = {Object@816}
stream = false
socket = null
serverSocket = null
fd = {FileDescriptor@817}
address = null
port = 0
localport = 0
oldImpl = false
closing = false
fd = {FileDescriptor@817}
fd = 1260
handle = -1
parent = {SocketInputStream@819}
eof = false
impl = {DualStackPlainSocketImpl@814} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
temp = null
socket = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
closing = false
fd = {FileDescriptor@817}
fd = 1260
handle = -1
parent = {SocketInputStream@819}
eof = false
impl = {DualStackPlainSocketImpl@814} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
exclusiveBind = true
isReuseAddress = false
timeout = 0
trafficClass = 0
shut_rd = false
shut_wr = false
socketInputStream = {SocketInputStream@819}
socketOutputStream = {SocketOutputStream@820}
fdUseCount = 0
fdLock = {Object@821}
closePending = false
CONNECTION_NOT_RESET = 0
CONNECTION_RESET_PENDING = 1
CONNECTION_RESET = 2
resetState = 0
resetLock = {Object@822}
stream = true
socket = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
serverSocket = null
fd = {FileDescriptor@817}
address = {Inet4Address@823} "localhost/127.0.0.1"
port = 1030
localport = 51099
temp = null
socket = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
closing = false
fd = {FileDescriptor@817}
path = null
channel = null
closeLock = {Object@826}
closed = false
otherParents = {ArrayList@833} size = 2
closed = false
path = null
channel = null
closeLock = {Object@826}
closed = false
otherParents = {ArrayList@833} size = 2
closed = false
path = null
channel = null
closeLock = {Object@826}
closed = false
socketOutputStream = {SocketOutputStream@820}
impl = {DualStackPlainSocketImpl@814} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
temp = {byte[1]@843}
socket = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
closing = false
fd = {FileDescriptor@817}
append = false
channel = null
path = null
closeLock = {Object@844}
closed = false
fdUseCount = 0
fdLock = {Object@821}
closePending = false
CONNECTION_NOT_RESET = 0
CONNECTION_RESET_PENDING = 1
CONNECTION_RESET = 2
resetState = 0
resetLock = {Object@822}
stream = true
socket = {Socket@804} "Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]"
serverSocket = null
fd = {FileDescriptor@817}
address = {Inet4Address@823} "localhost/127.0.0.1"
port = 1030
localport = 51099
timeout = 0
trafficClass = 0
shut_rd = false
shut_wr = false
socketInputStream = null
socketOutputStream = null
fdUseCount = 0
fdLock = {Object@815}
closePending = false
CONNECTION_NOT_RESET = 0
CONNECTION_RESET_PENDING = 1
CONNECTION_RESET = 2
resetState = 0
resetLock = {Object@816}
stream = false
socket = null
serverSocket = null
fd = {FileDescriptor@817}
address = null
port = 0
localport = 0
oldImpl = false
pg_input = {VisibleBufferedInputStream@805}
pg_output = {BufferedOutputStream@806}
streamBuffer = null
encoding = {Encoding@807} "UTF-8"
encodingWriter = {OutputStreamWriter@808}
user = "postgres"
database = "postgres"
executor = {QueryExecutorImpl@800}
logger = {Logger@778}
compatible = "9.0"
dbVersionNumber = "10.7"
commitQuery = {SimpleQuery@783} "COMMIT"
rollbackQuery = {SimpleQuery@784} "ROLLBACK"
_typeCache = {TypeInfoCache@785}
prepareThreshold = 5
autoCommit = true
readOnly = false
bindStringAsVarchar = true
firstWarning = null
timestampUtils = {TimestampUtils@786}
typemap = null
fastpath = null
largeobject = null
metadata = null
copyManager = null