SQL Server on Linux 安装与管理
大约 13 分钟约 3993 字
SQL Server on Linux 安装与管理
简介
SQL Server 自 2017 版本开始正式支持 Linux 操作系统,使得 .NET 开发者可以在 Linux 服务器上使用熟悉的 SQL Server 数据库。SQL Server on Linux 与 Windows 版本在核心数据库引擎功能上基本一致,支持 T-SQL、存储过程、触发器、视图等全部功能。对于 .NET 技术栈的团队来说,在 Linux 上使用 SQL Server 既可以享受 Linux 的稳定性和低成本,又能保持与 Windows 开发环境的一致性。
本文以 SQL Server 2019 为例,介绍在 CentOS/RHEL 上的安装、配置、数据库管理、用户权限管理、备份恢复、性能调优以及从 .NET 应用连接数据库等内容。
特点
优点
缺点
一、安装 SQL Server 2019
参考微软官方文档:https://learn.microsoft.com/zh-cn/sql/linux/quickstart-install-connect-red-hat?view=sql-server-ver15
下载存储库配置
# 下载 SQL Server 2019 Red Hat 存储库配置文件
sudo curl -o /etc/yum.repos.d/mssql-server.repo https://packages.microsoft.com/config/rhel/7/mssql-server-2019.repo安装 SQL Server
# 安装 mssql-server 包
sudo yum install -y mssql-server运行配置向导
# 运行 mssql-conf setup 进行初始化配置
sudo /opt/mssql/bin/mssql-conf setup配置向导中的选择:
| 步骤 | 选择 | 说明 |
|---|---|---|
| 选择版本 | 2(Developer) | 免费开发版,功能等同企业版 |
| 选择语言 | 10(中文简体) | 中文界面和提示信息 |
| 设置 SA 密码 | 自定义强密码 | 至少 8 位,包含大小写字母、数字和特殊符号 |
SQL Server 版本说明
| 版本 | 说明 | 费用 |
|---|---|---|
| Evaluation | 180 天试用期,功能完整 | 免费 |
| Developer | 企业级功能,无硬件限制 | 免费(不可用于生产) |
| Express | 可用于生产,CPU 4 核、内存 1GB、数据库 10GB 限制 | 免费 |
| Standard | 标准功能集 | 付费 |
| Enterprise | 全功能版本 | 付费 |
验证服务状态
# 查看 SQL Server 服务状态
systemctl status mssql-server
# 查看 SQL Server 进程
ps -ef | grep sqlservr修改排序规则
# 停止 SQL Server 服务
systemctl stop mssql-server
# 设置排序规则(防止中文乱码)
sudo /opt/mssql/bin/mssql-conf set-collation
# 输入排序规则名称:Chinese_PRC_CI_AS
# 重新启动服务
systemctl start mssql-server常用排序规则说明:
| 排序规则 | 说明 |
|---|---|
| Chinese_PRC_CI_AS | 简体中文,不区分大小写,区分重音 |
| Chinese_PRC_CS_AS | 简体中文,区分大小写,区分重音 |
| SQL_Latin1_General_CP1_CI_AS | 拉丁文,不区分大小写(默认) |
防火墙设置
# 开放 SQL Server 默认端口 1433
sudo firewall-cmd --zone=public --add-port=1433/tcp --permanent
sudo firewall-cmd --reload
# 验证端口是否开放
firewall-cmd --list-ports二、安装命令行工具
安装 mssql-tools 和 sqlcmd
# 下载 Red Hat 存储库配置文件
sudo curl -o /etc/yum.repos.d/msprod.repo https://packages.microsoft.com/config/rhel/7/prod.repo
# 删除旧的 unixODBC 包(如果之前安装过)
sudo yum remove unixODBC-utf16 unixODBC-utf16-devel
# 安装 mssql-tools 和 unixODBC
sudo yum install -y mssql-tools unixODBC-devel配置环境变量
# 添加到登录配置文件(交互式会话)
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
# 添加到 bashrc(非交互式会话)
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
# 立即生效
source ~/.bashrc三、服务管理
systemctl 服务命令
# 启动 SQL Server
sudo systemctl start mssql-server
# 停止 SQL Server
sudo systemctl stop mssql-server
# 重启 SQL Server
sudo systemctl restart mssql-server
# 查看服务状态
sudo systemctl status mssql-server
# 设置开机自动启动
sudo systemctl enable mssql-server
# 取消开机自动启动
sudo systemctl disable mssql-servermssql-conf 配置管理
# 查看所有配置
sudo /opt/mssql/bin/mssql-conf list
# 设置 SA 密码
sudo /opt/mssql/bin/mssql-conf set-sa-password
# 设置默认数据目录
sudo /opt/mssql/bin/mssql-conf set filelocation.defaultdatadir /data/sqlserver/data
# 设置默认日志目录
sudo /opt/mssql/bin/mssql-conf set filelocation.defaultlogdir /data/sqlserver/log
# 设置内存限制(MB)
sudo /opt/mssql/bin/mssql-conf set memory.memorylimitmb 2048
# 设置 TCP 端口
sudo /opt/mssql/bin/mssql-conf set network.tcpport 1433
# 重启服务使配置生效
sudo systemctl restart mssql-server四、数据库管理
使用 sqlcmd 连接数据库
# 本地连接(使用 SA 账户)
sqlcmd -S localhost -U SA -P '<YourPassword>'
# 指定端口连接
sqlcmd -S localhost,1433 -U SA -P '<YourPassword>'
# 使用 Windows 认证(Linux 上不支持)
# 使用 SQL 认证
sqlcmd -S 192.168.1.100 -U SA -P '<YourPassword>'数据库基本操作
-- 创建数据库
CREATE DATABASE MyDatabase;
GO
-- 查看所有数据库
SELECT name, database_id, state_desc FROM sys.databases;
GO
-- 切换数据库
USE MyDatabase;
GO
-- 删除数据库
DROP DATABASE MyDatabase;
GO
-- 创建表
CREATE TABLE Users (
Id INT IDENTITY(1,1) PRIMARY KEY,
UserName NVARCHAR(50) NOT NULL,
Email NVARCHAR(100),
CreatedAt DATETIME2 DEFAULT GETDATE(),
IsActive BIT DEFAULT 1
);
GO
-- 插入数据
INSERT INTO Users (UserName, Email) VALUES (N'张三', 'zhangsan@example.com');
INSERT INTO Users (UserName, Email) VALUES (N'李四', 'lisi@example.com');
GO
-- 查询数据
SELECT * FROM Users;
GO数据库文件管理
-- 查看数据库文件信息
SELECT
DB_NAME(database_id) AS DatabaseName,
name AS LogicalName,
physical_name AS PhysicalPath,
size * 8 / 1024 AS SizeMB,
type_desc AS FileType
FROM sys.master_files;
GO
-- 增加数据库文件大小
ALTER DATABASE MyDatabase
MODIFY FILE (NAME = MyDatabase, SIZE = 512MB, FILEGROWTH = 64MB);
GO
-- 添加日志文件
ALTER DATABASE MyDatabase
ADD LOG FILE (
NAME = MyDatabase_log2,
FILENAME = '/var/opt/mssql/data/MyDatabase_log2.ldf',
SIZE = 128MB,
FILEGROWTH = 32MB
);
GO五、用户与权限管理
创建登录名(Login)
-- 创建 SQL 登录名
CREATE LOGIN myapp_user WITH PASSWORD = 'StrongPassword123!';
GO
-- 查看所有登录名
SELECT name, type_desc, is_disabled FROM sys.server_principals
WHERE type IN ('S', 'U');
GO
-- 修改登录名密码
ALTER LOGIN myapp_user WITH PASSWORD = 'NewStrongPassword456!';
GO
-- 禁用登录名
ALTER LOGIN myapp_user DISABLE;
GO
-- 启用登录名
ALTER LOGIN myapp_user ENABLE;
GO
-- 删除登录名
DROP LOGIN myapp_user;
GO创建数据库用户(User)
-- 切换到目标数据库
USE MyDatabase;
GO
-- 为登录名创建数据库用户
CREATE USER myapp_user FOR LOGIN myapp_user;
GO
-- 查看数据库用户
SELECT name, type_desc FROM sys.database_principals WHERE type = 'S';
GO
-- 删除数据库用户
DROP USER myapp_user;
GO角色与权限管理
-- 常用固定数据库角色
-- db_owner:数据库所有者,拥有全部权限
ALTER ROLE db_owner ADD MEMBER myapp_user;
GO
-- db_datareader:可以读取所有表的数据
ALTER ROLE db_datareader ADD MEMBER myapp_user;
GO
-- db_datawriter:可以增删改所有表的数据
ALTER ROLE db_datawriter ADD MEMBER myapp_user;
GO
-- db_ddladmin:可以执行 DDL 操作(创建/修改表等)
ALTER ROLE db_ddladmin ADD MEMBER myapp_user;
GO
-- 移除角色成员
ALTER ROLE db_datareader DROP MEMBER myapp_user;
GO细粒度权限控制
-- 授予对特定表的 SELECT 权限
GRANT SELECT ON Users TO myapp_user;
GO
-- 授予对特定表的增删改查权限
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO myapp_user;
GO
-- 授予执行存储过程的权限
GRANT EXECUTE ON dbo.GetUserList TO myapp_user;
GO
-- 拒绝某个权限
DENY DELETE ON Users TO myapp_user;
GO
-- 撤销权限
REVOKE SELECT ON Users FROM myapp_user;
GO
-- 查看用户权限
SELECT
dp.name AS UserName,
dp2.name AS ObjectName,
permission_name AS Permission,
state_desc AS State
FROM sys.database_permissions p
JOIN sys.database_principals dp ON p.grantee_principal_id = dp.principal_id
JOIN sys.objects o ON p.major_id = o.object_id
JOIN sys.schemas s ON o.schema_id = s.schema_id
LEFT JOIN sys.database_principals dp2 ON p.major_id = dp2.principal_id;
GO创建应用专用账户的最佳实践
-- 1. 创建登录名
CREATE LOGIN myapp_login WITH PASSWORD = 'Complex!Pass#2024';
GO
-- 2. 在每个数据库中创建用户
USE MyDatabase;
CREATE USER myapp_user FOR LOGIN myapp_login;
GO
-- 3. 授予最小必要权限(推荐方式)
-- 仅授予应用需要的表和操作权限
GRANT SELECT, INSERT, UPDATE ON Users TO myapp_user;
GRANT SELECT, INSERT ON Orders TO myapp_user;
GRANT EXECUTE ON dbo.sp_CreateOrder TO myapp_user;
GO
-- 4. 或者使用 db_datareader + db_datawriter(简单方式)
ALTER ROLE db_datareader ADD MEMBER myapp_user;
ALTER ROLE db_datawriter ADD MEMBER myapp_user;
GO六、备份与恢复
完整备份
-- 备份到默认目录
BACKUP DATABASE MyDatabase
TO DISK = '/var/opt/mssql/backup/MyDatabase_full.bak'
WITH FORMAT,
MEDIANAME = 'MyDatabaseBackup',
NAME = 'Full Backup of MyDatabase',
COMPRESSION;
GO差异备份
-- 差异备份(基于上一次完整备份)
BACKUP DATABASE MyDatabase
TO DISK = '/var/opt/mssql/backup/MyDatabase_diff.bak'
WITH DIFFERENTIAL,
COMPRESSION;
GO事务日志备份
-- 事务日志备份(需要数据库为完整恢复模式)
ALTER DATABASE MyDatabase SET RECOVERY FULL;
GO
BACKUP LOG MyDatabase
TO DISK = '/var/opt/mssql/backup/MyDatabase_log.trn'
WITH COMPRESSION;
GO恢复数据库
-- 恢复完整备份
RESTORE DATABASE MyDatabase
FROM DISK = '/var/opt/mssql/backup/MyDatabase_full.bak'
WITH REPLACE,
MOVE 'MyDatabase' TO '/var/opt/mssql/data/MyDatabase.mdf',
MOVE 'MyDatabase_log' TO '/var/opt/mssql/data/MyDatabase_log.ldf';
GO
-- 查看备份文件内容
RESTORE FILELISTONLY FROM DISK = '/var/opt/mssql/backup/MyDatabase_full.bak';
GO
-- 查看备份头部信息
RESTORE HEADERONLY FROM DISK = '/var/opt/mssql/backup/MyDatabase_full.bak';
GO自动化备份脚本
#!/bin/bash
# /opt/mssql/backup/backup.sh
# 配置
DB_NAME="MyDatabase"
BACKUP_DIR="/var/opt/mssql/backup"
SA_PASSWORD="YourStrongPassword"
DATE=$(date +%Y%m%d_%H%M%S)
# 创建备份目录
mkdir -p $BACKUP_DIR
# 执行备份
sqlcmd -S localhost -U SA -P $SA_PASSWORD -Q "
BACKUP DATABASE [$DB_NAME]
TO DISK = '$BACKUP_DIR/${DB_NAME}_${DATE}.bak'
WITH FORMAT, COMPRESSION"
# 清理 7 天前的备份
find $BACKUP_DIR -name "${DB_NAME}_*.bak" -mtime +7 -delete
echo "Backup completed: ${DB_NAME}_${DATE}.bak"配置定时备份(cron)
# 编辑 crontab
crontab -e
# 每天凌晨 2 点执行完整备份
0 2 * * * /opt/mssql/backup/backup.sh >> /var/log/mssql_backup.log 2>&1
# 每 6 小时执行差异备份
0 */6 * * * /opt/mssql/backup/diff_backup.sh >> /var/log/mssql_backup.log 2>&1
# 每 30 分钟执行日志备份
*/30 * * * * /opt/mssql/backup/log_backup.sh >> /var/log/mssql_backup.log 2>&1七、性能配置
内存配置
# 设置 SQL Server 最大内存使用(MB)
sudo /opt/mssql/bin/mssql-conf set memory.memorylimitmb 2048
# 重启服务
sudo systemctl restart mssql-server-- 也可以通过 T-SQL 设置
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'max server memory (MB)', 2048;
RECONFIGURE;
GO
-- 查看当前内存配置
EXEC sp_configure 'max server memory (MB)';
GO
-- 查看内存使用情况
SELECT
physical_memory_in_use_kb / 1024 AS UsedMemoryMB,
total_physical_memory_kb / 1024 AS TotalMemoryMB,
available_physical_memory_kb / 1024 AS AvailableMemoryMB
FROM sys.dm_os_process_memory;
GOCPU 配置
-- 设置关联掩码(控制 SQL Server 使用的 CPU 核心)
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'affinity mask', 3; -- 使用 CPU 0 和 1
RECONFIGURE;
GO
-- 设置最大并行度
EXEC sp_configure 'max degree of parallelism', 4;
RECONFIGURE;
GO
-- 查看 CPU 使用情况
SELECT
cpu_count,
hyperthread_ratio,
cpu_ticks / 1000 AS CpuTicksMs
FROM sys.dm_os_sys_info;
GO索引维护
-- 查看索引碎片
SELECT
DB_NAME(database_id) AS DatabaseName,
OBJECT_NAME(object_id) AS TableName,
index_id,
index_type_desc,
avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 10
ORDER BY avg_fragmentation_in_percent DESC;
GO
-- 重建索引(碎片 > 30%)
ALTER INDEX ALL ON Users REBUILD;
GO
-- 重组索引(碎片 10%-30%)
ALTER INDEX ALL ON Users REORGANIZE;
GO常用性能查询
-- 查看当前活跃连接
SELECT
session_id,
status,
login_name,
host_name,
program_name,
cpu_time,
memory_usage,
total_elapsed_time
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;
GO
-- 查看耗时查询
SELECT TOP 10
total_elapsed_time / execution_count / 1000 AS AvgTimeMs,
execution_count,
total_elapsed_time / 1000 AS TotalTimeMs,
SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE qs.statement_end_offset END
- qs.statement_start_offset)/2) + 1) AS QueryText
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY AvgTimeMs DESC;
GO
-- 查看数据库大小
SELECT
DB_NAME(database_id) AS DatabaseName,
CAST(SUM(size) * 8.0 / 1024 AS DECIMAL(10,2)) AS SizeMB
FROM sys.master_files
GROUP BY database_id
ORDER BY SizeMB DESC;
GO八、从 .NET 连接 SQL Server
连接字符串配置
| 场景 | 连接字符串 |
|---|---|
| 基本连接 | Server=192.168.1.100;Database=MyDatabase;User Id=sa;Password=YourPassword; |
| 指定端口 | Server=192.168.1.100,1433;Database=MyDatabase;User Id=sa;Password=YourPassword; |
| 加密连接 | Server=192.168.1.100;Database=MyDatabase;User Id=sa;Password=YourPassword;Encrypt=True;TrustServerCertificate=True; |
| 连接池 | Server=192.168.1.100;Database=MyDatabase;User Id=sa;Password=YourPassword;Min Pool Size=5;Max Pool Size=100; |
ADO.NET 示例
using Microsoft.Data.SqlClient;
var connectionString = "Server=192.168.1.100;Database=MyDatabase;User Id=sa;Password=YourPassword;TrustServerCertificate=True;";
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
var command = new SqlCommand("SELECT Id, UserName, Email FROM Users WHERE IsActive = @IsActive", connection);
command.Parameters.AddWithValue("@IsActive", true);
await using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
Console.WriteLine($"Id: {reader["Id"]}, UserName: {reader["UserName"]}, Email: {reader["Email"]}");
}Entity Framework Core 配置
安装 NuGet 包:
dotnet add package Microsoft.EntityFrameworkCore.SqlServerusing Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
"Server=192.168.1.100;Database=MyDatabase;User Id=sa;Password=YourPassword;TrustServerCertificate=True;",
options =>
{
options.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(10),
errorNumbersToAdd: null);
options.CommandTimeout(30);
});
}
}
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public DateTime CreatedAt { get; set; }
public bool IsActive { get; set; }
}appsettings.json 配置
{
"ConnectionStrings": {
"DefaultConnection": "Server=192.168.1.100;Database=MyDatabase;User Id=sa;Password=YourPassword;TrustServerCertificate=True;Min Pool Size=5;Max Pool Size=100;"
}
}// Program.cs (ASP.NET Core)
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));九、SQL Server on Docker(可选方案)
除了直接安装,也可以使用 Docker 容器方式运行 SQL Server。
# 拉取 SQL Server 2019 镜像
docker pull mcr.microsoft.com/mssql/server:2019-latest
# 运行 SQL Server 容器
docker run -d \
--name sqlserver2019 \
-e 'ACCEPT_EULA=Y' \
-e 'SA_PASSWORD=YourStrongPassword123!' \
-e 'MSSQL_PID=Developer' \
-e 'MSSQL_LCID=2052' \
-e 'MSSQL_COLLATION=Chinese_PRC_CI_AS' \
-p 1433:1433 \
-v /data/sqlserver:/var/opt/mssql \
mcr.microsoft.com/mssql/server:2019-latest
# 查看容器状态
docker ps | grep sqlserver
# 查看容器日志
docker logs sqlserver2019
# 进入容器执行 sqlcmd
docker exec -it sqlserver2019 /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'YourStrongPassword123!'Docker 环境变量说明:
| 环境变量 | 说明 |
|---|---|
| ACCEPT_EULA | 接受许可协议(Y) |
| SA_PASSWORD | SA 账户密码 |
| MSSQL_PID | 版本(Developer/Express/Evaluation/Standard/Enterprise) |
| MSSQL_LCID | 语言 ID(2052 为简体中文) |
| MSSQL_COLLATION | 排序规则 |
十、常用运维命令速查
# 查看 SQL Server 版本
sqlcmd -S localhost -U SA -P '<password>' -Q "SELECT @@VERSION"
# 查看数据库列表
sqlcmd -S localhost -U SA -P '<password>' -Q "SELECT name FROM sys.databases"
# 查看当前连接数
sqlcmd -S localhost -U SA -P '<password>' -Q "SELECT COUNT(*) FROM sys.dm_exec_connections"
# 查看 SQL Server 错误日志
cat /var/opt/mssql/log/errorlog
# 查看 SQL Server 配置
sqlcmd -S localhost -U SA -P '<password>' -Q "EXEC sp_configure"
# 检查数据库完整性
sqlcmd -S localhost -U SA -P '<password>' -Q "DBCC CHECKDB('MyDatabase')"
# 查看磁盘空间使用
df -h /var/opt/mssql
# 查看 SQL Server 占用的内存
ps -eo pid,rss,cmd | grep sqlservr总结
SQL Server on Linux 提供了与 Windows 版本一致的功能。安装后需配置混合认证模式、内存限制、备份策略和定期维护计划。
关键知识点
- 部署类主题的核心不是“装成功”,而是“稳定运行、可排障、可回滚”。
- 同一个服务通常至少要关注版本、目录、端口、权限、数据、日志和备份。
- Linux 问题经常跨越系统层、网络层、服务层和应用层。
- 先把数据模型、访问模式和执行代价绑定起来理解。
项目落地视角
- 把安装步骤补成可重复执行的清单,必要时写成脚本或配置文件。
- 把配置目录、数据目录、日志目录和挂载点明确拆开。
- 上线前检查防火墙、SELinux、时区、磁盘、系统服务和健康检查。
- 保留执行计划、样本 SQL、索引定义和优化前后指标。
常见误区
- 使用 latest 或未固定版本,导致环境不可复现。
- 只验证启动成功,不验证持久化、开机自启和故障恢复。
- 遇到问题先改配置而不是先看日志和依赖链路。
- 脱离真实数据分布设计索引。
进阶路线
- 继续补齐 systemd、性能监控、安全加固和备份恢复。
- 把单机操作升级成 Docker、Kubernetes 或 IaC 方案。
- 建立标准化运维手册,包括巡检、扩容、回滚和灾备演练。
- 继续深入存储引擎、复制机制、归档与冷热分层治理。
适用场景
- 当你准备把《SQL Server on Linux 安装与管理》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合单机环境初始化、中间件快速搭建、测试环境验证和生产部署前准备。
- 当服务稳定性依赖端口、权限、目录、网络和系统参数时,这类主题会直接影响成败。
落地建议
- 固定版本号与镜像标签,避免“latest”带来的不可预期变化。
- 把配置、数据、日志目录拆开管理,并记录恢复步骤。
- 上线前确认端口、防火墙、SELinux、时区和磁盘空间。
排错清单
- 先查 systemctl、容器日志和应用日志,确认失败发生在哪一层。
- 检查端口占用、目录权限、挂载路径和网络连通性。
- 如果是新环境问题,优先对比与已知正常环境的差异。
复盘问题
- 如果把《SQL Server on Linux 安装与管理》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《SQL Server on Linux 安装与管理》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《SQL Server on Linux 安装与管理》最大的收益和代价分别是什么?
