1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>The Locking Subsystem</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /> 9 <link rel="start" href="index.html" title="Getting Started with Berkeley DB Transaction Processing" /> 10 <link rel="up" href="txnconcurrency.html" title="Chapter 4. Concurrency" /> 11 <link rel="prev" href="blocking_deadlocks.html" title="Locks, Blocks, and Deadlocks" /> 12 <link rel="next" href="isolation.html" title="Isolation" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">The Locking Subsystem</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a> </td> 22 <th width="60%" align="center">Chapter 4. Concurrency</th> 23 <td width="20%" align="right"> <a accesskey="n" href="isolation.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="lockingsubsystem"></a>The Locking Subsystem</h2> 33 </div> 34 </div> 35 </div> 36 <div class="toc"> 37 <dl> 38 <dt> 39 <span class="sect2"> 40 <a href="lockingsubsystem.html#configuringlock">Configuring the Locking Subsystem</a> 41 </span> 42 </dt> 43 <dt> 44 <span class="sect2"> 45 <a href="lockingsubsystem.html#configdeadlkdetect">Configuring Deadlock Detection</a> 46 </span> 47 </dt> 48 <dt> 49 <span class="sect2"> 50 <a href="lockingsubsystem.html#deadlockresolve">Resolving Deadlocks</a> 51 </span> 52 </dt> 53 </dl> 54 </div> 55 <p> 56 In order to allow concurrent operations, DB provides the locking 57 subsystem. This subsystem provides inter- and intra- process 58 concurrency mechanisms. It is extensively used by DB concurrent 59 applications, but it can also be generally used for non-DB 60 resources. 61 </p> 62 <p> 63 This section describes the locking subsystem as it is used to 64 protect DB resources. In particular, issues on configuration are 65 examined here. For information on using the locking subsystem to 66 manage non-DB resources, see the 67 <em class="citetitle">Berkeley DB Programmer's Reference Guide</em>. 68 </p> 69 <div class="sect2" lang="en" xml:lang="en"> 70 <div class="titlepage"> 71 <div> 72 <div> 73 <h3 class="title"><a id="configuringlock"></a>Configuring the Locking Subsystem</h3> 74 </div> 75 </div> 76 </div> 77 <p> 78 You initialize the locking subsystem by specifying 79 80 <span> 81 <code class="literal">true</code> to the 82 <code class="methodname">EnvironmentConfig.setInitializeLocking()</code> 83 method. 84 </span> 85 </p> 86 <p> 87 Before opening your environment, you can configure various 88 maximum values for your locking subsystem. Note that these 89 limits can only be configured before the environment is 90 opened. Also, these methods configure the entire environment, 91 not just a specific environment handle. 92 </p> 93 <p> 94 Finally, each bullet below identifies the 95 <code class="filename">DB_CONFIG</code> file parameter that can be used 96 to specify the specific locking limit. If used, these 97 <code class="filename">DB_CONFIG</code> file parameters override any 98 value that you might specify using the environment handle. 99 </p> 100 <p> 101 The limits that you can configure are as follows: 102 </p> 103 <div class="itemizedlist"> 104 <ul type="disc"> 105 <li> 106 <p> 107 The maximum number of lockers 108 supported by the environment. This value is used by 109 the environment when it is opened to estimate the amount 110 of space that it should allocate for various internal 111 data structures. By default, 1,000 lockers are 112 supported. 113 </p> 114 <p> 115 To configure this value, use the 116 117 <span> 118 <code class="methodname">EnvironmentConfig.setMaxLockers()</code> 119 method. 120 </span> 121 </p> 122 <p> 123 As an alternative to this method, you can configure this 124 value using the <code class="filename">DB_CONFIG</code> file's 125 <code class="literal">set_lk_max_lockers</code> parameter. 126 </p> 127 </li> 128 <li> 129 <p> 130 The maximum number of locks supported by the environment. 131 By default, 1,000 locks are supported. 132 </p> 133 <p> 134 To configure this value, use the 135 136 <span> 137 <code class="methodname">EnvironmentConfig.setMaxLocks()</code> 138 method. 139 </span> 140 </p> 141 <p> 142 As an alternative to this method, you can configure this 143 value using the <code class="filename">DB_CONFIG</code> file's 144 <code class="literal">set_lk_max_locks</code> parameter. 145 </p> 146 </li> 147 <li> 148 <p> 149 The maximum number of locked objects supported by the environment. 150 By default, 1,000 objects can be locked. 151 </p> 152 <p> 153 To configure this value, use the 154 155 <span> 156 <code class="methodname">EnvironmentConfig.setMaxLockObjects()</code> 157 method. 158 </span> 159 </p> 160 <p> 161 As an alternative to this method, you can configure this 162 value using the <code class="filename">DB_CONFIG</code> file's 163 <code class="literal">set_lk_max_objects</code> parameter. 164 </p> 165 </li> 166 </ul> 167 </div> 168 <p> 169 For a definition of lockers, locks, and locked objects, see 170 <a class="xref" href="blocking_deadlocks.html#lockresources" title="Lock Resources">Lock Resources</a>. 171 </p> 172 <p> 173 For example, to configure the maximum number of locks that your 174 environment can use: 175 </p> 176 <pre class="programlisting">package db.txn; 177 178import com.sleepycat.db.DatabaseException; 179import com.sleepycat.db.Environment; 180import com.sleepycat.db.EnvironmentConfig; 181 182import java.io.File; 183import java.io.FileNotFoundException; 184 185... 186 187Environment myEnv = null; 188try { 189 EnvironmentConfig myEnvConfig = new EnvironmentConfig(); 190 myEnvConfig.setTransactional(true); 191 myEnvConfig.setMaxLocks(5000); 192 193 myEnv = new Environment(new File("/my/env/home"), 194 myEnvConfig); 195 196} catch (DatabaseException de) { 197 // Exception handling goes here 198} catch (FileNotFoundException fnfe) { 199 // Exception handling goes here 200}</pre> 201 </div> 202 <div class="sect2" lang="en" xml:lang="en"> 203 <div class="titlepage"> 204 <div> 205 <div> 206 <h3 class="title"><a id="configdeadlkdetect"></a>Configuring Deadlock Detection</h3> 207 </div> 208 </div> 209 </div> 210 <p> 211 In order for DB to know that a deadlock has occurred, 212 some mechanism must be used to perform deadlock 213 detection. There are three ways that deadlock detection can 214 occur: 215 </p> 216 <div class="orderedlist"> 217 <ol type="1"> 218 <li> 219 <p> 220 Allow DB to internally detect deadlocks as they 221 occur. 222 </p> 223 <p> 224 To do this, you use 225 226 227 <span><code class="methodname">EnvironmentConfig.setLockDetectMode()</code>.</span> 228 This method causes DB to walk its internal lock table 229 looking for a deadlock whenever a lock request 230 is blocked. This method also identifies how DB decides which lock 231 requests are rejected when deadlocks are detected. For example, 232 DB can decide to reject the lock request for the transaction 233 that has the most number of locks, the least number of locks, 234 holds the oldest lock, holds the most number of write locks, and 235 so forth (see the API reference documentation for a complete 236 list of the lock detection policies). 237 </p> 238 <p> 239 You can call this method at any time during your application's 240 lifetime, but typically it is used before you open your environment. 241 </p> 242 <p> 243 Note that how you want DB to decide which thread of control should break a deadlock is 244 extremely dependent on the nature of your application. It is not unusual for some performance 245 testing to be required in order to make this determination. That said, a transaction that is 246 holding the maximum number of locks is usually indicative of the transaction that has performed 247 the most amount of work. Frequently you will not want a transaction that has performed a lot of 248 work to abandon its efforts and start all over again. It is not therefore uncommon for 249 application developers to initially select the transaction with the <span class="emphasis"><em>minimum</em></span> 250 number of write locks to break the deadlock. 251 </p> 252 <p> 253 Using this mechanism for deadlock detection means 254 that your application will never have to wait on a 255 lock before discovering that a deadlock has 256 occurred. However, walking the lock table every 257 time a lock request is blocked can be expensive 258 from a performance perspective. 259 </p> 260 </li> 261 <li> 262 <p> 263 Use a dedicated thread or external process to perform 264 deadlock detection. Note that this thread must be 265 performing no other database operations beyond deadlock 266 detection. 267 </p> 268 <p> 269 To externally perform lock detection, you can use 270 either the 271 272 273 <code class="methodname">Environment.detectDeadlocks()</code> 274 method, or use the 275 <span class="command"><strong>db_deadlock</strong></span> command line 276 utility. This method (or command) causes DB to walk the 277 lock table looking for deadlocks. 278 </p> 279 <p> 280 Note that like 281 282 283 <span><code class="methodname">EnvironmentConfig.setLockDetectMode()</code>,</span> 284 you also use this method (or command line utility) 285 to identify which lock requests are rejected in the 286 event that a deadlock is detected. 287 </p> 288 <p> 289 Applications that perform deadlock detection in 290 this way typically run deadlock detection between every few 291 seconds and a minute. This means that your 292 application may have to wait to be notified of a 293 deadlock, but you also save the overhead of walking 294 the lock table every time a lock request is blocked. 295 </p> 296 </li> 297 <li> 298 <p> 299 Lock timeouts. 300 </p> 301 <p> 302 You can configure your locking subsystem such that 303 it times out any lock that is not released within a 304 specified amount of time. To do this, use the 305 306 307 <span><code class="methodname">EnvironmentConfig.setLockTimeout()</code></span> 308 method. 309 Note that lock timeouts are only checked when a 310 lock request is blocked or when deadlock 311 detection is otherwise performed. Therefore, a lock can have timed out and still be held for 312 some length of time until DB has a reason to examine its locking tables. 313 </p> 314 <p> 315 Be aware that extremely long-lived transactions, or 316 operations that hold locks for a long time, may be 317 inappropriately timed out before the transaction or 318 operation has a chance to complete. You should 319 therefore use this mechanism only if you know your 320 application will hold locks for very short periods 321 of time. 322 </p> 323 </li> 324 </ol> 325 </div> 326 <p> 327 For example, to configure your application such that DB 328 checks the lock table for deadlocks every time a lock 329 request is blocked: 330 </p> 331 <pre class="programlisting">package db.txn; 332 333import com.sleepycat.db.Environment; 334import com.sleepycat.db.EnvironmentConfig; 335import com.sleepycat.db.LockDetectMode; 336 337import java.io.File; 338 339... 340 341Environment myEnv = null; 342try { 343 EnvironmentConfig myEnvConfig = new EnvironmentConfig(); 344 myEnvConfig.setTransactional(true); 345 myEnvConfig.setInitializeCache(true); 346 myEnvConfig.setInitializeLocking(true); 347 myEnvConfig.setInitializeLogging(true); 348 349 // Configure db to perform deadlock detection internally, and to 350 // choose the transaction that has performed the least amount 351 // of writing to break the deadlock in the event that one 352 // is detected. 353 envConfig.setLockDetectMode(LockDetectMode.MINWRITE); 354 355 myEnv = new Environment(new File("/my/env/home"), 356 myEnvConfig); 357 358 // From here, you open your databases, proceed with your 359 // database operations, and respond to deadlocks as 360 // is normal (omitted for brevity). 361 362 ...</pre> 363 <p> 364 Finally, the following command line call causes 365 deadlock detection to be run against the 366 environment contained in <code class="literal">/export/dbenv</code>. The 367 transaction with the youngest lock is chosen to break the 368 deadlock: 369 </p> 370 <pre class="programlisting">> /usr/local/db_install/bin/db_deadlock -h /export/dbenv -a y</pre> 371 <p> 372 For more information, see the 373 <a class="ulink" href="http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_deadlock.html" target="_top"> 374 <code class="literal">db_deadlock</code> reference documentation. 375 </a> 376 </p> 377 </div> 378 <div class="sect2" lang="en" xml:lang="en"> 379 <div class="titlepage"> 380 <div> 381 <div> 382 <h3 class="title"><a id="deadlockresolve"></a>Resolving Deadlocks</h3> 383 </div> 384 </div> 385 </div> 386 <p> 387 When DB determines that a deadlock has occurred, it will 388 select a thread of control to resolve the deadlock and then 389 390 391 <span> 392 throws <code class="literal">DeadlockException</code> in that 393 thread. 394 </span> 395 396 If a deadlock is detected, the thread must: 397 </p> 398 <div class="orderedlist"> 399 <ol type="1"> 400 <li> 401 <p> 402 Cease all read and write operations. 403 </p> 404 </li> 405 <li> 406 <p> 407 Close all open cursors. 408 </p> 409 </li> 410 <li> 411 <p> 412 Abort the transaction. 413 </p> 414 </li> 415 <li> 416 <p> 417 Optionally retry the operation. If your application 418 retries deadlocked operations, the new attempt must 419 be made using a new transaction. 420 </p> 421 </li> 422 </ol> 423 </div> 424 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"> 425 <h3 class="title">Note</h3> 426 <p> 427 If a thread has deadlocked, it may not make any 428 additional database calls using the handle that has 429 deadlocked. 430 </p> 431 </div> 432 <p> 433 For example: 434 </p> 435 <pre class="programlisting">// retry_count is a counter used to identify how many times 436// we've retried this operation. To avoid the potential for 437// endless looping, we won't retry more than MAX_DEADLOCK_RETRIES 438// times. 439 440// txn is a transaction handle. 441// key and data are DatabaseEntry handles. Their usage is not shown here. 442while (retry_count < MAX_DEADLOCK_RETRIES) { 443 try { 444 txn = myEnv.beginTransaction(null, null); 445 myDatabase.put(txn, key, data); 446 txn.commit(); 447 return 0; 448 } catch (DeadlockException de) { 449 try { 450 // Abort the transaction and increment the 451 // retry counter 452 txn.abort(); 453 retry_count++; 454 if (retry_count >= MAX_DEADLOCK_RETRIES) { 455 System.err.println("Exceeded retry limit. Giving up."); 456 return -1; 457 } 458 } catch (DatabaseException ae) { 459 System.err.println("txn abort failed: " + ae.toString()); 460 return -1; 461 } 462 } catch (DatabaseException e) { 463 try { 464 // Abort the transaction. 465 txn.abort(); 466 } catch (DatabaseException ae) { 467 System.err.println("txn abort failed: " + ae.toString()); 468 return -1; 469 } 470 } 471} </pre> 472 </div> 473 </div> 474 <div class="navfooter"> 475 <hr /> 476 <table width="100%" summary="Navigation footer"> 477 <tr> 478 <td width="40%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a> </td> 479 <td width="20%" align="center"> 480 <a accesskey="u" href="txnconcurrency.html">Up</a> 481 </td> 482 <td width="40%" align="right"> <a accesskey="n" href="isolation.html">Next</a></td> 483 </tr> 484 <tr> 485 <td width="40%" align="left" valign="top">Locks, Blocks, and Deadlocks </td> 486 <td width="20%" align="center"> 487 <a accesskey="h" href="index.html">Home</a> 488 </td> 489 <td width="40%" align="right" valign="top"> Isolation</td> 490 </tr> 491 </table> 492 </div> 493 </body> 494</html> 495