I am currently trying to maintain a postgres database of player information when I've encountered an issue with one of our players. The player came to us saying that he could not load his character into the game world. I did a small SELECT statement to pull up the player information with no problems. However, when they try to use a character then we update a field in the row that says that the player character is active. However we noticed that we couldn't run an update or a delete statement on that row. Every other row in the table gets modified without any issues.
On of our DB admins thought that it was a lock that was applied on that row, but after further investigation with see nothing that could be locking that row.
Any advice or suggestions is greatly appreciated.
It certainly sounds like a lock.
The "big hammer" approach is bouncing (stoping/starting) your database to kill any running queries.
The "scalpel" approach is to run show full processlist; and try to find a query that's running that might have created a lock. Note that the query itself might not lock the row, but an earlier query in the same transaction might have locked it. Any long-running query is a suspect.
EDIT
I have found an issue in postgres that keeps the lock even after a restart. Here's how you find and fix it:
Run this query:
select * from pg_prepared_xacts
Here's the doc for this system view
If there are any rows, it means there are orphaned/dangling transactions, which can hold locks even after restarting postgres.
To kill them, for every row get the gid (a long UUID), and execute this:
ROLLBACK PREPARED '<paste gid here>'
That should clean things up.
If you are on a *nix platform, you can run this single command that will do the lot:
psql -U postgres mydatabase -c "select * from pg_prepared_xacts" | grep -v transaction | grep \| | awk '{print $3}' | xargs -I % psql -U postgres mydatabase -c "ROLLBACK PREPARED '%'"
Related
Sometimes my commands in psql seem to be having no effect. Any idea why?
The below is the list of all tables in the database library_development:
library_development=> \d
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | Pavan | table | postgres
public | schema_migrations | table | sai
(2 rows)
After this I dropped the table Pavan using:
library_development-> drop table Pavan
But the Table isn't dropped and its shows as shown:
library_development=> \d
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | Pavan | table | postgres
public | schema_migrations | table | sai
(2 rows)
Also:
I am using PostgreSQL in Windows. Is there any command to clear the console (Like cl scr present in Oracle)?
Is there any concept of a "commit" I need to perform in Postgresql when working with DML scripts?
Statements end with semicolons.
In psql, pressing enter without a semicolon continues the statement onto the next line, adding what you wrote to the query buffer rather than executing it. You will notice that the prompt changes from dbname=> to dbname-> to indicate that you're on a continuation line.
regress=> DROP TABLE sometable
regress-> \r
Query buffer reset (cleared).
regress=> DROP TABLE sometable;
ERROR: table "sometable" does not exist
regress=>
Notice how after I press enter without a semicolon, the prompt changes to regress-# and no action is taken. There is no table sometable, so if the statement had run an error would be reported.
Next, see the use of \r on the next line? That clears the query buffer. Notice that the prompt changes back to regress=# when the buffer is cleared, as there's no partial statement buffered anymore.
This shows how statements can be split across lines:
regress=> DROP TABLE
regress-> sometable
regress-> ;
ERROR: table "sometable" does not exist
The confusing thing is that psql backslash commands like \d are newline-terminated, not semicolon terminated, so they do run when you press enter. That's handy when you want to (say) view a table definition while writing a statement, but it's a bit confusing for newcomers.
As for your additional questions:
If there's a "clear screen" command in psql for Windows I haven't found it yet. On Linux I just use control-L, same as any other readline-using program. In Windows \! cls will work.
DDL in PostgreSQL is transactional. You can BEGIN a transaction, issue some DDL, and COMMIT the transaction to have it take effect. If you don't do your DDL in an explicit transaction then it takes effect immediately.
I just encountered something similar, but the cause was different.
I was trying to use the dropdb command and what I was seeing was like my command having no effect (change of prompt means my command is in the buffer, but that's not the issue here):
postgres=# dropdb databasename
postgres-#
Commands like dropdb should be entered OUTSIDE psql. What i had been doing was:
$ psql postgres
postgres=# dropdb databasename
Notice the first command is in Bash and fires psql, and the second is sent within psql.
The correct way is to send the command directly in bash (the console):
$ dropdb databasename
I have 4 different services in my application which SELECT and UPDATE on the same table in my database (db2 v9.1) on AIX 6.1, not big table around 300,000 records.The 4 services work execute in parallel way, and each service execute in sequential way (not parallel).
The issue that everyday I face horrible deadlock problem, the db hangs for about 5 to 10 minutes then it get back to its normal performance.
My services are synchronized in a way which make them never SELECT or UPDATE on the same row so I believe even if a deadlock occurred it supposed to be on a row level not table level, RIGHT?
Also, in my SELECT queries I use "ONLY FOR FETCH WITH UR", in db2 v9.1 that means not to lock the row as its only for read purpose and there will be no update (UR = uncommitted read).
Any Ideas about whats happening and why?
Firstly, these are certainly not deadlocks: a deadlock would be resolved by DB2 within few seconds by rolling back one of the conflicting transactions. What you are experiencing are most likely lock waits.
As to what's happening, you will need to monitor locks as they occur. You can use the db2pd utility, e.g.
db2pd -d mydb -locks showlocks
or
db2pd -d mydb -locks wait
You can also use the snapshot monitor:
db2 update monitor switches using statement on lock on
db2 get snapshot for locks on mydb
or the snapshot views:
select * from sysibmadm.locks_held
select * from sysibmadm.lockwaits
I am trying to reset temporary tables via a simple commandline script and am using the following command:
#echo DELETE FROM A ; | sqlplus schema/pass#DSN
This works for table A.
For a similar table B, the statement is not executed. The commandline logs into the database and displays the SQL> shell. It does not react to keystrokes and does nothing. I have to exit the commandline interface.
I tried different ordering of the commands in the batch file and executed the statement from commandline directly. Same error.
(Question answered in a comment. See Question with no answers, but issue solved in the comments (or extended in chat) )
#Alex Poole wrote:
Do you have an uncommitted delete or update against that table in any other open sessions? In a Toad or SQL Developer window, for example? If you've tested the delete somewhere, roll back in that session and see if the batch version magically finishes.
The OP wrote:
Worked. I should have tried that before posting. Now I feel retarded.
SOLUTION: Uncommitted transactions in open session on table caused the error. Once transactions had been committed, the script worked fine.
I tried connecting to the database server using the command:
psql -h host_ip -d db_name -U user_name --password
It displays the following line and refuses to connect.
psql: FATAL: too many connections for role "user_name".
How to close the active connections?
I do not have admin rights for the database. I am just an ordinary user.
From inside any DB of the cluster:
Catch 22: you need to be connected to a database first. Maybe you can connect as another user? (By default, some connections are reserved for superusers with the superuser_reserved_connections setting.)
To get detailed information for each connection by this user:
SELECT *
FROM pg_stat_activity
WHERE usename = 'user_name';
As the same user or as superuser you can cancel all (other) connections of a user:
SELECT pg_cancel_backend(pid) -- (SIGINT)
-- pg_terminate_backend(pid) -- the less patient alternative (SIGTERM)
FROM pg_stat_activity
WHERE usename = 'user_name'
AND pid <> pg_backend_pid();
Better be sure it's ok to do so. You don't want to terminate important queries (or connections) that way.
pg_cancel_backend() and pg_terminate_backend() in the manual.
From a Linux shell
Did you start those other connections yourself? Maybe a hanging script of yours? You should be able to kill those (if you are sure it's ok to do so).
You can investigate with ps which processes might be at fault:
ps -aux
ps -aux | grep psql
If you identify a process to kill (better be sure, you do not want to kill the server):
kill 123457689 # pid of process here.
Or with SIGKILL instead of SIGTERM:
kill -9 123457689
I'm pretty new to pgAdmin, but so far I have not utilized the command line. I had the same issue and I found the easiest way to resolve the issue in my case was to simply delete the processes listed in "Database Activity" in the Dashboard.
(just click the X on the left side of the PID)
It's a bit tedious since you must delete each process individually, but doing so should free up your available connections.
Hope this is useful.
You need to connect on your postgresql db and run command:
ALTER ROLE your_username CONNECTION LIMIT -1;
Check pool_size this is probably too much or to small set value on local psql settings. You should at first check with pool_size = 10 (like default). This should fix errors of too_many_connections.
Please check how many connections are allowed on that user and you can just kill other connections for that user and log in again. But it's better to just increase the connection limit for that user.
This issue mostly arises on PgAdmin. It seems like after all these years still this issue persists.
This will drop existing connections except for yours:
Query pg_stat_activity and get the pid values you want to kill, then issue SELECT pg_terminate_backend(pid int) to them.
PostgreSQL 9.2 and above:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND pid <> pg_backend_pid();
PostgreSQL 9.1 and below:
SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND procpid <> pg_backend_pid();
from https://stackoverflow.com/a/5408501/13813241 (duplicate)
I was getting this for a specific incident.
Django Development. I had a shell open to query django models. I also have the dev server running. I was using elephantsql for testing/prototyping. So it threw error. Once I exited out of django manage.py shell, it started working.
I made a silly mistake at work once on one of our in house test databases. I was updating a record I just added because I made a typo but it resulted in many records being updated because in the where clause I used the foreign key instead of the unique id for the particular record I just added
One of our senior developers told me to do a select to test out what rows it will affect before actually editing it. Besides this, is there a way you can execute your query, see the results but not have it commit to the db until I tell it to do so? Next time I might not be so lucky. It's a good job only senior developers can do live updates!.
It seems to me that you just need to get into the habit of opening a transaction:
BEGIN TRANSACTION;
UPDATE [TABLENAME]
SET [Col1] = 'something', [Col2] = '..'
OUTPUT DELETED.*, INSERTED.* -- So you can see what your update did
WHERE ....;
ROLLBACK;
Than you just run again after seeing the results, changing ROLLBACK to COMMIT, and you are done!
If you are using Microsoft SQL Server Management Studio you can go to Tools > Options... > Query Execution > ANSI > SET IMPLICIT_TRANSACTIONS and SSMS will open the transaction automatically for you. Just dont forget to commit when you must and that you may be blocking other connections while you dont commit / rollback close the connection.
First assume you will make a mistake when updating a db so never do it unless you know how to recover, if you don't don't run the code until you do,
The most important idea is it is a dev database expect it to be messed up - so make sure you have a quick way to reload it.
The do a select first is always a good idea to see which rows are affected.
However for a quicker way back to a good state of the database which I would do anyway is
For a simple update etc
Use transactions
Do a begin transaction and then do all the updates etc and then select to check the data
The database will not be affected as far as others can see until you do a last commit which you only do when you are sure all is correct or a rollback to get to the state that was at the beginning
If you must test in a production database and you have the requisite permissions, then write your queries to create and use temporary tables that in name are similar to the production tables and whose schema other than index names is identical. Index names are unique across a databse, at least on Informix.
Then run your queries and look at the data.
Other than that, IMHO you need a development database, and perhaps even a development server with a development instance. That's paranoid advice, but you'd have to be very careful, even if you were allowed -- MS SQLSERVER lingo here -- a second instance on the same server.
I can reload our test database at will, and that's why we have a test system. Our production system contains citizens' tax payments and other information that cannot be harmed, "or else".
For our production data changes, we always ensure that we use a BEGIN TRAN and a ROLLBACK TRAN and then all statements have an OUTPUT clause. This way we can run the script first (usually in a copy of PRODUCTION db first) and see what is affected before changing the ROLLBACK TRAN to COMMIT TRAN
Have you considered explain ?
If there is a mistake in the command, it will report it as with usual commands.
But if there are no mistakes it will not run the command, it will just explain it.
Example of a "passed" test:
testdb=# explain select * from sometable ;
QUERY PLAN
------------------------------------------------------------
Seq Scan on sometable (cost=0.00..12.60 rows=260 width=278)
(1 row)
Example of a "failed" test:
testdb=# explain select * from sometaaable ;
ERROR: relation "sometaaable" does not exist
LINE 1: explain select * from sometaaable ;
It also works with insert, update and delete (i.e. the "dangerous" ones)