Skip to content

Commit bcdb5a0

Browse files
committed
Fix failing MySQL spec due to deadlock condition
`spec/features/uploads/user_uploads_file_to_note_spec.rb` was failing in master because MySQL detected a deadlock when a DELETE and INSERT for the same indexed item occurred within a transaction in the `uploads` table. Due to InnoDB's next-key locking algorithm (innodb_locks_unsafe_for_binlog in https://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html), InnoDB sets an exclusive lock for any of the indexed records it encounters, so the INSERT will fail until the DELETE is committed. To fix this, we just disable the transaction for MySQL and keep it for PostgreSQL. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/55161
1 parent 0e51078 commit bcdb5a0

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

app/uploaders/records_uploads.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,23 @@ def record_upload(_tempfile = nil)
2323
return unless model
2424
return unless file && file.exists?
2525

26-
Upload.transaction do
27-
uploads.where(path: upload_path).delete_all
28-
upload.delete if upload
29-
30-
self.upload = build_upload.tap(&:save!)
26+
# MySQL InnoDB may encounter a deadlock if a deletion and an
27+
# insert is in the same transaction due to its next-key locking
28+
# algorithm, so we need to skip the transaction.
29+
# https://gitlab.com/gitlab-org/gitlab-ce/issues/55161#note_131556351
30+
if Gitlab::Database.mysql?
31+
readd_upload
32+
else
33+
Upload.transaction { readd_upload }
3134
end
3235
end
36+
37+
def readd_upload
38+
uploads.where(path: upload_path).delete_all
39+
upload.delete if upload
40+
41+
self.upload = build_upload.tap(&:save!)
42+
end
3343
# rubocop: enable CodeReuse/ActiveRecord
3444

3545
def upload_path

0 commit comments

Comments
 (0)