1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002, 2014 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 
8 package com.sleepycat.je;
9 
10 /**
11  * Record lock modes for read operations. Lock mode parameters may be specified
12  * for all operations that retrieve data.
13  *
14  * <p><strong>Locking Rules</strong></p>
15  *
16  * <p>Together with {@link CursorConfig}, {@link TransactionConfig} and {@link
17  * EnvironmentConfig} settings, lock mode parameters determine how records are
18  * locked during read operations.  Record locking is used to enforce the
19  * isolation modes that are configured.  Record locking is summarized below for
20  * read and write operations.  For more information on isolation levels and
21  * transactions, see <a
22  * href="{@docRoot}/../TransactionGettingStarted/index.html"
23  * target="_top">Writing Transactional Applications</a>.</p>
24  *
25  * <p>With one exception, a record lock is always acquired when a record is
26  * read or written, and a cursor will always hold the lock as long as it is
27  * positioned on the record.  The exception is when {@link #READ_UNCOMMITTED}
28  * is specified, which allows a record to be read without any locking.</p>
29  *
30  * <p>Both read (shared) and write (exclusive) locks are used.  Read locks are
31  * normally acquired on read ({@code get} method) operations and write locks on
32  * write ({@code put} method) operations.  The only exception is that a write
33  * lock will be acquired on a read operation if {@link #RMW} is specified.</p>
34  *
35  * <p>Because read locks are shared, multiple accessors may read the same
36  * record.  Because write locks are exclusive, if a record is written by one
37  * accessor it may not be read or written by another accessor.  An accessor is
38  * either a transaction or a thread (for non-transactional operations).</p>
39  *
40  * <p>Whether additional locking is performed and how locks are released depend
41  * on whether the operation is transactional and other configuration
42  * settings.</p>
43  *
44  * <p><strong>Transactional Locking</strong></p>
45  *
46  * <p>Transactional operations include all write operations for a transactional
47  * database, and read operations when a non-null {@link Transaction} parameter
48  * is passed.  When a null transaction parameter is passed for a write
49  * operation for a transactional database, an auto-commit transaction is
50  * automatically used.</p>
51  *
52  * <p>With transactions, read and write locks are normally held until the end
53  * of the transaction (commit or abort).  Write locks are always held until the
54  * end of the transaction.  However, if {@link #READ_COMMITTED} is configured,
55  * then read locks for cursor operations are only held during the operation and
56  * while the cursor is positioned on the record.  The read lock is released
57  * when the cursor is moved to a different record or closed.  When {@link
58  * #READ_COMMITTED} is used for a database (non-cursor) operation, the read
59  * lock is released before the method returns.</p>
60  *
61  * <p>When neither {@link #READ_UNCOMMITTED} nor {@link #READ_COMMITTED} is
62  * specified, read and write locking as described above provide Repeatable Read
63  * isolation, which is the default transactional isolation level.  If
64  * Serializable isolation is configured, additional "next key" locking is
65  * performed to prevent "phantoms" -- records that are not visible at one point
66  * in a transaction but that become visible at a later point after being
67  * inserted by another transaction.  Serializable isolation is configured via
68  * {@link TransactionConfig#setSerializableIsolation} or {@link
69  * EnvironmentConfig#setTxnSerializableIsolation}.</p>
70  *
71  * <p><strong>Non-Transactional Locking</strong></p>
72  *
73  * <p>Non-transactional operations include all operations for a
74  * non-transactional database (including a Deferred Write database), and read
75  * operations for a transactional database when a null {@link Transaction}
76  * parameter is passed.</p>
77  *
78  * <p>For non-transactional operations, both read and write locks are only held
79  * while a cursor is positioned on the record, and are released when the cursor
80  * is moved to a different record or closed.  For database (non-cursor)
81  * operations, the read or write lock is released before the method
82  * returns.</p>
83  *
84  * <p>This behavior is similar to {@link #READ_COMMITTED}, except that both
85  * read and write locks are released.  Configuring {@link #READ_COMMITTED} for
86  * a non-transactional database cursor has no effect.</p>
87  *
88  * <p>Because the current thread is the accessor (locker) for non-transactional
89  * operations, a single thread may have multiple cursors open without locking
90  * conflicts.  Two non-transactional cursors in the same thread may access the
91  * same record via write or read operations without conflicts, and the changes
92  * make by one cursor will be visible to the other cursor.</p>
93  *
94  * <p>However, a non-transactional operation will conflict with a transactional
95  * operation for the same record even when performed in the same thread.  When
96  * using a transaction in a particular thread for a particular database, to
97  * avoid conflicts you should use that transaction for all access to that
98  * database in that thread.  In other words, to avoid conflicts always pass the
99  * transaction parameter, not null, for all operations.  If you don't wish to
100  * hold the read lock for the duration of the transaction, specify {@link
101  * #READ_COMMITTED}.</p>
102  *
103  * <p><strong>Read Uncommitted (Dirty-Read)</strong></string></p>
104  *
105  * <p>When {@link #READ_UNCOMMITTED} is configured, no locking is performed
106  * by a read operation.  {@code READ_UNCOMMITTED} does not apply to write
107  * operations.</p>
108  *
109  * <p>{@code READ_UNCOMMITTED} is sometimes called dirty-read because records
110  * are visible to the caller in their current state in the Btree at the time of
111  * the read, even when that state is due to operations performed using a
112  * transaction that has not yet committed.  In addition, because no lock is
113  * acquired by the dirty read operation, the record's state may change at any
114  * time, even while a cursor used to do the dirty-read is still positioned on
115  * the record.</p>
116  *
117  * <p>To illustrate this, let's say a record is read with dirty-read
118  * ({@code READ_UNCOMMITTED}) by calling {@link Cursor#getNext Cursor.getNext}
119  * with a cursor C, and changes to the record are also being made in another
120  * thread using transaction T. When a locking (non-dirty-read) call to {@link
121  * Cursor#getCurrent Cursor.getCurrent} is subsequently made to read the same
122  * record again with C at the current position, a result may be returned that
123  * is different than the result returned by the earlier call to {@code
124  * getNext}. For example:
125  * <ul>
126  *     <li>If the record is updated by T after the dirty-read {@code getNext}
127  *     call, and T is committed, a subsequent call to {@code getCurrent} will
128  *     return the data updated by T.</li>
129  *
130  *     <li>If the record is updated by T before the dirty-read {@code getNext}
131  *     call, the {@code getNext} will returned the data updated by T.  But if
132  *     call, the {@code getNext} will return the data updated by T.  But if
133  *     T is then aborted, a subsequent call to {@code getCurrent} will return
134  *     the version of the data before it was updated by T.</li>
135  *
136  *     <li>If the record was inserted by T before the dirty-read {@code
137  *     getNext} call, the {@code getNext} call will return the inserted record.
138  *     But if T is aborted, a subsequent call to {@code getCurrent} will return
139  *     {@link OperationStatus#KEYEMPTY}.</li>
140  *
141  *     <li>If the record is deleted by T after the dirty-read {@code getNext}
142  *     call, and T is committed, a subsequent call to {@code getCurrent} will
143  *     return {@link OperationStatus#KEYEMPTY}.</li>
144  * </ul>
145  * </p>
146  *
147  * <p>Note that deleted records are handled specially in JE. Deleted records
148  * remain in the Btree until after the deleting transaction is committed, and
149  * they are removed from the Btree asynchronously (not immediately at commit
150  * time). When using {@code #READ_UNCOMMITTED}, any record encountered in the
151  * Btree that was previously deleted, whether or not the deleting transaction
152  * has been committed, will be ignored (skipped over) by the read operation.
153  * Of course, if the deleting transaction is aborted, the record will no longer
154  * be deleted.  If the application is scanning records, for example, this means
155  * that such records may be skipped by the scan. If this behavior is not
156  * desirable, {@link #READ_UNCOMMITTED_ALL} may be used instead. This mode
157  * ensures that records deleted by a transaction that is later aborted will not
158  * be skipped by a read operation.  This is accomplished in two different ways
159  * depending on the type of database and whether the record's data is requested
160  * by the operation.
161  * <ol>
162  *     <li>If the DB is configured for duplicates or the record's data
163  *     is not requested, then a record that has been deleted by an open
164  *     transaction is returned by the read operation.</li>
165  *
166  *     <li>If the DB is not configured for duplicates and the record's data is
167  *     requested, then the read operation must wait for the deleting
168  *     transaction to close (commit or abort).  After the transaction is
169  *     closed, the record will be returned if it is actually deleted and
170  *     otherwise will be skipped.</li>
171  * </ol>
172  *
173  * <p>By "record data" we mean both the {@code data} parameter for a regular or
174  * primary DB, and the {@code pKey} parameter for a secondary DB. By "record
175  * data requested" we mean that all or part of the {@code DatabaseEntry} will
176  * be returned by the read operation.  Unless explicitly <em>not</em>
177  * requested, the complete {@code DatabaseEntry} is returned.  See
178  * <a href="Cursor.html#partialEntry">Using Partial DatabaseEntry
179  * Parameters</a> for more information.</p>
180  *
181  * <p>Because of this difference in behavior, although {@code
182  * #READ_UNCOMMITTED} is fully non-blocking, {@code #READ_UNCOMMITTED_ALL} is
183  * not (under the conditions described). As a result, when using {@code
184  * #READ_UNCOMMITTED_ALL} under these conditions, a {@link
185  * LockConflictException} will be thrown when blocking results in a deadlock or
186  * lock timeout.</p>
187  *
188  * <p>To summarize, callers that use {@code READ_UNCOMMITTED} or {@code
189  * #READ_UNCOMMITTED_ALL} should be prepared for the following behaviors.
190  * <ul>
191  *     <li>After a successful dirty-read operation, because no lock is acquired
192  *     the record can be changed by another transaction, even when the cursor
193  *     used to perform the dirty-read operation is still positioned on the
194  *     record.</li>
195  *
196  *     <li>After a successful dirty-read operation using a cursor C, say that
197  *     another transaction T deletes the record, and T is committed. In this
198  *     case, {@link OperationStatus#KEYEMPTY} will be returned by the following
199  *     methods if they are called while C is still positioned on the deleted
200  *     record: {@link Cursor#getCurrent Cursor.getCurrent}, {@link
201  *     Cursor#putCurrent Cursor.putCurrent} and {@link Cursor#delete
202  *     Cursor.delete}.</li>
203  *
204  *     <li>When using {@code READ_UNCOMMITTED}, deleted records will be skipped
205  *     even when the deleting transaction is still open. No blocking will occur
206  *     and {@link LockConflictException} is never thrown when using this
207  *     mode.</li>
208  *
209  *     <li>When using {@code #READ_UNCOMMITTED_ALL}, deleted records will not
210  *     be skipped even when the deleting transaction is open. If the DB is a
211  *     duplicates DB or the record's data is not requested, the deleted record
212  *     will be returned.  If the DB is not a duplicates DB and the record's
213  *     data is requested, blocking will occur until the deleting transaction is
214  *     closed. In the latter case, {@link LockConflictException} will be thrown
215  *     when this blocking results in a deadlock or a lock timeout.</li>
216  * </ul>
217  * </p>
218  */
219 public enum LockMode {
220 
221     /**
222      * Uses the default lock mode and is equivalent to passing {@code null} for
223      * the lock mode parameter.
224      *
225      * <p>The default lock mode is {@link #READ_UNCOMMITTED} when this lock
226      * mode is configured via {@link CursorConfig#setReadUncommitted} or {@link
227      * TransactionConfig#setReadUncommitted}.  The Read Uncommitted mode
228      * overrides any other configuration settings.</p>
229      *
230      * <p>Otherwise, the default lock mode is {@link #READ_COMMITTED} when this
231      * lock mode is configured via {@link CursorConfig#setReadCommitted} or
232      * {@link TransactionConfig#setReadCommitted}.  The Read Committed mode
233      * overrides other configuration settings except for {@link
234      * #READ_UNCOMMITTED}.</p>
235      *
236      * <p>Otherwise, the default lock mode is to acquire read locks and release
237      * them according to the {@link LockMode default locking rules} for
238      * transactional and non-transactional operations.</p>
239      */
240     DEFAULT,
241 
242     /**
243      * Reads modified but not yet committed data.
244      *
245      * <p>The Read Uncommitted mode is used if this lock mode is explicitly
246      * passed for the lock mode parameter, or if null or {@link #DEFAULT} is
247      * passed and Read Uncommitted is the default -- see {@link #DEFAULT} for
248      * details.</p>
249      *
250      * <p>Unlike {@link #READ_UNCOMMITTED_ALL}, deleted records will be skipped
251      * even when the deleting transaction is still open. No blocking will occur
252      * and {@link LockConflictException} is never thrown when using this
253      * mode.</p>
254      *
255      * <p>See the {@link LockMode locking rules} for information on how Read
256      * Uncommitted impacts transactional and non-transactional locking.</p>
257      */
258     READ_UNCOMMITTED,
259 
260     /**
261      * Reads modified but not yet committed data, ensuring that records are not
262      * skipped due to transaction aborts.
263      *
264      * <p>The Read Uncommitted mode is used only when this lock mode is
265      * explicitly passed for the lock mode parameter.</p>
266      *
267      * <p>Unlike {@link #READ_UNCOMMITTED}, deleted records will not be skipped
268      * even when the deleting transaction is open. If the DB is a duplicates DB
269      * or the record's data is not requested, the deleted record will be
270      * returned.  If the DB is not a duplicates DB and the record's data is
271      * requested, blocking will occur until the deleting transaction is closed.
272      * In the latter case, {@link LockConflictException} will be thrown when
273      * this blocking results in a deadlock or a lock timeout.</p>
274      *
275      * <p>See the {@link LockMode locking rules} for information on how Read
276      * Uncommitted impacts transactional and non-transactional locking.</p>
277      */
278     READ_UNCOMMITTED_ALL,
279 
280     /**
281      * Read committed isolation provides for cursor stability but not
282      * repeatable reads.  Data items which have been previously read by this
283      * transaction may be deleted or modified by other transactions before the
284      * cursor is closed or the transaction completes.
285      *
286      * Note that this LockMode may only be passed to {@link Database} get
287      * methods, not to {@link Cursor} methods.  To configure a cursor for Read
288      * Committed isolation, use {@link CursorConfig#setReadCommitted}.
289      *
290      * <p>See the {@link LockMode locking rules} for information on how Read
291      * Committed impacts transactional and non-transactional locking.</p>
292      */
293     READ_COMMITTED,
294 
295     /**
296      * Acquire write locks instead of read locks when doing the retrieval.
297      *
298      * <p>Because it causes a write lock to be acquired, specifying this lock
299      * mode as a {@link Cursor} or {@link Database} {@code get} (read) method
300      * parameter will override the Read Committed or Read Uncommitted isolation
301      * mode that is configured using {@link CursorConfig} or {@link
302      * TransactionConfig}.  The write lock will acquired and held until the end
303      * of the transaction.  For non-transactional use, the write lock will be
304      * released when the cursor is moved to a new position or closed.</p>
305      *
306      * <p>Setting this flag can eliminate deadlock during a read-modify-write
307      * cycle by acquiring the write lock during the read part of the cycle so
308      * that another thread of control acquiring a read lock for the same item,
309      * in its own read-modify-write cycle, will not result in deadlock.</p>
310      */
311     RMW;
312 
toString()313     public String toString() {
314         return "LockMode." + name();
315     }
316 }
317