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