本文可帮助你解决在安装后尝试运行 mssql-conf 时 SQL Server 终止并在 RHEL 7.4 上生成核心转储的问题。
原始产品版本:SQL Server
原始 KB 数: 4134638
现象
在 RHEL 7.4 上安装 Microsoft SQL Server 后,程序会在尝试运行 mssql-conf 工具时终止并生成核心转储。 此外,mssql-server 服务的 systemctl 日志中记录了以下条目(journalctl -u mssql-server.service):
此程序遇到严重错误,无法继续运行。
提供以下诊断信息:原因:0x00000003
消息:结果
Stacktrace:0000557212bcd92 0000557721266767
进程:590 - sqlservr
线程:594(应用程序线程0x1000)
实例 ID:afe0f97b-fdbc-4a4d-910c-038e7ee2049b
崩溃 ID:544c4c67-0f49-4877-a959-92c14798d58e
生成戳:f7473acad6f0299cd161863aaa02e4284434ab6d915c7b467e2a14e907290249
正在捕获核心转储和信息...
原因
之所以出现此问题,是因为Linux 上的 SQL Server与旧版 VA 布局不兼容。 由于 RHEL 7.4 上启用了设置,因此所有进程都从此开始 using legacy_va_layout
。
在启动期间,Linux 上的 SQL Server验证地址范围。 当它由于旧版 VA 布局而发现不兼容时,它会引发断言、终止程序并生成核心转储。
由于以下任一原因,RHEL 7.4 可能会切换到使用旧版 VA 布局:
- 软堆栈限制值设置为 “无限制 ”(例如,修改的 limits.conf 脚本或 ulimit -s 设置)。
- 启用了全局旧版 VA 布局(例如,
sysctl vm.legacy_va_layout
或modify/etc/sysctl.conf
)。
解决方法
在布局中
/etc/security/limits.conf
,添加新行,然后输入代码:mssql soft stack 8192 root soft stack 8192
在布局中
/etc/sysctl.conf
,添加新行,然后输入代码:vm.legacy_va_layout = 0
重新启动计算机:
reboot
。确保用户 (root 和 mssql)的软堆栈设置为 8192。 切换到用户的上下文,然后运行以下命令:
ulimit -s
确保全局旧版 VA 布局为 0:
Sysctl vm.legacy_va_layout
。
检查堆栈大小限制
检查堆栈大小限制和 legacy_va_layout 设置(默认值,取自全新 RHEL-7 安装)。
[root@localhost ~]# sysctl vm.legacy_va_layout
vm.legacy_va_layout = 0
[root@localhost ~]# ulimit -s
8192
当这些设置在 x64 系统中进行时,地址空间布局如下所示:
+----------------------+ TASK_SIZE(1UL << 47) - PAGE_SIZE)
|STACK |
+----------------------+
+----------------------+ MMAP_BASE(STACK_SIZE + RND_OFFSET)
|MMAP() |
|vvv|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|^^^^^^^^^^^^^^|
|HEAP |
+----------------------+
|ELF 段 |
+----------------------+
+----------------------+ 0
MMAP_BASE
位于地址空间的顶部附近。 随着映射的添加,地址空间分配会减少。 这是 RHEL 的默认设置,这是 SQL Server 在启动时需要遇到的设置。
运行简单程序
运行一个简单的程序,该程序映射页面并返回内核返回的地址(示例):
mmap code
=========
#include <stdio.h>
#include <sys/mman.h>
int main()
{
void* result = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
printf("mmap %p\n", result);
return 0;
}
[root@localhost ~]# ./mmap
mmap 0x7fb6976d6000
但是,如果更改了任一参数或两个参数,VA 布局可能会恢复到其旧版式:
+----------------------+ TASK_SIZE(1UL << 47) - PAGE_SIZE)
|STACK |
|vv^v|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|^^^^^^^^^^^^^^|
|MMAP() |
+----------------------+ TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)
| |
| |
| |
|^^^^^^^^^^^^^^|
|HEAP |
+----------------------+
|ELF 段 |
+----------------------+
+----------------------+ 0
此处,地址 MMAP_BASE
空间位于地址空间的三分之一处。 随着映射的添加,地址空间分配会增长(扩展)。
由于我们有 47 位虚拟地址空间(在 64 位 Linux 中) MMAP_BASE
放置在第 42 TB 虚拟0x2A0000000000左右。 因此,mssql 在尝试设置固定映射的映射时,在地址上已映射到 64 TB 以下。
调整堆栈大小,以无限增长 - 无限制
[root@localhost ~]# ulimit -s unlimited
[root@localhost ~]# ./mmap
mmap 0x2b6634464000
调整vm.legacy_va_layout
[root@localhost ~]# ulimit -s 8192
[root@localhost ~]# sysctl -w vm.legacy_va_layout=1
vm.legacy_va_layout = 1
[root@localhost ~]# ./mmap
mmap 0x2b46f28f9000
可以通过调整堆栈大小以无限增长来获得与设置 vm.legacy_va_layout
相同的效果。 区别在于,管理员设置 vm.legacy_va_layout=1
后,系统将全局对所有进程使用旧 VA 布局。 (重写此方法的唯一方法是将 sysctl knob 重置为 0。但是,如果有 vm.legacy_va_layout=0 (default)
,可以通过发出 ulimit(或自定义 limits.conf)来调整每个登录会话的堆栈大小限制来调整该特征。