【问题标题】:Cannot find the principal 'dbo', because it does not exist or you do not have permission找不到主体“dbo”,因为它不存在或您没有权限
【发布时间】:2021-07-22 14:34:21
【问题描述】:

这个问题的重点是为什么会发生这种情况。

我们从另一台发生故障的服务器上恢复了一个数据库。恢复成功,但是当我们尝试运行任何存储过程(使用“sa”登录或具有完全管理员访问权限的基于 Windows 的登录)时,我们收到此错误:

无法作为数据库主体执行,因为主体“dbo” 不存在,无法模拟此类主体,或者您 没有权限。

很多 SO 用户都遇到过同样的问题,所以我遵循了相关的答案。比如下面两个sn-ps:

EXEC sp_changedbowner 'dbo';
ALTER AUTHORIZATION ON DATABASE::MyDb TO dbo;

...结果:

找不到主体“dbo”,因为它不存在或您没有权限。

在以前的服务器(和我的恢复开发服务器)上,没有dbo 用户 可以重新关联为所有者。我不确定如何找到 principal,但它已在 Schema 中列出。

  1. 什么原因导致找不到“dbo”,或者 dbo 主体发生了什么?
  2. 可以恢复/重建吗?
  3. dbo 是否必须链接到实际的登录帐户?

【问题讨论】:

  • 有人让ALTER AUTHORIZATION ON DATABASE::MyDb TO dbo 工作吗?目标主体需要是登录名而不是(数据库)用户。 sp_changedbowner 也是如此。
  • 有一个关于 SO 的答案有 500 个赞成票,所以我想是的。不过在这里没用!
  • 对于alter authorization,一般来说,也许,但alter authorization on database 不能使用数据库主体——这会导致悖论并破坏整个宇宙。另请参阅sp_changedbowner

标签: sql-server dbo


【解决方案1】:

数据库所有者是服务器级主体(即登录名)或 Windows 用户(不一定具有登录名)。如 cmets 中所述,dbo 是数据库主体而不是服务器主体(假设您碰巧没有名为 dbo 的登录名)。

所有者存储在主数据库中,并作为sys.databases 目录视图的owner_sid 列可见:

SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

数据库所有者也作为众所周知的dbo用户存储在数据库本身中:

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM sys.database_principals AS dp
WHERE name = N'dbo';

当一个数据库被恢复并且它不存在时,所有者(授权)最初被设置为恢复数据库的人。但是,数据库本身中的dbo 条目保持不变。这会导致 sys.databases 中的所有者与 sys.database_principals dbo 用户之间的不匹配。需要在还原后对所需所有者执行ALTER AUTHORIZATION ON DATABASE 以纠正不匹配。

下面的脚本演示了当执行还原的个人未以sa 登录时出现的问题。

CREATE DATABASE MyDb; --database is owned by current login

ALTER AUTHORIZATION ON DATABASE::MyDb TO sa; --sa is an example; can be any login

--shows owners are same (sa)
SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM MyDb.sys.database_principals AS dp
WHERE name = N'dbo';

BACKUP DATABASE MyDb TO DISK=N'C:\Backups\MyDb.bak' WITH INIT;

DROP DATABASE MyDb;

RESTORE DATABASE MyDb FROM DISK=N'C:\Backups\MyDb.bak';

--shows owners are different (current user and sa)
SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM MyDb.sys.database_principals AS dp
WHERE name = N'dbo';

ALTER AUTHORIZATION ON DATABASE::MyDb TO sa; --sa is an example; can be any login

--shows owners are same (sa)
SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM MyDb.sys.database_principals AS dp
WHERE name = N'dbo';

以下是the documentation 关于数据库所有者主体的摘录。

新的所有者主体必须是以下之一:

A SQL Server authentication login.
A Windows authentication login representing a Windows user (not a group).
A Windows user that authenticates through a Windows authentication login representing a Windows group.

【讨论】:

  • 感谢您非常明确的回答。第二个代码示例现在生成行,所以我运行它成功完成,ALTER AUTHORIZATION ON DATABASE::MyDatabase TO [AzureAD\MyName];。但是,再次运行第二个代码示例仍然不返回任何行,但在 Properties 中列出了我的名字。从数据库运行 proc 会产生,无法获取有关 Windows NT 组/用户 'AzureAD\MyName' 的信息,错误代码 0x54b。 请问为什么会出现这种情况?
猜你喜欢
  • 2013-04-09
  • 2021-10-03
  • 2016-11-22
  • 2015-05-27
  • 2010-12-08
  • 2017-03-19
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
相关资源
最近更新 更多