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 <span> 80 <code class="literal">DB_INIT_LOCK</code> to the 81 82 <code class="methodname">DbEnv::open()</code> 83 method. 84 </span> 85 86 </p> 87 <p> 88 Before opening your environment, you can configure various 89 maximum values for your locking subsystem. Note that these 90 limits can only be configured before the environment is 91 opened. Also, these methods configure the entire environment, 92 not just a specific environment handle. 93 </p> 94 <p> 95 Finally, each bullet below identifies the 96 <code class="filename">DB_CONFIG</code> file parameter that can be used 97 to specify the specific locking limit. If used, these 98 <code class="filename">DB_CONFIG</code> file parameters override any 99 value that you might specify using the environment handle. 100 </p> 101 <p> 102 The limits that you can configure are as follows: 103 </p> 104 <div class="itemizedlist"> 105 <ul type="disc"> 106 <li> 107 <p> 108 The maximum number of lockers 109 supported by the environment. This value is used by 110 the environment when it is opened to estimate the amount 111 of space that it should allocate for various internal 112 data structures. By default, 1,000 lockers are 113 supported. 114 </p> 115 <p> 116 To configure this value, use the 117 <span> 118 119 <code class="methodname">DbEnv::set_lk_max_lockers()</code> 120 method. 121 </span> 122 123 </p> 124 <p> 125 As an alternative to this method, you can configure this 126 value using the <code class="filename">DB_CONFIG</code> file's 127 <code class="literal">set_lk_max_lockers</code> parameter. 128 </p> 129 </li> 130 <li> 131 <p> 132 The maximum number of locks supported by the environment. 133 By default, 1,000 locks are supported. 134 </p> 135 <p> 136 To configure this value, use the 137 <span> 138 139 <code class="methodname">DbEnv::set_lk_max_locks()</code> 140 method. 141 </span> 142 143 </p> 144 <p> 145 As an alternative to this method, you can configure this 146 value using the <code class="filename">DB_CONFIG</code> file's 147 <code class="literal">set_lk_max_locks</code> parameter. 148 </p> 149 </li> 150 <li> 151 <p> 152 The maximum number of locked objects supported by the environment. 153 By default, 1,000 objects can be locked. 154 </p> 155 <p> 156 To configure this value, use the 157 <span> 158 159 <code class="methodname">DbEnv::set_lk_max_objects()</code> 160 method. 161 </span> 162 163 </p> 164 <p> 165 As an alternative to this method, you can configure this 166 value using the <code class="filename">DB_CONFIG</code> file's 167 <code class="literal">set_lk_max_objects</code> parameter. 168 </p> 169 </li> 170 </ul> 171 </div> 172 <p> 173 For a definition of lockers, locks, and locked objects, see 174 <a class="xref" href="blocking_deadlocks.html#lockresources" title="Lock Resources">Lock Resources</a>. 175 </p> 176 <p> 177 For example, to configure the maximum number of locks that your 178 environment can use: 179 </p> 180 <pre class="programlisting">#include "db_cxx.h" 181 182... 183 184int main(void) 185{ 186 u_int32_t env_flags = DB_CREATE | // If the environment does not 187 // exist, create it. 188 DB_INIT_LOCK | // Initialize locking 189 DB_INIT_LOG | // Initialize logging 190 DB_INIT_MPOOL | // Initialize the cache 191 DB_THREAD | // Free-thread the env handle. 192 DB_INIT_TXN; // Initialize transactions 193 194 std::string envHome("/export1/testEnv"); 195 DbEnv myEnv(0); 196 197 try { 198 199 // Configure max locks 200 myEnv.set_lk_max_locks(envp, 5000); 201 202 myEnv.open(envHome.c_str(), env_flags, 0); 203 204 } catch(DbException &e) { 205 std::cerr << "Error opening database environment: " 206 << envHome << std::endl; 207 std::cerr << e.what() << std::endl; 208 return (EXIT_FAILURE); 209 } 210 211 try { 212 myEnv.close(0); 213 } catch(DbException &e) { 214 std::cerr << "Error closing database environment: " 215 << envHome << std::endl; 216 std::cerr << e.what() << std::endl; 217 return (EXIT_FAILURE); 218 } 219 220 return (EXIT_SUCCESS); 221} </pre> 222 </div> 223 <div class="sect2" lang="en" xml:lang="en"> 224 <div class="titlepage"> 225 <div> 226 <div> 227 <h3 class="title"><a id="configdeadlkdetect"></a>Configuring Deadlock Detection</h3> 228 </div> 229 </div> 230 </div> 231 <p> 232 In order for DB to know that a deadlock has occurred, 233 some mechanism must be used to perform deadlock 234 detection. There are three ways that deadlock detection can 235 occur: 236 </p> 237 <div class="orderedlist"> 238 <ol type="1"> 239 <li> 240 <p> 241 Allow DB to internally detect deadlocks as they 242 occur. 243 </p> 244 <p> 245 To do this, you use 246 247 <span><code class="methodname">DbEnv::set_lk_detect()</code>.</span> 248 249 This method causes DB to walk its internal lock table 250 looking for a deadlock whenever a lock request 251 is blocked. This method also identifies how DB decides which lock 252 requests are rejected when deadlocks are detected. For example, 253 DB can decide to reject the lock request for the transaction 254 that has the most number of locks, the least number of locks, 255 holds the oldest lock, holds the most number of write locks, and 256 so forth (see the API reference documentation for a complete 257 list of the lock detection policies). 258 </p> 259 <p> 260 You can call this method at any time during your application's 261 lifetime, but typically it is used before you open your environment. 262 </p> 263 <p> 264 Note that how you want DB to decide which thread of control should break a deadlock is 265 extremely dependent on the nature of your application. It is not unusual for some performance 266 testing to be required in order to make this determination. That said, a transaction that is 267 holding the maximum number of locks is usually indicative of the transaction that has performed 268 the most amount of work. Frequently you will not want a transaction that has performed a lot of 269 work to abandon its efforts and start all over again. It is not therefore uncommon for 270 application developers to initially select the transaction with the <span class="emphasis"><em>minimum</em></span> 271 number of write locks to break the deadlock. 272 </p> 273 <p> 274 Using this mechanism for deadlock detection means 275 that your application will never have to wait on a 276 lock before discovering that a deadlock has 277 occurred. However, walking the lock table every 278 time a lock request is blocked can be expensive 279 from a performance perspective. 280 </p> 281 </li> 282 <li> 283 <p> 284 Use a dedicated thread or external process to perform 285 deadlock detection. Note that this thread must be 286 performing no other database operations beyond deadlock 287 detection. 288 </p> 289 <p> 290 To externally perform lock detection, you can use 291 either the 292 293 <code class="methodname">DbEnv::lock_detect()</code> 294 295 method, or use the 296 <span class="command"><strong>db_deadlock</strong></span> command line 297 utility. This method (or command) causes DB to walk the 298 lock table looking for deadlocks. 299 </p> 300 <p> 301 Note that like 302 303 <span><code class="methodname">DbEnv::set_lk_detect()</code>,</span> 304 305 you also use this method (or command line utility) 306 to identify which lock requests are rejected in the 307 event that a deadlock is detected. 308 </p> 309 <p> 310 Applications that perform deadlock detection in 311 this way typically run deadlock detection between every few 312 seconds and a minute. This means that your 313 application may have to wait to be notified of a 314 deadlock, but you also save the overhead of walking 315 the lock table every time a lock request is blocked. 316 </p> 317 </li> 318 <li> 319 <p> 320 Lock timeouts. 321 </p> 322 <p> 323 You can configure your locking subsystem such that 324 it times out any lock that is not released within a 325 specified amount of time. To do this, use the 326 327 <span><code class="methodname">DbEnv::set_timeout()</code></span> 328 329 method. 330 Note that lock timeouts are only checked when a 331 lock request is blocked or when deadlock 332 detection is otherwise performed. Therefore, a lock can have timed out and still be held for 333 some length of time until DB has a reason to examine its locking tables. 334 </p> 335 <p> 336 Be aware that extremely long-lived transactions, or 337 operations that hold locks for a long time, may be 338 inappropriately timed out before the transaction or 339 operation has a chance to complete. You should 340 therefore use this mechanism only if you know your 341 application will hold locks for very short periods 342 of time. 343 </p> 344 </li> 345 </ol> 346 </div> 347 <p> 348 For example, to configure your application such that DB 349 checks the lock table for deadlocks every time a lock 350 request is blocked: 351 </p> 352 <pre class="programlisting">#include "db_cxx.h" 353 354... 355 356int main(void) 357{ 358 u_int32_t env_flags = DB_CREATE | // If the environment does not 359 // exist, create it. 360 DB_INIT_LOCK | // Initialize locking 361 DB_INIT_LOG | // Initialize logging 362 DB_INIT_MPOOL | // Initialize the cache 363 DB_THREAD | // Free-thread the env handle 364 DB_INIT_TXN; // Initialize transactions 365 366 std::string envHome("/export1/testEnv"); 367 DbEnv myEnv(0); 368 369 try { 370 371 // Configure db to perform deadlock detection internally, and to 372 // choose the transaction that has performed the least amount 373 // of writing to break the deadlock in the event that one 374 // is detected. 375 myEnv.set_lk_detect(DB_LOCK_MINWRITE); 376 myEnv.open(envHome.c_str(), env_flags, 0); 377 378 // From here, you open your databases, proceed with your 379 // database operations, and respond to deadlocks as 380 // is normal (omitted for brevity). 381 382 383 ...</pre> 384 <p> 385 Finally, the following command line call causes 386 deadlock detection to be run against the 387 environment contained in <code class="literal">/export/dbenv</code>. The 388 transaction with the youngest lock is chosen to break the 389 deadlock: 390 </p> 391 <pre class="programlisting">> /usr/local/db_install/bin/db_deadlock -h /export/dbenv -a y</pre> 392 <p> 393 For more information, see the 394 <a class="ulink" href="http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_deadlock.html" target="_top"> 395 <code class="literal">db_deadlock</code> reference documentation. 396 </a> 397 </p> 398 </div> 399 <div class="sect2" lang="en" xml:lang="en"> 400 <div class="titlepage"> 401 <div> 402 <div> 403 <h3 class="title"><a id="deadlockresolve"></a>Resolving Deadlocks</h3> 404 </div> 405 </div> 406 </div> 407 <p> 408 When DB determines that a deadlock has occurred, it will 409 select a thread of control to resolve the deadlock and then 410 411 <span> 412 throws <code class="literal">DbDeadlockException</code> in that 413 thread. 414 </span> 415 416 417 If a deadlock is detected, the thread must: 418 </p> 419 <div class="orderedlist"> 420 <ol type="1"> 421 <li> 422 <p> 423 Cease all read and write operations. 424 </p> 425 </li> 426 <li> 427 <p> 428 Close all open cursors. 429 </p> 430 </li> 431 <li> 432 <p> 433 Abort the transaction. 434 </p> 435 </li> 436 <li> 437 <p> 438 Optionally retry the operation. If your application 439 retries deadlocked operations, the new attempt must 440 be made using a new transaction. 441 </p> 442 </li> 443 </ol> 444 </div> 445 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"> 446 <h3 class="title">Note</h3> 447 <p> 448 If a thread has deadlocked, it may not make any 449 additional database calls using the handle that has 450 deadlocked. 451 </p> 452 </div> 453 <p> 454 For example: 455 </p> 456 <pre class="programlisting">// retry_count is a counter used to identify how many times 457// we've retried this operation. To avoid the potential for 458// endless looping, we won't retry more than MAX_DEADLOCK_RETRIES 459// times. 460 461// txn is a transaction handle. 462// key and data are DBT handles. Their usage is not shown here. 463while (retry_count < MAX_DEADLOCK_RETRIES) { 464 try { 465 envp->txn_begin(NULL, txn, 0); 466 dbp->put(txn, &key, &data, 0); 467 txn->commit(0); 468 return (EXIT_SUCCESS); 469 } catch (DbDeadlockException &de) { 470 try { 471 // Abort the transaction and increment the 472 // retry counter 473 txn->abort(); 474 retry_count++; 475 // If we've retried too many times, log it and exit 476 if (retry_count >= MAX_DEADLOCK_RETRIES) { 477 envp->errx("Exceeded retry limit. Giving up."); 478 return (EXIT_FAILURE); 479 } 480 } catch (DbException &ae) { 481 envp->err(ae.get_errno(), "txn abort failed."); 482 return (EXIT_FAILURE); 483 } 484 } catch (DbException &e) { 485 try { 486 // For a generic error, log it and abort. 487 envp->err(e.get_errno(), "Error putting data."); 488 txn->abort(); 489 } catch (DbException &ae) { 490 envp->err(ae.get_errno(), "txn abort failed."); 491 return (EXIT_FAILURE); 492 } 493 } 494} </pre> 495 </div> 496 </div> 497 <div class="navfooter"> 498 <hr /> 499 <table width="100%" summary="Navigation footer"> 500 <tr> 501 <td width="40%" align="left"><a accesskey="p" href="blocking_deadlocks.html">Prev</a> </td> 502 <td width="20%" align="center"> 503 <a accesskey="u" href="txnconcurrency.html">Up</a> 504 </td> 505 <td width="40%" align="right"> <a accesskey="n" href="isolation.html">Next</a></td> 506 </tr> 507 <tr> 508 <td width="40%" align="left" valign="top">Locks, Blocks, and Deadlocks </td> 509 <td width="20%" align="center"> 510 <a accesskey="h" href="index.html">Home</a> 511 </td> 512 <td width="40%" align="right" valign="top"> Isolation</td> 513 </tr> 514 </table> 515 </div> 516 </body> 517</html> 518