TypeORM 连接 Microsoft SQL Server 完全指南:mssql 驱动选项、连接池调优与 Vector 向量类型实战
【免费下载链接】typeormTypeScript & JavaScript ORM for Node.js — supports PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, and more.项目地址: https://gitcode.com/GitHub_Trending/ty/typeorm
本篇指南基于 TypeORM 官方文档中 SQL Server 驱动章节,系统讲解如何在 Node.js 应用中通过mssql驱动连接 Microsoft SQL Server:从数据源选项(连接参数、认证方式、连接池、options底层配置)到各参数在源码中的实际处理逻辑,再到 SQL Server 支持的列类型清单、新的vector向量类型及其相似度搜索实践,以及连接池隔离级别不重置这一已知问题的规避方案。读完后你可以完成一套可复制的 SQL Server 数据源配置,并理解每个关键参数在 SqlServerDriver 中的落点。
一、安装驱动与底层依赖加载
SQL Server 驱动基于 tedious 的 MSSQL 实现,TypeORM 通过mssql包与之通信。安装方式:
npm install mssql驱动包并非 TypeORM 的默认依赖,需要在 SqlServerDriver.loadDependencies 中显式加载:它优先使用数据源中显式传入的driver对象(this.options.driver ?? PlatformTools.load("mssql")),加载失败则抛出DriverPackageNotInstalledError("SQL Server", "mssql")。这解释了 SqlServerDataSourceOptions 中为何存在一个driver?: any字段——当mssql无法通过require解析(例如打包环境)时,你可以把驱动实例直接注入该字段。
二、数据源选项总览
通用数据源选项(logging、synchronize、entities等)请参考 Data Source Options。SQL Server 专属选项定义在 SqlServerConnectionCredentialsOptions 与 SqlServerDataSourceOptions 中,type固定为"mssql":
import { DataSource } from "typeorm" const dataSource = new DataSource({ type: "mssql", host: "localhost", port: 1433, username: "sa", password: "Admin12345", database: "tempdb", logging: false, })仓库自带的 ormconfig.sample.json 中就包含了一份mssql测试配置(localhost:1433,sa/Admin12345,库名tempdb),可作为最小可运行样例参考。
2.1 连接基础参数
| 选项 | 说明 |
|---|---|
url | 连接 URL。注意:其他数据源选项会覆盖从 URL 解析出的参数 |
host | 数据库主机 |
port | 数据库主机端口,MSSQL 默认1433 |
username | 数据库用户名 |
password | 数据库密码 |
database | 数据库名 |
schema | Schema 名,默认"dbo" |
domain | 设置后驱动将以 domain 登录方式连接 SQL Server |
从源码结构看,connect()阶段若未显式提供database/schema,SqlServerDriver.connect 会通过 QueryRunner 执行getCurrentDatabase()/getCurrentSchema()探测当前库与searchSchema,再回落到this.schema ??= this.searchSchema——这就是默认 schema 表现为dbo的机制。
2.2 认证方式(authentication)
除了username/password,SqlServerConnectionCredentialsOptions 还支持authentication字段,它是一个联合类型,传入后会覆盖username与password。仓库中 src/driver/sqlserver/authentication 目录定义了八种认证形态:
DefaultAuthentication:普通 SQL 认证(对应username/password);NtlmAuthentication:Windows 域登录,type: "ntlm",需提供 Windows 账户的userName、password以及必填的domain(见 NtlmAuthentication.ts);- 六种 Azure Active Directory 认证:
azure-active-directory-password、azure-active-directory-default、azure-active-directory-access-token、azure-active-directory-msi-app-service、azure-active-directory-msi-vm、azure-active-directory-service-principal-secret。
例如 Azure AD 密码认证的配置(字段定义见 AzureActiveDirectoryPasswordAuthentication.ts):
authentication: { type: "azure-active-directory-password", options: { userName: "myUser", password: "myPassword", domain: "myTenant", // 可选,指定 Azure 租户 ID }, },这些认证对象最终原样传给mssql驱动:SqlServerDriver.createPool 中connectionOptions的authentication: credentials.authentication字段直接把认证配置透传给new this.mssql.ConnectionPool(connectionOptions)。
三、超时、流式读取与连接池选项
3.1 顶层选项
| 选项 | 说明 | 默认值 |
|---|---|---|
connectionTimeout | 连接超时(毫秒) | 15000 |
requestTimeout | 请求超时(毫秒)。注意msnodesqlv8驱动不支持小于 1 秒的超时 | 15000 |
stream | 以流式方式逐行返回结果集,而非一次性全部返回。也可以对单个请求单独启用(request.stream = true)。如果你要处理大量行,请始终设为true | false |
replication | 读写分离:master(写库)+slaves[](只读库列表)+defaultMode(默认"slave") | - |
createPool会把这三个顶层值直接并入驱动连接参数(connectionTimeout、requestTimeout、stream),并强制默认useUTC: false(若未显式设置),同时追加enableArithAbort: true以匹配即将发布的 tedious 配置约定(见 createPool 实现)。
3.2 pool 连接池选项
pool字段(完整定义见 SqlServerDataSourceOptions.ts):
| 选项 | 说明 | 默认值 |
|---|---|---|
pool.max | 连接池最大连接数 | 10 |
pool.min | 连接池最小连接数 | 0 |
pool.maxWaitingClients | 允许排队的请求数,超出后acquire调用将在后续事件循环中以错误回调 | - |
pool.acquireTimeoutMillis | acquire调用等待资源的最长毫秒数(默认无限制),若提供须为非零正整数 | 无限制 |
pool.fifo | true表示最老的连接最先分配;false则把池从队列变成栈(最近释放的先分配) | true |
pool.priorityRange | 整数,设置为 1~x 后,无可用资源时借用者可以指定其在队列中的相对优先级 | 1 |
pool.evictionRunIntervalMillis | 驱逐检查的执行频率(毫秒) | 0(不执行) |
pool.numTestsPerRun | 每次驱逐检查检查的资源数量 | 3 |
pool.softIdleTimeoutMillis | 对象在池中空闲多久后有资格被空闲驱逐器驱逐(前提是池中至少保留 “min idle” 个实例) | -1(不可被驱逐) |
pool.idleTimeoutMillis | 对象空闲多久后有资格因空闲被驱逐,优先级高于softIdleTimeoutMillis | 30000 |
pool.errorHandler | 底层池发出'error'事件时的处理函数,接收单个 error 参数,默认以warn级别记录日志 | 记录日志 |
关于errorHandler值得一提源码中的一个细节:createPool 中,若你没有提供pool.errorHandler,TypeORM 会自动挂一个默认处理器,通过数据源的 logger 以warn级别输出MSSQL pool raised an error.。注释明确说明这是必需的,否则池错误会成为未处理异常并导致宿主应用崩溃——生产环境建议始终传入自己的errorHandler。
四、options:底层驱动行为配置
options字段(定义见 SqlServerDataSourceOptions.ts)对应mssql/tedious的底层行为开关:
| 选项 | 说明 | 默认值 |
|---|---|---|
options.fallbackToDefaultDb | 若options.database请求的库不可访问,默认连接会失败;设为true则改用用户的默认数据库 | false |
options.instanceName | 要连接的实例名。要求数据库服务器上运行 SQL Server Browser 服务且 UDP 1434 端口可达。与port互斥 | 无 |
options.enableAnsiNullDefault | true时初始 SQL 中执行SET ANSI_NULL_DFLT_ON ON,新建列默认可空 | true |
options.cancelTimeout | 请求取消(中止)被视为失败前的毫秒数 | 5000 |
options.packetSize | TDS 包大小(与服务端协商),应为 2 的幂 | 4096 |
options.useUTC | 时间值按 UTC 还是本地时间传递 | false |
options.abortTransactionOnError | 事务执行中遇到任何错误时是否自动回滚(初始 SQL 阶段设置SET XACT_ABORT) | - |
options.localAddress | 连接时使用的本机网络接口(IP 地址) | - |
options.useColumnNames | 行以键值集合而非数组形式返回 | false |
options.camelCaseColumns | 返回列名首字母是否转小写;提供了columnNameReplacer时此值被忽略 | false |
options.isolationLevel | 事务默认隔离级别:READ UNCOMMITTED/READ COMMITTED/REPEATABLE READ/SERIALIZABLE/SNAPSHOT。⚠️ 存在连接池复用的限制,见已知问题 | READ COMMITTED |
options.connectionIsolationLevel | 新连接的默认隔离级别,所有事务外查询按此执行。⚠️ 同样受上述限制 | READ COMMITTED |
options.readOnlyIntent | 是否向 SQL Server 可用性组请求只读访问 | false |
options.encrypt | 是否加密连接,在 Windows Azure 上应设为true | true |
options.cryptoCredentialsDetails | 使用加密时传给tls.createSecurePair首参的对象 | {} |
options.rowCollectionOnDone | true时在 Request 的done*事件中暴露接收到的行。注意:大量行时可能过度占用内存 | false |
options.rowCollectionOnRequestCompletion | true时在 Request 完成回调中暴露接收到的行。同样有内存风险 | false |
options.tdsVersion | TDS 版本:7_1/7_2/7_3_A/7_3_B/7_4;服务端不支持指定版本时会协商降级 | 7_4 |
options.appName | 用于在 SQL Server 的性能剖析、日志或跟踪工具中标识应用 | node-mssql |
options.trustServerCertificate | 无可信服务器证书时是否仍加密 | false |
options.multiSubnetFailover | 是否并行连接 DNS 返回的所有 IP(AlwaysOn 多子网场景) | false |
options.debug.packet/data/payload/token | 四个调试开关,分别控制是否发出描述包详情、包数据、包负载、token 流的debug事件 | 均false |
TypeORM 侧对隔离级别做了一层转换:convertIsolationLevel 把字符串(如"READ COMMITTED")映射为mssql.ISOLATION_LEVEL枚举值,底层驱动要求的是枚举而非字符串;非法级别会由 validate-isolation-level 校验后抛出TypeORMError。
五、支持的列类型与默认值
SQL Server 驱动支持的全部列类型(与 SqlServerDriver.supportedDataTypes 一致):
int, bigint, bit, decimal, money, numeric, smallint, smallmoney, tinyint, float, real, date, datetime2, datetime, datetimeoffset, smalldatetime, time, char, varchar, text, nchar, nvarchar, ntext, binary, image, varbinary, hierarchyid, sql_variant, timestamp, uniqueidentifier, xml, geometry, geography, rowversion, vector几组容易踩坑的类型细节,均可在 SqlServerDriver 中验证:
- JS 类型映射(
normalizeType):Number→int,String→nvarchar,Date→datetime,Boolean→bit,"uuid"→uniqueidentifier,"simple-array"/"simple-json"→ntext。 - 类型默认长度/精度(
dataTypeDefaults):varchar/nvarchar默认长度255,char/nchar默认1,decimal/numeric默认(18, 0),time/datetime2/datetimeoffset默认精度7,vector默认长度255。未显式指定长度时,nvarchar列会落成nvarchar(255)。 - ORM 内部列映射(
mappedDataTypes):CreateDateColumn等时间列使用datetime2并默认getdate();乐观锁VersionColumn使用int;缓存列使用nvarchar(MAX)。 - 可空性:
deleteDateNullable: true,即软删除列可空。 - 参数化:SQL Server 参数需携带类型信息,
parametrizeValue会把值包装为 MssqlParameter,参数前缀为@(parametersPrefix = "@")。
六、Vector 向量类型与相似度搜索
SQL Server 新增的vector数据类型用于存储高维向量,常见场景:嵌入语义检索、推荐系统、相似度匹配、机器学习应用。注意:通用的halfvec类型支持不可用,因为该特性仍处于预览阶段(见 Microsoft 的 Vector data type 文档)。
6.1 定义向量列
@Entity() export class DocumentChunk { @PrimaryGeneratedColumn() id: number @Column("varchar") content: string // 1998 维向量列 @Column("vector", { length: 1998 }) embedding: number[] }要求:
- 需要支持 vector 的 SQL Server 版本;
- 向量维度必须通过
length选项指定。
从源码看,维度会直接进入建表 DDL:createFullType 中vector类型被渲染为`vector(${column.length})`;读写时 preparePersistentValue 会把number[]序列化为 JSON 字符串写入,prepareHydratedValue在读取时用JSON.parse还原为数组(解析失败则原样返回)。
6.2 使用 VECTOR_DISTANCE 做相似度搜索
SQL Server 提供VECTOR_DISTANCE函数计算向量间距离:
const queryEmbedding = [/* 你的查询向量 */] const results = await dataSource.query( ` DECLARE @question AS VECTOR (1998) = @0; SELECT TOP (10) dc.*, VECTOR_DISTANCE('cosine', @question, embedding) AS distance FROM document_chunk dc ORDER BY VECTOR_DISTANCE('cosine', @question, embedding) `, [JSON.stringify(queryEmbedding)], )距离度量:
'cosine'— 余弦距离(语义检索中最常用);'euclidean'— 欧氏(L2)距离;'dot'— 负点积。
仓库中的功能测试 test/functional/database-schema/vectors/sqlserver/vector.test.ts 覆盖了完整闭环:建表后校验embedding列类型为vector且长度为1998、保存/读取 1998 维随机向量的精度比较(closeTo 0.0001)、更新向量值,以及用VECTOR_DISTANCE执行余弦相似度检索并按距离排序——与本文示例完全对应,可作为验证基准。
七、已知问题:连接池不重置隔离级别
驱动专属的options.isolationLevel与options.connectionIsolationLevel在底层 node-mssql 驱动创建连接时会被正确应用。但node-mssql在把连接归还到池时不会调用connection.reset()——这意味着任何操作(例如一个不同隔离级别的显式事务)一旦修改了池中某个连接的隔离级别,该修改会持续存在,并泄漏给该连接的下一个使用者。
实际后果:对于同时使用“逐事务隔离级别”的应用,这两个选项变得不可靠。
推荐替代方案:改用所有驱动通用的顶层isolationLevel数据源选项。它在每次事务开始时显式应用隔离级别,完全绕开池的限制,详见 Transactions 文档 > Default Isolation Level。这也是 SqlServerDataSourceOptions 中两个隔离级别字段注释所明确警示的行为:“this setting may not be reliably preserved across pooled connection reuse”。该上游限制已被跟踪在 tediousjs/node-mssql#1483 中。
八、小结
- 连接 SQL Server 需先
npm install mssql,type设为"mssql",基础参数与 ormconfig.sample.json 中的示例对齐即可起步; - 认证支持 SQL、NTLM(Windows 域,需
domain)与六种 Azure AD 方式,authentication优先于username/password; pool与options两层配置分别控制池行为与 TDS 层行为;池错误务必挂接errorHandler,否则可能导致应用崩溃;- 类型系统以
nvarchar/datetime/bit为 JS 类型默认映射,varchar/nvarchar缺省长度为255,向量列必须显式给出length; - 隔离级别不要依赖
options.isolationLevel(连接池不重置),统一使用顶层isolationLevel选项。
主要参考路径:SqlServerDataSourceOptions.ts、SqlServerConnectionCredentialsOptions.ts、SqlServerDriver.ts、authentications、sqlserver vector 测试。
【免费下载链接】typeormTypeScript & JavaScript ORM for Node.js — supports PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, and more.项目地址: https://gitcode.com/GitHub_Trending/ty/typeorm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考