数据库连接与原始 TCP 连接

Ash*_*oyi 4 mysql postgresql oracle sql-server connections

我有一些关于数据库客户端和数据库如何交互的基本问题

  1. 数据库是否支持在来自客户端的单个数据库连接上同时进行多个事务?如果没有,为什么不呢?(因为多路复用可以节省每个连接的资源开销,当需要同时执行数千个并发查询时,连接池是争用的来源,这肯定可以避免多路复用)
  2. 数据库客户端级别连接与物理原始 TCP 连接之间的关系是什么。是多对一[多路复用](或)一对一?如果不是多路复用,为什么不呢?
  3. 如果多路复用,数据库服务器是否从其末端(或)多个逻辑连接维护单个逻辑连接

PS:我知道其中一些细节会因数据库而异,但我想大致了解 Postgres、Mysql、Oracle、SQL server 和 DB2 等流行的实现是如何实现这些的

Dav*_*oft 11

数据库是否支持在来自客户端的单个数据库连接上同时进行多个事务?

对于 SQL Server,没有。

如果没有,为什么不呢?(因为多路复用可以节省每个连接的资源开销)

这会使网络协议变得严重复杂,该协议必须在多个客户端平台上实现,从而可能导致错误和性能问题。

并且由多个连接引起的资源开销很小,并且通过连接池在很大程度上减轻了连接池,其中一组长寿命连接在客户端程序中的所有线程之间共享。

  • TCP/IP 连接根本就不是值得这种设计的昂贵资源。性能可能不会“好得多”,而且可能会更糟,因为会话必须与其他想要读写数据的会话协调 TCP/IP 套接字的使用。 (6认同)

Bal*_*app 5

甲骨文

一个鲜为人知的事实是,在 Oracle 中,一个人可以在同一个 TCP 连接中拥有 0 个、1 个甚至更多的会话。

这在本书中讨论的专家Oracle数据库体系结构(ISBN 978-1-4302-6299-2,作者:凯特,托马斯,库恩,卡尔)中Chapter 5 - Oracle Processes

https://books.google.com/books?id=NG4RpD8aLEIC&pg=PA170

连接与会话

许多人惊讶地发现连接并不是会话的同义词。在大多数人看来,它们是相同的,但事实并非必须如此。一个连接上可能建立了零个、一个或多个会话。 每个会话都是独立的,即使它们都共享相同的数据库物理连接。一个会话中的提交不会影响该连接上的任何其他会话。事实上,使用该连接的每个会话都可以使用不同的用户身份!在 Oracle 中,连接只是客户端进程和数据库实例之间的物理电路 — 最常见的是网络连接。连接可能是到一个专用的服务器进程或一个调度程序。如前所述,一个连接可能有零个或多个会话,这意味着可能存在没有相应会话的连接。

演示:

登录数据库:

[oracle@o71 ~]$ sqlplus bp/bp@\'localhost:1521/min18\'

SQL*Plus: Release 18.0.0.0.0 - Production on Thu Dec 27 21:20:03 2018
Version 18.4.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.

Last Successful login time: Thu Dec 27 2018 21:07:47 +01:00

Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0

SQL>
Run Code Online (Sandbox Code Playgroud)

在另一个会话中,从别处开始,查询 BP 的会话:

SQL> select sid, process, port, paddr from v$session where username = 'BP';

       SID PROCESS                        PORT PADDR
---------- ------------------------ ---------- ----------------
       395 31251                         35298 0000000066E75338
Run Code Online (Sandbox Code Playgroud)

现在在原始会话中启用自动跟踪:

SQL> set autotrace on
Run Code Online (Sandbox Code Playgroud)

然后从另一个会话再次检查会话:

SQL> select sid, process, port, paddr from v$session where username = 'BP';

       SID PROCESS                        PORT PADDR
---------- ------------------------ ---------- ----------------
       395 31251                         35298 0000000066E75338
       399 31251                         35298 0000000066E75338

SQL> !sudo netstat -tanlp | grep 35298
tcp        0      0 127.0.0.1:35298         127.0.0.1:1521          ESTABLISHED 31251/sqlplus
tcp        0      0 127.0.0.1:1521          127.0.0.1:35298         ESTABLISHED 31253/oracleMIN18
Run Code Online (Sandbox Code Playgroud)

我们有 2 个会话,使用相同的客户端和服务器进程以及相同的 TCP 连接(这通常是令人惊讶的部分)。现在,如果我们disconnect让 sqlplus 在第一个会话中运行:

SQL> disconnect
Disconnected from Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0
SQL>
Run Code Online (Sandbox Code Playgroud)

并从另一个会话再次检查数据库:

SQL> select sid, process, port, paddr from v$session where username = 'BP';

no rows selected

SQL> select spid from v$process where addr = '0000000066E75338';

SPID
------------------------
31253

SQL> !sudo netstat -tanlp | grep 35298
tcp        0      0 127.0.0.1:35298         127.0.0.1:1521          ESTABLISHED 31251/sqlplus
tcp        0      0 127.0.0.1:1521          127.0.0.1:35298         ESTABLISHED 31253/oracleMIN18

SQL> select sid, process, port, paddr from v$session where paddr = '0000000066E75338';

no rows selected
Run Code Online (Sandbox Code Playgroud)

我们仍然有数据库服务器进程,我们仍然有客户端进程,我们仍然有它们之间的 TCP 连接,但是我们有 0 个与它们关联的会话。使用 退出 sqlplus 后exit,即进程和连接终止时:

SQL> exit
[oracle@o71 ~]$
Run Code Online (Sandbox Code Playgroud)

和:

SQL> select spid from v$process where addr = '0000000066E75338';

no rows selected

SQL> !sudo netstat -tanlp | grep 35298
tcp        0      0 127.0.0.1:35298         127.0.0.1:1521          TIME_WAIT   -
Run Code Online (Sandbox Code Playgroud)

所以这是可能的,但除了上面的书和基于它构建的演示之外,我从未在实践中看到过这种情况。