I think the deadlock graph makes it quite clear that the locks are incompatible.
If you want to look at it more closely, you can use my beta_lockinfo.
As you say, the locks are short-lived, but you can do this. In one window run
CREATE USER nisse WITHOUT LOGIN
CREATE USER katrin WITHOUT LOGIN
GRANT SELECT ON dbo.sometable TO katrin
go
BEGIN TRANSACTION
GRANT SELECT, UPDATE, DELETE, INSERT ON SCHEMA::dbo TO nisse
In a second window, run:
EXECUTE AS USER = 'katrin'
go
SELECT * FROM dbo.sometbale
go
REVERT
This will block. Then in a third window run beta_lockinfo to look at the locks. !! in the blklvl
column means that this is a lead blocker. 1 means that this the directly blocked process.
This was the easy part. The next to study is the locks on the SECURITY CACHE, that can be more difficult. One option is to set up the deadlock, which will be unresolved for five seconds. beta_lockinfo will display DD in the blklvl
column in this case.
As for the actual problem, I'm thinking: can't you add this temporary user to a role with the required permissions instead? That role would include the user being blocked. (Or is the user running the SP also one of these temporary users?)
If that is not feasible, I would deal with this deadlock problem on the Vault side. One option is to use SET DEADLOCK_PRIORTY LOW, so that this process always becomes the deadlock victim. Then again, that seems to happen already. Also, you will need to wait five seconds until the deadlock is resolved.
A better approach is that the Vault process issues SET LOCK_TIMEOUT 0, so if it can't get a lock, it gets error 1222. You trap that error and wait for, say, 100 ms and try again. By backing out directly, you don't disturb the other process.
You could of course also put the retry logic in the procedure that runs the dynamic SQL, but I suspect that this is not the only one that runs into deadlock, so I'm thinking there are fewer places to change on the Vault side.