Skip to content

Commit

Permalink
store: Use a different locking strategy for deployments
Browse files Browse the repository at this point in the history
We used 'select for update' to lock a deployment against concurrent
writes. It seems that that has bad consequences for performance in general;
advisory locks are more lightweight than locking table rows, hopefully
using them here will help write performance.
  • Loading branch information
lutter committed Sep 29, 2022
1 parent 487c35e commit 5ed153a
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 13 deletions.
9 changes: 9 additions & 0 deletions store/postgres/src/advisory_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//! We use the following 2x 32-bit locks
//! * 1, n: to lock copying of the deployment with id n in the destination
//! shard
//! * 2, n: to lock the deployment with id n to make sure only one write
//! happens to it
use diesel::{sql_query, PgConnection, RunQueryDsl};
use graph::prelude::StoreError;
Expand Down Expand Up @@ -44,3 +46,10 @@ pub(crate) fn unlock_copying(conn: &PgConnection, dst: &Site) -> Result<(), Stor
.map(|_| ())
.map_err(StoreError::from)
}

pub(crate) fn lock_deployment_xact(conn: &PgConnection, site: &Site) -> Result<(), StoreError> {
sql_query(&format!("select pg_advisory_xact_lock(2, {})", site.id))
.execute(conn)
.map(|_| ())
.map_err(StoreError::from)
}
19 changes: 6 additions & 13 deletions store/postgres/src/deployment.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Utilities for dealing with deployment metadata. Any connection passed
//! into these methods must be for the shard that holds the actual
//! deployment data and metadata
use crate::{detail::GraphNodeVersion, primary::DeploymentId};
use crate::{advisory_lock, detail::GraphNodeVersion, primary::DeploymentId};
use diesel::{
connection::SimpleConnection,
dsl::{count, delete, insert_into, select, sql, update},
Expand Down Expand Up @@ -1024,18 +1024,11 @@ pub fn set_earliest_block(
Ok(())
}

/// Lock the row for `site` in `subgraph_deployment` for update for the
/// remainder of the current transaction. This lock is used to coordinate
/// the changes that the subgraph writer makes with changes that other parts
/// of the system, in particular, pruning make
/// Lock the deployment `site` for writes for the remainder of the current
/// transaction. This lock is used to coordinate the changes that the
/// subgraph writer makes with changes that other parts of the system, in
/// particular, pruning make
// see also: deployment-lock-for-update
pub fn lock(conn: &PgConnection, site: &Site) -> Result<(), StoreError> {
use subgraph_deployment as d;

d::table
.select(d::id)
.filter(d::id.eq(site.id))
.for_update()
.get_result::<DeploymentId>(conn)?;
Ok(())
advisory_lock::lock_deployment_xact(conn, site)
}

0 comments on commit 5ed153a

Please sign in to comment.