I haven't read the patch and the btree code is an area I really don't know, so take this for what it's worth....
It seems to me that the nature of the problem is that there will unavoidably be a nexus between the two parts of the code here. We can try to isolate it as much as possible but we're going to need a bit of a compromise. I'm imagining a function that takes two target heap buffers and a btree key. It would descend the btree and holding the leaf page lock do a try_lock on the heap pages. If it fails to get the locks then it releases whatever it got and returns for the heap update to find new pages and try again. This still leaves the potential problem with page splits and I assume it would still be tricky to call it without unsatisfactorily mixing executor and btree code. But that's as far as I got. -- greg