当前位置:网站首页>Postgresql源码(59)分析事务ID分配、溢出判断方法
Postgresql源码(59)分析事务ID分配、溢出判断方法
2022-07-07 02:05:00 【mingjie73】
xid取值规律
xid是uint32类型的,GetNewTransactionId函数中xid在ShmemVariableCache->nextXid中取值,但是ShmemVariableCache->nextXid是long int类型的。
unsigned int : 0 ~ 4294967295 ( 0 ~ 2^32-1 )
int : -2147483648 ~ 2147483647 ( -2^31 ~ 2^31-1 )
long int : -9223372036854775808 ~ 9223372036854775807 ( -2^63 ~ 2^63-1 )
GetNewTransactionId
FullTransactionId full_xid;
TransactionId xid;
full_xid = ShmemVariableCache->nextXid;
xid = XidFromFullTransactionId(full_xid);
所以xid的取值会从0到4294967295在归零再次到4294967295不停循环。而ShmemVariableCache->nextXid是一直上涨的,因为ShmemVariableCache->nextXid的范围是( -2^63 ~ 2^63-1 )。
注意ShmemVariableCache->nextXid到正数最大值9223372036854775807后在加一会溢出到负数最小值-9223372036854775808,这时强转到uint32时为0,又是一轮循环。
取值规律见下面实例:
ShmemVariableCache->nextXid
nextXid: 0 1 2 3 ... 4294967295 4294967296 4294967297 4294967298 ... 9223372036854775807
xid : 0 1 2 3 ... 4294967295 0 1 2 ... 4294967295
ShmemVariableCache->nextXid
nextXid: 9223372036854775807 -9223372036854775808 -9223372036854775807 ... 0
xid : 4294967295 0 1 0
ShmemVariableCache->nextXid自加使用FullTransactionIdAdvance函数
- 该函数从0开始增加nextXid的值,第一个if保证nextXid可以正常返回0、1、2的值
- 在后面nextXid增加到4294967296时,会走while循环把4294967296、4294967297、4294967298的值跳过,因为这三个值转换为uint32后会变成0、1、2,正常事务ID不使用这三个值。
- 在后面nextXid继续增加每次碰到上述情况,都会走while跳过这三个数的倍数。
static inline void
FullTransactionIdAdvance(FullTransactionId *dest)
{
dest->value++;
/* see FullTransactionIdAdvance() */
if (FullTransactionIdPrecedes(*dest, FirstNormalFullTransactionId))
return;
while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId)
dest->value++;
}
xid大小判断规律
已TransactionIdFollows函数为例,入参是两个uint32(0 ~ 2^32-1)。
但是做减法的时候结果保存到diff是int32(-2^31 ~ 2^31-1)。
typedef uint32 TransactionId;
/*
* TransactionIdPrecedes --- is id1 logically < id2?
*/
bool
TransactionIdPrecedes(TransactionId id1, TransactionId id2)
{
/*
* If either ID is a permanent XID then we can just do unsigned
* comparison. If both are normal, do a modulo-2^32 comparison.
*/
int32 diff;
if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
return (id1 < id2);
diff = (int32) (id1 - id2);
return (diff < 0);
}
- 注意
(id1 - id2)
不管怎么减结果都是正数,因为这是两个uint32在减。这个正数结果代表这两个值的距离。
当前距离-5
id1 = 4294967290u
id2 = 4294967295u
id1 - id2 = 4294967291u
diff = (int32)(id1 - id2) = -5
id2继续增长,但是id2是uint32最大值就是4294967295u了,继续增长后溢出
id1 = 4294967290u
id2 = 10u
id1 - id2 = 4294967280u
diff = (int32)(id1 - id2) = -16
可以看到溢出后,结果仍然是负数,TransactionIdPrecedes函数的计算是正确的id1 logically < id2
。
但是如果id1和id2距离过大,超过2^31
后,例如id2从刚才的10继续增长到2147483647,id2领先id1的距离已经超过了2^31:
id1 = 4294967290u
id2 = 2147483647u
id1 - id2 = 2147483643u
diff = (int32)(id1 - id2) = 2147483643
结果diff又翻转了一次变成了正数,虽然id1逻辑上应该<id2,但是这时TransactionIdPrecedes的结果已经是false了。
显然TransactionIdPrecedes函数计算错误。
总结
所以在PG现有的xid分配机制上,为了保证xid回卷后还能正确的对比大小,两个xid的距离不能超过2^31。
方便记忆:事务ID可以回卷,但最老的到最新的距离不能超过20亿,否则会发生第二次符号翻转,事务ID计算结果全部都会出错。
边栏推荐
- PostgreSQL database timescaledb function time_ bucket_ Gapfill() error resolution and license replacement
- 哈趣投影黑马之姿,仅用半年强势突围千元投影仪市场!
- 字符串常量与字符串对象分配内存时的区别
- 请问如何查一篇外文文献的DOI号?
- Find duplicate email addresses
- uniapp开发小程序如何使用微信云托管或云函数进行云开发
- Subghz, lorawan, Nb IOT, Internet of things
- LM小型可编程控制器软件(基于CoDeSys)笔记二十三:伺服电机运行(步进电机)相对坐标转换为绝对坐标
- k8s运行oracle
- 当我们谈论不可变基础设施时,我们在谈论什么
猜你喜欢
地质学类比较有名的外文期刊有哪些?
string(讲解)
dolphinscheduler3.x本地启动
Ant manor safety helmet 7.8 ant manor answer
Software testing knowledge reserve: how much do you know about the basic knowledge of "login security"?
postgresql 数据库 timescaledb 函数time_bucket_gapfill()报错解决及更换 license
Etcd database source code analysis -- starting from the start function of raftnode
Handling hardfault in RT thread
go-microservice-simple(2) go-Probuffer
港科大&MSRA新研究:关于图像到图像转换,Fine-tuning is all you need
随机推荐
Tkinter window selects PCD file and displays point cloud (open3d)
A very good JVM interview question article (74 questions and answers)
FlexRay通信协议概述
UIC(组态UI工程)公版文件库新增7款行业素材
[shell] summary of common shell commands and test judgment statements
Basic DOS commands
docker-compose启动redis集群
Experience of Niuke SQL
rt-thread 中对 hardfault 的处理
You don't know the complete collection of recruitment slang of Internet companies
The difference between string constants and string objects when allocating memory
Knight defeats demon king (Backpack & DP)
Developers don't miss it! Oar hacker marathon phase III chain oar track registration opens
3428. Put apples
How to set up in touch designer 2022 to solve the problem that leap motion is not recognized?
VMware安装后打开就蓝屏
Markdown 并排显示图片
哈趣投影黑马之姿,仅用半年强势突围千元投影仪市场!
Jstack of JVM command: print thread snapshots in JVM
How to solve sqlstate[hy000]: General error: 1364 field 'xxxxx' doesn't have a default value error