Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The only portable way to achieve consistency between rooms and tags and making sure rooms are never returned after they had been deleted is locking them with <code>SELECT FOR UPDATE</code>.</p> <p>However in some systems locking is a side effect of concurrency control, and you achieve the same results without specifying <code>FOR UPDATE</code> explicitly.</p> <hr> <blockquote> <p>To solve this problem, Thread 1 should <code>SELECT id FROM rooms FOR UPDATE</code>, thereby preventing Thread 2 from deleting from <code>rooms</code> until Thread 1 is done. Is that correct?</p> </blockquote> <p>This depends on the concurrency control your database system is using.</p> <ul> <li><p><code>MyISAM</code> in <code>MySQL</code> (and several other old systems) does lock the whole table for the duration of a query.</p></li> <li><p>In <code>SQL Server</code>, <code>SELECT</code> queries place shared locks on the records / pages / tables they have examined, while <code>DML</code> queries place update locks (which later get promoted to exclusive or demoted to shared locks). Exclusive locks are incompatible with shared locks, so either <code>SELECT</code> or <code>DELETE</code> query will lock until another session commits.</p></li> <li><p>In databases which use <code>MVCC</code> (like <code>Oracle</code>, <code>PostgreSQL</code>, <code>MySQL</code> with <code>InnoDB</code>), a <code>DML</code> query creates a copy of the record (in one or another way) and generally readers do not block writers and vice versa. For these databases, a <code>SELECT FOR UPDATE</code> would come handy: it would lock either <code>SELECT</code> or the <code>DELETE</code> query until another session commits, just as <code>SQL Server</code> does.</p></li> </ul> <blockquote> <p>When should one use <code>REPEATABLE_READ</code> transaction isolation versus <code>READ_COMMITTED</code> with <code>SELECT ... FOR UPDATE</code>?</p> </blockquote> <p>Generally, <code>REPEATABLE READ</code> does not forbid phantom rows (rows that appeared or disappeared in another transaction, rather than being modified)</p> <ul> <li><p>In <code>Oracle</code> and earlier <code>PostgreSQL</code> versions, <code>REPEATABLE READ</code> is actually a synonym for <code>SERIALIZABLE</code>. Basically, this means that the transaction does not see changes made after it has started. So in this setup, the last <code>Thread 1</code> query will return the room as if it has never been deleted (which may or may not be what you wanted). If you don't want to show the rooms after they have been deleted, you should lock the rows with <code>SELECT FOR UPDATE</code></p></li> <li><p>In <code>InnoDB</code>, <code>REPEATABLE READ</code> and <code>SERIALIZABLE</code> are different things: readers in <code>SERIALIZABLE</code> mode set next-key locks on the records they evaluate, effectively preventing the concurrent <code>DML</code> on them. So you don't need a <code>SELECT FOR UPDATE</code> in serializable mode, but do need them in <code>REPEATABLE READ</code> or <code>READ COMMITED</code>.</p></li> </ul> <p>Note that the standard on isolation modes does prescribe that you don't see certain quirks in your queries but does not define how (with locking or with <code>MVCC</code> or otherwise).</p> <p>When I say "you don't need <code>SELECT FOR UPDATE</code>" I really should have added "because of side effects of certain database engine implementation".</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload