Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does postgresql lock tables when inserting and selecting?

I'm migrating data from one table to another in an environment where any long locks or downtime is not acceptable, in total about 80000 rows. Essentially the query boils down to this simple case:

INSERT INTO table_2
SELECT * FROM table_1
JOIN table_3 on table_1.id = table_3.id

All 3 tables are being read from and could have an insert at any time. I want to just run the query above, but I'm not sure how the locking works and whether the tables will be totally inaccessible during the operation. My understanding tells me that only the affected rows (newly inserted) will be locked. Table 1 is just being selected, so no harm, and concurrent inserts are safe so table 2 should be freely accessible.

Is this understanding correct, and can I run this query in a production environment without fear? If it's not safe, what is the standard way to accomplish this?

like image 763
ssb Avatar asked Mar 06 '18 10:03

ssb


People also ask

Does SELECT query lock table in PostgreSQL?

The SELECT command acquires a lock of this mode on referenced tables. In general, any query that only reads a table and does not modify it will acquire this lock mode.

How does locking work in PostgreSQL?

Locks or Exclusive Locks or Write Locks prevent users from modifying a row or an entire table. Rows modified by UPDATE and DELETE are then exclusively locked automatically for the duration of the transaction. This prevents other users from changing the row until the transaction is either committed or rolled back.

Do Selects lock a table?

SELECT statements get a shared lock on the entire table. Other statements get exclusive locks on the entire table, which are released when the transaction commits. SELECT statements get shared locks on a range of rows. UPDATE and DELETE statements get exclusive locks on a range of rows.

How do I stop table locking in Postgres?

1: Never add a column with a default value Adding a column takes a very aggressive lock on the table, which blocks read and write. If you add a column with a default, PostgreSQL will rewrite the whole table to fill in the default for every row, which can take hours on large tables.


1 Answers

You're fine.

If you're interested in the details, you can read up on multiversion concurrency control, or on the details of the Postgres MVCC implementation, or how its various locking modes interact, but the implications for your case are nicely summarised in the docs:

reading never blocks writing and writing never blocks reading

In short, every record stored in the database has some version number attached to it, and every query knows which versions to consider and which to ignore.

This means that an INSERT can safely write to a table without locking it, as any concurrent queries will simply ignore the new rows until the inserting transaction decides to commit.

like image 116
Nick Barnes Avatar answered Oct 13 '22 19:10

Nick Barnes