The loser(s) get the winner's Id written into
MasterRecordId. Check Contact for example. Nothing is saved on winner record though so when the losers eventually get wiped from recycle bin the Id is really gone.(*)
If you want to persist such info - you have to do it yourself. SF doesn't save anything on master (*) because what do you think would happen when you merge 10 contacts into 1? If you want to save the values anyway - use a text field and not lookups ;)
Id won't be reused for sure. "Ensuring" is done internally.
If you need to notify external systems - it's your job again. Triggers will fire on merge, send your callouts from them for example?
If you're concerned - either track them with your own code or "soft delete" your records (tick some checkbox that will cause them to be assigned to user that's outside Role hierarchy, excluded in criteria-based sharing rules etc.). Users with "View all data" will still see them but otherwise they'll disappear from reports for example.
(*) Actually there's something that's retained for you out of the box - in the field history tracking tables. We can see the name of the merged record but queries won't show the id. So in your external systems scenarios you probably could only "identify suspect winners" that way:
SELECT Id, Field, NewValue, OldValue
WHERE Field = 'accountMerged'
- The query result renders incorrectly in workbench.developerforce.com. Try with the Developer Console if you're getting funny results.
- If you plan to build your logic around history trackers be aware that it's royal paint to unit test the code - histories are written to tables only after successful commit.
- ... and they can be truncated / shortened when you refresh a sandbox.