我试图找出如何在Postgres中锁定整个表以防止写入,但似乎并没有起作用,因此我认为我做错了什么。
例如,表名为“users”。
LOCK TABLE users IN EXCLUSIVE MODE;
当我检查pg_locks视图时,它似乎不在其中。我尝试了其他锁定模式,但都无济于事。
其他事务也能执行LOCK函数,并且不像我想象的那样被阻塞。
在psql工具(8.1)中,我只是得到了LOCK TABLE的返回结果。
任何帮助都将是美好的。
我试图找出如何在Postgres中锁定整个表以防止写入,但似乎并没有起作用,因此我认为我做错了什么。
例如,表名为“users”。
LOCK TABLE users IN EXCLUSIVE MODE;
当我检查pg_locks视图时,它似乎不在其中。我尝试了其他锁定模式,但都无济于事。
其他事务也能执行LOCK函数,并且不像我想象的那样被阻塞。
在psql工具(8.1)中,我只是得到了LOCK TABLE的返回结果。
任何帮助都将是美好的。
SQL标准中没有LOCK TABLE,而是使用SET TRANSACTION来指定事务的并发级别。您应该能够在像这样的事务中使用LOCK。
BEGIN WORK;
LOCK TABLE table_name IN ACCESS EXCLUSIVE MODE;
SELECT * FROM table_name WHERE id=10;
Update table_name SET field1=test WHERE id=10;
COMMIT WORK;
我实际在我的数据库上测试过这个。
access exclusive mode
不仅阻止其他进程对表进行写操作,还阻止其读取表的任何内容。您可以使用 share row exclusive mode
来专门锁定表,以防止其他进程对其进行更新或插入操作。 - undefined锁定只在当前事务结束时生效,并在提交(或回滚)事务时释放。
因此,您需要将语句嵌入到 BEGIN
和 COMMIT/ROLLBACK
块中。执行后:
BEGIN;
LOCK TABLE users IN EXCLUSIVE MODE;
您可以运行以下查询以查看当前在users
表上活动的锁:
SELECT * FROM pg_locks pl LEFT JOIN pg_stat_activity psa ON pl.pid = psa.pid WHERE relation = 'users'::regclass::oid;
查询应该显示对users
表的独占锁。在执行COMMIT
并重新运行上述查询之后,该锁不应再存在。
此外,您还可以使用类似https://github.com/jnidzwetzki/pg-lock-tracer/的锁追踪工具来实时了解PostgreSQL服务器的锁定活动。使用这样的锁追踪工具,您可以实时查看哪些锁被获取和释放。