暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Postgres事务系统介绍


作者时间QQ技术交流群
perrynzhou@gmail.com2024/04/14672152841

交流群.png

介绍

  • • postgres
    事务系统分为事务块(上层系统)和事务(底层系统)两个部分,上层的事务块提供统一的事务抽象,事务底层系统负责执行具体的底层事务的功能

  • • 在postgres
    中执行如下四个语句,这个语句中BEGIN
    COMMIT
    是属于事务块的开始和结束状态;其中的(2)和(3)
    是底层事务系统负责具体的执行。

(1) BEGIN
(2) SELECT * FROM foo
(3) INSERT INTO foo VALUES (...)
(4) COMMIT

  • • 以上的语句都对应postgres
    中的事务系统的处理函数。

     /  StartTransactionCommand;
    /       StartTransaction;
1) <    ProcessUtility;                 << BEGIN
    \       BeginTransactionBlock;
     \  CommitTransactionCommand;

    /   StartTransactionCommand;
2) /    PortalRunSelect;                << SELECT ...
   \    CommitTransactionCommand;
    \       CommandCounterIncrement;

    /   StartTransactionCommand;
3) /    ProcessQuery;                   << INSERT ...
   \    CommitTransactionCommand;
    \       CommandCounterIncrement;

     /  StartTransactionCommand;
    /   ProcessUtility;                 << COMMIT
4) <        EndTransactionBlock;
    \   CommitTransactionCommand;
     \      CommitTransaction;

  • • 上层的事务块系统中,每个事务块都有都有对应的状态,具体定义如下

// 事务块的状态
typedef enum TBlockState
{

   // 事务块默认状态
   TBLOCK_DEFAULT,        
   // 执行简单的语句的事务块状态
   TBLOCK_STARTED,           

   // 事务块遇到begin命令设置的状态
   TBLOCK_BEGIN,          
   // 事务块正在处理状态
   TBLOCK_INPROGRESS,         
   // 隐世begin开启事务块处理的状态
   TBLOCK_IMPLICIT_INPROGRESS, 
   TBLOCK_PARALLEL_INPROGRESS, 
   // 事务块遇到commit/end的时候设置的事务块状态
   TBLOCK_END,           
   // 事务块出错等待rollback
   TBLOCK_ABORT,          
   // 事务块出错以接受到rollback
   TBLOCK_ABORT_END,       
   // 事务块处理中接受到rollback
   TBLOCK_ABORT_PENDING,      
   TBLOCK_PREPARE,         

   /* subtransaction states */
   // 事务块中子事务块状态
   TBLOCK_SUBBEGIN,        /* starting a subtransaction */
   TBLOCK_SUBINPROGRESS,      /* live subtransaction */
   TBLOCK_SUBRELEASE,         /* RELEASE received */
   TBLOCK_SUBCOMMIT,       /* COMMIT received while TBLOCK_SUBINPROGRESS */
   TBLOCK_SUBABORT,        /* failed subxact, awaiting ROLLBACK */
   TBLOCK_SUBABORT_END,    /* failed subxact, ROLLBACK received */
   TBLOCK_SUBABORT_PENDING,   /* live subxact, ROLLBACK received */
   TBLOCK_SUBRESTART,         /* live subxact, ROLLBACK TO received */
   TBLOCK_SUBABORT_RESTART    /* failed subxact, ROLLBACK TO received */
} TBlockState;

  • • 事务块对应的处理函数,从事务块启动、事务块提交、事务块终止三个方面定义了处理函数

// 开启事务的统一入口
void StartTransactionCommand(void)
// 事务提交的统一入口函数
void CommitTransactionCommand(void)
// 事务终止函数
void AbortCurrentTransaction(void)

  • • 对于底层的事务系统在postgres
    中定义6种底层事务状态

// 底层事务的状态
typedef enum TransState
{

   // 事务默认状态
   TRANS_DEFAULT,        
   // 事务开启
   TRANS_START,           
   // 事务正在处理状态
   TRANS_INPROGRESS,       
   // 事务提交状态
   TRANS_COMMIT,           
   // 事务终止状态
   TRANS_ABORT,            
   // 事务准备状态
   TRANS_PREPARE           
} TransState;

postgres
接受请求的整体流程

1.png
// postgres的服务端主进程代码,监听来自客户端的fd
static int ServerLoop(void)
{

   for (;;)
   {
      // 基于select的模型检查fd
      for (int i = 0; i < nevents; i++)
      {
         // 判断event是否有新的连接
         if (events[i].events & WL_SOCKET_ACCEPT)
         {
            Port     *port;
            port = ConnCreate(events[i].fd);
            if (port)
            {
               // 创建和启动启动子进程
               BackendStartup(port)
               {
                  pid = fork_process();
                  if(pid == 0){           /* child */
                  
               
                   // 运行新的子进程
                   BackendRun(port)
                   {
                     // postgres的进程代码,对于没客户端这是子进程的逻辑
                     PostgresMain(port->database_name, port->user_name)
                     {
                        for (;;)
                        {
                           // 读取客户端请求,根据请求命令执行不同的操作
                           firstchar = ReadCommand(&input_message);
                           switch (firstchar)
                           {
                              case 'Q':         /* simple query */
                              {
                                 // 执行简单的SQL语句
                                 exec_simple_query(query_string);
                              }
                        }
                     }
                   }

               }
            }
         }
      }

   }
}

select
执行流程

• 简单的SQL语句中会在事务块内进行SQL语句的执行,整体的流入是事务开启->SQL语句从客户端获取->SQL语句解析->SQL语句重写->生成SQL执行计划->SQL语句执行->事务结束

2.png
static void exec_simple_query(const char *query_string)
{
    // 开启事务块
    start_xact_command()
    {
        // 具体实现函数
        StartTransactionCommand();
    }
    // 解析SQL语句
    parsetree_list = pg_parse_query(query_string);
    // 重写SQL语句
    querytree_list = pg_analyze_and_rewrite_fixedparams(parsetree, query_string,...);
    // 生成执行计划
    plantree_list = pg_plan_queries(querytree_list, query_string,...);
    // 执行SQL语句
    (void) PortalRun(portal,...)
    {
        // 执行SQL语句
        nprocessed = PortalRunSelect(portal, true, count, dest)
        {
            // 根据执行计划执行SQL语句
            ExecutorRun(queryDesc, direction, (uint64) count,...)
            {
                // 执行SQL语句
                standard_ExecutorRun(queryDesc, direction,...)
                {
                    // 根据SQL执行计划获取数据
                    ExecutePlan(estate,...)
                    {
                        for (;;)
                        {
                            slot = ExecProcNode(planstate)
                            {
                                // 拿nest loop方式扫表方式,这里定义的就是ExecNestLoop
                                node->ExecProcNode(node)
                            }
                        }
                    }
                }
            }
        }
    }
    // 事务块结束
    finish_xact_command()
    {
        CommitTransactionCommand();
    }
}


文章转载自存储内核技术交流,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论