当我们说我们已经在数据库和应用程序之间创建了一个连接(可以存储在连接池中)时,真正的“连接”在这里意味着什么?
TCP/ TLS
连接有什么关系吗?“连接”只不过是Socket
的细节,还有额外的细节(如用户名,密码等)。每个连接都有不同的套接字连接。
例如:
连接1:
Socket[addr=localhost/127.0.0.1,port=1030,localport=51099]
连接2:
Socket[addr=localhost/127.0.0.1,port=1030,localport=51246]
我在一个JVM进程中创建了两个连接,以演示服务器如何知道要在哪个Socket
中发送回复。 A socket,如果我根据UNIX定义的是用于进程间通信的special file:
srwxr-xr-x. 1 root root 0 Mar 3 19:30 /tmp/somesocket
创建套接字时(即,创建此特殊套接字文件时; how to create a socket?和this)操作系统会创建指向该文件的文件描述符。服务器将Socket与以下属性区分开来:Ref.
{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}
PROTOCOL
:我用postgres
作为例子,postgres
驱动程序中的套接字连接是用SocksSocketImpl
完成的,这是一个TCP socket implementation (RFC 1928)
返回我创建的两个连接,如果仔细观察,两个连接的localport
是不同的,所以服务器清楚地知道它必须发送回复的位置。
现在,您可以在操作系统中打开文件(或文件描述符)的数量有限制,因此建议不要保持连接悬空(称为连接泄漏)
它是否为每个连接加载数据库架构?
答:不,这是结果集来处理它。
数据库架构更改时,连接会发生什么
答案:连接和数据库架构是两回事。 Connection只定义了如何与另一个进程通信。数据库模式是应用程序和数据库之间的契约,应用程序可能抛出合同被破坏的错误,或者它可能只是忽略它。
如果你有兴趣挖掘更多,你应该为连接对象添加一个断点,下面是它的样子(参见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
在这里,您正在谈论的连接意味着应用程序调用以打开和读取/修改/删除数据库或其子项的打开功能。
例如,如果我们谈论PHP
文件(用于在服务器中加载网站请求,如HTML
)或HTML
文件,您在其中登录名称为:https://example.com/login.php(PHP
)或https://example.com/login.html(HTML
)的页面,页面需要如果给定的值(例如:用户名:“demoUser”和密码:“password * 1234”)在数据库中作为特定表格中的行存在,则访问用户的数据库以检查您插入的凭据是否正确。数据库可以包含无限表和内部的无限行。一个简单数据库的示例,只有一个名为Users的表:username
| password
| date_created
//表格列
"demoUser"
| "password"
| "23-03-2019"
//示例如上所示
"user1213"
| "passw0rd"
| "04-02-2019"
//第二个用户示例然后在上面如果应用程序需要验证该数据库中是否存在该值,应用程序的操作系统将使用简单的文件读取文件访问数据库,通常使用.db然后它将读取每个行来查找值。
为此,login.php / login.html页面中的代码调用运行该文件的服务器,服务器打开数据库,然后服务器接受查询(要在数据库中检查的代码请求),然后执行它好像数据库是一个简单的文件(例如:) .db
。这里的连接代表查询
用简单的话说。 “数据库连接”是应用程序进程与数据库服务进程之间的链接。
客户端: 当您创建连接时,您的应用程序会存储以下信息:数据库地址是什么,连接使用什么套接字,负责处理请求的服务器进程等等。此信息取决于连接驱动程序实现,并且因数据库而异。
服务器端: 当来自客户端应用程序的请求到达时,数据库执行客户端的身份验证和授权,并创建新进程或负责提供它的线程。此服务器进程加载的实现和数据也依赖于供应商,因数据库而异。 “准备”数据库以服务新客户端的过程需要花费大量时间,而这正是连接池提供帮助的地方。
连接池: 连接池基本上用于减少打开新连接的需要,并浪费时间进行身份验证,授权,创建服务器进程等。它允许重用已建立的连接。 当数据库架构发生更改并且正在进行活动事务时,连接(已在应用程序连接池中加载)会发生什么? 首先,数据库不知道任何连接池。对于数据库来说,这是一个客户端功能。发生的事情还取决于特定的数据库及其实现。通常,数据库具有阻止机制,以防止对象在仍在使用时进行修改,反之亦然。