Closed DimitriyKh closed 2 years ago
I would suggest using the project/target name in get_lock somehow, or maybe there is a way to disable get_lock at all
something like this would also work for me
diff --git a/lib/App/Sqitch/Engine/mysql.pm b/lib/App/Sqitch/Engine/mysql.pm
--- a/lib/App/Sqitch/Engine/mysql.pm (revision caaa1ef5ee0260cc02bf5a0ba81a8475f5d30749)
+++ b/lib/App/Sqitch/Engine/mysql.pm (date 1660561471871)
@@ -317,8 +317,9 @@
my $self = shift;
# Can't create a lock in the registry if it doesn't exist.
$self->initialize unless $self->initialized;
+ my $lock_name = $self->uri->dbname;
$self->dbh->selectcol_arrayref(
- q{SELECT get_lock('sqitch working', 0)}
+ qq{SELECT get_lock('sqitch working on $lock_name', 0)}
)->[0]
}
It should probably lock on the registry name.
On second thought I'm a bit stumped on what to do here, since MySQL allows one to make changes to any database without reconnecting. They're effectively schemas, not databases. This is why the lock name today is global to the server: to prevent any conflicting runs at all.
I suspect very few people connect to one database and make changes to another, but it's only a suspicion, and I certainly have written Postgres Sqitch projects that update multipole schemas. And the lock there for the whole database ensures only one instance can run at a time that's updating that database. This is identical to the behavior or the MySQL engine, except that there are no completely independent namespaces in a single server.
So I'm not entirely sure what to do here. The options, as I see them, are:
Database is an alias to schema in mysql, the current approach blocks not only the database, but the whole server from not concurrent but parallel deploys. So the lock has to be either removed or renamed. We have tens of clients on single "server", deploying them one-by-one is a total time waste. As for locking with registry name, I see no reason for it as you already lock the whole registry itself in Engine/mysql.pm
# Override to lock the Sqitch tables. This ensures that only one instance of
# Sqitch runs at one time.
sub begin_work {
my $self = shift;
my $dbh = $self->dbh;
# Start transaction and lock all tables to disallow concurrent changes.
$dbh->do('LOCK TABLES ' . join ', ', map {
"$_ WRITE"
} qw(releases changes dependencies events projects tags));
$dbh->begin_work;
return $self;
Okay, option 2 has the least problematic trade-offs, and is probably the most intuitive solution: one probably would expect the lock to be scoped just to the one database you connect to.
Proposed fix in #677.
Since get_lock from
Instantiates serverwide exclusive lock, there is no possibility to run simultaneous deploy on different schemas.
Also, the error message
appears to be misleading, and displays the target name of current deploy, not the one that holds the lock
steps to reproduce: create a target DBs, users and grants:
create two sqtich projects, init sqitch, add targets and add a target per project so sqitch.config looks as follows:
add sample migration with sqitch add for each project
run sqitch in two terminal windows in parallel project1
sqitch deploy -t t1
project2sqitch deploy -t t2
while the first run works, the second one returns an error: