mcpField
D
Dataparity

Dataparity

本地服务
github.com数据库02 周前更新

关于 Dataparity

Dataparity 提供 CLI、MCP 服务和库,可比较同一数据库或不同数据库中的表。它为 Agent 返回变更详情、归因和风险判断;跨库比较时,行数据留在各自数据库内。

主要功能

  1. 01跨数据库表比较
  2. 02可移植的规范行哈希
  3. 03列级变更详情
  4. 04变更归因与风险判断
  5. 05只读 MCP 工具

适用场景

  1. 01检查生产与暂存表的差异
  2. 02将数据库表与 Parquet 或 CSV 数据比较
  3. 03在 CI 中执行数据差异检查

MCP 相关

它提供四种只读工具,用于列出数据源、查看表信息和比较表内容。工具使用数据源名称而非连接字符串,且不会写入数据库。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"arif-js-dataparity": {
"command": "npx",
"args": [
"-y",
"dataparity"
]
}
}
}
启动命令npx -y dataparity

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmdataparity0.1.0

工具

4

收录的工具列表 · 更新于 2 周前

此工具无需参数。

详细介绍

Dataparity 徽标

Dataparity

为 AI Agent 提供跨数据库数据差异比较与协调功能,并支持可移植的行哈希。

比较两个表格——无论它们位于同一个数据库还是两个不同的数据库——并获取变更内容、发生变更的列,以及变更集中在哪部分数据中。 可作为命令行工具、MCP 服务和库运行。采用 MIT 许可证。

npm CI License: MIT MCP Glama Node

功能 · 哈希为何可移植 · 安装 · 命令行工具 · MCP · 库 · 工作原理 · 状态


功能

提供两个表格和一个键,即可了解变更内容:

HIGH  3 difference(s) found across 5 row(s) (60.00% of the left side).

left   pg :: public.orders_prod  (5 rows)
right  mysql :: analytics.orders_staging  (5 rows)
strategy  checksum   keys  id

added 1   removed 1   modified 1   unchanged 3

where the changes are concentrated:
  country = DE  4 change(s)  80.0% of changes  6.7x over-represented

sample changes:
  removed  key=2
  modified key=3  amount
  added    key=6

signals:
  - 1 row(s) exist only on the left
  - 1 row(s) exist only on the right
  - 1 row(s) differ in at least one column

与自己编写的 SELECT EXCEPT 相比,它有三个不同之处:

  1. 可跨两个不同的数据库使用。 Postgres ↔ MySQL、Postgres ↔ DuckDB、 Parquet ↔ Postgres。两侧都在各自的引擎中计算相同的规范行哈希,因此只有哈希会通过网络传输——绝不传输行数据。

  2. 它会指出变更发生在哪里,而不只是告知存在变更。 如果差异比较只报告 “432 行不同”,几乎毫无用处。而如果报告“98.6% 的已修改行都是德国订单”,就能告诉你增值税规则已生效,其他内容则未受影响。

  3. 专为 Agent 构建。 MCP 服务提供四个只读工具、稳定的 JSON 结果契约,以及可供编码 Agent 执行操作的风险判定(none / low / medium / high / critical)。

哈希为何可移植

要跨引擎比较行,就必须对值的含义达成一致。Postgres 和 MySQL 中的 0.1 都是最接近十分之一的双精度浮点数,而 0.1 + 0.2 并不等于 0.3。 在 Postgres 中,布尔值是 true,在 MySQL 中则是 1。一个引擎中的时间戳精度为微秒,另一个引擎中的则为秒。NULL 不等于空字符串。

Dataparity 通过两条规则解决这个问题,并在每个引擎中以相同方式应用:

  • 为每个值添加类型标记。 NULL 表示为 N;其他每个值都表示为 V,后接其规范化文本。NULL 和 '' 永远不会混淆,真实值也永远不会被误认为 NULL。
  • 将每个值按长度前缀编码后再拼接成行哈希。包含字段分隔符的文本值无法移动列边界并伪造匹配结果。

浮点数会先在精确十进制算术中缩放到固定小数位数,再进行表示,因此 0.1 + 0.2 和 0.3 会得到一致结果。时间戳会规范化为 UTC 并截断到秒。布尔值在所有地方都表示为 true / false。

最终得到的 MD5 行哈希在不同引擎之间逐字节一致。这并非 README 中的一纸声明,而是由 test/integration/canonical.test.ts 断言:该测试会将相同的特殊值写入 Postgres、MySQL 和 DuckDB,并要求哈希匹配:

docker run -d --name pgdiff -e POSTGRES_PASSWORD=test -e POSTGRES_DB=difftest -p 55432:5432 postgres:16-alpine
docker run -d --name mydiff -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=difftest -p 53306:3306 mysql:8
npm run test:integration

这些测试需要数据库。如果某个数据库无法访问,测试会报告为已跳过,而不是通过,因此绿色运行绝不意味着“什么都没测”——如果有任何测试被跳过,CI 就会使任务失败。

安装

npm install -g dataparity

也可以不安装,直接运行:

npx dataparity --help

需要 Node.js 22.16 或更高版本。

CLI

在 ~/.dataparity/config.json 中配置一次数据源(或将 DATAPARITY_CONFIG 指向其他路径):

{
  "sources": [
    { "name": "prod",    "type": "postgres", "connectionString": "postgres://..." },
    { "name": "staging", "type": "postgres", "connectionString": "postgres://..." },
    { "name": "mysql",   "type": "mysql", "host": "127.0.0.1", "port": 3306,
                         "user": "readonly", "password": "...", "database": "analytics" },
    { "name": "local",   "type": "sqlite", "path": "data/app.db" },
    { "name": "files",   "type": "duckdb", "files": ["data/orders.parquet"] }
  ]
}

然后进行差异比较:

# Two tables in the same database
dataparity diff \
  --left prod --right staging \
  --left-table public.orders_prod --right-table public.orders_staging \
  --key id

# Two tables in two different databases
dataparity diff \
  --left prod --right mysql \
  --left-table public.orders_prod --right-table orders_staging \
  --key id --json

# Explore first
dataparity tables --source prod
dataparity describe --source prod --table public.orders_prod

退出码遵循 GNU diff 约定:0 表示相同,1 表示发现差异,2 表示错误。 因此可以直接用于 CI 检查。

选项含义
--left、--right配置文件中的数据源名称
--left-table、--right-table要比较的表
--key用于匹配行的逗号分隔键列
--columns要比较的列(默认为所有共有列)
--where应用于两侧的 WHERE 表达式
--max-changes要报告的最大行变更数(默认为 100)
--max-attributions要报告的最大归因片段数(默认为 5)
--sample仅比较样本;结果会标记为抽样结果
--sample-limit每侧的最大抽样行数(默认为 100000)
--bucket-count跨数据库差异比较的显式分桶数
--json机器可读输出

凭据可以通过环境变量提供,而不必写入磁盘:

export DATAPARITY_PROD_CONNECTION_STRING='postgres://...'
export DATAPARITY_MYSQL_PASSWORD='...'

MCP

claude mcp add --scope user dataparity -- npx -y dataparity mcp

或在 .cursor/mcp.json 中配置:

{
  "mcpServers": {
    "dataparity": { "command": "npx", "args": ["-y", "dataparity", "mcp"] }
  }
}

四个只读工具:

工具功能
dataparity_list_sources已配置的数据源及其引擎类型
dataparity_list_tables数据源中的表及其列
dataparity_describe_table单个表的列、类型和可空性
dataparity_diff比较两张表并报告变更

工具接收数据源 名称,而非连接字符串——凭据不会经过模型。所有工具均为只读;dataparity 不会向数据库写入任何内容。

库

import { diffTables, PostgresSource, MysqlSource } from 'dataparity';

const prod = await PostgresSource.connect({ connectionString: process.env.PROD_URL! });
const staging = await MysqlSource.connect({
  host: '127.0.0.1', port: 3306, user: 'ro', password: '...', database: 'analytics',
});

const report = await diffTables(prod, 'public.orders', staging, 'orders_staging', {
  keyColumns: ['id'],
});

if (report.risk.level === 'critical') {
  console.error(report.risk.signals.join('\n'));
  process.exit(1);
}

工作原理

同一数据库 → 单次数据库内联接。 三路分类(新增、移除、修改)通过一个反联接和一个外联接完成,完全在数据库内部执行。行数据不会离开数据库,结果准确无误。

不同数据库 → 规范化哈希,按分桶比较。 两侧分别在各自的引擎中计算每个桶的计数和两个独立校验和。只有聚合结果不一致的桶才会展开到行级别,因此,即使十亿行的表只有少数行存在差异,也只会传输少量哈希,而不是十亿行数据。

归因。 对于每个候选列,会将该列在变更行中的分布与其在整个表中的分布进行比较。如果某个值在变更行中的出现频率远高于预期,就表明受影响的数据切片可能与该值有关。评分仅作描述(“占比过高”),并不表示因果关系。

风险。 判定会综合考虑变更规模与架构差异。如果新增或移除行的同时还移除了列或更改了列类型,则风险为 critical;如果变更行占比很小且架构没有变化,则风险为 low。

支持的引擎
引擎同库跨库备注
PostgreSQL是是
MySQL是是
SQLite是是通过 node:sqlite,默认只读
DuckDB是是可直接读取 Parquet、CSV 和 JSON
Parquet / CSV / JSON—是通过 DuckDB

布尔值和 0/1 整数会被视为相同的逻辑类型,因此,Postgres 中的布尔列可以正确地与 SQLite 不得不使用的整数列进行比较。

状态

早期阶段。核心功能稳固,并已针对实时 Postgres、MySQL 和 DuckDB 完成测试,但功能范围较小,边界条件也较为严格。

目前可用的功能

  • 同一数据库之间的差异比较,提供精确到列级别的详情
  • Postgres、MySQL、SQLite 和 DuckDB 之间的跨数据库差异比较
  • 架构比较、变更归因、风险评估
  • CLI、MCP 服务和类型化库 API
  • 设计上只读;凭据不会传给模型
  • 跨数据库差异比较可定位哪些列发生了变化:通过在每个引擎内部计算逐列哈希进行比较,因此即使经过哈希比较,列级详情也能保留下来,且不会有任何值通过网络传输

已知限制

  • 跨数据库差异比较会报告哪些列发生了变化,但不会报告变更前后的值:只有哈希会通过网络传输,因此值本身不会离开任一引擎。同一数据库内的差异比较也会包含值。
  • JSON 列会按文本进行比较,因此键顺序不同也会被判定为变更。请改为进行结构化比较。
  • 浮点数和十进制数会比较到小数点后六位。超过此精度时,两个引擎对末尾位的结果可能不一致。
  • where 子句是原始 SQL 片段。它会传给你的引擎,而不是模型,但请将其视为可信输入。
  • 没有监控、没有血缘图、没有 dbt 集成,也没有 UI。

贡献

docs/design.md 是功能范围及其关键决策的权威依据。更改行为前请先阅读——其中记录的是决策理由,而不只是结果。

工作流程如下:

npm ci
npm test                   # unit tests
npm run test:integration   # needs live Postgres + MySQL; skips if absent
npm run test:audit         # every engine x every option x every error path
npm run lint
npm run typecheck
npm run build

集成测试套件需要 Postgres 16 在 :55432 上运行,MySQL 8 在 :53306 上运行:

docker run -d --name pgdiff -e POSTGRES_PASSWORD=test -e POSTGRES_DB=difftest -p 55432:5432 postgres:16-alpine
docker run -d --name mydiff -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=difftest -p 53306:3306 mysql:8

许可证

MIT。请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。