Yes, a SHARE-LOCK can exist outside of transactions.
The following examples show the confirmed behavior in OpenEdge 11.7.0. Earlier releases may show different behavior.
1. A SHARE-LOCK read does not implicitly start a transaction, unless the same code block is also anticipated to update the record.
Compare:
/* ASSIGN is intent to update in same block, this starts transaction */
FIND FIRST customer SHARE-LOCK.
PAUSE MESSAGE "step 1".
ASSIGN
customer.comments = customer.comments + ".".
PAUSE MESSAGE "step 2".
RELEASE customer.
with:
/* ASSIGN is in it's own transaction block.
Before that block starts, no transaction is active. */
FIND FIRST customer.
PAUSE MESSAGE "step 1".
DO TRANSACTION:
ASSIGN
customer.comments = TRIM(comments,".").
PAUSE MESSAGE "step 2".
END.
PAUSE MESSAGE "step 3".
RELEASE customer.
* To confirm the behavior, at each PAUSE in the code check: PROMON > 4. Record Locking Table and 1. User Control
2. When the Buffer Scope is wider than the Transaction Scope, the record will be held with a share-lock after the transaction ends.
DEFINE BUFFER bCustomer FOR Customer.
FIND FIRST bCustomer NO-LOCK.
RUN LockIt.
PAUSE MESSAGE "Check
PROMON > 4. Record Locking Table and
PROMON > 1. User Control".
/* at this point, User Control will report transaction ID 0,
Record Locking Table still shows previous transaction ID
but in "None" state to indicate it is now inactive*/
PROCEDURE LockIt:
FIND FIRST bCustomer EXCLUSIVE-LOCK.
PAUSE MESSAGE "Check
PROMON > 4. Record Locking Table and
PROMON > 1. User Control."
/* at this point, User Control will report the same transaction ID as Lock table,
Lock table also shows transaction is in "Begin" state */
END.
* To confirm the behavior, at each PAUSE in the code check: PROMON > 4. Record Locking Table and 1. User Control
The following scenario can cause record locking issues if the record actually gets updated. When the record lock is downgraded, it will retain the
D (downgraded) flag, which will prevent other clients from obtaining a lock on the record. This is further explained in
Why does a record still have a SDL lock when a new transaction starts?
DEFINE BUFFER bCustomer FOR Customer.
FIND FIRST bCustomer NO-LOCK.
RUN LockIt.
PAUSE MESSAGE "Check
PROMON > 4. Record Locking Table and
PROMON > 1. User Control".
/* at this point, User Control will report transaction ID 0,
Record Locking Table still shows previous transaction ID
but in "None" state to indicate it is now inactive*/
PROCEDURE LockIt:
FIND FIRST bCustomer EXCLUSIVE-LOCK.
bCustomer.comments = bCustomer.comments + ".".
PAUSE MESSAGE "Check
PROMON > 4. Record Locking Table and
PROMON > 1. User Control".
/* at this point, User Control will report same transaction ID as Lock table,
Lock table also shows that the transaction is in "Begin" state */
END.