<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>论文解读 on 最后的DBA</title><link>https://lastdba.com/categories/%E8%AE%BA%E6%96%87%E8%A7%A3%E8%AF%BB/</link><description>Recent content in 论文解读 on 最后的DBA</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><copyright>© 2026 liuzhilong62</copyright><lastBuildDate>Sat, 03 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://lastdba.com/categories/%E8%AE%BA%E6%96%87%E8%A7%A3%E8%AF%BB/index.xml" rel="self" type="application/rss+xml"/><item><title>论文精读：插件无政府状态</title><link>https://lastdba.com/2026/01/03/%E8%AE%BA%E6%96%87%E7%B2%BE%E8%AF%BB%E6%8F%92%E4%BB%B6%E6%97%A0%E6%94%BF%E5%BA%9C%E7%8A%B6%E6%80%81/</link><pubDate>Sat, 03 Jan 2026 00:00:00 +0000</pubDate><guid>https://lastdba.com/2026/01/03/%E8%AE%BA%E6%96%87%E7%B2%BE%E8%AF%BB%E6%8F%92%E4%BB%B6%E6%97%A0%E6%94%BF%E5%BA%9C%E7%8A%B6%E6%80%81/</guid><description>&lt;p&gt;论文：Anarchy in the Database: A Survey and Evaluation of Database Management System Extensibility&lt;/p&gt;
&lt;p&gt;github：https://github.com/cmu-db/ext-analyzer&lt;/p&gt;
&lt;p&gt;pgconf：The trouble with extensions (PGConf.dev 2025)&lt;/p&gt;</description><content:encoded>&lt;p&gt;论文：Anarchy in the Database: A Survey and Evaluation of Database Management System Extensibility&lt;/p&gt;
&lt;p&gt;github：https://github.com/cmu-db/ext-analyzer&lt;/p&gt;
&lt;p&gt;pgconf：The trouble with extensions (PGConf.dev 2025)&lt;/p&gt;

&lt;h2 class="relative group"&gt;why this paper
 &lt;div id="why-this-paper" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-this-paper" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;这是一篇数据库插件综述（主要是Postgres），主要讲不同数据库插件的实现方式、存在的问题和最重要的兼容性。其中最重磅的结论是：对 400 多个 PostgreSQL 扩展的评估显示，其中 16.8% 的扩展与至少一个其他扩展存在兼容性问题，且可能导致系统故障。&lt;/p&gt;
&lt;p&gt;分析工具和结果见github；Marco Slot的ppt演讲见PGconf。&lt;/p&gt;

&lt;h2 class="relative group"&gt;插件类别
 &lt;div id="插件类别" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%92%e4%bb%b6%e7%b1%bb%e5%88%ab" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;插件分类
 &lt;div id="插件分类" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%92%e4%bb%b6%e5%88%86%e7%b1%bb" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;插件分类章节特别冗长，其实一个图就能看明白了。&lt;/p&gt;
&lt;p&gt;6种数据库的插件：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/c2025f80a5c9.png" alt="image-20251228140624785" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL（1986）：C 语言编写，从设计之初就定位为可扩展架构。因此，PostgreSQL 拥有最为丰富多样的可扩展生态网络。&lt;/li&gt;
&lt;li&gt;MySQL（1994）： C++ 语言编写，其最知名的特性是存储引擎插件架构。&lt;/li&gt;
&lt;li&gt;MariaDB（2009）：作为 MySQL 的分支版本，它同样基于 C++ 开发，支持的扩展数量比原版 MySQL 更多。&lt;/li&gt;
&lt;li&gt;SQLite（2000）：嵌入式数据库，C 语言编写，可适配各类硬件设备与操作系统环境。&lt;/li&gt;
&lt;li&gt;Redis（2009）：内存型键值库，C++ 语言编写，其可扩展性独具特色 —— 仅支持在 DBMS key-value存储层之上运行。&lt;/li&gt;
&lt;li&gt;DuckDB（2018）：嵌入式分析型数据库，C++ 编写，拥有快速兴起的可扩展生态系统。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;灵活性和安全性
 &lt;div id="灵活性和安全性" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%81%b5%e6%b4%bb%e6%80%a7%e5%92%8c%e5%ae%89%e5%85%a8%e6%80%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;插件的安全性和灵活性只能二选一，pg的插件是最灵活也是最不安全的，redis是最安全也最不灵活的：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/a4b3110396a3.png" alt="image-20260103140026801" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;postgres的插件一般怎么实现的
 &lt;div id="postgres的插件一般怎么实现的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#postgres%e7%9a%84%e6%8f%92%e4%bb%b6%e4%b8%80%e8%88%ac%e6%80%8e%e4%b9%88%e5%ae%9e%e7%8e%b0%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg总体有两种方式实现扩展：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过handler function实现，如UDF,UDTs, external tables, storage engines, and index access methods.&lt;/li&gt;
&lt;li&gt;通过hooks钩子实现扩展。将钩子声明为全局变量中的函数指针，如果设置了钩子，它将调用这些指针而不是自己的代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实现方式可能是都包含的，并不排他。其他5个库的实现总体类似，但是&lt;strong&gt;他们都没有hooks这种形式的实现&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/a0199291618a.png" alt="image-20251228170307440" /&gt;&lt;/p&gt;
&lt;p&gt;插件可能使用不同的方式来实现，比如funcion+types+index am，这就是可扩展性类型数量（number of extensibility types）。从figure 1可以看到有1-3中类型的扩展是最多的，而使用最多的实现方式就是function。&lt;/p&gt;
&lt;p&gt;从table3可以看出，有92.5%的插件都在使用UDF，毕竟是面向用户的特性，开发最为方便、门槛低。最少的是客户端认证，因为这种场景本身也不多。&lt;/p&gt;

&lt;h2 class="relative group"&gt;插件代码的copy率
 &lt;div id="插件代码的copy率" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%92%e4%bb%b6%e4%bb%a3%e7%a0%81%e7%9a%84copy%e7%8e%87" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;文章还进行了一个有趣的调查研究，插件代码从build-in代码中的copy情况：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/69d841de287f.png" alt="image-20260103104107929" /&gt;&lt;/p&gt;
&lt;p&gt;441个插件中有16.6%&amp;ndash;73个插件含有至少1行从PG源码中copy的代码。详细分布如上图左。&lt;/p&gt;
&lt;p&gt;为什么有这么多插件是copy的代码呢？因为&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pg源码中有些是静态声明的函数，只能在本文件中调用，所以只能copy&lt;/li&gt;
&lt;li&gt;因为插件本身的需求，函数可能需要做出一点调整，所以只能copy出来调整&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而插件一般copy函数调整了多少呢？如上图右。&lt;/p&gt;
&lt;p&gt;可以看出，原封不动copy的其实是很少的。&lt;/p&gt;
&lt;p&gt;总之，插件代码从pg源码中copy，是因为某些原因而不得已的，整体copy率也不高。&lt;/p&gt;

&lt;h2 class="relative group"&gt;重磅！——PG插件的兼容性
 &lt;div id="重磅pg插件的兼容性" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%87%8d%e7%a3%85pg%e6%8f%92%e4%bb%b6%e7%9a%84%e5%85%bc%e5%ae%b9%e6%80%a7" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;这是这篇文章最有趣的部分，总计对96个extension进行1对1的兼容性测试，测试发现有16.8%的两个插件是不兼容的！&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/6d87c80af09b.png" alt="image-20260103111359805" /&gt;&lt;/p&gt;
&lt;p&gt;测试方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装。是的，安装就可能有问题了，并且作者进行了A-&amp;gt;B,B-&amp;gt;A两种顺序的安装和测试，所以可以看到图是不对称的&lt;/li&gt;
&lt;li&gt;运行扩展提供的单元测试&lt;/li&gt;
&lt;li&gt;pgbench。冒烟测试。pgbench当然很简单，不过结果很不错的话也可以说明一定问题了。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在兼容性最差的插件top20里面，也能看到很多常见的插件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;常用的插件：pg_hint_plan,vector,pg_show_plans,pgsentinel,pg_cron,pg_stat_kcache&lt;/li&gt;
&lt;li&gt;很重的插件：citus,timescaledb&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些极其常见的插件和明星插件的兼容性可以这么差，这个结果足以惊掉下巴。&lt;/p&gt;
&lt;p&gt;细思极恐的是，这还只是简单的捉对测试，3-10个插件的运行才应该是生产常态，而且生产环境也比论文中的三种测试方式更加复杂多变。&lt;/p&gt;
&lt;p&gt;最后论文还提出插件兼容性较差的原因：插件使用越多的组件、扩展type、hooks，就越有可能跟其他扩展不兼容。&lt;/p&gt;

&lt;h2 class="relative group"&gt;挑刺
 &lt;div id="挑刺" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8c%91%e5%88%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;其实还是研究的postgres&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;文章标题是写DBMS的，但主要还是写pg的兼容性，mysql、redis等等的兼容性只是综述带过，完全没有实验数据。（虽然综述也很有意思，可以了解到mysql和redis的插件是怎么实现的）。&lt;/p&gt;
&lt;p&gt;另一个方面，这个文章有一种另类”总-分-总“的感觉，“ DBMS-postgres-DBMS”&amp;#x1f605;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;兼容性测试不足&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;PG有400+插件，只测试了其中96个兼容性测试，也只有1-1的兼容性测试，不包含3个插件及以上的测试。兼容性测试不算特别全面。&lt;/p&gt;

&lt;h2 class="relative group"&gt;结论
 &lt;div id="结论" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%bb%93%e8%ae%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;PG的插件确实很多很灵活，数量也很多，你都很难找到哪些是PG插件&lt;em&gt;不支持&lt;/em&gt;的功能。但是插件本身几乎是“无政府状态”，插件的开发和使用都有些问题。&lt;/p&gt;
&lt;p&gt;从兼容性结果来看，插件的兼容性是比较差的，甚至插件的安装顺序影响兼容性，多插件本身也依赖hook的执行顺序，比如2个插件都要求自己最后执行就比较尴尬了。“什么都有”不代表“什么都装”。&lt;/p&gt;

&lt;h3 class="relative group"&gt;插件的安全问题
 &lt;div id="插件的安全问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%92%e4%bb%b6%e7%9a%84%e5%ae%89%e5%85%a8%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;PG的插件在安全层面管理几乎是没有的，无论是插件本身不安全还是用户使用插件提权。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;如果扩展包含有不安全的语言，能限制其行为的只有OS而不是DBMS&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果扩展可以访问用户空间，OS层就做不了管理了&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过查询（如UDF）实现的extension基本不会绕过ACL策略。虽然UDF更安全，但是也不是绝对安全，因为可以有含管理员权限的UDF。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;单hook可能不会受到ACL的限制，因为在postgres中ACL只在planning和execution层执行。PG提供了&lt;code&gt;SECURITY LABEL&lt;/code&gt;来限制对象（包括插件）的访问控制&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;软件管理的哲学思考
 &lt;div id="软件管理的哲学思考" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bd%af%e4%bb%b6%e7%ae%a1%e7%90%86%e7%9a%84%e5%93%b2%e5%ad%a6%e6%80%9d%e8%80%83" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;“如果扩展包含有不安全的语言，能限制其行为的只有OS而不是DBMS”&lt;/p&gt;
&lt;p&gt;这句话本身没有毛病，但是含有“你的目录会被删除”的暗示。为了反驳一下这句话，可以这样思考。&lt;/p&gt;
&lt;p&gt;如果你使用这款软件，那么就是信任这款软件，如同pg本身一样（但即使使用pg这款软件，也需要建立postgres这个os user，而不是直接使用root）。至于插件，可以把它当成pg软件的一部分。pg之所以被信任，能直接在生产环境安装，是因为业界有口皆碑。同样插件也是一样的，选择有口皆碑的插件，而不是胡乱使用。这本质上是postgres社区把关和插件提供方把关的区别。对于云服务商，很多插件都是不支持的，云服务商承担了插件把关的职能和背锅的责任。&lt;/p&gt;

&lt;h3 class="relative group"&gt;版本收敛
 &lt;div id="版本收敛" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%89%88%e6%9c%ac%e6%94%b6%e6%95%9b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;pg的插件版本有这些特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;同一个插件，不同的数据库版本会有不同的插件包&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;插件有不同的版本&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就导致对插件版本没有管理的话，会出现多到难以管理的软件version。针对这个问题，限制不同PG版本安装指定的某一个插件版本，是一个不错的选择。至于处于某些需求的原因需要插件升级，通过pg版本升级来实现。这样的策略相当于牺牲了一定的灵活性，来保证稳定性。我个人认为是值得的，因为升级插件这个需求本身不多，但可以减少很多软件管理问题和未知的兼容性问题。&lt;/p&gt;

&lt;h3 class="relative group"&gt;使用插件时要考虑兼容性问题
 &lt;div id="使用插件时要考虑兼容性问题" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bd%bf%e7%94%a8%e6%8f%92%e4%bb%b6%e6%97%b6%e8%a6%81%e8%80%83%e8%99%91%e5%85%bc%e5%ae%b9%e6%80%a7%e9%97%ae%e9%a2%98" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;既然插件兼容性不怎么样，那么&lt;strong&gt;管理插件变得尤为重要&lt;/strong&gt;，我们不希望数据库返回奇怪的结果甚至跑着跑着就挂了&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;插件管理策略：1.安装必要插件 2.再按需创建需要的插件 3.不要装没什么人用的插件&lt;/li&gt;
&lt;li&gt;搜索兼容性矩阵。虽然PG兼容性测试并不完美，但还是有价值的。因为论文不好直接搜兼容性矩阵，但可以“ctrl+f”搜索&lt;a href="https://github.com/cmu-db/ext-analyzer/blob/main/plot_scripts/csvs/compatibility_results.csv" target="_blank" rel="noreferrer"&gt;ext-analyzer的兼容性表格&lt;/a&gt;，初步判断你需要使用的插件的兼容性是否优秀。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;趣闻
 &lt;div id="趣闻" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%b6%a3%e9%97%bb" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;在1976年的INGRES论文中，已通过扩展实现了UDF；即使是POSTGRES，也在1986年的初始版本中转移了这个功能实现。而ORACLE 的UDF实现是ORACLE 7，release时间是&lt;a href="https://www.orafaq.com/wiki/Oracle_7" target="_blank" rel="noreferrer"&gt;1992年&lt;/a&gt;，比PG晚不少。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/da3915cf7a37.png" alt="image-20251228104850349" /&gt;&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/2830dc6d8871.png" alt="image-20251228104840046" /&gt;&lt;/p&gt;
&lt;p&gt;而SQL标准是1996年才包含了UDF，离INGRES的UDF过去了整20年。stone braker确实是不太注重标准的推动。&lt;/p&gt;</content:encoded></item><item><title>论文精读：DBAIOps</title><link>https://lastdba.com/2025/12/21/%E8%AE%BA%E6%96%87%E7%B2%BE%E8%AF%BBdbaiops/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/12/21/%E8%AE%BA%E6%96%87%E7%B2%BE%E8%AF%BBdbaiops/</guid><description>&lt;p&gt;论文：&lt;a href="https://www.arxiv.org/pdf/2508.01136" target="_blank" rel="noreferrer"&gt;DBAIOps: A Reasoning LLM-Enhanced Database Operation and Maintenance System using Knowledge Graphs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;repo：https://github.com/weAIDB/DBAIOps/&lt;/p&gt;

&lt;h2 class="relative group"&gt;什么是DBAIOps
 &lt;div id="什么是dbaiops" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bb%80%e4%b9%88%e6%98%afdbaiops" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;1.why DBAIOps：&lt;/p&gt;</description><content:encoded>&lt;p&gt;论文：&lt;a href="https://www.arxiv.org/pdf/2508.01136" target="_blank" rel="noreferrer"&gt;DBAIOps: A Reasoning LLM-Enhanced Database Operation and Maintenance System using Knowledge Graphs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;repo：https://github.com/weAIDB/DBAIOps/&lt;/p&gt;

&lt;h2 class="relative group"&gt;什么是DBAIOps
 &lt;div id="什么是dbaiops" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%bb%80%e4%b9%88%e6%98%afdbaiops" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;1.why DBAIOps：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;人力运维非常耗时&lt;/li&gt;
&lt;li&gt;人力运维难以扩展&lt;/li&gt;
&lt;li&gt;人力运维常期困于重复的故障&lt;/li&gt;
&lt;li&gt;文档+RAG模型不准确（没有DBA经验集成或有限制的局限性）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;总之，人力运维和现有方案都一般般，所以推出了DBAIOps——&lt;strong&gt;结合大模型推理和知识图谱的运维系统，实现类DBA的诊断能力&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;2.数据库故障分析方案对比：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;预设规则方案：传统方案，比较死板&lt;/li&gt;
&lt;li&gt;机器学习方案：本质上是基于规则的，有许多类似的限制；依赖训练数据，会造成较低的生成能力，一般适合特点问题常见的诊断。&lt;/li&gt;
&lt;li&gt;基于LLM方案：使用一般文档和LLM（例如基于决策树），容易给出一般结果&lt;/li&gt;
&lt;li&gt;LLM+RAG方案：搜索基于分片的top-k临近知识，结果不准确&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3.对比了以上方案后，可以看出&lt;strong&gt;结合了图知识、DBA经验、LLM的DBAIOps的优势：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;结合DBA经验&lt;/li&gt;
&lt;li&gt;保留原始关系&lt;/li&gt;
&lt;li&gt;支持新的根因定位和解决方案&lt;/li&gt;
&lt;li&gt;可扩展&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;overview
 &lt;div id="overview" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#overview" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/0901d29f4881.png" alt="image-20251214092938211" /&gt;&lt;/p&gt;
&lt;p&gt;左侧是架构，右侧是示例。&lt;/p&gt;
&lt;p&gt;offline做的是DBA经验嵌入neo4j，嵌入后的图模型叫ExperienceGraph，图的边代表异常现象或者metric的关系。嵌入后的异常模型称为AnomalyModel。&lt;/p&gt;
&lt;p&gt;online做的是异常分析、检索、生成报告。其中AnomalyProcessor提取标准故障信息和AnomalyModel信息，然后通过ExperienceRetriever检索图；最后RootCauseAnlyser调用LLM生成分析报告。&lt;/p&gt;
&lt;p&gt;从右侧的示例可以看到，通过图相关性找到LOG FILE SYNC关联的LOG WRITE性能、IO性能；通过REDO ALLOCATION可以找到表结构变更和DDL。&lt;/p&gt;

&lt;h2 class="relative group"&gt;运维经验的图模型
 &lt;div id="运维经验的图模型" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%90%e7%bb%b4%e7%bb%8f%e9%aa%8c%e7%9a%84%e5%9b%be%e6%a8%a1%e5%9e%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;不同于基于规则或者基于文档chunk的RAG，ExperienceGraph是编码了运维经验异构信息的图模型。图包含三个元素：（顶点、带方向的边，边上的关系）。&lt;/p&gt;
&lt;p&gt;根据运维经验的特性，DBAIOps对其中顶点进行了分类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;trigger vertex：用于检测数据库异常，是异常分析的入口。例如LOG FILE SYNC就是入口顶点&lt;/li&gt;
&lt;li&gt;metric vertex：数据库运行时的metric。如果是离线知识，指的应该是运维案例里的metric（如果有的话）&lt;/li&gt;
&lt;li&gt;experience vertex：编码了领域特定的运维经验，涵盖异常的含义及处置方法。比如LOG FILE SYNC超过60ms代表提交过于频繁或者其他参数需要调整。&lt;/li&gt;
&lt;li&gt;tool vertex：收集和分析异常指标的可执行脚本&lt;/li&gt;
&lt;li&gt;tag vertex：图顶点的语义类别。比如并发事务Concurrent Transactions涉及多种顶点，tag vertex可以加强跨案例的关联性&lt;/li&gt;
&lt;li&gt;auxiliary vertex：解释指标的含义&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对边的分类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;containment edge：Trigger Vertex-Experience Vertex&lt;/li&gt;
&lt;li&gt;relevance edge：Trigger Vertex-Metric Vertex&lt;/li&gt;
&lt;li&gt;diagnosis edge：Experience Vertex -Metric Vertex&lt;/li&gt;
&lt;li&gt;sysnonym edge：只出现在Tag Vertices-Tag Vertices之间，表示语义上同义，比如physical_read and disk_read; shared_pool and shared_buffer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以示例来分析运维经验图模型：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/af2763d6d88b.png" alt="image-20251215210049114" /&gt;&lt;/p&gt;
&lt;p&gt;LOG FILE SYNC有多种TAG，TAG跟Experience、metric、tool关联。能看出来关联性非常强，它代表了人类DBA对LOG FILE SYNC的理解和运维经验。&lt;/p&gt;

&lt;h2 class="relative group"&gt;图的构建
 &lt;div id="图的构建" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%9b%be%e7%9a%84%e6%9e%84%e5%bb%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;手搓图是不靠谱的，现有的ML生成图可能生成没关系的关系，所以提出了半自动的图生成方案。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;图的初始化：这一部分是手动生成的，根据规则来定义trigger vertices。trigger vertices一旦生成，其关联的metric vertex、experience vertex等会自动生成。这部分有点像人类DBA指导创建知识草图，总的框架不能动，不能生成一些稀奇古怪的东西。&lt;/li&gt;
&lt;li&gt;图的存放：就是放到Neo4J里；另外，不同的数据库类型通过tag来标记，这样很多知识是通用的，也避免了重复构建图。&lt;/li&gt;
&lt;li&gt;图的增强：生成更多的边&lt;/li&gt;
&lt;li&gt;图的更新：DBAIOps支持增量更新。这里的更新不仅指新增新的vertex，也包括去掉老的vertex&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;异常模型
 &lt;div id="异常模型" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%bc%82%e5%b8%b8%e6%a8%a1%e5%9e%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;metric
 &lt;div id="metric" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#metric" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;metric的来源有很多，包括运行信息（CPU %，吞吐等日常监控）、日志、trace等等，再加上相关性的差异，还需要从中取出关联性较强的metric。所以将metric分成了2类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;立即收集的metric：运行信息、日志、trace&lt;/li&gt;
&lt;li&gt;后续收集的metric：周期、delta等metric，需要的时候再生成，比如AWR/ASH数据&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在metric和异常相关性上，不同于基于基线的关联方式，DBAIOps采用每种异常都基于特定的metric组合。&lt;/p&gt;
&lt;p&gt;最后通过一个公式来判断是否确实发生异常：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/3693e91d7723.png" alt="image-20251214093339574" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;两阶段图演化
 &lt;div id="两阶段图演化" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%a4%e9%98%b6%e6%ae%b5%e5%9b%be%e6%bc%94%e5%8c%96" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;数据库异常很少孤立发生，一个性能问题可能同时触发或恶化其他问题。然而，预构建的知识图谱中不同异常模型 (如 LOG_FILE_SYNC 和 REDO_ALLOCATION) 之间的连接往往松散，共享的经验片段稀疏且碎片化。这导致传统方法难以发现跨模型的复合根因，如 I/O 瓶颈与内存压力的组合问题。&lt;/p&gt;
&lt;p&gt;为解决这一挑战，DBAIOps 提出了自动 &amp;ldquo;图演化&amp;rdquo; 机制，动态发现并连接不同异常模型间的相关经验片段，使知识图谱从初始的稀疏结构逐步演化为密集互联的网络，从而支持更全面的根因分析。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;第一阶段-Graph Inference and Proximity Discovery (图推理与邻近发现)：通过图查询语言 (Cypher) 收集和聚合相关指标，基于可配置阈值遍历相关节点和边，构建关联网络。例如LOG_FILE_SYNC 延迟，从顶点出发，遍历最多 3 跳的关联节点。在 LOG_FILE_SYNC 和 REDO_ALLOCATION 模型间建立连接，因为它们都与 I/O 相关的并发问题有关。通过多次迭代，知识图谱逐渐演变为更密集的结构，使诊断能考虑更多潜在因素和复合原因。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;第二阶段-Adaptive Abnormal Metric Detection (自适应异常指标检测)：在图扩展路径上识别真正异常的指标。通过自适应检测函数（ADF），结合指标波动性、动态基线偏差等维度计算综合异常分数，依据异常评分结果，决定是否需要进一步扩展知识图谱结构，为后续 LLM 的根因推理筛选出精准的异常指标子集。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/313bde49387f.png" alt="image-20251214103841593" /&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;生成分析报告
 &lt;div id="生成分析报告" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%94%9f%e6%88%90%e5%88%86%e6%9e%90%e6%8a%a5%e5%91%8a" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;图搞定后，就需要prompt喂给LLM来生成想要的报告，一个合理的prompt也可以提升报告的准确性。&lt;/p&gt;
&lt;p&gt;异象有5种成分，这5种成分作为prompt给LLM：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anomaly：异常描述（“CPU usage spiked to 95% at 16:00 on 2023-10-05”）&lt;/li&gt;
&lt;li&gt;Condition：异常触发条件（“exceeds 90% for &amp;gt;5 min”）&lt;/li&gt;
&lt;li&gt;Metrics&lt;/li&gt;
&lt;li&gt;Experience：提供正常负载值，或者最近的维护任务&lt;/li&gt;
&lt;li&gt;Output：描述报告的组成的。有异常验证（需要继续分析的）、根因分析、恢复方案、汇总、SQL文本&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;自己的一点想法&lt;/em&gt;：&lt;/p&gt;
&lt;p&gt;最近的维护任务很有用，维护任务一般来说关联性是比较大的，故障分析也不是能是简单的技术分析。不过谁去更新这个维护任务、哪些要更新哪些不更新应该是问题。&lt;/p&gt;
&lt;p&gt;output中前几个都好理解，最后一个SQL文本可谓神来一笔。在生产环境中，抛开硬件故障，数据库的运行状态跟SQL是强相关的，我个人认为可以无脑抓SQL，抓出来再说因果关系的问题。从运维工作的角度来讲，故障都需要跟开发共同排查，那么SQL文本基本是必抓取的。&lt;/p&gt;

&lt;h2 class="relative group"&gt;评估
 &lt;div id="评估" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%af%84%e4%bc%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;不同工具、方式下，生成的分析报告的效果对比：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/2f2ecc9b755b.png" alt="image-20251215082259815" /&gt;&lt;/p&gt;
&lt;p&gt;可以看出来很强了。特别要注意的是，DBAIOps特别强调了中型大模型的分析效果就已经很好了。这个还是比较重要的，DeepSeek-R1 671B裸跑就不差，但是成本不是一个级别的。&lt;/p&gt;

&lt;h2 class="relative group"&gt;挑点刺
 &lt;div id="挑点刺" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8c%91%e7%82%b9%e5%88%ba" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;1.不能完全叫Ops，只是有故障分析功能。Ops内容是很多的，故障分析只是冰山一角。&lt;/p&gt;
&lt;p&gt;2.图的分类和图的示例对不上号。定义的tag vertex和edge跟示例的差别比较大。&lt;/p&gt;
&lt;p&gt;示例中的vertex作用很大，但是没有定义这些边的类型：tag vertex-tool vertex、tag vertex-experience vertex、tag vertex-metric vertex。而应该存在的边，看上去基本都没有，只有一个sysnonym edge。&lt;/p&gt;
&lt;p&gt;应该列举出来示例中没有说明的部分，不然看的云里雾里的。&lt;/p&gt;
&lt;p&gt;3.两阶段图演化的效果有点怪：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/5fd6929e7dee.png" alt="image-20251214165952773" /&gt;&lt;/p&gt;
&lt;p&gt;w/o ADF代表没有第二阶段图演化（自适应异常指标检测）&lt;/p&gt;
&lt;p&gt;w/o ADF代表没有第一阶段图演化（图推理与邻近发现）&lt;/p&gt;
&lt;p&gt;w/o ADF代表两个阶段都没有的图演化&lt;/p&gt;
&lt;p&gt;这里少了两阶段都有的图演化，有的话就更能说明两阶段图演化的效果。&lt;/p&gt;
&lt;p&gt;4.根因有些少：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/4e7faebf0b1a.png" alt="image-20251214114018609" /&gt;&lt;/p&gt;
&lt;p&gt;上面几个圈起来的应该是比较常见的（我只看了oracle、postgres），但是暂时没有这些根因。&lt;/p&gt;
&lt;p&gt;pg的根因有点少，刷脏一般不算太大的问题，刷脏根因本身，大概率排到众多根因的后面了。&lt;/p&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;我个人非常喜欢的点：&lt;/p&gt;
&lt;p&gt;1.GraphRAG在故障诊断方面，应该会比vector RAG好。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/eddb311c9614.png" alt="image-20251215212534234" /&gt;&lt;/p&gt;
&lt;p&gt;（GraphRAG原始论文：&lt;a href="https://arxiv.org/pdf/2404.16130" target="_blank" rel="noreferrer"&gt;From Local to Global: A GraphRAG Approach to Query-Focused Summarization&lt;/a&gt;）&lt;/p&gt;
&lt;p&gt;SS代表vector RAG，TS代表源文本摘要，C0/C1/C2/C3代表不同知识粒度的GraphRAG。从这个图可以简单得出结论：GraphRAG更适合多预料复杂场景，多角度分析，但在精准度上其实不一定比vectorRAG好&lt;/p&gt;
&lt;p&gt;2.半自动的图生成方案&lt;/p&gt;
&lt;p&gt;图生成是半自动的，trigger vertex手搓，其他可以自动生成。例如LOG FILE SYNC就是trigger vertex。故障的入口确实可以做出明显的异常点，这就是入口，PG也是一样的，任何故障应该也是一样的，符合人类对故障的理解逻辑。&lt;/p&gt;
&lt;p&gt;.自动图演化&lt;/p&gt;
&lt;p&gt;加强某些vertex的关联性，是有意义的，Performance of DBAIOps** Variants表格可见一斑&lt;/p&gt;
&lt;p&gt;4.自动基线调整&lt;/p&gt;
&lt;p&gt;在《可观测性工程》中对AIOps有这么一段话：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;AI只有在存在清晰可辨的模式并且可以识别不断变化的基线来进行预测时才能提供帮助——目前还没有这种AIOps&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;DBAIOps在我的眼中&lt;/p&gt;
&lt;p&gt;清晰可辨的模式= DBAIOps中的图，它包括了故障模型、异常关系、监控数据和日志&lt;/p&gt;
&lt;p&gt;不断变化的基线= DBAIOps中的自适应异常指标检测&lt;/p&gt;
&lt;p&gt;总之，比随意chunk故障知识、拍一个基线、vector近似搜索的RAG模型要进步很多了。&lt;/p&gt;</content:encoded></item><item><title>CXL和PolarDB-CXL</title><link>https://lastdba.com/2025/11/30/cxl%E5%92%8Cpolardb-cxl/</link><pubDate>Sun, 30 Nov 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/11/30/cxl%E5%92%8Cpolardb-cxl/</guid><description>&lt;p&gt;论文：Unlocking the Potential of CXL for Disaggregated Memory in Cloud-Native Databases&lt;/p&gt;
&lt;p&gt;SIGMOD best paper：&lt;a href="https://sigmod.org/sigmod-awards/sigmod-best-paper-award/" target="_blank" rel="noreferrer"&gt;https://sigmod.org/sigmod-awards/sigmod-best-paper-award/&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;CXL和PolarDB-CXL
 &lt;div id="cxl和polardb-cxl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cxl%e5%92%8cpolardb-cxl" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;CXL的概念
 &lt;div id="cxl的概念" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cxl%e7%9a%84%e6%a6%82%e5%bf%b5" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;CXL&lt;/strong&gt;：开放的行业标准，由 CXL 联盟 (2019 年由英特尔、AMD、ARM 等科技巨头创立) 制定的高速互连规范。它代表了计算架构的演进方向。目前刚演进到CXL 4.0&lt;/p&gt;</description><content:encoded>&lt;p&gt;论文：Unlocking the Potential of CXL for Disaggregated Memory in Cloud-Native Databases&lt;/p&gt;
&lt;p&gt;SIGMOD best paper：&lt;a href="https://sigmod.org/sigmod-awards/sigmod-best-paper-award/" target="_blank" rel="noreferrer"&gt;https://sigmod.org/sigmod-awards/sigmod-best-paper-award/&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;CXL和PolarDB-CXL
 &lt;div id="cxl和polardb-cxl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cxl%e5%92%8cpolardb-cxl" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;CXL的概念
 &lt;div id="cxl的概念" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cxl%e7%9a%84%e6%a6%82%e5%bf%b5" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;CXL&lt;/strong&gt;：开放的行业标准，由 CXL 联盟 (2019 年由英特尔、AMD、ARM 等科技巨头创立) 制定的高速互连规范。它代表了计算架构的演进方向。目前刚演进到CXL 4.0&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;特性&lt;/th&gt;
 &lt;th&gt;CXL 1.0/1.1&lt;/th&gt;
 &lt;th&gt;CXL 2.0&lt;/th&gt;
 &lt;th&gt;CXL 3.0/3.1&lt;/th&gt;
 &lt;th&gt;CXL 4.0 (最新)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;发布时间&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;2019 年 3 月 / 9 月&lt;/td&gt;
 &lt;td&gt;2020 年 10 月&lt;/td&gt;
 &lt;td&gt;2022 年 8 月 / 2023 年 11 月&lt;/td&gt;
 &lt;td&gt;2025 年 11 月&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;基础协议&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;PCIe 5.0 (32 GT/s)&lt;/td&gt;
 &lt;td&gt;PCIe 5.0 (32 GT/s)&lt;/td&gt;
 &lt;td&gt;PCIe 6.0 (64 GT/s)&lt;/td&gt;
 &lt;td&gt;PCIe 7.0 (128 GT/s)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;最大带宽&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;1TB/s&lt;/td&gt;
 &lt;td&gt;1TB/s&lt;/td&gt;
 &lt;td&gt;2TB/s&lt;/td&gt;
 &lt;td&gt;4TB/s+&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;拓扑规模&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;点对点 / 简单星型&lt;/td&gt;
 &lt;td&gt;单交换机 (≤32 节点)&lt;/td&gt;
 &lt;td&gt;多级 Fabric (4096 节点)&lt;/td&gt;
 &lt;td&gt;超大规模 Fabric&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;据我搜索的资料中，摘取两个比较影响深刻的对CXL的描述：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内存即服务&lt;/li&gt;
&lt;li&gt;近内存计算和扩展&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;CXL switch&lt;/strong&gt;：是交换芯片，物理硬件。很多厂商在做工业化实现，论文中特指产商是XConn Tech的产品 &lt;a href="https://www.xconn-tech.com/products" target="_blank" rel="noreferrer"&gt;CXL 2.0 switch&lt;/a&gt;。需要注意的是，截止2025年11月22日，XConn这家只有CXL 2.0 switch，没有3.0的产品，市面上是有支持3.0+标准的交换芯片的产品&lt;a href="https://panmnesia.com/news/en/2025-11-13-switch-sample/" target="_blank" rel="noreferrer"&gt;panmnesia CXL 3.2 Fabric Switch&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;polarCXLMem&lt;/strong&gt;：据论文所说是“首个基于CXL-switch的分离式内存系统”。但是论文中提到“we leverage the world’s first CXL switch[50]”也就是特指Xconn tech CXL 2.0 switch，然后再提到“PolarCXLMem is the first CXL-switch-based disaggregated memory”。这句话可以理解为两种含义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首个基于CXL switch的分离式内存系统&lt;/li&gt;
&lt;li&gt;首个基于Xconn tech CXL 2.0 switch的分离式内存系统&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;polardb-cxl&lt;/strong&gt;：其实论文中没有这个概念，但是行业在用这个词。这个词代表“integrate &lt;em&gt;PolarCXLMem&lt;/em&gt; into the multi-primary version of PolarDB,known as PolarDB-MP”，相当于“&lt;strong&gt;PolarDB-MP的CXL升级版&lt;/strong&gt;”。论文中反复使用这么长一段话，但是始终没有用polardb-cxl这个词。为了方便起见，本文中使用polardb-cxl这个词代表其本质含义。&lt;/p&gt;

&lt;h3 class="relative group"&gt;RDMA vs CXL
 &lt;div id="rdma-vs-cxl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#rdma-vs-cxl" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;PolarDB-MP用的是RDMA架构，PolarDB-CXL是CXL架构：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/fc236ee67755.png" alt="image-20251122115316339" /&gt;&lt;/p&gt;
&lt;p&gt;（https://medium.com/@anan.mirji/cxl-switch-vs-rdma-a-technical-comparison-for-high-performance-interconnects-6aaa031cde31）&lt;/p&gt;
&lt;p&gt;RDMA架构是跨主机的分布式互联架构，CXL架构这是单主机的扩展互联架构。&lt;/p&gt;
&lt;p&gt;核心差异&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;维度&lt;/th&gt;
 &lt;th&gt;RDMA 架构&lt;/th&gt;
 &lt;th&gt;CXL 架构&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;拓扑结构&lt;/td&gt;
 &lt;td&gt;多主机 + 网络交换机的分布式架构&lt;/td&gt;
 &lt;td&gt;单主机 + CXL 交换机的扩展架构&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;通信介质&lt;/td&gt;
 &lt;td&gt;网络（InfiniBand/RoCE）&lt;/td&gt;
 &lt;td&gt;PCIe 总线（CXL 基于 PCIe 物理层）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;核心组件&lt;/td&gt;
 &lt;td&gt;RDMA NIC（专用网卡）&lt;/td&gt;
 &lt;td&gt;CXL Controller、CXL Switch&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;资源归属&lt;/td&gt;
 &lt;td&gt;跨独立主机的 “远程资源”&lt;/td&gt;
 &lt;td&gt;主机架构内的 “扩展资源”&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 class="relative group"&gt;CXL的优势
 &lt;div id="cxl的优势" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cxl%e7%9a%84%e4%bc%98%e5%8a%bf" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;CXL相较于RDMA的优势：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;低延迟：CXL通过PCIe连接主机或者设备上的内存；而RDMA 需要在InfiniBand与PCIe 之间进行协议接口转换&lt;/p&gt;
&lt;p&gt;指令支持：CXL提供了原生的 load/store指令，使CPU能像访问本地内存一样直接操作远程CXL设备内存；而RDMA需要从远端内存读到本地内存，在本地处理后再回写到远端内存。&lt;/p&gt;
&lt;p&gt;简化应用：RDMA需要特殊的接口和驱动，需要专业人员设计复杂的程序；而CXL提供透明的内存空间极大简化应用设计&lt;/p&gt;
&lt;p&gt;内存融合：CXL 3.0支持物理硬件级内存融合&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;polardb-mp存在的问题和CXL能提供的价值：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CXL说MP的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;内存页是4-16K的，就算只需要很少的数据传输，也必须在本地内存和共享内存间传输数据，这导致了读写放大。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;维护本地内存需要额外的内存开销，这降低了吞吐&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;恢复非常花时间&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDMA远好于TCP/IP，但在高并发下有 “门铃寄存器隐式竞争” 和 “缓存颠簸”问题&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据库本身要维护共享内存&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CXL带来的好处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;消除“共享内存-本地内存”的层级内存结构，也消除了层级结构的维护消耗和读写放大问题。因为CXL load/store本地内存足够快，所以允许直接store所有的buffer pages&lt;/li&gt;
&lt;li&gt;以缓存行（64B）为最小CPU缓存和主存的传输单位，而不是polardb-MP的4K&lt;/li&gt;
&lt;li&gt;节约主存。主存（DRAM）的成本非常高，大约占服务器/机架成本的40-50%&lt;/li&gt;
&lt;li&gt;简化系统设计。在现有系统上最小化改造，对于商业数据库的稳定性来说很重要。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;PolarRecv&lt;/em&gt;：基于CXL做的立即恢复的系统。在数据库crash后，data和metadata都还在CXL上，可以直接在CXL memory上读到一致性状态，所以恢复非常快。（这看起来跟pg的page cache缓存可以帮助crash后快速启动有类似处）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;DRAM vs RDMA vs CXL&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/66af810eb94e.png" alt="image-20251122155133782" /&gt;&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/ae9cc24e5158.png" alt="image-20251122155109014" /&gt;&lt;/p&gt;
&lt;p&gt;在数据量较少时，RDMA比CXL延迟高不少，数据大一点RDMA的延迟就稍微好点。本地访问内存DRAM要略好于通过CXL访问。&lt;/p&gt;
&lt;p&gt;总体来说，CXL内存访问的延迟略高于DRAM但好于RDMA。&lt;/p&gt;
&lt;p&gt;对于CXL延迟高于DRAM，论文这样解释“database buffer pool operations are more sensitive to bandwidth than latency”，对于数据库内存来说，带宽比延迟重要。&lt;/p&gt;

&lt;h2 class="relative group"&gt;自研机架
 &lt;div id="自研机架" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%87%aa%e7%a0%94%e6%9c%ba%e6%9e%b6" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;自研的物理原型机架。左边的机架集成了两个支持 CXL 交换机的集群，每个集群均连接至内存设备与主机；右边的机架集成了1个CXL 交换机，连接至内存设备和主机。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/45333b6bf088.png" alt="image-20251122151718276" /&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;PolarCXLMem
 &lt;div id="polarcxlmem" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#polarcxlmem" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;CXL 2.0 switch支持内存池但驱动没有完全支持，所以PolarCXLMem还是设计了CXL的内存分配和使用，不是完全透明的。PolarCXLMem经过一些处理，将CXL memory分成了多租户的模式，不同的主机节点分配不同的CXL内存区域。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/ddc3509d74d0.png" alt="image-20251123094443287" /&gt;&lt;/p&gt;
&lt;p&gt;PolarCXLMem的特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点有各自的CXL内存区域，不同的节点不会交叠CXL内存&lt;/li&gt;
&lt;li&gt;buffer pool仍在数据库启动后就分配（由上图中的CXL mem manager分配），运行状态不会改变内存分配区&lt;/li&gt;
&lt;li&gt;cxl mem中的内存单位结构是block，block会存储page的数据和page的元数据，这些元数据包括：id代表页id，lock state代表页是否有被update锁定，prev/next是LRU双链，lsn为page的最新日志序列号。&lt;/li&gt;
&lt;li&gt;free list/in-use list用来做LRU的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;疑问：pg的pageheader有lsn、起始空闲空间指针、prune xid等等，polardb-cxl的页头又是什么结构呢？&lt;/em&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;PolarRecv
 &lt;div id="polarrecv" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#polarrecv" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;PolarDB-MP是基于RDMA设计的，数据页在本地写入即可，分离式共享内存中没有最新版本的数据页。这导致主机crash后需要扫描和应用所有redo log文件（论文中说是redo不是wal）或一点点共享内存中的页。&lt;/p&gt;
&lt;p&gt;而CXL switch有独立的电源，即便主机宕机，最新的数据还在CXL内存中。所以PolarRecv利用这一点来极大的提高主机宕机后数据库的恢复速度。&lt;/p&gt;
&lt;p&gt;但是，虽然CXL switch内存透明又持久，crash后直接使用还是需要处理以下问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LRU list可能在crash时是不一致的&lt;/li&gt;
&lt;li&gt;B-tree SMO（B-tree结构变化），例如索引分裂时，可能在crash时是不一致的&lt;/li&gt;
&lt;li&gt;页在更新时crash，可能是不一致的&lt;/li&gt;
&lt;li&gt;redo log buffer用的本地DRAM，当redolog还没有刷盘时crash，CXL中的buffer pool中的page lsn可能大于redolog文件中的lsn，这直接违反了ARIES原则&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PolarRecv设计的对应策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;用mutex来保护LRU结构，mutex锁的状态代表LRU是否在crash时被修改，如果是的话，LRU需要重建，如果不是则直接使用CXL内存中的LRU。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B-tree SMO时会有一个mini-tranaction保护索引页，这个mini-tranaction是对应于page锁的两阶段锁。当mini-transaction提交时才会flush到redolog。所以在恢复过程中发现索引页有写锁，从redologs中恢复。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;polarcxl的读写锁是放在cxl内存中的。如果写锁还在，说明crash时update在中间状态没有完成。此时老实从redolog文件中读取page而不是在cxl内存中读取不一致的page。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;recovering过程中，首先会拿到redolog中最大LSN，然后检查CXL内存中page的锁和LSN，如果cxl内存中page的LSN大于最大LSN，那就用redolog中的信息去重建page而不是用CXL内存中版本。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;内存融合
 &lt;div id="内存融合" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98%e8%9e%8d%e5%90%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;因为PolarCXLMem是基于CXL 2.0 switch设计的，CXL 3.0才支持内存融合，所以还是要做内存融合的设计。因为每个节点的buffer pool都是隔离式地放在PolarCXLMem中，&lt;strong&gt;CXL 2.0的内存融合通过对DBP的元数据管理来实现，每个buffer pool都只存页的CXL内存地址而不是页本身&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/d3b28a223927.png" alt="image-20251123142605871" /&gt;&lt;/p&gt;
&lt;p&gt;看懂上图需要注意区分CXL memory，dbp和本地buffer ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CXL memory是物理硬件，CXL mem本身&lt;/li&gt;
&lt;li&gt;dbp是CXL中开辟出来的区域用于管理内存融合服务&lt;/li&gt;
&lt;li&gt;本地 metadata buffer包含了本地buffer的元数据和CXL的部分&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外还需要了解，对于每个buffer pool中的page都有两个标志：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;invalid：其他节点写入页后，当前节点需要invalidate本地cpu cache&lt;/li&gt;
&lt;li&gt;removal：page从in-use list转移到free list，所有节点都要设置removal标志&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;内存融合page的访问流程：&lt;/p&gt;
&lt;p&gt;1.请求的页不在本地page metadata buffer中，&lt;/p&gt;
&lt;p&gt;1.1 从freelist中分配新的meta record，并通过rpc给内存融合服务提供invalid、removal地址&lt;/p&gt;
&lt;p&gt;请求的页在本地page metadata buffer中，&lt;/p&gt;
&lt;p&gt;2.1先检查removal flag，若removal被设置，代表内存融合服务已经回收了该page，需要通过RPC请求内存融合服务的新内存地址&lt;/p&gt;
&lt;p&gt;2.2然后检查invalid flag，invalid flag被设置，代表页被其他节点修改，需要invalidate cpu cache以确保一致性&lt;/p&gt;
&lt;p&gt;融合一致性：&lt;/p&gt;
&lt;p&gt;因为CXL 2.0没有内存融合，cpu cache不会被自动更新。polarcxl通过页级锁来实现多节点并发写入控制。&lt;/p&gt;
&lt;p&gt;节点读写page需要拿到读写锁。&lt;strong&gt;当一个节点正在写入page时，其他节点不能获得读写该page&lt;/strong&gt;。当节点写完后，还需要&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前节点将cpu cache &lt;em&gt;lflush&lt;/em&gt;到CXL mem中，以确保CXL mem是最新版本的page&lt;/li&gt;
&lt;li&gt;设置invalid flag，以确保其他节点不去读其cpu cache的老版本page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;内存融合小节：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CXL 2.0本身支持不太完整的内存融合，导致数据库层还是需要设计内存融合方案。内存页通过CXL地址访问，而不是像RDMA方案一样本地/远程访问整个page。本地CPU cache需要数据库层来刷新以确保节点访问数据的一致性，这是硬性限制。这也导致了跨节点更新仍然是排他页级锁（RDMA方案也是排他页级锁）。&lt;/strong&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;性能评估
 &lt;div id="性能评估" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%a7%e8%83%bd%e8%af%84%e4%bc%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;多节点读写
 &lt;div id="多节点读写" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%a4%9a%e8%8a%82%e7%82%b9%e8%af%bb%e5%86%99" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;一个192 vC的主机上放12个实例进行的压测，对比RDMA（PolarDB-MP）和CXL（PolarDB-MP with PolarCXLMem）的性能：&lt;/p&gt;
&lt;p&gt;点查：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/c5ac5a1f0d82.png" alt="image-20251124083738393" /&gt;&lt;/p&gt;
&lt;p&gt;范围查询：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/169bdabdbf3c.png" alt="image-20251125082404440" /&gt;&lt;/p&gt;
&lt;p&gt;读写：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/532e83b71906.png" alt="image-20251125082418710" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点查：点查的读放大问题最严重，CXL的带宽消耗比RDMA小3-4倍。当节点达到3个时，RDMA的带宽已经被占满，再增加节点不会有任何带宽上的提升。&lt;/li&gt;
&lt;li&gt;范围查询：范围查询的读放大问题没有那么严重，只是在节点大于4时达到带宽上限11GB/s，而CXL还可以随节点线性增长。&lt;/li&gt;
&lt;li&gt;读写：表现与范围查询类似，只是差异再小一点&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;PolarRecv恢复时效
 &lt;div id="polarrecv恢复时效" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#polarrecv%e6%81%a2%e5%a4%8d%e6%97%b6%e6%95%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;vanilla指一般方案，应该是指类似pg从本地cache或disk中读取（也有可能是polar redo）&lt;/li&gt;
&lt;li&gt;RDMA-based指polardb-mp有些数据可以从分离式共享存储中读取&lt;/li&gt;
&lt;li&gt;PolarRecv指从大部分数据从CXL中继续读，少部分patial page需要从redo文件中恢复&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/6d0ae251efed.png" alt="image-20251125085711364" /&gt;&lt;/p&gt;
&lt;p&gt;论文中论述恢复时效其实分为2个阶段：起库/recovery和负载达到crash前的水平。只读不需要recovery，只要有数据就能起库承接负载。当有写入时，就需要做恢复，此时继续从CXL内存读数的优势就体现出来了。1分钟、2分钟、4分钟的恢复时效，还是有差距的，差距可能就是业务几乎无感和有感的区别。&lt;/p&gt;

&lt;h3 class="relative group"&gt;共享数据更新
 &lt;div id="共享数据更新" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%85%b1%e4%ba%ab%e6%95%b0%e6%8d%ae%e6%9b%b4%e6%96%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;分布式数据库性能PK的焦点就是对共享数据的更新。在Polardb-mp性能暴打taurus-mm后，Polardb-cxl也暴打了Polardb-mp：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/30660f6b6fd5.png" alt="image-20251130164309249" /&gt;&lt;/p&gt;
&lt;p&gt;0%的 shared data的情况下，RDMA-based就访问local buffer就行了，Polardb-CXL只是把CXL当成内存池使用。即便如此，CXL-based还是性能更好，主要是之前说的，RDMA-based方案有读写放大和带宽上限问题。&lt;/p&gt;
&lt;p&gt;从上的性对比图可以看出来Polardb-CXL明显好于Polardb-MP，数据是非常清晰的。但是要注意，当shared data&amp;gt;60%时，Polardb-CXL性能提升不明显了，主要原因如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;页级锁成为瓶颈&lt;/li&gt;
&lt;li&gt;随着锁竞争加剧，进程会进入sleep状态，频繁的上下文切换也加剧了资源争用&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;PolarDB-CXL优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;消灭了RDMA的“本地-远程”层级内结构设计&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解决了RDMA的读写放大问题&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;提供基于CXL的内存池&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PolarRecv基于CXL持久内存，数据库崩溃恢复速度更快&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;压测显示polardb-mp cxl性能优于polardb-MP RDMA&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PolarDB-CXL缺点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;跨节点更新仍然是页级锁，在共享数据更新的场景下，仍是性能瓶颈的主因&lt;/li&gt;
&lt;li&gt;CXL 2.0 switch看起来有点老了，在论文发表的时候已经有支持3.2的交换设备了，在2025年11月也发布CXL 4.0标准。可以预测未来应该有基于更新CXL标准的交换设备的数据库出现。&lt;/li&gt;
&lt;li&gt;论文质量其实没有MP这篇高，主要是围绕CXL 2.0 switch物理硬件做的解决方案，跟PoalrDB-MP论文中有大量的数据库层面的设计还是有区别的&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>论文精读|PolarDB-MP|2024 SIGMOD最佳工业论文</title><link>https://lastdba.com/2025/11/30/%E8%AE%BA%E6%96%87%E7%B2%BE%E8%AF%BBpolardb-mp2024-sigmod%E6%9C%80%E4%BD%B3%E5%B7%A5%E4%B8%9A%E8%AE%BA%E6%96%87/</link><pubDate>Sun, 30 Nov 2025 00:00:00 +0000</pubDate><guid>https://lastdba.com/2025/11/30/%E8%AE%BA%E6%96%87%E7%B2%BE%E8%AF%BBpolardb-mp2024-sigmod%E6%9C%80%E4%BD%B3%E5%B7%A5%E4%B8%9A%E8%AE%BA%E6%96%87/</guid><description>&lt;p&gt;论文：PolarDB-MP: A Multi-Primary Cloud-Native Database via Disaggregated Shared Memory&lt;/p&gt;
&lt;p&gt;SIGMOD best paper：https://sigmod.org/sigmod-awards/sigmod-best-paper-award/&lt;/p&gt;</description><content:encoded>&lt;p&gt;论文：PolarDB-MP: A Multi-Primary Cloud-Native Database via Disaggregated Shared Memory&lt;/p&gt;
&lt;p&gt;SIGMOD best paper：https://sigmod.org/sigmod-awards/sigmod-best-paper-award/&lt;/p&gt;

&lt;h2 class="relative group"&gt;前言和摘要
 &lt;div id="前言和摘要" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%89%8d%e8%a8%80%e5%92%8c%e6%91%98%e8%a6%81" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;开篇提出问题：主从库的写入吞吐受主库限制。shared-nothing架构是可扩展的多主集群，可以解决单主受限问题，但是该架构因分布式事务的开销而出现性能瓶颈。最近基于共享存储的云原生多主数据库出现，但该架构在高冲突场景下，有冲突解决代价高和数据融合效率低的问题。&lt;/p&gt;
&lt;p&gt;所以，提出的问题的是：单主主从架构、shared-nothing架构、共享存储云原生多主架构，都有各自的问题。&lt;/p&gt;
&lt;p&gt;本篇论文提议PolarDB-MP，它是结合了分离式共享内存与共享存储的新型多主云原生数据库。（an innovative multi-primary cloud-native database ，多主云原生数据库已经有了，所以得是新型）。&lt;/p&gt;
&lt;p&gt;PolarDB-MP的基本特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;所有节点都能平等访问全部数据，从而使事务能够在单个节点上独立处理，&lt;strong&gt;无需使用传统的分布式事务机制&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;共享存储：PolarStore and PolarFS，或者其他兼容性共享存储方案&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;构建在分离式共享内存之上&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过&lt;strong&gt;RDMA&lt;/strong&gt;远程直接内存访问实现低延迟通信&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LLSN&lt;/strong&gt;（局部逻辑序列号，Local Logical Sequence Number）。用于为不同节点生成的预写日志建立部分有序关系（partial order）**，**并配合定制化恢复策略，确保系统在异常恢复时的一致性与高效性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;核心组件&lt;strong&gt;PMFS&lt;/strong&gt;（Polar Multi-Primary Fusion Server多主融合服务器）负责：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Transaction Fusion（事务融合）——负责事务排序与可见性管理&lt;/li&gt;
&lt;li&gt;Buffer Fusion（缓冲区融合） —— 提供分布式共享缓冲机制&lt;/li&gt;
&lt;li&gt;Lock Fusion（锁融合）—— 用于跨节点并发控制&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;分类
 &lt;div id="分类" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%88%86%e7%b1%bb" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;分类主要是为了看清polardb-mp的历史位置，也是为了理解”第一的定语“:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;PolarDB-MP is the first multi-primary cloud-native database that utilizes disaggregated shared memory and shared storage for transaction coordination and buffer fusion&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/3532d59aa524.png" alt="image-20251109213814089" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;竞品黑点
 &lt;div id="竞品黑点" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e7%ab%9e%e5%93%81%e9%bb%91%e7%82%b9" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;shared-nothing产品：对于这类产品没有一个个提黑点，只是一句话带过：事务在跨多分区访问时，分布式事物需要显著的额外开销。&lt;/p&gt;
&lt;p&gt;oracle：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;昂贵的分布式锁管理&lt;/li&gt;
&lt;li&gt;昂贵的网络开销&lt;/li&gt;
&lt;li&gt;比较依赖精致的机器（alien tech）&lt;/li&gt;
&lt;li&gt;难以上云，或者上云后比云原生数据库的TCO成本（包含维护、人力成本）更高&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AWS Aurora-MM：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;采用乐观事物模型，事务冲突时有较高的事物中止率&lt;/li&gt;
&lt;li&gt;某些场景下，4节点吞吐低于单节点&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;华为 Taurus-MM：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;悲观事物模型。依赖页存储和日志重放来保证缓存一致性，在并发控制和数据同步方面存在较高的开销。&lt;/li&gt;
&lt;li&gt;50% shared data 读写场景下，8节点只有1.5倍的单节点性能提升&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;oracle这里的黑点主要是看着有道理的口嗨，Aurora-MM和Taurus-MM是有原厂商引述的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Aurora-MM “某些场景下，4节点吞吐低于单节点”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Taurus-MM “50% shared data 读写场景下，8节点只有1.5倍的单节点性能提升”&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;事务融合
 &lt;div id="事务融合" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%ba%8b%e5%8a%a1%e8%9e%8d%e5%90%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;事务融合概述
 &lt;div id="事务融合概述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%ba%8b%e5%8a%a1%e8%9e%8d%e5%90%88%e6%a6%82%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;多主如何保证一致性数据视图？&lt;/p&gt;
&lt;p&gt;快照隔离是常见的MVCC实现方式。快照隔离有一个特性是，查询或者事务必须在执行期间保持自己的一致性数据视图（consistent data view）。但是在多主架构中，因为远端的数据更新，本地无法保证一致性数据视图。&lt;/p&gt;
&lt;p&gt;为了解决这个问题，一般的多主共享存储架构，会引入全局事务的机制（AuroraMM or Taurus-MM）。而在PolarDB-MP中提出了创新技术&amp;ndash;PMFS中的事务融合技术。&lt;strong&gt;每个节点只维护本地事务信息，通过RDMA被其他节点访问&lt;/strong&gt;。与全局事务相反，事务融合是去中心化的。&lt;/p&gt;

&lt;h3 class="relative group"&gt;本地事物和TIT表
 &lt;div id="本地事物和tit表" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9c%ac%e5%9c%b0%e4%ba%8b%e7%89%a9%e5%92%8ctit%e8%a1%a8" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;polardb-mp的每个节点都会有一小部分内存来存储本地的事务信息（可以被其他节点通过RDMA访问）。这些本地事务信息存储在transaction Information Table (TIT)中。&lt;/p&gt;
&lt;p&gt;TIT表的内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事务对象指针&lt;/li&gt;
&lt;li&gt;由全局时间戳协调器(TSO)分配的事务提交时间戳CTS（commit timestamp）&lt;/li&gt;
&lt;li&gt;version，代表同一slot中的不同事务（&lt;em&gt;事务对象指针不是指向一个事务？？？&lt;/em&gt;）&lt;/li&gt;
&lt;li&gt;ref，标识这个事物是否被其他事物等待释放锁（应该是Plock或者Rlock）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/90641c3618d1.png" alt="image-20251101131556184" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;事务是如何进行的
 &lt;div id="事务是如何进行的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%ba%8b%e5%8a%a1%e6%98%af%e5%a6%82%e4%bd%95%e8%bf%9b%e8%a1%8c%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;当事务开始时，本地事务id(应该就是txid了）会被分配，TIT slot会存放这个事务对象指针、ref初始化为0、CTS初始化为&lt;code&gt;CSN_INIT&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Polardb-mp用全局事务ID标识一个事务，全局事务ID=（node_id, trx_id, slot_id, version）。全局事务ID是不包含CTS的，如果要知道事务的提交顺序，比如构建事务可见性视图时，就需要通过全局事物ID，经过RDMA，去目标节点找到CTS（类似pg中的&lt;code&gt;pg_xact_commit_timestamp()&lt;/code&gt;函数通过事务id从本地文件找到对应的事务提交时间）。&lt;/p&gt;
&lt;p&gt;如果trx_id是pg中事务ID的话，那么node_id,trx_id就可以标识事务的全局唯一性了，或者node_id,slot_id,version在某种程度上也可以（未复用slot id的情况下，比如某个时刻可以标识唯一事物id），当然多出来的信息组合起来也唯一。毕竟这些信息是polardb-mp实现事务融合的关键。&lt;/p&gt;
&lt;p&gt;每个事务都会通过全局事务ID和CTS来构造可见性视图。可见性视图的概念跟pg是一致的，当前read view可读read view前已提交事务的数据行，且为最新版本行。&lt;/p&gt;

&lt;h3 class="relative group"&gt;访问远端的CTS
 &lt;div id="访问远端的cts" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%ae%bf%e9%97%ae%e8%bf%9c%e7%ab%af%e7%9a%84cts" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;因为CTS在本地（TIT or本地文件系统上）的缘故，所以获得读取事务的CTS是一个有意思活：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/41db536b2114.png" alt="image-20251101153437311" /&gt;&lt;/p&gt;
&lt;p&gt;1.1 如果一个行的CTS是CSN_INIT/CTS_INIT，即事务仍然活跃，那么返回最大CTS表示其对所有事务不可见，除了自己。&lt;/p&gt;
&lt;p&gt;1.如果一个行的CTS不是CSN_INIT/CTS_INIT，即事务已提交，且在本地的TIT中，那么直接返回CTS&lt;/p&gt;
&lt;p&gt;2.如果一个行没有CTS，通过行的g_trx_id获取CTS&lt;/p&gt;
&lt;p&gt;2.1 如果事务属于本地节点（ g_trx_id有node id），那么从本地文件系统读到本地TIT&lt;/p&gt;
&lt;p&gt;2.2 如果事务不属于本地节点，那么从远端文件系统读到远端TIT，通过RDMA去访问&lt;/p&gt;
&lt;p&gt;3.1 如果slot.version != g_trx_id.version，那么事务一定提交了，那么该行一定被所有事务可见（准确来说应该是一定被当前及以后的read view可见，但是&lt;em&gt;理论上&lt;/em&gt;TIT slot不会把活动事务访问的row给刷下去，所以是所有事务可见），返回最小CTS表示其对所有事务可见&lt;/p&gt;
&lt;p&gt;3.2 如果slot.version = g_trx_id.version，参考1.1、1.2&lt;/p&gt;
&lt;p&gt;polardb-mp的事务可见性理念跟pg很相似，只是pg用的是txid而不是CTS表示事务新旧，也不需要考虑远程访问。&lt;/p&gt;

&lt;h3 class="relative group"&gt;行更新事务
 &lt;div id="行更新事务" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%a1%8c%e6%9b%b4%e6%96%b0%e4%ba%8b%e5%8a%a1" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;除此之外，行更新也很像：&lt;/p&gt;
&lt;p&gt;polardb-mp更新行的时候，除了更新数据本身，还需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;更新行的全局事务ID（g_trx_id）（如果是行上更新，那么就改造了pg的行头）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;更新行的CTS。（这里没有说是行头还是文件系统，如果类似pg，那么应该是文件系统上的&lt;code&gt;commit_ts&lt;/code&gt;目录上。polar未证实）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;提问事务融合（没看懂的）
 &lt;div id="提问事务融合没看懂的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%90%e9%97%ae%e4%ba%8b%e5%8a%a1%e8%9e%8d%e5%90%88%e6%b2%a1%e7%9c%8b%e6%87%82%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;g_trx_id是行的元数据，写入磁盘的。如果节点减加，需要更新数据行g_trx_id中的node_id吗？如果不需要，下次读取出来应该加载到哪个节点？&lt;/p&gt;
&lt;p&gt;一个新行的CTS存储在本地节点A，如果一个其他节点B又更新了这个行，新的CTS在A还是B节点？&lt;/p&gt;
&lt;p&gt;assigned a read view, which consists of its own g_trx_id and the current CTS。只读事务在构建读视图时，也会分配g_trx_id吗？&lt;/p&gt;
&lt;p&gt;毫无疑问，类似&lt;code&gt;track_commit_timestamp&lt;/code&gt;参数一定是强制打开的&lt;/p&gt;
&lt;p&gt;如果有大量的写在A节点，读在B节点，B节点的读会通过RDMA访问A节点的TIT对应的数据，是不是会产生大量的网络IO？那么是不是需要在考虑读写分离时，或者多节点写入和读取时，应该考虑这个问题？不知道原文能不能回答这个问题&amp;ndash;“多主架构天生就需要在节点间同步大量的数据和消息，以支撑关联多节点的并发访问。随着网络技术的发展（InfiniBand，RDMA）和商业化落地，网络瓶颈变得不那么重要。”&lt;/p&gt;
&lt;p&gt;全局时间戳可能成为分布式系统的瓶颈，PolarDB-SCC是基于共享存储的时间戳，看上去性能不错。时间有限，先按下再说。&lt;/p&gt;

&lt;h2 class="relative group"&gt;内存融合
 &lt;div id="内存融合" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98%e8%9e%8d%e5%90%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;内存融合引述
 &lt;div id="内存融合引述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98%e8%9e%8d%e5%90%88%e5%bc%95%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;polardb-mp的每个节点都可以更新任何数据页，这会导致大量的数据转移。Buffer Fusion’s distributed buffer pool (DBP)就是为了解决这个问题。每个节点都有本地内存池LBP，属于DBP的子集。&lt;/p&gt;

&lt;h3 class="relative group"&gt;内存融合是如何进行的
 &lt;div id="内存融合是如何进行的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%86%85%e5%ad%98%e8%9e%8d%e5%90%88%e6%98%af%e5%a6%82%e4%bd%95%e8%bf%9b%e8%a1%8c%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;LBP有两个新的东西用以存放页的元数据：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;valid：是否被其他节点更新&lt;/li&gt;
&lt;li&gt;r_addr：指针，指向DBP上的page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/652bf5e74943.png" alt="image-20251102105723909" /&gt;&lt;/p&gt;
&lt;p&gt;从LBP访问page时，当前节点需要先检查page是否是有效的，如果无效，需要通过r_addr去访问dbp。当dbp中存放page的新的版本后，内存融合会让所有远端的page失效。在LBP中，脏page会在后台周期性地或释放Plock锁后刷到DBP中。&lt;/p&gt;
&lt;p&gt;page访问的步骤：&lt;/p&gt;
&lt;p&gt;1.1 如果page在LBP且valid，直接访问。&lt;/p&gt;
&lt;p&gt;1.2 如果page在LBP且invalid，经过RDMA访问DBP&lt;/p&gt;
&lt;p&gt;2 如果page既不在LBP也不在DBP，从共享存储读取&lt;/p&gt;
&lt;p&gt;3 page从一个node加载到LBP，并注册到DBP中&lt;/p&gt;
&lt;p&gt;PolarDB内存融合的关键组件是分离式共享内存。看上去是一个/组物理硬件或者其上集成后的完整组件，游离于计算节点之外。这部分跟传统分布式系统的内存有很大的不同。&lt;/p&gt;
&lt;p&gt;跟事务融合也有不同，事务融合需要访问相同架构的远端节点，内存融合不需要访问相同架构的远端节点，而是单独访问分离式共享存储这个组件。&lt;/p&gt;

&lt;h3 class="relative group"&gt;提问内存融合（没看懂的）
 &lt;div id="提问内存融合没看懂的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%90%e9%97%ae%e5%86%85%e5%ad%98%e8%9e%8d%e5%90%88%e6%b2%a1%e7%9c%8b%e6%87%82%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;分离式共享内存像游离于标准主机之外的组件，所以它到底是个什么玩意儿？&lt;/p&gt;

&lt;h2 class="relative group"&gt;锁融合
 &lt;div id="锁融合" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%94%81%e8%9e%8d%e5%90%88" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;锁融合中锁的类型
 &lt;div id="锁融合中锁的类型" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%94%81%e8%9e%8d%e5%90%88%e4%b8%ad%e9%94%81%e7%9a%84%e7%b1%bb%e5%9e%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;内存融合是为了解决节点怎么访问远端数据，锁融合是为了解决并发访问控制。&lt;/p&gt;
&lt;p&gt;内存融合有两种锁：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;page-locking (PLock)：类似latch，控制原子访问和内部结构一致性。单节点page访问没有Plock。&lt;/li&gt;
&lt;li&gt;row-locking (RLock)：负责跨节点的事务控制，遵循两阶段锁协议&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;PLock访问流程
 &lt;div id="plock访问流程" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#plock%e8%ae%bf%e9%97%ae%e6%b5%81%e7%a8%8b" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;（论文没有说锁融合发生在哪，因为Plock是页上的栓锁，页的融合发生在共享内存上，所以我先假设锁融合也发生在共享内存上，因为这样容易理解一点）&lt;/p&gt;
&lt;p&gt;1 在更新/读取page前，通过&lt;em&gt;本地锁管理器&lt;/em&gt;检查本地节点是已持有对应的X/S Plock（或更高级别的锁）&lt;/p&gt;
&lt;p&gt;1.1如果有，原地执行操作&lt;/p&gt;
&lt;p&gt;1.2 如果没有，通过Lock fusion拿到PLock&lt;/p&gt;
&lt;p&gt;2 锁融合在响应前先检查冲突，如果冲突存在则请求等待&lt;/p&gt;
&lt;p&gt;3 当PLock被一个节点释放，会通知锁融合，锁融合更新Plock的状态，并通知其他节点继续执行自己的操作&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/92aa2082d68f.png" alt="image-20251102142359091" /&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;Plock lazy releasing
 &lt;div id="plock-lazy-releasing" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#plock-lazy-releasing" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;根据上面PLock访问流程，一个Plock在本地执行完操作后会被立即释放。这可能不是最优解，根据时间局部性原理——“一个数据或指令在某一时刻被访问，那么在短期内，它很可能会被再次访问”。lazy releasing就是为了最小化Plock锁的RPC访问负载。&lt;/p&gt;
&lt;p&gt;原理很简单，Plock在本地节点使用后不会被立即释放，而是等ref为0时才释放。&lt;/p&gt;
&lt;p&gt;当其他节点需要PLock时，锁融合还会发送谈判信息干预本地节点一直持有锁，本地必须与锁融合通信而不是自主处理PLock。锁融合采用“先进先出”的策略解决跨节点锁归属权问题，同样直到本地节点的ref=0时，其他节点才可以拿到锁。&lt;/p&gt;
&lt;p&gt;lazy releasing是有效的分布式锁解决方案，为了平衡本地锁优化和全局锁分配。&lt;/p&gt;

&lt;h3 class="relative group"&gt;RLock概述
 &lt;div id="rlock概述" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#rlock%e6%a6%82%e8%bf%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;RLock是通过全局事务ID来判断的（跟pg类似）。根据事务融合的内容，全局事务ID包含了节点id、事务id、slot id、version。所以，本地节点读取行时直接就可以拿到行上所需要的锁信息，知道锁在哪（node id），知道锁是否活跃。&lt;/p&gt;
&lt;p&gt;判断事务活跃也有2个好玩的点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从事务融合访问远端的CTS的流程来看，事物的CTS是有效值或事物在TIT中属于同一slot但不是同一version，说明事物肯定提交了，所以不需要再检查是否活跃。源事务不活跃当然就不等待锁，直接运行。&lt;/li&gt;
&lt;li&gt;pg中会有最小活跃事物ID的概念，在polardb-mp中也存在。如果行上的事务ID小于全局的最小活跃事务ID，那么源事务肯定也提交（或回滚）了。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Rlock是如何进行的
 &lt;div id="rlock是如何进行的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#rlock%e6%98%af%e5%a6%82%e4%bd%95%e8%bf%9b%e8%a1%8c%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;本地行本地处理即可，只有冲突的时候会在锁融合中处理，跨节点行锁才需要RLock。”The transaction ID in the row functions as a lock indicator. So this protocol only supports exclusive (X) lock. The shared (S) lock on a row is not supported in PolarDB-MP, but it’s acceptable“ ，真冲突的排他锁才需要RLock，共享锁不需要RLock。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/a84d705b09b8.png" alt="image-20251102155613001" /&gt;&lt;/p&gt;
&lt;p&gt;1 T30从共享存储中读取行，从行的元数据（g_trx_id)就可以知道事物活跃且事务在哪个节点&lt;/p&gt;
&lt;p&gt;2 T30远程调整T10的事物ref&lt;/p&gt;
&lt;p&gt;3 T30发送等待状态给锁融合服务&lt;/p&gt;
&lt;p&gt;4 锁融合添加等待信息到wait info table中&lt;/p&gt;
&lt;p&gt;5 T10执行结束，通知Lock Fusion&lt;/p&gt;
&lt;p&gt;6 Lock Fusion检查wait info table，然后通知T30可以继续执行了&lt;/p&gt;

&lt;h3 class="relative group"&gt;提问锁融合（没看懂的）
 &lt;div id="提问锁融合没看懂的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%90%e9%97%ae%e9%94%81%e8%9e%8d%e5%90%88%e6%b2%a1%e7%9c%8b%e6%87%82%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;“when attempting to update a row, it must already hold an X PLock lock on the page containing the row”&lt;/p&gt;
&lt;p&gt;update还要持有page的PLock排他锁，也就是说同一page上的update是相互阻塞的，这会影响并发吧？本地应该不会有这种行为，pg是没有update场景的page排他的。&lt;/p&gt;
&lt;p&gt;在Logs ordering and recovery章节有这么两句话：“Thanks to the PLock design, only one transaction can update a page at a time&amp;quot;，“When a page is updated across two nodes, one node pushes its updated page to the DBP before releasing the PLock,allowing the next node to retrieve it from the DBP.”&lt;/p&gt;
&lt;p&gt;是的，在&lt;strong&gt;跨节点&lt;/strong&gt;数据更新时，有页级排他锁。&lt;/p&gt;

&lt;h2 class="relative group"&gt;PMFS小结（锐评）
 &lt;div id="pmfs小结锐评" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#pmfs%e5%b0%8f%e7%bb%93%e9%94%90%e8%af%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;PMFS（Polar Multi-Primary Fusion Server）是PolarDB-MP多主分布式系统实现的核心组件。其中，&lt;strong&gt;全局事务ID&lt;/strong&gt;设计巧妙，它转化了pg的事务ID为包含节点信息、事务id和事务融合中的slot和version信息并放在行头。这样做有几个好处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接访问行就知道行的版本新旧情况&lt;/li&gt;
&lt;li&gt;直接访问行就知道行是哪个节点更新的&lt;/li&gt;
&lt;li&gt;直接访问行就知道是否可能存在跨节点锁&lt;/li&gt;
&lt;li&gt;利用最小活动事务以减少冲突判断&lt;/li&gt;
&lt;li&gt;利用全局事务ID信息，实现分布式获取事务提交时间CTS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PMFS中的内存融合和锁融合看上去高度依赖共享内存组件&lt;/li&gt;
&lt;li&gt;RDMA的应用时刻存在&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;日志的顺序
 &lt;div id="日志的顺序" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%97%a5%e5%bf%97%e7%9a%84%e9%a1%ba%e5%ba%8f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;partial order
 &lt;div id="partial-order" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#partial-order" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;首先，wal在每个节点上都生成，且不需要任何并发控制机制，各自往共享存储中写。每个节点的LSN对于各自的节点而言是顺序的，但是多节点就不能体现wal记录在全局的顺序性。&lt;/p&gt;
&lt;p&gt;但是，需要在写入时体现wal记录的全局顺序吗？&lt;/p&gt;
&lt;p&gt;从论文来看，大部分情况是不需要的。&lt;/p&gt;
&lt;p&gt;只有1种情况需要保证写入时的全局顺序性，那就是跨节点更新同一个page时。&lt;/p&gt;
&lt;p&gt;但是，根据PMFS锁融合机制，跨节点更新同一page是排他的。锁融合就可以保证跨节点page更新的顺序了。&lt;/p&gt;

&lt;h3 class="relative group"&gt;恢复的顺序
 &lt;div id="恢复的顺序" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%81%a2%e5%a4%8d%e7%9a%84%e9%a1%ba%e5%ba%8f" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;由于跨节点写入的LLSN来自多个节点很可能不是顺序的，恢复时就需要按顺序进行恢复。全量读取wal记录再按LLSN排序是一个简单的方案，但是大量的排序非常消耗资源。&lt;/p&gt;
&lt;p&gt;polardb-mp提出了分段排序LLSN，每段称为chunk，chunk的边界称为LLSN bound。polardb-mp可保证LLSN bound一定小于下一个bound，然后在chunk内排序LLSN即可。&lt;/p&gt;

&lt;h3 class="relative group"&gt;提问日志的顺序（没看懂的）
 &lt;div id="提问日志的顺序没看懂的" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8f%90%e9%97%ae%e6%97%a5%e5%bf%97%e7%9a%84%e9%a1%ba%e5%ba%8f%e6%b2%a1%e7%9c%8b%e6%87%82%e7%9a%84" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;”utilizing redo (write-ahead) logs for data recovery and undo logs for rolling back uncommitted changes“&lt;/p&gt;
&lt;p&gt;polardb-mp有undo日志文件？这个undo是干嘛的？&lt;/p&gt;
&lt;p&gt;LLSN没有看出来有什么特别的，论文也没有详细说明它的结构，LSN看上去都够了，maybe全局事务id那有些区别。&lt;/p&gt;

&lt;h2 class="relative group"&gt;评估
 &lt;div id="评估" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%af%84%e4%bc%b0" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;只读都是本地的，所以加节点吞吐提升是线性的。如果读写/只写的数据都分区得好，不跨节点，也几乎是线性的。&lt;/p&gt;
&lt;p&gt;问题就在于读写/只写节点间共享数据的情况，非常考验分布式数据库的性能。&lt;/p&gt;
&lt;p&gt;论文直接拿华为的taurus-mm来对比。结论就是：polardb跨多节点写数据性能确实要好不少。&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/eec82fe8cb39.png" alt="image-20251109212445723" /&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;吹毛索疵
 &lt;div id="吹毛索疵" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%90%b9%e6%af%9b%e7%b4%a2%e7%96%b5" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;文章有2个地方提到Taurus-MM在8节点共享数据下的性能提升，但是数据有歧义：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The eight-node cluster only improves
the throughput by 1.8× compared to the single-node version in the
read-write workload with 50% shared data.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;the throughput of Taurus-MM ’s eight-node cluster is approximately 1.8× that
of a single node under the SysBench write-only workload with 30%
shared data, illustrating the trade-offs and challenges in optimizing
multi-primary cloud databases&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;一会30% shared data，一会50% shared data，不是很严谨。原文&lt;a href="https://www.vldb.org/pvldb/vol16/p3488-depoutovitch.pdf" target="_blank" rel="noreferrer"&gt;Taurus MM&lt;/a&gt;是50%：&lt;/p&gt;
&lt;p&gt;


&lt;img src="https://lastdba.com/img/csdn/34c0ec5e940b.png" alt="image-20251025162117902" /&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;总结
 &lt;div id="总结" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%bb%e7%bb%93" aria-label="锚点"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;好像没什么好总结的，看章节&lt;em&gt;前言和摘要&lt;/em&gt;和&lt;em&gt;PMFS小结&lt;/em&gt; 就行。&lt;/p&gt;</content:encoded></item></channel></rss>