服务代理 - 跨数据库选择插入本地数据库?

Service broker - Cross-database SELECTs to insert into local DB?

我正在使用 Remus 的文章 http://rusanu.com/2006/03/07/call-a-procedure-in-another-database-from-an-activated-procedure/ 作为指南。

我想做什么:

我有一个激活的存储过程(在激活的 SP 中)调用 2 个不同的存储过程。 those 存储过程之一需要访问另一个数据库中的表以查找一些数据,之后它使用额外信息在本地写入记录。由于我正在跨数据库,我的选择是

所以我做了以下操作,但它仍然失败 "lock time out exceeded" 和“无法访问数据库...在当前安全上下文下。

数据库服务代理运行于:

USE database_with_service_broker_and_queue
GO
CREATE CERTIFICATE mysp_Auditing ENCRYPTION 
    BY PASSWORD = '123457' 
    with subject = 'god_i_hope_this_works'
ADD SIGNATURE TO OBJECT::myschema.mystoredprocedure 
    BY CERTIFICATE mysp_Auditing 
    WITH PASSWORD = '123457'
ALTER CERTIFICATE mysp_Auditing REMOVE PRIVATE KEY
BACKUP CERTIFICATE mysp_Auditing to file = 'c:\mysp_auditing.CER'

现在数据库中有额外的表:

USE db_with_tables_I_need
GO
CREATE CERTIFICATE mysp_Auditing from file = 'c:\mysp_auditing.CER'
CREATE USER mysp_Auditing FROM CERTIFICATE mysp_Auditing
GRANT AUTHENTICATE to mysp_Auditing
GRANT SELECT ON TABLE1 to mysp_Auditing
GRANT SELECT on TABLE2 to mysp_Auditing

然后我启用队列并观察所有错误消息滚动。我什至尝试更改存储过程以添加 EXECUTE AS OWNER,但仍然不起作用。

感谢任何帮助。

看起来像元数据锁。如果您在激活过程中执行任何 DDL,例如创建索引或操作列,如果激活过程的多个实例在服务中,您可能会预期锁定超时。请记住,激活过程通常是一个很长的 运行 事务,如果它锁定任何对象,它将保持锁定状态直到事务结束。

太长 post 作为评论

not able to access database... under the current security context.

这意味着证书业务设置不正确(我不怪你,第一次尝试很难成功)。我会看看这些:

  • 确保 'dbo' 是有效用户。在涉及的两个数据库上尝试 运行ning EXECUTE AS USER='dbo';。如果失败(这意味着数据库是由不再有效的 Windows SID 创建的)运行 ALTER AUTHORIZATION ON DATABASE:<dbname> TO sa

  • 确保您在签署后不要更改程序。任何 ALTER 都会默默地删除签名并使您的信任链无效。

add EXECUTE AS OWNER

该过程必须有一个EXECUTE AS 子句,但它是什么并不重要,只要有一个即可。您正在授予对证书的 SELECT 权限(因此对签名),因此无论程序模拟谁,它都应该有效。

对于调试,我建议您通过简单地从 SSMS 查询 window:

手动 运行 手动存储过程来完成
 USE myactivateddb;
 GO

 EXECUTE AS USER='dbo'; -- does not matter who, is important to be AS USER
 GO

 EXEC myotherdb.dbo.myotherproc ...;
 GO

 REVERT;
 GO

这比尝试从激活的程序进行调试更容易调试。如果这有效,则尝试相同但不是执行其他数据库存储过程,而是从 SSMS 查询 window 执行激活过程(w/o t运行ing 在队列上激活) .