第八章 SQL Server 安装
本章涵盖
- 有意义的实例名称
- 使用正确的操作系统和 SQL Server 版本
- 自动安装
- SQL Server 的占用空间
- 云中的安装注意事项
在本章中,我们将讨论用于安装 SQL Server 的各种选项。回顾十年前,规划 SQL Server 部署相对来说比较简单。我们需要选择最合适的 SQL Server 版本进行安装,并考虑如何安装它(图形界面还是脚本)。我们需要考虑实例所需的功能,并给它一个合适的名称,但大致就是这些。
快进到今天,SQL Server 的安装可能性无穷无尽。这可能导致一连串的错误,其中许多是由于在没有考虑更优替代方案的情况下进行传统安装而产生的。
在本章中,我们将为 MagicChoc 安装一系列 SQL Server 实例,并探讨可能等待意外数据库管理员 (DBA) 的一些陷阱。这将涵盖部署规划和执行的多个方面,从实例命名到选择合适的操作系统环境和 SQL Server 版本。我们还将探讨手动安装的挑战、安装不必要的功能以及实例过度合并的问题。
错误33# 使用晦涩的实例名称
在第2章中,我们讨论了命名标准以及使用未经深思熟虑的对象名称可能产生的后果。如果我们没有仔细考虑实例名称,SQL Server 实例也可能出现类似问题。为了探讨这一点,我们假设 MagicChoc 已经要求我们构建四个 SQL Server 实例,分布在两台服务器上,这些实例将托管以下应用程序使用的数据库:
- Choc Maker, which is used by manufacturing
- Magic Sales, a sales team application
- Temperature Smart, an application used in the manufacturing process
- HR Manager, a tool used by the human resources team
有四个应用程序和四个实例,所以我们决定在两台服务器上创建四个实例,并为它们命名,使其与应用程序名称一致:
- MagicServer1\ChocMaker
- MagicServer1\MagicSales
- MagicServer2\TempSmart
- MagicServer2\HRManager
当时,这听起来完全合理。然而几个月后,我们意识到这是一个错误。数据库负责人要求我们将巧克力制造商和温控智能应用整合到一个实例中。
我们现在有三个选项。我们可以让 Choc Maker 在一个名为 TempSmart 的实例中运行,这将可能在未来引起一定程度的混乱;我们也可以让 Temperature Smart 在一个名为 ChocMaker 的实例中运行,这同样会引起相同程度的混乱;或者我们可以将 SQL Server 实例重命名为 Manufacturing,这可能会产生大量额外工作,取决于应用程序如何访问该实例以及使用的功能。
那么,我是在推荐按部门而不是按应用来命名 SQL Server 实例吗?不,我当然不是。这可能会带来一系列挑战,例如在不同服务器上存在多个同名实例——更糟的是,可能需要在同一台服务器上有两个同名实例(这是不可能的)。当然,还存在部门在重组过程中更改名称的风险。例如,销售部门可能会拆分成两个部门,分别称为销售和市场。
我们如何命名实例取决于我们的组织以及 SQL Server 系统的结构。例如,除了根据应用程序或部门来命名实例外,它也可以以业务服务命名。
可能还需要有命名规范,其中包括名称中的各个方面。举一个例子,考虑实例名称 MAPRDENTLON01。这个实例名称通过两个字母的代码反映部门,MA = 制造。它通过三个字母的代码反映生态系统,在此例中 PRD = 生产。接下来的三个字母指定应用于该实例的许可类型。在此例中,ENT = 企业版。名称中的接下来的三个字符表示实例所在的位置:LON = 伦敦。最后,还有一个两位数的递增标识符。
简而言之,我的建议是应当对实例名称给予适当考虑,并以适当的方式进行命名,确保将来不会引起混淆。命名标准应在整个系统中保持一致。
错误34# 随意使用 Windows
直到2017年,SQL Server只能在Windows上运行。在两款产品均由微软开发的背景下,这一点非常合情合理。然而,在SQL Server 2017中发生了重大转变,微软引入了对SQL Server在Ubuntu、SUSE和Red Hat等Linux版本上运行的支持。它甚至支持在Docker容器中运行。但这难道不显得有点奇怪吗?我们难道不会只想在Windows上运行SQL Server吗?好了,让我们通过MagicChoc来探索一个场景。
在第4章中,我们讨论了MagicChoc如何觉得其流程过于分散,因此它委托开发了一个新应用程序,将其非互联网销售和采购功能整合到一个界面和一个后台中。我们没有讨论的是,这个应用程序将用Go语言编写,并将在运行Ubuntu的虚拟机上托管。性能和稳定性对该应用程序至关重要。
应用团队最初计划使用 MySQL,但 MagicChoc 的 DBA 团队在 MySQL 上没有经验。他们还想使用高级 SQL Server 功能,例如 AlwaysOn,应用团队意识到他们也可以受益于其他高级 T-SQL 功能,例如 HIERARCHYID 数据类型和窗口函数。
因此,决定让 DBA 团队在运行 Windows Server 2022 的虚拟机上构建 SQL Server 实例。但对于这种情况,这是一个错误。为什么这是一个错误的线索都在案例研究中。
首先,DBA 团队不想支持 MySQL,因为他们在该领域缺乏技能,但同时他们又希望基于 Linux 的开发人员切换到 Windows 环境来使用数据库引擎。如果 SQL Server 部署在 Linux 上,入门门槛本来会更低。
第二个原因是该应用程序正在 Ubuntu 上构建。这是一个无许可证的 Linux 发行版,这意味着成本是一个重要因素。许多企业应用程序都是在 Red Hat 或 SUSE 发行版上构建的,因为这些发行版有许可证费用,但也提供外部支持。如果 SQL Server 安装在 Ubuntu 而不是 Windows 上,那么 Windows Server 的许可证费用就可以避免。
最后一个原因是对应用程序快速且稳定的要求。虽然 SQL Server 本身在任何操作系统上都具备这两个要求,但由于操作系统的特性,在 Linux 上这些要求得到了某种程度的增强。
Linux 是一个非常轻量级的操作系统。这意味着出错的可能性更小。尽管过去十年来 Windows 的稳定性大幅提高,但在这方面 Linux 发行版仍然领先。轻量化的特性也可以带来性能优势。2021 年,官方基准测试将 Red Hat Linux 评为 SQL Server 性能最优的操作系统。
当然,在这种情况下的所有这些好处并不意味着 Linux 应该成为 SQL Server 安装的默认选择。这意味着在为使用 SQL Server 的应用程序的数据层设计平台环境时,应考虑 Linux。在某些情况下,Linux 是最佳选择,但在许多情况下,Windows 仍然是更好的选项。
例如,如果该应用程序是基于 Windows 的应用程序,那么通过引入 Linux 服务器,我们只会增加复杂性。我们可能还会因为不得不启用 SQL Server 认证而降低安全性,而不是仅依靠 Windows 认证。
注意:可以将 Linux 服务器注册到 Active Directory(AD),但这是一个非典型配置。
根据我们的组织情况,我们可能缺乏 Linux 技能。如果是这种情况,那么我们不太可能想在一个我们难以支持的操作系统上安装像 SQL Server 这样复杂的产品。
在 Linux 上也有一些功能限制。例如,不支持 SQL Server 报表服务。其他图形工具,例如 SQL Server Management Studio (SSMS),在 Linux 服务器上不受支持,但我们可以将其安装在 Windows 设备上,并像对待其他实例一样连接到托管在 Linux 上的实例。
图 8.1 显示了一个可以进行分析的可能决策树。
简而言之,在规划安装时,应仔细考虑 SQL Server 的托管环境。在做出决定之前,我们应考虑应用层的性质和需求、SQL Server 的技术要求、操作系统许可成本、支持模式以及团队的技能。然而,在我们的考虑中,始终不应忘记在 Linux 上安装的可能性。
提示 本书不涵盖在 Linux 上安装 SQL Server 的内容。微软提供了一个操作指南,网址为 https://mng.bz/aVO7。或者,您也可以在我的书《Pro SQL Server 2022 Administration》中找到相关指导和操作步骤,该书可在 https://mng.bz/gA9V 获取。
错误35# 忘记了容器有多有用
当我刚开始使用 SQL Server 时,它总是安装在物理服务器上,或者叫做“裸机”。随着时间的推移,虚拟机变得越来越流行,尽管 SQL Server 进入这一领域有点晚,但最终在虚拟机上安装 SQL Server 成为了常态。近年来,容器变得越来越受欢迎,自 SQL Server 2017 起,SQL Server 就已经支持在容器上运行。
与虚拟机不同,虚拟机虚拟化硬件,而容器虚拟化的是操作系统的内核。这使得容器具有可移植性、隔离性和轻量性。容器带来了许多优势,例如它们在微服务应用中的使用,并且使部署应用程序变得非常简单,尤其是在 DevOps 场景中。
尽管微软在容器领域的到来时间出乎意料地快,我常看到的一个DBA的持续错误是未能采用它们。这通常是由于缺乏理解以及未能看到它们对SQL Server的价值。考虑到这一点,我们来看看一个MagicChoc的场景。
MagicChoc 刚刚与一家咨询公司签署了一项协议,开发一个用于管理生产流程的新型集成应用程序。这是一个大型项目,预计需要一年多时间才能完成,项目团队将由 15 名开发人员和 5 名测试人员组成。项目团队的每个成员都需要一个专用的 SQL Server 实例。
项目团队的一些成员使用 Windows 笔记本电脑,但大多数人使用 Mac。因此,他们不能只是简单地在笔记本上安装 SQL Server。一个开发人员嘀咕着要使用容器,但数据库管理员中止了那场讨论,因为容器是无状态的,开发人员无法保存他们的工作。相反,数据库管理员让 Windows 团队启动 15 台虚拟机。不幸的是,VMware 集群的剩余容量不足以执行此操作。于是,他们启动了一台大型虚拟机,数据库管理员在上面安装了 20 个 SQL Server 实例。
这种情况在大型组织的IT部门的对话中相当典型,但不幸的是,它充满了误解和错误。对于这种情况最优的答案是使用容器。让我们更详细地探讨这些误解。
DBA 团队不愿意使用容器,因为容器是无状态的,因此他们认为开发人员无法保存他们的工作。虽然容器确实是无状态的这一点是完全正确的,但认为开发人员无法保存工作这一假设则不正确。在容器中使用 SQL Server 时,数据必须持久化。否则,当容器被移除时,容器内的所有内容,包括数据库和代码,都会丢失。
为了在容器外部保存数据,我们将使用 Docker 卷,它是由 Docker 管理的资源,指向容器外部的文件系统位置。内置驱动程序是本地的。简单来说,这意味着 SQL Server 实例将托管在容器内,但 Docker 卷存在于主机上。我们可以使用以下列表中的命令创建一个名为 sqldata 的 Docker 卷。
sudo docker volume create sqldata
提示:其他驱动程序插件也可用于 Docker。例如,Flocker 使我们能够在外部存储上创建 Docker 卷,例如 AWS 的弹性块存储。
一旦 Docker 卷被创建,我们就可以在创建容器时使用 -v 参数将内部文件系统映射到外部卷,如清单 8.2 所示。这将创建一个名为 production 的容器,并将存储系统数据库的文件夹映射到 sqldata Docker 卷。
注意:本示例假设已安装并运行 Docker,并且您已下载了默认的 SQL Server 2022 容器镜像。
sudo docker run -e “ACCEPT_EULA=Y” \
-e “MSSQL_SA_PASSWORD=Pa$$w0rd” \
-p 1433:1433 \
–name production \
–hostname production \
-v sqldata:/var/opt/mssql \
-d mcr.microsoft.com/mssql/server:2022-latest
另一种方法是将主机目录直接挂载为容器内部的数据卷。然而,使用 Docker 卷有几个优点。当我们使用 Docker 卷时,可以通过 Docker CLI 来管理它。这使得卷在容器之间迁移或共享更加容易。与挂载主机目录不同,Docker 卷还有一个额外的优点,即不依赖于主机的目录结构。
容器无疑在任何现代数据库管理员(DBA)的生活中都有一席之地。它们为应用程序提供了进程和用户隔离,并且可以大幅减少大型团队开发环境的部署和管理开销。尽管 SQL Server 引擎在容器内运行,但数据可以通过存储在容器外部来持久化。这意味着数据可以在容器被移除后依然保留。
错误36# 不必要地使用桌面体验
在本章前面,我们讨论了在计划安装 SQL Server 时为什么应考虑将 Linux 作为潜在的托管平台。然而,同时,如果我们决定绝对需要 Windows,那么我们应该考虑是否真的需要图形用户界面(GUI)。很多时候,答案是否定的,如果是这种情况,那么 SQL Server 可以安装在 Windows Server Core 上。
为了探讨这一点,让我们看看另一个 MagicChoc 的需求。在第 6 章中,我们创建了一个营销数据库。我们还构建了一个 SSIS 包,用于填充该数据库中的展示数据。业务智能开发人员没有 Linux 经验,并且不愿意在此平台上提供应用程序支持。因此,数据库管理员团队决定 SQL Server 实例应构建在 Windows Server 2022 上。
一个虚拟机被建立,他们使用安装向导安装了 SQL Server 的默认实例。他们之所以做出这个决定,是因为 SSIS 包是在使用 Visual Studio 的图形界面中开发的。这是一个错误,但为什么呢?
Windows Server Core 是 Windows Server,但没有图形用户界面 (GUI)。服务器不是通过 GUI 管理,而是使用 PowerShell 管理。移除 GUI 可以去掉 Windows 的大量冗余,使其成为一个更轻量级、更安全的操作系统。它比桌面体验占用更少的磁盘空间、处理器和内存,这意味着它更高效,而且由于运行的组件和服务更少,攻击面也更小。换句话说,攻击者可以攻击的功能更少。这些特性使其成为运行 SQL Server 的优秀操作系统。
但是开发人员将使用 Visual Studio 来开发包,而 Visual Studio 无法在 Server Core 上运行,所以在这种情况下我们肯定需要 GUI 吗?其实,这并不正确;这也突显了另一个“小错误”。具体来说,相当多的管理员认为开发人员需要在运行 SSIS 或业务智能堆栈其他元素的生产环境服务器上安装 Visual Studio。实际上,这应当避免。从技术上没有任何理由这样做。集成开发环境(IDE)理想情况下应运行在开发人员的工作站上,或在极少数情况下运行在开发服务器上。
开发服务器上的IDE
理想的情况是开发人员在各自的工作站上专门使用集成开发环境(IDE),并将这些IDE连接到托管在开发服务器上的数据库。然而,我也遇到过这种做法不切实际的情况。
我遇到的一个具体场景是,当我为一个非常大的数据仓库开发 SSIS 包时。我必须针对完整的数据集进行开发,因为有些转换需要多个月的数据才能产生有意义的结果,而且业务分析师无法构建一个能够反映业务规则的样本数据集。
数据非常庞大,以至于我的工作站根本没有足够的内存来高效运行这些软件包。此外,我经常需要远程工作,通过慢速互联网连接通过VPN传输如此大量的数据效果不佳。
因此,为了及时开发这些软件包,我不得不使用远程桌面协议连接到开发服务器并在本地运行这些软件包。然而,这更多的是例外,而不是常规做法。
允许开发人员在生产服务器上安装 IDE 会增加生产环境的攻击面,但它也给开发人员留下了进入生产环境的后门。这个后门让管理员面临风险,即开发人员可能在管理员不知情的情况下执行操作,甚至发布代码,这会危及服务并使服务器无法维护。组织还可能发现他们违反了确保职责适当分离的监管要求。
考虑到这个小错误,实际上在我们的场景中并不需要操作系统,而且管理员应该在运行 Windows Server Core 的服务器上构建 SQL Server 实例。
图 8.2 在图 8.1 的基础上扩展,将 Windows Server Core 添加到决策树中。
在带有桌面体验的 Windows Server 上安装 SQL Server 总是错误的吗?不是;在某些情况下这是正确的选择。错误在于仅仅因为“我们一直都是这样做的”而在带有桌面体验的 Windows Server 上安装 SQL Server。应该始终考虑在 Windows Server Core 上安装 SQL Server,只有在有正当理由时才放弃。那些正当理由包括对图形功能的需求,例如需要 SQL Server 数据质量服务 (DQS) 或主数据服务 (Master Data Services) 的情况。
错误37# 滥用企业版
SQL Server 很贵。为了让 SQL Server 更加易于获取并降低客户成本,微软提供了多个版本的产品,每个版本具有不同的功能和许可证限制。例如,Express 版本是免费的,但它有显著的技术限制,例如最大 10 GB 的数据库大小和最大计算能力为一个插槽或四个核心。还有许多功能限制。另一方面,开发者版本也是免费的,但它支持企业版的全部功能。唯一的限制是该许可证不允许在生产环境中使用。
MagicChoc 正在尝试确定用于托管其营销应用程序数据层部分的 SQL Server 正确版本。它已决定将其托管在企业版上,因为它是一个大型 2 TB 数据库,需要在带有同步副本的可用性组上托管,并且正在运行 SSIS。这是一个错误。为了理解原因,让我们分解这些需求。
首先,如果我们考虑数据库的规模,标准版支持的数据库最大可达 524 PB,与企业版相同。这样考虑的原因可能是,由于这是一个大型数据库,它将需要大量的处理器容量和内存,而这些在标准版中是有限制的。
这是真的,但需求中没有提到容量规划。这只是一个假设。鉴于标准版支持 128 GB 内存和 24 核(或 4 插槽)处理器,这个假设应该通过容量规划来验证。否则,我们的组织很可能会花费大量额外的钱。在撰写本文时,企业版两核许可的目录价格为 15,123 美元。相比之下,两核标准版许可的目录价格为 3,945 美元。如果容量规划显示数据层应用程序需要 16 核,使用标准版将节省 89,424 美元的成本。
资本支出 vs. 运营支出
如果我们在公共云环境中构建虚拟机(VM),例如 Azure 或 AWS,我们可以将 SQL Server 许可证的费用包含在 EC2 实例的按小时费用中。这有一些优势,例如在不再需要该许可证时可以停止支付费用,以及在实例关闭时无需支付许可证费用。这种将资本支出(CAPEX)转换为运营支出(OPEX)的做法也符合云计算的财务模型,而不是数据中心托管模型。
然而,从另一方面来看,如果我们知道我们的应用程序会有较长的使用寿命,那么随着时间的推移,我们支付的费用将会超过购买永久许可证的费用。这应当在我们为新应用程序或考虑迁移到云的应用程序制定的商业案例的财务模型中加以考虑。
我们也来考虑功能需求。MagicChoc 已经说明该应用程序应托管在可用性组上,而这是我常听到作为企业版需求的一个常见原因。但 MagicChoc 请求的是一个单一的同步副本,而标准版支持一个名为基本可用性组的功能。此功能是可用性组的简化版本,提供单个副本(可以是同步或异步)。该副本在故障切换之前必须处于非活动状态。这意味着它不支持高级功能,如可读辅助副本、在辅助副本上备份或在辅助副本上进行完整性检查。然而,它确实符合 MagicChoc 的需求,因此没有理由使用企业版。我们将在第13章中进一步讨论可用性组。
企业版的最后一个原因是需要 SSIS。这是一个常见的误解,即使是一些相当有经验的数据库管理员也会有这种误解。实际上,SSIS 在标准版上是受支持的,只是有一些限制。这些限制包括作为扩展主节点操作的能力以及一些高级控制流任务和数据源转换。例如,在变更数据捕获(CDC)任务以及涉及文本匹配和提取的转换方面存在限制。对于高级数据源和目标,也有一些限制,例如 Oracle、Teradata、SAP 和 SSAS。
我听到的应用程序需要企业版的最常见原因之一是“它可能需要一些数据库级别的企业功能,但我不确定,也不想冒险。”然而,这种说法很容易被反驳,因为它很容易检查。下面清单中的脚本创建了一个包含使用表分区的表的数据库,而表分区是仅在企业版中提供的功能。
CREATE DATABASE EnterpriseDatabase ;
GO
USE EnterpriseDatabase ;
GO
CREATE PARTITION FUNCTION PartFunc (INT)
AS RANGE LEFT FOR VALUES (100, 200, 300) ;
CREATE PARTITION SCHEME PartScheme
AS PARTITION PartFunc
ALL TO (‘PRIMARY’) ;
CREATE TABLE VeryLargeTable (
KeyColumn INT PRIMARY KEY IDENTITY,
OtherColumn VARCHAR(50)
) ON PartScheme(KeyColumn) ;
我们现在可以简单地查询 sys.dm_db_persisted_sku_features 动态管理视图 (DMV) 来返回企业功能列表。如清单 8.4 所示,如果我们从之前创建的数据库中查询此 DMV,它将返回分区的单行。如果数据库没有使用任何仅限企业的功能,则它将返回一个空结果集。
USE EnterpriseDatabase ;
GO
SELECT feature_name
FROM sys.dm_db_persisted_sku_features ;
总的来说,我们绝不应该将企业版作为默认选项。它比标准版贵得多,应该仅在需要企业独有功能的情况下使用。在开发环境中,应使用开发者版,因为它是一个功能齐全的版本,唯一的限制是我们不能在生产环境中使用它。
错误38# 在 DBaaS 或 PaaS 足够的情况下安装实例
三大主要公共云提供商——GCP、AWS 和 Azure——都提供 SQL Server 数据库即服务(DBaaS)功能,Azure 还提供 SQL Server 实例作为平台即服务(PaaS)。这些产品可以为某些(但并非全部)工作负载提供大量业务优势。
让我们来思考一下 MagicChoc 及其正在云中构建的新应用程序,该应用程序将提供流程自动化以减少文书工作负担。该应用程序将在 Azure 上构建,并将使用各种云原生组件,包括 Azure Event Grid,这是一种基于发布/订阅的云原生消息分发服务;Azure Functions,这是一个无服务器选项,用于执行事件驱动代码;以及 Azure Kubernetes Service,这是一个托管的容器服务。由于该应用程序是全新开发的,因此没人真正知道运行数据库所需的计算容量是多少。
MagicChoc 的 DBA 团队人手紧张。他们是一个小团队,除了目前在 MagicChoc 进行的大量项目外,他们还需要解决多个运营问题,主要是围绕性能调优。首席 DBA 可以看到拥有完全云原生应用的好处,但他们没有推荐使用 Azure SQL 数据库,而是建议在 Azure 中构建一个 SQL Server 虚拟机。这是一个错误,而且仍然相当常见。问题在于许多 DBA 仍然不愿意接受云产品。我注意到这种立场有两个常见原因。第一个是缺乏或被认为缺乏云技能,同时不愿意学习全新的技术栈。第二个原因是担心 SQL 云产品会使他们失去工作。
这些恐惧中的第一个在某种程度上取决于个人。学习一个新的技术栈总是一项艰巨的任务,但云计算不会消失,作为数据库专业人士,我们可以选择适应,或者像渡渡鸟一样被历史淘汰。然而,这些恐惧中的第二个显然不是真的。云计算会改变数据库管理员所需的技能,但它绝不会让数据库管理员变得多余。
提示:DBA们也应该放心,尽管 SQL Azure 与在数据中心运行的实例相比有很大的飞跃,但其基础的数据库引擎与他们熟悉的数据库引擎非常相似。
在我们的具体情境中,DBA 团队面临很大压力。他们需要处理高价值、高技能的工作,例如诊断和解决性能问题,以及协助业务开展需要新数据库的项目。通过避免使用 DBaaS,DBA 们只是给自己增加了又一个需要管理、配置、解决补丁失败、安排停机以及处理其他所有琐碎工作的实例。如果他们选择了 DBaaS 服务,那么他们就会有更多时间专注于更高价值的工作。
在这种情况下选择 Azure SQL 数据库的另一个好处是自动缩放。在我们的场景中,计算能力尚不确定。如果我们使用无服务器计算层构建 Azure SQL 数据库,就可以实现自动缩放。这将释放更多时间,因为我们对合适的资源配置不必过于担心。通过指定要使用的最大 vCore 数量,我们可以避免成本失控。同时,通过设置最少 vCore 数量,也可以避免数据库扩展过度。列表 8.5 中的脚本使用 PowerShell 创建一个新的 Azure SQL 数据库,该数据库可以在 2 到 16 个 vCore 之间自动缩放。代码使用了一种称为 splatting 的技术,通过从哈希表向命令传递参数,使代码更易读。
$sqlAdminName = ‘MagicChocAdmin’
$sqlAdminPassword = ‘Passw0rd!’
$credentials = $(New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $sqlAdminName, $(ConvertTo-SecureString -String $sqlAdminPassword -AsPlainText -Force))
$serverParameters = @{
ServerName = ‘processautomationsql’
Location = ‘eastus2’
SqlAdministratorCredentials = $credentials
ResourceGroupName = ‘MagicChocApps’
}
New-AzSqlServer @serverParameters
$databaseParameters = @{
ResourceGroupName = ‘MagicChocApps’
ServerName = ‘processautomationsql’
DatabaseName = ‘AutoPro’
Edition = ‘GeneralPurpose’
ComputeModel = ‘Serverless’
ComputeGeneration = ‘Gen5’
MinimumCapacity = 2
Vcore = 16
}
New-AzSqlDatabase @databaseParameters
虽然 DBaaS 并不适用于每一个数据库需求,但它是 DBA 工具库中一个强大的工具。它不应因为恐惧而被忽视,那些计划在未来几年乃至几十年内继续从事数据库工作的专业人员应该花时间学习并接受云原生产品。
错误39# 安装所有功能
通过 GUI 安装 SQL Server 时,很容易且极具诱惑去进行我所称的“下一步,下一步,安装”的安装。这是指有人在安装向导的每一页上点击下一步,接受默认设置(我们将在下一节中详细讨论这个),然后在“要安装的功能”页面上选择所有功能。
当我们从命令行安装 SQL Server 时,指定 /ROLE 参数为 AllFeatures_WithDefaults 也非常简单且很诱人。这将具有与在 GUI 安装中从列表中选择所有功能相同的效果。
当然,我在专业环境中并没有遇到很多进行“下一步,下一步,安装”式安装的人,但我确实遇到了很多团队,其标准是安装所有功能。让我们来看看这可能的原因。
MagicChoc 的一个开发团队联系了 DBA 团队,要求提供一台安装了 SQL Server 的新虚拟机。DBA 团队询问他们需要哪些功能,开发人员表示他们不确定。“我们能一开始就装上所有功能吗,因为我们还没有设计整个系统?”
几个月后,项目即将完成,团队要求建立一台生产服务器。“我们希望它和开发服务器完全一样,因为我们知道那台服务器是可行的。”
DBA 团队通常倾向于采取阻力最小的路径,只是随便批准这类请求。毕竟,这能造成什么伤害呢,对吧?在某些情况下,DBA 团队只是按照公司标准在所有情况下建立一个包含所有功能的 SQL Server 实例。这是因为如果将来需要任何新功能,这样可以减少工作量。然而,这种做法是一个错误——特别是在生产环境中。
SQL Server 产品堆栈是一个大型的应用程序套件,每个应用程序都作为其自己的服务运行。服务是后台运行的应用程序。如果我们安装所有功能,那么最终会安装以下服务:
- SQL Server Database Engine
- SQL Server Agent
- PolyBase Engine
- PolyBase Data Movement
- Analysis Services
- SQL Browser
- SQL Server Full Text
- Integration Services
我们还将安装主数据服务和数据质量客户端应用程序。如果我们安装的是旧版本的 SQL Server,我们还将安装整个工具套件(2019 及以下版本),甚至可能还会安装报表服务(2016 及以下版本)。
这是大量的服务和应用程序。这带来了两个问题。第一个问题是服务在运行时会消耗资源,即使它们没有被使用。因此,通过运行不需要的服务,我们正在消耗本可以被我们正在使用的功能使用的资源。
提示 当然,我们可以通过将不需要的服务保持在停止状态来解决这个问题,但我们为什么要额外做这些工作呢?这也无法解决使用额外磁盘容量的问题。虽然这并不是大量的空间,并且通常不是大问题,但在某些情况下,这可能会决定是否需要调整磁盘大小。
运行如此数量的服务的第二个、更加严重的问题与安全性有关。服务器上安装的服务越多,服务器的攻击面就越大。如果恶意行为者找到方法利用我们服务器上运行的某个服务,他们可能能够横向访问其他服务器。因此,最好只安装我们需要的功能,这是一个良好的做法。
提示 与安全性相关的另一个考虑因素是打补丁。如果你安装了额外的 SQL Server 功能,这些功能在不需要时也会以自己的服务运行,那么它们仍然需要打补丁。这会增加对不必要服务的维护工作量。
可以从 SQL Server 2022 安装向导中安装的完整功能列表可以在表 8.1 中找到。
| Feature | Parent feature | Feature type | Description |
| Database Engine Services | N/A | Instance level | Provides core relational database functionality |
| SQL Server Replication | Database Engine Services | Instance level | Allows data to be disbursed between disparate instances using a publisher/subscriber model |
| Machine Learning Services and Language Extensions | Database Engine Services | Instance level | Supports distributed machine learning solutions with support for R and Python |
| Full-Text and Semantic Extractions for Search | Database Engine Services | Instance level | Provides advanced searching and matching functionality inside binary data, as well as textual columns with features such as fuzzy matching and thesaurus |
| Data Quality Services | Database Engine Services | Instance level | Core DQS functionality, including data quality functionality and storage |
| PolyBase Query Service for External Data | Database Engine Services | Instance level | Allows for multiple heterogeneous data sources to be queried |
| Analysis Services | N/A | Instance level | Provides multidimensional and tabular data modeling and querying functionality |
| Data Quality Client | N/A | Shared between all instances on server | A standalone application used to interact with DQS Services and both prepare and clean data |
| Integration Services | N/A | Shared between all instances on server | An extract, transform, and load tool used to orchestrate data ingestion and transformation, as well as exports to other systems. Further details can be found in chapter 6. |
| Scale Out Master | Integration Services | Shared between all instances on server | SSIS Scale Out can reduce bottlenecks by horizontally scaling the execution of packages. The Scale Out Master is responsible for the management of this scale out. |
| Scale Out Worker | Integration Services | Shared between all instances on server | The Scale Out Workers execute tasks that they have retrieved from the Scale Out Master. |
| Master Data Services | N/A | Shared between all instances on server | Allows you to create models that allow your data to be mastered across the enterprise. This is very useful in sprawling organizations, where different departments have different terminology for the same data item, as it allows you to map these terms to a single source of truth. |
熟悉极限编程理念的你们应该对 YAGNI 原则很熟悉。YAGNI 是“You Aren’t Going to Need It”(你不会需要它)的缩写,旨在消除开发中的低效。同样的原则也应适用于 SQL Server 的安装。
错误40# 不编写 SQL Server 安装脚本
手动安装 SQL Server 然后配置实例以满足最佳实践指南是繁琐的。这也容易出错。即使 DBA 团队有详细的 SQL Server 实例安装和配置操作手册,如果有多人手动安装多个实例,随着时间的推移错误还是会发生,我们的环境最终会变得不一致,这使得维护变得更加困难。
让我们以 MagicChoc 为例。它的 DBA 团队管理着 120 个 SQL Server 实例,这些实例分布在 100 台虚拟机上。其中一些在本地,其他则在云端。他们有一个构建标准和详细的构建操作手册,但每个实例都是手动构建和配置的。构建标准的高层次方面如下:
- 使用适当的版本安装默认实例,但如果服务器要有多个实例,则可以通过实例名称覆盖默认实例。
- 强化实例。
- 除非特别需要其他功能,否则仅安装数据库引擎。
提示 在你的环境中,我强烈建议你也考虑性能优化。这些优化将涉及操作系统和 SQL Server 两个层面。我们将在第10章讨论许多这些选项。
不幸的是,最近对实例的审计显示,这些领域在所有服务器上都没有得到持续应用。这是因为,多年来,多位数据库管理员在匆忙构建实例时未能彻底遵循操作手册。错误在于期望数据库管理员手动安装和配置实例。
与其手动安装和配置实例,DBA 团队可以采用脚本化的方法。使用这种方法,一个通常用 PowerShell 编写的脚本将安装和配置实例。这意味着当需要新的 SQL Server 实例时,DBA 只需运行一个可重用的脚本,就完成了任务。这样不仅提高了一致性,还减少了构建实例所需的大量时间和精力,使 DBA 能够专注于更高价值的工作。
Gold images
有些人仍然使用“Gold images”方法进行 SQL 安装。在这种方法中,将创建一个预安装了 SQL Server 的 Windows Server 映像。然而,脚本化方法要灵活得多。
Gold images当然能提高一致性,但可能有点过头。它们往往导致所有 SQL 实例都安装为企业版,并且所有实例都配置为联机事务处理(OLTP),即使公司有许多数据仓库。
解决方法是拥有多个Gold image,但这会产生大量工作——例如,当镜像需要更新时,比如升级以使用最新的服务包。
因此,我建议优先采用脚本方法,而不是Gold image。通过使用可以传递给脚本的参数,更容易在一致性和灵活性之间取得合适的平衡。
让我们看看如何通过创建一个 PowerShell 脚本来改进这一过程,该脚本将安装 SQL Server 实例,运行一些基本的冒烟测试,然后配置该实例。不过,首先,让我们思考一下我们的构建标准可能是什么,以确保我们的实例是加固的:
- 禁用远程访问
- 重命名 sa 账户
警告 在此示例中,我们仅会进行两项加固配置。这是为了示例的清晰和简洁。在您的环境中,应考虑许多加固配置。我建议参考 SQL Server 2022 的互联网安全中心(CIS)基准,该基准可从 CIS 获取,网址为 https://mng.bz/eV0Q。
除了强化实例之外,我们还需要考虑所需的版本。对于开发机器,我们希望安装开发者版本,而对于生产实例,我们希望能够在企业版和标准版之间进行选择。
所以让我们先考虑一下希望传递给脚本的参数。根据我们的配置选项,我们希望能够传递用于运行数据库引擎和 SQL Server 代理的服务帐户的用户名和密码。我们希望传递版本信息,也希望传递我们为 sa 帐户选择的名称和密码。因此,我们需要在脚本顶部创建一个 param 块,以便脚本知道要预期哪些参数。我们还需要接受实例名称的参数,但由于标准行为(符合我们的要求)应该是安装默认实例,而命名实例应为例外,因此我们将为该参数指定 MSSQLSERVER 的默认值。这意味着将安装默认实例,除非我们在执行时通过手动提供参数值来特意覆盖该值。
我们脚本执行的第一个任务是安装 sqlserver PowerShell 模块。这将使我们能够在脚本的后面运行 Invoke-SqlCmd。我们可以使用 Install-Module cmdlet 来运行它。
我们的第二个任务是根据 edition 参数确定 $pid 变量的值。SQL Server 安装程序根据产品密钥来决定安装哪一版 SQL Server。因此,产品密钥必须传递给 /PID 参数。如果没有传递产品密钥,安装程序将默认为评估版,如果在试用期结束后没有升级,它将停止工作。
警告 在真实环境中,产品密钥,也称为产品 ID(PID),理想情况下应存储在密码保险库中,并由脚本从保险库中读取。这可以避免公司特定的详细信息被存储在源代码管理中。
许多组织拥有批量许可密钥。这意味着他们将为所有的 SQL Server 安装使用相同的密钥。因此,我们可以通过将产品密钥映射到一个版本来简化安装过程。然后,对于每次安装,数据库管理员只需提供他们想要安装的版本值,而不必每次都去找出一个批量许可密钥。
警告 示例脚本中用于企业版和标准版的产品密钥 00000-00000-00000-00000-00000 实际上是评估版的产品密钥。预期您在执行之前将此密钥替换为贵组织的适当产品密钥。
接下来,我们将通过调用 setup.exe 来安装 SQL Server。脚本假设您已经下载了安装介质并且可用,并且脚本是在存放安装介质的文件夹中调用的。该命令接受我们传递给脚本的大多数参数:实例名称、服务账户名称及密码,以及版本。我们还传递了 /IACCEPTSQLSERVERLICENSETERMS 和 /Q 参数,这些参数是接受许可条款并执行静默安装所必需的。对于无人值守安装,这两个参数都是必需的。该命令还使用了 $pid 参数,这是我们根据 $edition 参数计算得出的,并且我们将向 /SECURITYMODE 参数传递值 SQL 以启用混合模式身份验证。这意味着我们还必须传递 sa 账户的密码。
注意 安装完成后,sa 账户将使用其默认名称。我们将在脚本中稍后更改它。
实例安装完成后,我们应该运行一些简单的冒烟测试以验证安装情况。最后,我们将使用 Invoke-SqlCmd 工具来配置实例的加固。第一个 sqlcmd 命令禁用远程访问。这会禁用允许通过链接服务器从远程服务器运行本地存储过程及其反向操作的已弃用功能。第二个命令将 sa 账户的名称更改为我们将作为参数传递给脚本的名称。这么做的理由是 sa 是管理员账户的常用名称。由于 sa 会在二级身份验证过程中使用,将其更改为一个新名称可以降低恶意行为者通过暴力破解攻击实例以获取管理员权限的风险。
清单 8.6 中的脚本将所有这些组件整合到一个脚本中,DBA 团队每次需要安装和配置新的 SQL Server 实例时都可以执行该脚本。
提示:不要忘记更改 PID 以反映您组织的产品密钥。
[CmdletBinding()]
param(
[string] $SQLServiceAccount,
[string] $SQLServiceAccountPassword,
[string] $AgentServiceAccount,
[string] $AgentServiceAccountPassword,
[string] $SaName,
[string] $SaPassword,
[string] $edition,
[string] $InstanceName = ‘MSSQLSERVER’
)
if ($edition -eq ‘Developer’) {
$sqlPid = ‘22222-00000-00000-00000-00000’
} elseif ($edition -eq ‘Standard’) {
$sqlPid = ‘00000-00000-00000-00000-00000’
} elseif ($edition -eq ‘Enterprise’) {
$sqlPid = ‘00000-00000-00000-00000-00000’
}
If(-not(Get-Module NuGet -ErrorAction silentlycontinue)){
Install-Module NuGet -Confirm:$False -Force
} #A
If(-not(Get-Module SQLServer -ErrorAction silentlycontinue)){
Install-Module SQLServer -Confirm:$False -Force -AllowClobber
} #B
./setup.exe /ACTION=Install /FEATURES=SQLENGINE /INSTANCENAME=$InstanceName /SQLSVCACCOUNT=$SQLServiceAccount /SQLSVCPASSWORD=$SQLServiceAccountPassword /AGTSVCACCOUNT=$AgentServiceAccount /AGTSVCPASSWORD=$AgentServiceAccountPassword /PID=$sqlPid /IACCEPTSQLSERVERLICENSETERMS /Q /SECURITYMODE=SQL /SAPWD=$SaPassword /SQLSYSADMINACCOUNTS=Administrator #C
if ($InstanceName -ne ‘MSSQLSERVER’) { #D
$ServiceName = ‘MSSQL$’ + $InstanceName
$ServerInstance = ‘localhost\’ + $InstanceName
} else {
$ServiceName = $InstanceName
$ServerInstance = ‘localhost’
}
$ServiceStatus = Get-Service -servicename $ServiceName
if ($ServiceStatus.Status -eq ‘Running’) {
$output = “The service for SQL Server instance: {0} is Running” -f $InstanceName
Write-Output $output
} else {
$output = “The service for SQL Server instance: {0} is NOT Running. Script terminating” -f $InstanceName
Write-Output $output
exit
}
$ServerName = Invoke-Sqlcmd -ServerInstance $ServerInstance -query ‘SELECT @@SERVERNAME ;’ -Username ‘sa’ -Password $SaPassword
if ($ServerName -ne $null) {
$output = “The SQL Server instance: {0} is accessible” -f $InstanceName
Write-Output $output
} else {
$output = “The SQL Server instance: {0} is NOT accessible. Script terminating” -f $InstanceName
Write-Output $output
exit
} #E
Invoke-Sqlcmd -ServerInstance $ServerInstance -Query “EXEC sp_configure ‘show advanced options’, 1 ; RECONFIGURE ; EXEC sp_configure ‘remote access’, 0 ; RECONFIGURE ; EXEC sp_configure ‘show advanced options’, 0 ; RECONFIGURE ;” -Username ‘sa’ -Password $SaPassword #F
$Query = “ALTER LOGIN sa WITH NAME = {0}” -f $SaName
Invoke-Sqlcmd -ServerInstance $ServerInstance -Query $Query -Username ‘sa’ -Password $SaPassword #G
如果将脚本保存为 InstallSQLServer.ps1 到包含安装介质的文件夹根目录中,则可以使用清单 8.7 中的命令执行它。
提示 该脚本需要以管理员身份运行。
./InstallSQLServer.ps1 -SqlServiceAccount ‘sqlServiceAccount’ -SqlServiceAccountPassword ‘Pa$$w0rd’ -AgentServiceAccount ‘sqlServiceAccount’ -AgentServiceAccountPassword ‘Pa$$w0rd’ -SaName ‘SQLAdmin’ -SaPassword ‘Pa££w0rd’ -Edition ‘Developer’
自动化 SQL Server 安装应该是每个 DBA 待办事项清单的首要任务。它可以减少手工操作并促进标准化。它还带来其他优势,例如能够将构建存储在 GitHub 中,提供版本控制和简单的变更机制。
错误41# 认为配置管理不适用于 SQL Server
自动化 SQL Server 安装的主要原因之一是为了促进一致性。这对于使我们的企业可支持以及确保我们的安全基线到位非常重要。问题是,在我们的构建完成后,拥有适当访问权限的任何人都可以轻松更改它。
例如,假设我们刚刚创建了一个 SQL Server 实例。它配置正确,并符合 CIS 第一级标准。不幸的是,在创建实例几天后,一名初级 DBA 启用了 xp_cmdshell。我们将在第14章中更详细地讨论这个扩展存储过程,但目前你只需要了解两点。首先,它允许从 SQL Server 实例中执行操作系统命令。其次,它是一个严重的安全漏洞,不应启用。
所以在实例刚建立几天后,它就不再处于预期状态,并且存在一个实时的安全漏洞。我们可以部分地通过正确限制权限和审查活动来处理这个问题。然而,这两种方法都不能完全解决问题。
一个完整的解决方案是应用一种称为配置管理的技术。这是一种在服务器首次构建时完全应用配置的技术,但配置随后会定期进行评估。如果评估确定发生了漂移,那么该漂移将被自动修复。因此,如果配置管理每30分钟评估一次我们服务器的状态,那么诸如安全漏洞之类的误配置将在发生后的0到30分钟之间自动解决。
配置管理在 Linux 上已经流行了十多年,并且是许多 DevOps 环境的关键。它在 Windows 环境中的使用已经增加了若干年,但仍然没有像在 Linux 环境中那样普遍使用。有多种配置管理工具可用,其中一些最受欢迎的包括 Puppet、Ansible 和 PowerShell 期望状态配置(DSC)。
在最基本的层面上,这些工具使用以下概念:
- 资源是一个代码单元,用于评估和配置特定服务器配置的当前状态。此配置可以是从注册表项到文件夹,甚至是软件的安装。每个资源将具有以下方法:
- 一种测试方法,用于确定当前配置是否正确。测试方法通常在每次评估资源时执行。
- 一个设置方法,如果配置不处于期望状态,则更新配置。通常只有在测试方法发现偏差时才运行此方法。
- 清单,用于列出必须运行以配置服务器的资源,以及应传递给这些资源的值。
图 8.3 中的示意图说明了这一点。它展示了一个 DSC 配置被应用到托管 SQL Server 实例的多个服务器上。图中显示了在每台服务器上执行的过程,以实施禁用 xp_cmdshell 的最佳做法。每 30 分钟,DSC 测试函数会运行并检查 xp_cmdshell 是否已启用。如果发现所需状态(禁用)已达到,则退出该过程并继续处理清单中的下一个配置。然而,如果配置未达到所需状态,它会运行设置函数以禁用此功能。
配置管理是一种安装和配置 SQL Server 实例的有效方法。然而问题在于,许多 DBA 要么不熟悉它,要么因为不熟悉相关概念而未能使用它。这是一个错误。使用配置管理不仅可以减少工作量,使企业管理更轻松、更一致,还可以在合规性和安全性等方面提供帮助。
虽然对 PowerShell DSC 的全面讨论超出了本书的范围,因为它本身就值得有一本书专门讲解,但让我们来探讨如何创建一个简单的 DSC 管理对象格式(MOF)文档,这是 DSC 对清单的实现方式。我们创建的 MOF 将确保创建一个 SQL 实例。然后,它将禁用远程访问,并为名为 Pete 的本地 Windows 用户创建一个 SQL 登录。接下来,我们将探讨如何编译并应用该配置。
不过,在我们开始之前,让我们先进行设置。我们需要安装 SqlServerDsc PowerShell 模块,这可以通过下面列表中的脚本来实现。
Install-Module SqlServerDsc
提示 如果我们想配置操作系统,我们还应该安装 PSDscResources PowerShell 模块。
我们将创建的配置称为 InstallSql,并接受用于实例名称的参数(默认为默认实例)以及我们想要安装的版本。配置中的第一条语句导入 SqlServerDsc 模块。在创建配置时,导入将要使用的模块被认为是良好的实践。然后,我们根据版本确定应使用的 PID。这使用了与上一节中相同的逻辑。
然后我们将定义一个节点。这是我们希望运行配置的服务器的名称。在我们的例子中,我们只为本地主机定义了一个节点,但在更复杂的例子中,我们可以创建一个中央 DSC 推送服务,它将把配置推送到多个服务器。在这种情况下,我们可以定义多个节点。
在节点定义中,我们将定义三个 DSC 资源。这些资源中的第一个确保 SQL Server 实例已被创建。如果实例存在,则该资源不会执行任何操作;如果实例缺失,则该资源将创建它。
以下两个资源分别禁用远程访问并为 Pete 创建登录。如果这些资源在实例创建之前被执行,那么它们当然会报错,因为这些资源将无法连接到实例。因此,使用 DependsOn 属性来确保它们在实例存在之前不会被执行。可以在以下列表中查看该配置。
Configuration InstallSql {
param (
$SqlInstanceName = ‘MSSQLSERVER’,
$Edition
)
Import-DscResource -ModuleName SqlServerDsc
if ($Edition -eq ‘Developer’) {
$ProductKey = ‘22222-00000-00000-00000-00000’
} elseif ($edition -eq ‘Standard’) {
$ProductKey = ‘00000-00000-00000-00000-00000’
} elseif ($edition -eq ‘Enterprise’) {
$ProductKey = ‘00000-00000-00000-00000-00000’
}
node localhost {
SqlSetup ‘InstallInstance’ {
InstanceName = $SqlInstanceName
Features = ‘SQLENGINE’
SourcePath = ‘C:\SQL Media’
SQLSysAdminAccounts = @(‘Administrator’)
ProductKey = $ProductKey
}
SqlConfiguration ‘RemoteAccess’ {
InstanceName = $SqlInstanceName
OptionName = ‘remote access’
OptionValue = 1
DependsOn = ‘[SqlSetup]InstallInstance’
}
SqlLogin ‘AddSqlAdmin’ {
Ensure = ‘Present’
Name = ‘Pete’
InstanceName = $SqlInstanceName
LoginType = ‘WindowsUser’
DependsOn = ‘[SqlSetup]InstallInstance’
}
}
}
现在我们已经定义了配置,我们需要将其编译,这将生成 MOF 文件。为了编译配置,我们首先需要点源该文件,将其加载到当前上下文中。然后我们将运行 InstallSql 配置,像对 cmdlet 一样传递参数值。因此,假设我们将配置保存为 c:DSC 文件夹中的 SqlInstallDsc.ps1,清单 8.10 中的脚本将编译 MOF。
提示 如果你一直在跟随本章的示例,并且已经创建了 SQL Server 的默认实例,你可能希望修改本节中的代码示例以创建一个命名实例。这样可以避免卸载现有实例或使用不同的虚拟机。当然,你需要提供你自己的文件路径。
. c:\DSC\SqlInstallDsc.ps1
InstallSql -Edition Developer
在工作目录中将创建一个以配置命名的文件夹。在此文件夹中,我们可以找到已编译的 MOF 文件。由我们的编译创建的 MOF 文件是
/*
@TargetNode=’localhost’
@GeneratedBy=Administrator
@GenerationDate=11/05/2023 11:49:28
@GenerationHost=EC2AMAZ-43B3PBE
*/
instance of DSC_SqlSetup as $DSC_SqlSetup1ref
{
SourcePath = “C:\\SQL Media”;
InstanceName = “MSSQLSERVER”;
ProductKey = “22222-00000-00000-00000-00000”;
SourceInfo = “C:\\dsc\\SqlInstallDsc.ps1::18::11::SqlSetup”;
ResourceID = “[SqlSetup]InstallInstance”;
ModuleName = “SqlServerDsc”;
SQLSysAdminAccounts = {
“Administrator”
};
ModuleVersion = “16.5.0”;
Features = “SQLENGINE”;
ConfigurationName = “InstallSql”;
};
instance of DSC_SqlConfiguration as $DSC_SqlConfiguration1ref
{
ResourceID = “[SqlConfiguration]RemoteAccess”;
InstanceName = “MSSQLSERVER”;
SourceInfo = “C:\\dsc\\SqlInstallDsc2.ps1::26::11::SqlConfiguration”;
OptionValue = 1;
ModuleName = “SqlServerDsc”;
OptionName = “remote access”;
ModuleVersion = “16.5.0”;
DependsOn = {
“[SqlSetup]InstallInstance”};
ConfigurationName = “InstallSql”;
};
instance of DSC_SqlLogin as $DSC_SqlLogin1ref
{
ResourceID = “[SqlLogin]AddSqlAdmin”;
InstanceName = “MSSQLSERVER”;
Ensure = “Present”;
SourceInfo = “C:\\dsc\\SqlInstallDsc2.ps1::34::11::SqlLogin”;
Name = “Pete”;
ModuleName = “SqlServerDsc”;
LoginType = “WindowsUser”;
ModuleVersion = “16.5.0”;
DependsOn = {
“[SqlSetup]InstallInstance”};
ConfigurationName = “InstallSql”;
};
instance of OMI_ConfigurationDocument
{
Version=”2.0.0″;
MinimumCompatibleVersion = “1.0.0”;
CompatibleVersionAdditionalProperties=
{“Omi_BaseResource:ConfigurationName”};
Author=”Administrator”;
GenerationDate=”11/05/2023 11:49:28″;
GenerationHost=”EC2AMAZ-42B3QBE”;
Name=”InstallSql”;
};
可以使用列表 8.11 中的命令将目录应用到服务器。然后可以将此命令添加到计划任务中,该任务将按计划运行,并确保服务器始终按要求进行配置。
Start-DscConfiguration -Path ‘C:\dsc\InstallSql’ -Verbose
提示 我们不局限于 SqlServerDsc 模块中提供的 DSC 资源。DSC 是完全可扩展的,我们可以创建自己的自定义 DSC 资源。虽然这超出了本书的范围,但我鼓励您去探索。作为起点,《Windows PowerShell 实战》第三版中有一章专门介绍 DSC,可以在 https://mng.bz/px5z 找到,或者查看微软提供的一个非常基础的入门教程,可以在 https://mng.bz/OmNE 找到。
配置管理是一种强大的工具,DBA 应该将其视为通过确保 SQL 系统一致性来减少管理开销的一种手段。这是现代化的自动化方法,并且是完全可扩展的,无论我们采用哪种框架。
提示 如果您的组织使用 Azure,那么可以通过 Azure 自动管理机器配置(以前称为 Azure 策略来宾配置)将 DSC 应用于启用 Azure Arc 的服务器。
错误42# 使用 SQL Server 云镜像而不修改它们
所有主要的云服务提供商都提供预装了 SQL Server 的镜像。这使得在云中快速启动 SQL Server 虚拟机变得非常容易。如果我们希望使用包含许可的 SQL Server 付费模式,使用云提供的镜像也非常重要。在这种模式下,我们无需自带 SQL Server 许可,许可成本已包含在虚拟机的小时费率中。要使用包含许可的模式,我们必须使用云提供商的 SQL Server 镜像,因为正是它触发了许可的包含。
组织使用提供的此镜像非常普遍,以便在需要新的 SQL Server 虚拟机时,只需在其选择的云中快速创建一个新的虚拟机。然而,这是一个错误。
为了说明为什么这是一个错误,让我们回想一下本章中已经讨论过的一些内容。例如,我们已经讨论过为什么不应该安装所有的 SQL Server 功能,而是应将安装限制在仅所需的功能上。我们还讨论了使用配置管理以保持服务器和 SQL Server 实例的期望配置。在第 10 章中,我们还将讨论为什么应该避免使用跟踪标志 1117 和 1118。
尽管有这些良好的做法,如果我们在 AWS 上构建一个新的 SQL Server EC2 实例,我们会注意到所有功能都已安装。这包括 SSMS,它实际上应该作为客户端工具使用,而不是安装在服务器上。图 8.4 中的图片取自使用 AWS 提供的 SQL Server AMI 新建的 EC2 实例。
在 Azure 中,情况更糟。不仅所有功能和工具都会被安装,而且 SQL Server 实例上还会配置跟踪标志 T1117 和 T1118。图 8.5 的图片取自使用 Azure 提供的虚拟机镜像新建的 Azure 虚拟机。图片显示了 SQL Server 配置管理器,所有 SQL 服务均在运行,并且数据库引擎服务的启动参数已展开以显示已配置的跟踪标志。
为什么云提供商会这样做?答案是,这是试图让所有客户无论其需求如何都能轻松使用。然而,这也带来了我们在本章前面讨论过的缺点。更重要的是,因为 SQL Server 实例已经集成在镜像中,所以它完全可能发生漂移。
这意味着直接使用云提供商的 SQL Server 镜像可能被认为是一个错误——而且是非常常见的错误。避免这个错误的方法,同时仍然保持许可合规,是创建我们自己的自定义镜像,但将该镜像基于云提供商的 SQL Server 镜像。
为此,我们可以基于云提供商的 SQL Server 镜像创建一个新的虚拟机,然后根据我们的需求进行自定义。例如,如果我们不需要某些组件,可以卸载诸如分析服务(Analysis Services)和集成服务(Integration Services)等组件。我们还可以将实例配置为符合 CIS 标准。我们甚至可以创建一个 DSC MOF,以确保实例保持我们所需的配置。
一旦我们完成了对虚拟机的修改,就可以基于我们的虚拟机创建一个新的镜像。这个过程在不同的云提供商之间有所不同,但通常都非常简单。例如,在 Azure 中,我们可以在 Azure 门户中导航到虚拟机,然后从顶部菜单中选择“捕获”选项。这将显示“创建镜像”页面,我们可以在此配置镜像的属性,例如资源组,并决定是否将镜像共享到 Azure 计算图库,这将使其公开,或者我们是否希望将其保留为一个(私有的)托管镜像(这几乎肯定是你会选择的选项)。
或者,要从 AWS EC2 实例创建镜像,我们可以简单地在 AWS 控制台中导航到 EC2 实例。然后,右键点击 EC2 实例,并从上下文菜单中选择“镜像和模板 > 创建镜像”。这将显示“创建镜像”窗口。在这里,我们可以为镜像命名并添加标签。我们还可以添加额外的卷并配置卷的大小。
警告 如果你使用云端图像创建,请注意 SQL Server 非常昂贵,当它包含在虚拟机的每小时费用中时,价格可能会累积。确保在不使用实例时将其关闭,并在不再需要时终止/删除它们。
在云中构建 SQL Server 虚拟机时,我们不应直接使用云提供商的镜像。相反,我们应该修改服务器以满足我们的需求,然后创建我们自己的镜像。
总结:
- 在构建 SQL Server 实例时,使用有意义的实例名称非常重要,以便使环境易于识别并避免混淆。
- 适当地为实例命名在某种程度上可以说是一种艺术多于科学。
- 在规划部署时,考虑将 Linux 作为可行的操作系统。
- SQL Server 2022 支持在 Red Hat、SUSE 和 Ubuntu 上运行。
- 考虑使用 SQL Server 容器,而不是假设 SQL Server 始终应该安装在虚拟机或裸机上——尤其是在大型开发环境中。
- 在容器中使用 SQL Server 时,使用 Docker 卷将数据存储在容器外部。这可以确保即使容器被移除,数据仍能被保留。
- SQL Server 在 Linux 容器上完全受支持。目前它在 Windows 容器上不受支持,但如果我们自己创建容器镜像,Windows 容器仍然可以用于非生产环境中的 SQL Server。
- 在规划 SQL Server 安装时,应考虑使用 Server Core。默认情况下不应在带有桌面体验的 Windows Server 上安装 SQL Server。除非有特定原因需要 GUI,否则 Server Core 是一个不错的选择。
- 没有图形用户界面时,服务器核心比带有桌面体验的 Windows 服务器更高性能、更安全。
- SQL Server 企业版价格昂贵,应仅在生产环境中需要企业级功能的情况下使用。
- 在生产环境中适当使用标准版。
- 在非生产环境中使用开发者版本。
- 在规划 SQL Server 部署时,应考虑云提供商的 DBaaS 服务。它们可以减少管理负担,因为我们不需要管理操作系统或 SQL Server 实例。
- 虽然云原生 SQL Server 产品有可能改变 DBA 所需的技能,但它们并不能消除对 DBA 的需求。因此,DBA 不应害怕云。
- 只安装所需的功能,而不是所有功能。这将减少安全漏洞并避免不必要的资源消耗。
- 手动安装 SQL Server 耗时且容易出错。
- 自动化 SQL Server 安装可以节省管理开销,并使系统环境更易于管理。
- 编写部署脚本只能确保在构建时的一致性和良好实践。部署后可能会发生偏移。
- 使用配置管理技术可以使我们在应用程序的整个生命周期内保持服务器和 SQL Server 实例的正确配置。
- SQL Server 可以使用配置管理工具进行配置,例如 PowerShell DSC 和 Puppet。
- 使用配置管理有助于我们遵守安全要求,并减少 SQL Server 资产的管理开销。
- 配置管理工具包括 Ansible 和 Puppet。微软还在 PowerShell 中提供配置管理。这被称为 PowerShell DSC。
- PowerShell DSC 是完全可扩展的,如果需要,可以创建自定义 DSC 资源。
- 预先加载了 SQL Server 的云镜像具有所有功能已安装,这会消耗额外资源并增加 SQL Server 实例的攻击面。
- 基于供应商提供的镜像创建自定义云镜像,并使用自定义镜像代替供应商提供的镜像。
- 当需要“包含许可”许可模式时,自定义镜像必须基于供应商提供的镜像。这确保了 SQL Server 许可证的费用包含在虚拟机的每小时费用中。




