Skip to content

Commit 7ba6405

Browse files
committed
fix: Stop locking catalog for every resources.
Historically, this provider takes a (golang) lock on a database for every resource of this database. So only one create/update/delete of resource by database can be done at the same time. (As it's a RWLock, read of resources can be parallelized) Since #5 refactoring, I mistakenly change the lock which now takes a write lock even for read operations (basically the plan part of Terraform). So provider was slower since v1.10 We could fix this and take a read lock for read operations as before but actually I don't see the point of this lock. For me, most operations could be done at the same time. Most of the request are now done in a transaction, the only risk is that a transaction will fail to commit if multiple resources modifies the same database line. That's the case for `postgresql_default_privileges`, one `pg_default_acl` row could represents multiple resources, so this PR takes a lock on the owner role to avoid that. This should make the provider way faster. Fix #48
1 parent 89f50c2 commit 7ba6405

File tree

3 files changed

+20
-14
lines changed

3 files changed

+20
-14
lines changed

postgresql/config.go

-7
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,6 @@ type Client struct {
141141
config Config
142142

143143
databaseName string
144-
145-
// PostgreSQL lock on pg_catalog. Many of the operations that Terraform
146-
// performs are not permitted to be concurrent. Unlike traditional
147-
// PostgreSQL tables that use MVCC, many of the PostgreSQL system
148-
// catalogs look like tables, but are not in-fact able to be
149-
// concurrently updated.
150-
catalogLock sync.RWMutex
151144
}
152145

153146
// NewClient returns client config for the specified database.

postgresql/helpers.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ func PGResourceFunc(fn func(*DBConnection, *schema.ResourceData) error) func(*sc
1414
return func(d *schema.ResourceData, meta interface{}) error {
1515
client := meta.(*Client)
1616

17-
client.catalogLock.Lock()
18-
defer client.catalogLock.Unlock()
19-
2017
db, err := client.Connect()
2118
if err != nil {
2219
return err
@@ -30,9 +27,6 @@ func PGResourceExistsFunc(fn func(*DBConnection, *schema.ResourceData) (bool, er
3027
return func(d *schema.ResourceData, meta interface{}) (bool, error) {
3128
client := meta.(*Client)
3229

33-
client.catalogLock.Lock()
34-
defer client.catalogLock.Unlock()
35-
3630
db, err := client.Connect()
3731
if err != nil {
3832
return false, err
@@ -447,3 +441,11 @@ func getRoleOID(db QueryAble, role string) (int, error) {
447441
}
448442
return oid, nil
449443
}
444+
445+
func pgLockRole(txn *sql.Tx, role string) error {
446+
if _, err := txn.Exec("SELECT pg_advisory_lock(oid::bigint) from pg_roles where rolname = $1", role); err != nil {
447+
return fmt.Errorf("could not get advisory lock for role %s: %w", role, err)
448+
}
449+
450+
return nil
451+
}

postgresql/resource_postgresql_default_privileges.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ func resourcePostgreSQLDefaultPrivilegesCreate(db *DBConnection, d *schema.Resou
114114
}
115115
defer deferredRollback(txn)
116116

117+
if err := pgLockRole(txn, owner); err != nil {
118+
return err
119+
}
120+
117121
// Needed in order to set the owner of the db if the connection user is not a superuser
118122
if err := withRolesGranted(txn, []string{owner}, func() error {
119123

@@ -156,6 +160,10 @@ func resourcePostgreSQLDefaultPrivilegesDelete(db *DBConnection, d *schema.Resou
156160
}
157161
defer deferredRollback(txn)
158162

163+
if err := pgLockRole(txn, owner); err != nil {
164+
return err
165+
}
166+
159167
// Needed in order to set the owner of the db if the connection user is not a superuser
160168
if err := withRolesGranted(txn, []string{owner}, func() error {
161169
return revokeRoleDefaultPrivileges(txn, d)
@@ -176,6 +184,10 @@ func readRoleDefaultPrivileges(txn *sql.Tx, d *schema.ResourceData) error {
176184
pgSchema := d.Get("schema").(string)
177185
objectType := d.Get("object_type").(string)
178186

187+
if err := pgLockRole(txn, owner); err != nil {
188+
return err
189+
}
190+
179191
roleOID, err := getRoleOID(txn, role)
180192
if err != nil {
181193
return err
@@ -208,7 +220,6 @@ func readRoleDefaultPrivileges(txn *sql.Tx, d *schema.ResourceData) error {
208220
// and the specified object type (defaclobjtype).
209221

210222
var privileges pq.ByteaArray
211-
212223
if err := txn.QueryRow(
213224
query, queryArgs...,
214225
).Scan(&privileges); err != nil {

0 commit comments

Comments
 (0)