Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to make these two simultaneous transactions succeed at all times, without causing a uniqueness violation?
    primarykey
    data
    text
    <p>Let's pretend that there's a <code>tags</code> table with a unique field called <code>name</code>.</p> <p>I have a transaction in which I perform a select to see if a tag with a specific name exists, and if it wasn't I create it:</p> <pre><code>START TRANSACTION; SELECT * FROM TAGS WHERE NAME = "FOO"; -- IF A TAG NAMED "FOO" DIDN'T EXIST THEN INSERT INTO TAGS VALUES("FOO"); COMMIT; </code></pre> <p>When two clients run this transaction in the default isolation level (repeatable read), this interleaving will lead one of them to fail with a uniqueness violation:</p> <pre><code>START TRANSACTION; START TRANSACTION; SELECT * FROM TAGS WHERE NAME = "FOO"; SELECT * FROM TAGS WHERE NAME = "FOO"; -- IF A TAG NAMED "FOO" DIDN'T EXIST THEN INSERT INTO TAGS VALUES("FOO"); -- IF A TAG NAMED "FOO" DIDN'T EXIST THEN INSERT INTO TAGS VALUES("FOO"); COMMIT; COMMIT; </code></pre> <p>I thought if I set the isolation level to serializable, I can avoid this situation, but I noticed that the same interleaving will then lead to a deadlock.</p> <p>How can I modify the transaction so that it never fails due to uniqueness constraint violation?</p> <p>For the record, this is the Ruby on Rails (ActiveRecord) code that corresponds to this scenario:</p> <pre><code>class Tag &lt; ActiveRecord::Base def self.create_tag(name) transaction do # setting isolation level to serializable leads to a deadlock # Tag.connection.execute("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE") gets tag = Tag.find_by_name(name) if tag.nil? gets Tag.create!(:name =&gt; name) end end end end </code></pre>
    singulars
    1. This table or related slice is empty.
    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.
 

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