Problem/Motivation
I am seeing a lot of these errors in PostgreSQL logs - generally when running update.php, but also at other times (I haven't nailed down exactly what triggers it, but seems to be related to theme caching):
message: duplicate key value violates unique constraint "semaphore____pkey"
detail: Key (name)=(library_info:gin:Drupal\Core\Cache\CacheCollector) already exists
query: INSERT INTO "semaphore" ("name", "value", "expire") VALUES ('library_info:gin:Drupal\Core\Cache\CacheCollector', '682342772636186141f2d65.49789030', '1667335733.4565')
and:
message: duplicate key value violates unique constraint "key_value____pkey"
detail: Key (collection, name)=(state, system.theme.files) already exists.
query: INSERT INTO "key_value" ("name", "collection", "value") VALUES ('system.theme.files', 'state', '...')
I am not sure if this is specific to Gin, or if this is an upstream issue with Drupal core and PostgreSQL more generally. I will start this issue here, but move it to core if I can reproduce it with another theme (eg: Claro).
I did find two similar issues filed against Drupal 7 core. They may provide some clues, but they appear to be different in their origin:
- #1874966: ERROR: duplicate key value violates unique constraint "semaphore_pkey" - continous error on PostgreSQL
- #1907230: PostgreSQL - duplicate key value violates unique constraint “drupal_cache_block_pkey”
Steps to reproduce
TBD
Proposed resolution
TBD
Remaining tasks
TBD
User interface changes
None.
API changes
None.
Data model changes
None.
For the committer
The changes to the .gitlab-ci.yml file need to be removed before merging!
Issue fork drupal-3318915
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
m.stentaReading more in #1874966: ERROR: duplicate key value violates unique constraint "semaphore_pkey" - continous error on PostgreSQL and #1907230: PostgreSQL - duplicate key value violates unique constraint “drupal_cache_block_pkey” - it sounds like maybe these errors are actually expected behavior of Drupal core for PostgreSQL. Moving this over to the core issue queue because it probably isn't a Gin-specific issue.
Comment #3
mradcliffeI wonder if this race condition is happening because of the .theme include stuff? Might be something to combine the include/.theme files back into the main .theme file and comment out that line that does the include. It's possible that line might be doing something during a cache flush or cache clear?
Comment #4
andypostMaybe that's how "upsert" works now in core?
Comment #5
daffie commentedI think this is a Drupal 7 problem, not Drupal 10.
Comment #6
m.stenta@daffie No, I still get these errors consistently on Drupal 9. I've just set up my error log monitoring to ignore them, but it would be nice if I didn't have to do that.
Comment #7
daffie commented@m.stenta: Could you add a test or an other way to reproduce the bug? It is now a bit difficult to solve.
Comment #8
daffie commentedComment #9
m.stentaI haven't figured out what causes it, and haven't been able to intentionally reproduce it. I host a large number of sites running D9 on PostgreSQL though and my logs show that it is happening pretty consistently. It seems to be correlated to cache rebuild (and/or some cron runs), but it doesn't happen all the time so it's hard to nail down.
Comment #10
daffie commented@m.stenta: Could you possibly add the full query that is failing. That is including the part "EXCLUDED" and the part after "ON CONFLICT". Maybe too many Drupal merge queries in a short timeframe.
Comment #11
m.stentaAs far as I know, the query I pasted in the issue summary is the entire query that failed.
I admit I don't have a good sense for how the
semaphoretable works, but I'm not sure thatupsert()is being used forsemaphoretable modifications... it looks like onlyinsert()andupdate()are used. Am I reading that correctly?https://git.drupalcode.org/project/drupal/-/blob/bef31d1d77de39e8622678a...
Comment #13
luisnicg commentedComment #14
mfbThis same error message happens on a clean install of drupal, aside from the theme name being olivero, claro, etc.
This is because of how drupal tries to acquire the lock by inserting, and then catching the exception. Postgres by default logs an error for such failed inserts, although you could configure postgres to do less verbose logging.
Failing to acquire the lock is almost guaranteed even with just a single user, because that one page load can bootstrap drupal multiple times when loading CSS and JS files. Easiest way to reproduce is to clear drupal cache and shift-reload page to force your browser to reload all the CSS and JS files.
Comment #15
andypostChecked my logs and found that pgsql sometimes hangs and after restart is unable to insert into
semaphoreComment #16
andypostComment #17
chi commentedRe #7 Writing a test requires concurrent requests and reading PostgreSQL log. That's not what Drupal testing system is capable of. To reproduce the issue manually you can run simultaneously a couple CLI scripts which acquire a lock with the same ID.
The root reason of this error is explained well in #14.
Comment #18
chi commentedPossible solution is execution SELECT query before the INSERT in the same transaction. Though it may behave differently depending on configured transaction isolation level.
We can also consider using some third party lock implementation, for instance symfony/lock.
Comment #19
chi commentedRe: #18
This snippet works for me.
Overall, I think the default lock implementation should use flock backend instead of database.
Comment #20
revathidinesh commented@chi
Where should we add the above code snippet?
Comment #21
chi commentedThe snippet needs to be converted to a patch for DatabaseLockBackend.
Comment #25
daffie commentedDisclosure: I have used AI for the PR.
Comment #26
smustgrave commentedAppears to need a rebase for a conflict in the performance test.