Skip to content

Instantly share code, notes, and snippets.

@creotiv
Created November 24, 2023 14:51
Show Gist options
  • Save creotiv/7ef5d0b3e970d79dcf9fe47e8dd68065 to your computer and use it in GitHub Desktop.
Save creotiv/7ef5d0b3e970d79dcf9fe47e8dd68065 to your computer and use it in GitHub Desktop.
Postgresql Deadlock example using Pgx.Batch
CREATE DATABASE testdb;
CREATE TABLE items (
id SERIAL PRIMARY KEY,
name TEXT,
quantity INT
);
INSERT INTO items (name, quantity) VALUES ('Item1', 10);
INSERT INTO items (name, quantity) VALUES ('Item2', 20);
package main
import (
"context"
"fmt"
"os"
"sync"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
connStr := "postgres://localhost/testdb"
pool, err := pgxpool.New(context.Background(), connStr)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
defer pool.Close()
var wg sync.WaitGroup
wg.Add(8)
go updateItems(pool, &wg, 1, 2)
go updateItems(pool, &wg, 2, 1)
go updateItems(pool, &wg, 1, 2)
go updateItems(pool, &wg, 2, 1)
go updateItems(pool, &wg, 1, 2)
go updateItems(pool, &wg, 2, 1)
go updateItems(pool, &wg, 1, 2)
go updateItems(pool, &wg, 2, 1)
wg.Wait()
}
func updateItems(pool *pgxpool.Pool, wg *sync.WaitGroup, firstItemID, secondItemID int) {
// Begin a batch of updates
batch := &pgx.Batch{}
batch.Queue(fmt.Sprintf("UPDATE items SET quantity = 11 WHERE id = %d", firstItemID))
batch.Queue("SELECT pg_sleep(1)")
batch.Queue(fmt.Sprintf("UPDATE items SET quantity = 21 WHERE id = %d", secondItemID))
br := pool.SendBatch(context.Background(), batch)
defer br.Close()
_, err := br.Exec()
if err != nil {
fmt.Println("Error during batch execution:", err)
return
}
wg.Done()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment