这篇博文主要演示”CREATE FILE encountered operating system error 5(Access is denied.)“错误如出现的原因(当然只是导致这个错误出现的一种场景而已)和如何解决这个问题以及一些不解的迷惑。
实验环境:
操作系统版本: Windows Server 2012 SP2
数据库的版本:Microsoft SQL Server 2014 - 12.0.2000.8
如下所示,SQL Server Database Services 服务的启动账号为NT Service\MSSQLSERVER, 我们先设置一下数据库的默认路径为E:\SQL_DATA
此时查看E:\SQL_DATA 目录的权限(被屏蔽的是一域账号)。此时我们创建数据库Test完全没有问题。我们先删除数据库Test。
现在我们删除用户GETTESTNT55\Users这个账号,在目录E:\SQL_DATA的属性(Properties)->安全(Security)-> 编辑(Edit)下直接删除会遇到下面错误。
我们从E盘的根目录,右键属性选择Security 删除这个用户,然后我创建新的数据库时就会遇到CREATE FILE encountered operating system error 5(Access is denied.)错误。
那么如何解决呢? 我们可以给当前目录添加虚拟帐户NT Service\MSSQLSERVER 并授予相关权限解决这个问题。具体可以参考MSDN文档,截取部分如下所示
-
使用 Windows 资源管理器,导航到存储数据库文件的文件系统位置。右键单击文件系统文件夹,然后单击“属性”。
-
在“安全性”选项卡上,单击“编辑”,然后单击“添加”。
-
在“选择用户、计算机、服务帐户或组”对话框中,单击“位置”,在位置列表的顶部选择您的计算机名称,然后单击“确定”。
-
在“输入要选择的对象名称”框中,键入联机丛书主题“配置 Windows 服务帐户和权限”中所列的每个服务 SID 的名称。 (对于数据库引擎每个服务 SID,将 NT SERVICE\MSSQLSERVER 用于默认实例,或将 NT SERVICE\MSSQL$InstanceName 用于命名实例。)
-
单击“检查名称”以验证该条目。验证经常失败,而且可能告知您找不到该名称。单击“确定”时,将显示“找到多个名称”对话框。
-
现在选择每个服务 SID(MSSQLSERVER 或 NT SERVICE\MSSQL$InstanceName),然后单击“确定”。
-
再次单击“确定”以返回“权限”对话框。
-
在“组或用户”名称框中,选择每个服务 SID,然后在“<名称> 的权限”框中,为“完全控制”选中“允许”复选框。
单击“应用”,然后单击“确定”两次以退出。
具体操作过程的截图如下所示
权限的话,至少需要”Read & Execute“、”List Folder Content“、”Read“、”Write“权限,当然如果你能给”Full Control“权限那肯定是可以。权限我们应该尽量控制最小范围内。
此时就能解决这个错误,此时你删除该用户,然后在这个目录添加EVERYONE用户,授予上面的权限也能解决这个错误。当然在安全性上就不如给虚拟账户NT Service\MSSQLSERVER账号授权。
肯定有细心的人会问,我们不添加虚拟账户NT Service\MSSQLSERVER或EVERYONE,我们重新添加这个用户GETTESTNT55\Users、授予同样的权限是否可以解决这个问题? 答案是依然会遇到这个错误,为什么呢? 暂时我没有搞明白具体原因,是不是有点讽刺,知道了怎么解决,但是依然不清楚具体原因。当然涉及权限的问题确实有点复杂。如果哪位知道具体原因,请不吝赐教。
----------------------------------------------分割线 2015-12-15补充--------------------------------------------------
今天有空,为了搞清楚这个问题,我查了大量的资料。下面是一些来自MSDN的资料和我的一些验证。下面我们一一梳理清楚。
关于SQL SERVER服务的一些属性与配置的信息(中文与英文信息)。
用于启动和运行 SQL Server 的启动帐户可以是域用户帐户、本地用户帐户、托管服务帐户、虚拟帐户或内置系统帐户。 若要启动和运行 SQL Server 中的每项服务,这些服务都必须有一个在安装过程中配置的启动帐户。
此部分介绍可配置为启动 SQL Server 服务的帐户、SQL Server 安装程序使用的默认值、Per-service SID 的概念、启动选项以及配置防火墙。
Service Properties and Configuration
Startup accounts used to start and run SQL Server can be domain user accounts, local user accounts, managed service accounts, virtual accounts, or built-in system accounts. To start and run, each service in SQL Server must have a startup account configured during installation.
This section describes the accounts that can be configured to start SQL Server services, the default values used by SQL Server Setup, the concept of per-service SID’s, the startup options, and configuring the firewall.
NT Service\MSSQLSERVER 它属于虚拟账户(Virtual Account)。虚拟账户的概念请看下面MSDN描述(中文与英文)
虚拟帐户
Windows Server 2008 R2 和 Windows 7 中的虚拟帐户是“托管的本地帐户”,此类帐户提供以下功能以简化服务管理。 虚拟帐户是自动管理的,并且虚拟帐户可以访问域环境中的网络。 如果在 Windows Server 2008 R2 或 Windows 7 上安装 SQL Server 时对服务帐户使用默认值,则将使用将实例名称用作服务名称的虚拟帐户,格式为 NT SERVICE\<SERVICENAME>。 以虚拟帐户身份运行的服务通过使用计算机帐户的凭据(格式为 <domain_name>\<computer_name>$)访问网络资源。 当指定一个虚拟帐户以启动 SQL Server 时,应将密码留空。 如果虚拟帐户无法注册服务主体名称 (SPN),则手动注册该 SPN。 有关手动注册 SPN 的详细信息,请参阅手动注册 SPN。
Virtual Accounts
Virtual accounts in Windows Server 2008 R2 and Windows 7 are managed local accounts that provide the following features to simplify service administration. The virtual account is auto-managed, and the virtual account can access the network in a domain environment. If the default value is used for the service accounts during SQL Server setup on Windows Server 2008 R2 or Windows 7, a virtual account using the instance name as the service name is used, in the format NT SERVICE\<SERVICENAME>. Services that run as virtual accounts access network resources by using the credentials of the computer account in the format <domain_name>\<computer_name>$. When specifying a virtual account to start SQL Server, leave the password blank. If the virtual account fails to register the Service Principal Name (SPN), register the SPN manually. For more information on registering a SPN manually, see Manual SPN Registration.
关于Users组的概念
A built-in group. After the initial installation of the operating system, the only member is the Authenticated Users group. When a computer joins a domain, the Domain Users group is added to the Users group on the computer. Users can perform tasks such as running applications, using local and network printers, shutting down the computer, and locking the computer. Users can install applications that only they are allowed to use if the installation program of the application supports per-user installation.
那么我们用Icacls命令来查看E:\SQL_DATA目录的随机访问控制列表 (DACL),我们可以对比GETTESTNT55\Users删除前后的权限,发现删除该用户组后,BUILTIN\Users对该目录的权限没有了。
看来SQL SERVER服务访问相关的文件系统权限的最终映射到了这个“内置帐户”账户上了(仅仅个人猜想、判断)。所以才会出现我上面的错误。
在文件上面我曾经介绍过“我们不添加虚拟账户NT Service\MSSQLSERVER,我们重新添加这个用户、授予同样的权限是否可以解决这个问题? 答案是依然会遇到这个错误,为什么呢?” ,当时我是在E:\SQL_DATA目录设置权限。这样依然不行,如果我去E盘设置权限则不会出现这个错误(实验验证结果)。我对比了下两者在E:\SQL_DATA文件上的随机访问控制列表 (DACL)的不同。如下所示。权限的顺序有所不同(真是脑壳痛,研究到此为止),看来是某种权限控制机制导致。
参考资料:
http://www.guyellisrocks.com/2010/07/create-file-encountered-operating.html
https://msdn.microsoft.com/zh-cn/library/jj219062.aspx
http://ss64.com/nt/syntax-security_groups.html
https://msdn.microsoft.com/zh-cn/library/ms143504(v=sql.120).aspx#VA_Desc