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