前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Postgresql中无锁修改buffer状态

Postgresql中无锁修改buffer状态

作者头像
mingjie
发布2023-03-01 13:32:23
6790
发布2023-03-01 13:32:23
举报
文章被收录于专栏:Postgresql源码分析

概述

Postgresql中缓冲块的状态操作是非常频繁的,尤其是pin/unpin的操作。

这类操作类似于引用计数,具体由int类型记录:

  • pin:buf_state += BUF_USAGECOUNT_ONE
  • unpin:buf_state -= BUF_USAGECOUNT_ONE

这类+1的动作是concurrency unsafe的,需要使用锁或原子操作来保护。

(背景知识)

  • PG的缓存页面每一个有8kB空间;对应的每一个页面都对应一个状态描述符BufferDesc。
  • BufferDesc中记录缓存页面的信息,包括锁、引用计数、状态等等。
  • PG对引用计数为0的buffer采用时钟算法淘汰

PinBuffer早期实现:spin lock

早期PG使用spin lock实现pin的自增操作,并发性能比较差。

代码语言:javascript
复制
PinBuffer
    ...
    ...
    LockBufHdr(buf);
	buf->refcount++;
	...
	...
	if (buf->usage_count < BM_MAX_USAGE_COUNT)
		buf->usage_count++;

	result = (buf->flags & BM_VALID) != 0;
	UnlockBufHdr(buf);

PinBuffer优化实现:CAS

使用CAS函数pg_atomic_compare_exchange_u32来做check&swap,兼顾原子性与性能(高并发readonly场景有8倍的性能提升)。

代码语言:javascript
复制
		old_buf_state = pg_atomic_read_u32(&buf->state);
		for (;;)
		{
			if (old_buf_state & BM_LOCKED)
				old_buf_state = WaitBufHdrUnlocked(buf);

			buf_state = old_buf_state;

			/* increase refcount */
			buf_state += BUF_REFCOUNT_ONE;

			/* increase usagecount unless already max */
			if (BUF_STATE_GET_USAGECOUNT(buf_state) != BM_MAX_USAGE_COUNT)
				buf_state += BUF_USAGECOUNT_ONE;

			if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state,
											   buf_state))
			{
				result = (buf_state & BM_VALID) != 0;
				break;
			}
		}
  1. 整体流程是:
    • 拿到state(包含引用计数)
    • 增加引用计数、
    • CAS检查拿到的state是否被并发修改
      • 修改了:old_buf_state更新为最新的state,在最新的state基础上,再去增加引用计数。
      • 没修改:old_buf_state更新为最新的state,buf->state更新为 ++后的state。
  2. 可以直观总结CAS的用法:
    • 参数2总会更新为参数一的值,也就是拿到共享变量最新的状态。
    • 参数1会将 检查和更新 合并为原子动作,如果检查参1==参2,则更新,更新后函数返回true。
    • 参数1会将 检查和更新 合并为原子动作,如果检查参1!=参2,说明参1被并发修改,函数返回false。

PG的CAS函数惯用法:

代码语言:javascript
复制
原子函数拿到OLD
while(1)
    用拿到的OLD做一些更新,记录到NEW,但不能修改OLD
    if (pg_atomic_compare_exchange_u32(共享变量,OLD,NEW))
		break;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • PinBuffer早期实现:spin lock
  • PinBuffer优化实现:CAS
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档