关于“交易ID环绕”


10

现在,我阅读了有关“ Transaction ID Wraparound”的文档,但是我确实不了解某些内容,该文档为以下网址 http://www.postgresql.org/docs/9.0/static/routine-vacuuming .html#VACUUM-FOR-WRAPAROUND

23.1.4。防止事务ID绕回失败

PostgreSQL的MVCC事务语义取决于能否比较事务ID(XID)编号:插入XID大于当前事务XID的行版本是“将来的”,并且对当前事务不可见。但是,由于事务ID的大小有限(32位),因此运行时间较长(超过40亿个事务)的群集将遭受事务ID环绕:XID计数器环绕为零,并且所有突然出现的交易过去似乎是未来-这意味着它们的输出将变得不可见。简而言之,灾难性的数据丢失。(实际上,数据仍然存在,但是如果您不能获得它,那真是令人感到安慰。)为避免这种情况,有必要对每个数据库中的每个表进行至少20亿次事务清理。

我不理解以下语句:“将使事务ID发生折回:XID计数器回绕为零,过去突然出现的所有事务似乎都将在将来发生-这意味着它们的输出变得不可见”

有人可以解释吗?为什么在数据库遭受事务ID折回后,过去的事务似乎会在将来出现?简而言之,我想知道PostgreSQL在自动清除事务ID后是否会处于“数据丢失”的情况。

就我个人而言,我们可以使用txid_current()函数获取当前事务ID,该函数的输出是64位并且不会被循环。所以我认为知道xmin的元组的插入事务ID会比获得通过txid_current()函数。除了在关闭PostgreSQL Server之后将使用pg_resetxlog reset reset transaction ID之外。我对吗 ?谢谢


我认为,如果可能的话,您的最新编辑可能应该是一个新问题
杰克说请尝试topanswers.xyz 2011年

Answers:


10

为什么在数据库遭受事务ID折回后,过去的事务似乎会在将来出现?

他们没有。引用的文本仅说明了为什么postgres需要使用模2 31算术(这意味着只要旧的事务足够早地“冻结”,事务就可以回绕):

使用模2 ^ 31算术比较正常的XID。这意味着对于每个普通XID,有20亿个“旧” XID和20亿个“较新” XID

再具体一点:

旧行版本必须在达到20亿笔交易的旧标记之前的某个时间重新分配XID FrozenXID

或将XID包裹起来会导致事情中断。为了防止这种情况,postgres将开始发出警告,并最终关闭并在必要时拒绝启动新的事务子:

如果由于某种原因autovacuum无法从表中清除旧的XID,则当数据库中最旧的XID从环绕点到达一千万笔事务时,系统将开始发出如下警告消息:

WARNING:  database "mydb" must be vacuumed within 177009986 transactions 
HINT:  To avoid a database shutdown, execute a database-wide VACUUM in "mydb". 

(如提示所示,手动VACUUM应该可以解决该问题;但是请注意VACUUM必须由超级用户执行,否则它将无法处理系统目录,因此无法推进数据库的datfrozenxid。)如果出现这些警告,被忽略时,一旦剩余交易少于一百万次,系统将关闭并拒绝启动任何新交易,直到折回

换句话说,“过去的交易似乎是将来的交易”和“数据丢失”完全是理论上的,实际上不会由事务ID环绕引起。



5

您粘贴的块似乎可以回答问题。这完全取决于用于隐藏“未来”交易的逻辑。

事务ID(XID)计数器被限制为32位,并且如果达到下一个数字,它会从零重新开始,而不是替换旧的最大事务。

好吧,现在它是零,所以PostgreSQL对它隐藏了所有大于0的事务。因此,即使事务#2,147,483,633在20秒钟前发生,PostgreSQL仍认为在另外2,147,483,633个事务中也不会发生。


1
该文档已在2013年12月得到更正。XID是使用modulo-2 ^ 31计算的。
eradman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.