summaryrefslogtreecommitdiff
path: root/app/uploaders
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2019-01-14 16:08:28 -0800
committerStan Hu <stanhu@gmail.com>2019-01-14 21:17:40 -0800
commitbcdb5a0a2d62caa685c32c5d1a4453bd5926b5b1 (patch)
tree73053901d8d0d565d949e8359c2d03f1de65bffc /app/uploaders
parent0e510780a15955b06445fb4c440230151da9ae93 (diff)
downloadgitlab-ce-bcdb5a0a2d62caa685c32c5d1a4453bd5926b5b1.tar.gz
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
Diffstat (limited to 'app/uploaders')
-rw-r--r--app/uploaders/records_uploads.rb20
1 files changed, 15 insertions, 5 deletions
diff --git a/app/uploaders/records_uploads.rb b/app/uploaders/records_uploads.rb
index 0efca895a50..9a243e07936 100644
--- a/app/uploaders/records_uploads.rb
+++ b/app/uploaders/records_uploads.rb
@@ -23,13 +23,23 @@ module RecordsUploads
return unless model
return unless file && file.exists?
- Upload.transaction do
- uploads.where(path: upload_path).delete_all
- upload.delete if upload
-
- self.upload = build_upload.tap(&:save!)
+ # MySQL InnoDB may encounter a deadlock if a deletion and an
+ # insert is in the same transaction due to its next-key locking
+ # algorithm, so we need to skip the transaction.
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/55161#note_131556351
+ if Gitlab::Database.mysql?
+ readd_upload
+ else
+ Upload.transaction { readd_upload }
end
end
+
+ def readd_upload
+ uploads.where(path: upload_path).delete_all
+ upload.delete if upload
+
+ self.upload = build_upload.tap(&:save!)
+ end
# rubocop: enable CodeReuse/ActiveRecord
def upload_path