我试图理解postgres中的锁定,这是我到目前为止所理解的。
根据我的理解,virtualxids不是真正的交易,而transactionidxid是指示交易。
当我对psql shell进行简单连接时,我查询了pg_locks表,那里已经存在一个virtualxid。
我没有启动事务或运行查询,为什么要创建这个virtualxid?是因为这个连接可能在将来启动交易吗?
我在这里缺少什么?
答案 0 :(得分:5)
如果会话当前没有当前打开的事务,则连接不会创建事务,但会隐式发出select * from pg_locks
。
这是根据您在问题中引用的规则: postgres中的所有语句都在事务内部运行显式/隐式
查询select * from pg_locks
不能是中立的观察者,因为它需要自己使用事务并锁定pg_locks
。因此,此选择将始终报告至少两个条目,如下例所示:
test=> \x test=> SELECT relation::regclass AS relname, * FROM pg_locks; -[ RECORD 1 ]------+---------------- relname | pg_locks locktype | relation database | 113270 relation | 11000 page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | 2/5789 pid | 31376 mode | AccessShareLock granted | t -[ RECORD 2 ]------+---------------- relname | locktype | virtualxid database | relation | page | tuple | virtualxid | 2/5789 transactionid | classid | objid | objsubid | virtualtransaction | 2/5789 pid | 31376 mode | ExclusiveLock granted | t
答案 1 :(得分:4)
只要查询pg_locks,实际上就是运行查询,从而启动事务。例如,它需要在pg_locks上获取AccessShareLock。这就是分配virtualxid的原因。
但与真实交易ID不同,虚拟交易ID非常“免费”。 Virtualxid是后端的本地(它由后端编号和一些序列号组成)。真正的事务id是系统范围的32位数字,因此当计数器回绕到零时有可能出现回绕。此时必须Special action来防止系统失败,因此PostgreSQL不愿意在实际需要之前分配真实的事务ID。