当前位置:网站首页>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计算结果全部都会出错。
边栏推荐
- Crudini 配置文件编辑工具
- [FPGA] EEPROM based on I2C
- c语言面试写一个函数在字符串N中查找第一次出现子串M的位置。
- Qtthread, one of many methods of QT multithreading
- 你不知道的互联网公司招聘黑话大全
- Software testing knowledge reserve: how much do you know about the basic knowledge of "login security"?
- Jstack of JVM command: print thread snapshots in JVM
- Redisl garbled code and expiration time configuration
- The difference between string constants and string objects when allocating memory
- Array proof during st table preprocessing
猜你喜欢

dolphinscheduler3.x本地启动

面试中有哪些经典的数据库问题?

A program lets you understand what static inner classes, local inner classes, and anonymous inner classes are

Open the blue screen after VMware installation

字符串常量与字符串对象分配内存时的区别

win系统下安装redis以及windows扩展方法

Find duplicate email addresses

LM small programmable controller software (based on CoDeSys) Note 23: conversion of relative coordinates of servo motor operation (stepping motor) to absolute coordinates

Redis (I) -- getting to know redis for the first time
![[opencv] morphological filtering (2): open operation, morphological gradient, top hat, black hat](/img/45/f3b960e3c56f50674b0e6374cba705.png)
[opencv] morphological filtering (2): open operation, morphological gradient, top hat, black hat
随机推荐
Developers don't miss it! Oar hacker marathon phase III chain oar track registration opens
When we talk about immutable infrastructure, what are we talking about
Handling hardfault in RT thread
蚂蚁庄园安全头盔 7.8蚂蚁庄园答案
计算模型 FPS
雷特智能家居龙海祁:从专业调光到全宅智能,20年专注成就专业
Experience sharing of contribution of "management world"
程序员的日常 | 每日趣闻
进程间通信之共享内存
Redis (I) -- getting to know redis for the first time
对称的二叉树【树的遍历】
How to use wechat cloud hosting or cloud functions for cloud development of unapp development applet
matlab / ENVI 主成分分析实现及结果分析
Test the foundation of development, and teach you to prepare for a fully functional web platform environment
Oracle迁移中关于大容量表使用数据泵(expdp、impdp)导出导入容易出现的问题和注意事项
Basic DOS commands
【解决】Final app status- UNDEFINED, exitCode- 16
Force deduction 62 different paths (the number of all paths from the upper left to the lower right of the matrix) (dynamic planning)
软件测试的几个关键步骤,你需要知道
docker-compose启动redis集群