The code is already thread-safe because CREATE SYNONYM
takes a SCH-M
(schema-modification) lock, which blocks others' attempts to create the same synonym, and they will wait until the lock owner's transaction completes.
This will also inherently prevent errors related to the synonym object already existing. In fact, even checking for existence of the synonym (without using NOLOCK
/READ UNCOMMITTED
) from another thread will also block until the lock is released.
Therefore, this design could never allow concurrent operations in the first place. If concurrent access is a requirement, the design could be changed in the following way:
Since most of the time the local version of the synonym would be used, create it permanently in the database with the local definition. When the remote version is needed, the code can (within a transaction) drop and recreate the synonym with the remote definition, do its work, then drop and recreate with the local definition to return the state to where it was when the transaction started.
This will block other callers for the same reason above if the remote caller acquires the lock first. If a local caller is using the synonym, it acquires and potentially holds a SCH-S
(schema-stability) lock, which will prevent the synonym from being dropped, and therefore block a remote caller for as long as the lock is held. This sets up a situation where a local caller could be in process and wait in the middle while a remote caller does its work.
I'm a little wary of allowing that because it makes things a little unpredictable (i.e., if you're recording timing metrics of the process, it could be all over the place). To solve that, we can use sp_getapplock
and request a Shared
lock for a local caller, and an Exclusive
lock for a remote caller. This will allow concurrent local callers (which will wait if a remote caller is running), and a remote caller will wait for all local callers to complete before running.
Well, you could go by object creation date:
SELECT AO.*
FROM ALL_OBJECTS AO
INNER JOIN ALL_SYNONYMS ASY ON AO.OWNER = ASY.OWNER and AO.OBJECT_NAME = ASY.SYNONYM_NAME
AND ASY.OWNER = 'PUBLIC'
ORDER by AO.CREATED DESC
The system created synonyms should all have the same created date, equal to the creation time of the database and the earliest of this list.
You can also filter out the system owned objects being referenced by the synonym using this :
SELECT AO.*
FROM ALL_OBJECTS AO
INNER JOIN ALL_SYNONYMS ASY ON AO.OWNER = ASY.OWNER and AO.OBJECT_NAME = ASY.SYNONYM_NAME
AND ASY.OWNER = 'PUBLIC'
AND ASY.TABLE_OWNER NOT IN ('CTXSYS','EXFSYS','APPQOSSYS','XDB','SYS', 'DVSYS', 'FLOWS_FILES', 'LBACSYS', 'MDSYS', 'OLAPSYS', 'ORDSYS', 'ORDDATA','WMSYS','SYSTEM', 'DBMS_PRIVILEGE_CAPTURE')
and ASY.TABLE_OWNER not like 'APEX_%'
ORDER by AO.CREATED DESC
Best Answer
To avoid problems with cycles in your graph, I would suggest that you re-design your structure to:
I created a Fiddle, I just used integer for keys since I don't know what identifies your entities. To get the synonyms of chiptune: