正在加载,请稍候…

PlanetScale 与 Vitess:基于数据库分支的 MySQL 扩展方案

了解 PlanetScale 如何基于 Vitess 实现水平可扩展的 MySQL,包括数据库分支工作流、无阻塞 schema 变更、部署请求等核心功能。

PlanetScale 与 Vitess:基于数据库分支的 MySQL 扩展方案

PlanetScale 架构

PlanetScale 是基于 Vitess(被 YouTube、Slack、GitHub 使用)构建的 MySQL 兼容数据库。它增加了:

  • 数据库分支:类似 git,但用于 schema
  • 无阻塞 schema 变更:ALTER TABLE 无需锁表
  • 水平分片:自动扩展至每秒数百万查询

PlanetScale 与 Vitess:基于数据库分支的 MySQL 扩展方案示意图

分支工作流

# 安装 PlanetScale CLI
brew install planetscale/tap/pscale

# 连接到主分支
pscale shell myapp main

# 创建开发分支
pscale branch create myapp add-user-avatar

# 连接到分支
pscale connect myapp add-user-avatar --port 3309

# 在分支上执行 schema 变更
mysql -h 127.0.0.1 -P 3309 -u root myapp
ALTER TABLE users ADD COLUMN avatar_url VARCHAR(500);
CREATE INDEX idx_users_email ON users (email);

# 创建部署请求(类似 pull request)
pscale deploy-request create myapp add-user-avatar

# 审核后部署到主分支(无阻塞!)
pscale deploy-request deploy myapp 1

在 Node.js 中连接

import mysql2 from 'mysql2/promise'

const pool = mysql2.createPool({
  host: process.env.DATABASE_HOST,
  database: process.env.DATABASE_NAME,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
  ssl: { rejectUnauthorized: true },
  pool: {
    min: 2,
    max: 10,
    acquireTimeout: 30000,
  },
})

// 或者使用 PlanetScale serverless 驱动(边缘兼容)
import { connect } from '@planetscale/database'

const conn = connect({
  host: process.env.DATABASE_HOST,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
})

const results = await conn.execute('SELECT * FROM users WHERE id = ?', [userId])

PlanetScale 与 Vitess:基于数据库分支的 MySQL 扩展方案示意图

Vitess 限制

Vitess 中禁用了外键(请使用应用层完整性检查):

// 替代外键约束,在应用中验证
async function createPost(userId: string, title: string) {
  // 检查用户是否存在
  const user = await db.query('SELECT id FROM users WHERE id = ?', [userId])
  if (!user.rows.length) throw new Error('User not found')
  
  return db.query('INSERT INTO posts (user_id, title) VALUES (?, ?)', [userId, title])
}

生产环境中的 Schema 变更

PlanetScale 使用 Vitess 的 Online DDL:

-- 这些操作在线执行,不会阻塞
ALTER TABLE orders ADD COLUMN tracking_number VARCHAR(100);
ALTER TABLE products MODIFY COLUMN description TEXT;
CREATE INDEX idx_orders_date ON orders (created_at);
DROP INDEX idx_old_unused ON products;

PlanetScale 与 Vitess:基于数据库分支的 MySQL 扩展方案示意图

水平分片

-- 在 schema 中定义分片键
CREATE TABLE orders (
  id BIGINT NOT NULL,
  customer_id BIGINT NOT NULL,  -- 此字段成为分片键
  amount DECIMAL(10,2),
  PRIMARY KEY (customer_id, id)  -- 主键中包含 customer_id 以实现数据共置
) ENGINE=InnoDB;

性能数据

PlanetScale/Vitess 可处理:

  • 150 万 QPS(YouTube 2019 年数据)
  • 无限水平扩展
  • 对数十亿行表进行零停机 schema 变更