PlanetScale 数据库连接 #

本章将介绍如何从各种编程语言和框架连接 PlanetScale 数据库,包括连接字符串配置、连接池管理、安全最佳实践等。

连接方式概览 #

三种连接方式 #

text
┌─────────────────────────────────────────────────────────────┐
│                    连接方式对比                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   1. 连接字符串(推荐生产使用)                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  mysql://user:pass@host/db?sslaccept=strict         │  │
│   │                                                      │  │
│   │  特点:                                              │  │
│   │  ✅ 适合应用部署                                     │  │
│   │  ✅ 需要创建密码                                     │  │
│   │  ✅ 支持 SSL 加密                                    │  │
│   │  ✅ 可配置连接池                                     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   2. CLI Shell                                              │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  pscale shell my-database main                       │  │
│   │                                                      │  │
│   │  特点:                                              │  │
│   │  ✅ 适合开发调试                                     │  │
│   │  ✅ 无需创建密码                                     │  │
│   │  ✅ 需要登录认证                                     │  │
│   │  ❌ 不适合生产使用                                   │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   3. CLI 代理                                               │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  pscale connect my-database main                     │  │
│   │                                                      │  │
│   │  特点:                                              │  │
│   │  ✅ 适合本地开发                                     │  │
│   │  ✅ 创建本地代理                                     │  │
│   │  ✅ 兼容现有工具                                     │  │
│   │  ❌ 不适合生产使用                                   │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

连接字符串 #

获取连接字符串 #

bash
# 创建密码
pscale password create my-database main production-app

# 输出示例
# Password created successfully!
# 
# Connection string:
# mysql://abc123:pscale_pw_xxxxxxxxxxxx@aws.connect.psdb.cloud/my-database?sslaccept=strict

连接字符串格式 #

text
┌─────────────────────────────────────────────────────────────┐
│                    连接字符串结构                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   mysql://username:password@host/database?options          │
│                                                             │
│   组成部分:                                                │
│   ├── mysql://     - 协议                                  │
│   ├── username     - 用户名(从密码创建时获得)            │
│   ├── password     - 密码(从密码创建时获得)              │
│   ├── host         - 主机地址(aws.connect.psdb.cloud)   │
│   ├── database     - 数据库名                              │
│   └── options      - 连接选项                              │
│                                                             │
│   示例:                                                    │
│   mysql://abc123:pscale_pw_xxx@aws.connect.psdb.cloud/     │
│   my-database?sslaccept=strict                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

连接选项 #

text
┌─────────────────────────────────────────────────────────────┐
│                    常用连接选项                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   SSL 配置:                                                │
│   ├── sslaccept=strict      - 强制 SSL(推荐)             │
│   └── sslaccept=disabled    - 禁用 SSL(不推荐)           │
│                                                             │
│   字符集:                                                  │
│   └── charset=utf8mb4       - 使用 UTF-8 字符集            │
│                                                             │
│   时区:                                                    │
│   └── timezone=UTC          - 设置时区                     │
│                                                             │
│   完整示例:                                                │
│   mysql://user:pass@host/db?                               │
│     sslaccept=strict&                                      │
│     charset=utf8mb4&                                       │
│     timezone=UTC                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

密码管理 #

创建密码 #

bash
# 基本创建
pscale password create my-database main my-app

# 指定角色
pscale password create my-database main my-app --role writer

# 设置过期时间
pscale password create my-database main temp-password --ttl 24h

密码角色 #

text
┌─────────────────────────────────────────────────────────────┐
│                    角色权限                                   │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   reader(只读)                                            │
│   ├── SELECT                                               │
│   └── 适合报表、分析服务                                   │
│                                                             │
│   writer(读写)                                            │
│   ├── SELECT                                               │
│   ├── INSERT                                               │
│   ├── UPDATE                                               │
│   ├── DELETE                                               │
│   └── 适合大多数应用                                       │
│                                                             │
│   admin(管理员)                                           │
│   ├── ALL PRIVILEGES                                       │
│   └── 适合管理工具                                         │
│                                                             │
│   建议原则:                                                │
│   - 遵循最小权限原则                                       │
│   - 不同服务使用不同密码                                   │
│   - 定期轮换密码                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

管理密码 #

bash
# 列出所有密码
pscale password list my-database main

# 删除密码
pscale password delete my-database main my-app

# 更新密码(删除旧密码,创建新密码)
pscale password delete my-database main my-app
pscale password create my-database main my-app

Node.js 连接 #

使用 mysql2 #

javascript
import mysql from 'mysql2/promise';

const connection = await mysql.createConnection({
  host: 'aws.connect.psdb.cloud',
  user: 'abc123',
  password: 'pscale_pw_xxx',
  database: 'my-database',
  ssl: {
    rejectUnauthorized: true
  }
});

const [rows] = await connection.execute('SELECT * FROM users');
console.log(rows);

await connection.end();

使用连接池 #

javascript
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: 'aws.connect.psdb.cloud',
  user: 'abc123',
  password: 'pscale_pw_xxx',
  database: 'my-database',
  ssl: {
    rejectUnauthorized: true
  },
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

async function getUsers() {
  const [rows] = await pool.execute('SELECT * FROM users LIMIT 10');
  return rows;
}

async function createUser(name, email) {
  const [result] = await pool.execute(
    'INSERT INTO users (name, email) VALUES (?, ?)',
    [name, email]
  );
  return result.insertId;
}

process.on('SIGINT', async () => {
  await pool.end();
  process.exit();
});

使用环境变量 #

javascript
import mysql from 'mysql2/promise';
import 'dotenv/config';

const pool = mysql.createPool(process.env.DATABASE_URL);

export { pool };
env
DATABASE_URL=mysql://abc123:pscale_pw_xxx@aws.connect.psdb.cloud/my-database?sslaccept=strict

Python 连接 #

使用 mysql-connector-python #

python
import mysql.connector
import os

connection = mysql.connector.connect(
    host='aws.connect.psdb.cloud',
    user='abc123',
    password='pscale_pw_xxx',
    database='my-database',
    ssl_ca='/path/to/ca.pem',
    ssl_verify_cert=True
)

cursor = connection.cursor(dictionary=True)

cursor.execute('SELECT * FROM users')
users = cursor.fetchall()

for user in users:
    print(user)

cursor.close()
connection.close()

使用 PyMySQL #

python
import pymysql
import ssl

connection = pymysql.connect(
    host='aws.connect.psdb.cloud',
    user='abc123',
    password='pscale_pw_xxx',
    database='my-database',
    ssl={
        'ssl': True
    }
)

try:
    with connection.cursor() as cursor:
        cursor.execute('SELECT * FROM users')
        users = cursor.fetchall()
        print(users)
finally:
    connection.close()

使用 SQLAlchemy #

python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import os

DATABASE_URL = os.environ.get('DATABASE_URL')

engine = create_engine(
    DATABASE_URL,
    pool_size=10,
    max_overflow=20,
    pool_pre_ping=True
)

SessionLocal = sessionmaker(bind=engine)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

Go 连接 #

使用 go-sql-driver #

go
package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    dsn := "abc123:pscale_pw_xxx@tcp(aws.connect.psdb.cloud:3306)/my-database?tls=true"
    
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    }

    rows, err := db.Query("SELECT id, name, email FROM users")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    for rows.Next() {
        var id int
        var name, email string
        err = rows.Scan(&id, &name, &email)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%d: %s (%s)\n", id, name, email)
    }
}

使用 GORM #

go
package main

import (
    "fmt"
    "log"

    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type User struct {
    ID        uint   `gorm:"primaryKey"`
    Name      string
    Email     string
    CreatedAt time.Time
}

func main() {
    dsn := "abc123:pscale_pw_xxx@tcp(aws.connect.psdb.cloud:3306)/my-database?tls=true"
    
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        log.Fatal(err)
    }

    var users []User
    db.Find(&users)

    for _, user := range users {
        fmt.Printf("%d: %s\n", user.ID, user.Name)
    }
}

Java 连接 #

使用 JDBC #

java
import java.sql.*;

public class PlanetScaleExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://aws.connect.psdb.cloud:3306/my-database?sslMode=REQUIRED";
        String user = "abc123";
        String password = "pscale_pw_xxx";

        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            String sql = "SELECT id, name, email FROM users";
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                System.out.printf("%d: %s (%s)%n", id, name, email);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

使用 Spring Boot #

yaml
spring:
  datasource:
    url: jdbc:mysql://aws.connect.psdb.cloud:3306/my-database?sslMode=REQUIRED
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: none
    show-sql: true

PHP 连接 #

使用 PDO #

php
<?php

$host = 'aws.connect.psdb.cloud';
$dbname = 'my-database';
$user = 'abc123';
$pass = 'pscale_pw_xxx';

try {
    $pdo = new PDO(
        "mysql:host=$host;dbname=$dbname;charset=utf8mb4",
        $user,
        $pass,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::MYSQL_ATTR_SSL_CA => '/path/to/ca.pem',
        ]
    );

    $stmt = $pdo->query('SELECT * FROM users');
    $users = $stmt->fetchAll();

    foreach ($users as $user) {
        echo $user['name'] . "\n";
    }
} catch (PDOException $e) {
    echo "Connection failed: " . $e->getMessage();
}

使用 Laravel #

env
DB_CONNECTION=mysql
DB_HOST=aws.connect.psdb.cloud
DB_PORT=3306
DB_DATABASE=my-database
DB_USERNAME=abc123
DB_PASSWORD=pscale_pw_xxx
php
// config/database.php
'mysql' => [
    'driver' => 'mysql',
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
    'options' => [
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    ],
],

连接池最佳实践 #

连接池配置 #

text
┌─────────────────────────────────────────────────────────────┐
│                    连接池配置建议                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   基本参数:                                                │
│   ├── pool_size: 10-20          - 连接池大小               │
│   ├── max_overflow: 10-20       - 最大溢出连接             │
│   ├── pool_timeout: 30          - 获取连接超时(秒)       │
│   └── idle_timeout: 600         - 空闲连接超时(秒)       │
│                                                             │
│   PlanetScale 限制:                                        │
│   ├── Hobby: 100 并发连接                                  │
│   ├── Scaler: 1000 并发连接                                │
│   └── Scaler Pro: 自定义                                   │
│                                                             │
│   建议:                                                    │
│   - pool_size 不要超过限制                                 │
│   - 留出连接给其他应用                                     │
│   - 使用 pool_pre_ping 检测断开连接                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

连接池监控 #

javascript
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: 'aws.connect.psdb.cloud',
  user: 'abc123',
  password: 'pscale_pw_xxx',
  database: 'my-database',
  ssl: { rejectUnauthorized: true },
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

setInterval(() => {
  console.log('Pool status:', {
    totalConnections: pool.pool._allConnections.length,
    freeConnections: pool.pool._freeConnections.length,
    waitingRequests: pool.pool._connectionQueue.length
  });
}, 60000);

CLI 代理连接 #

启动代理 #

bash
# 基本代理
pscale connect my-database main

# 指定端口
pscale connect my-database main --port 3307

# 指定地址
pscale connect my-database main --host 127.0.0.1 --port 3306

# 后台运行
pscale connect my-database main &

使用代理连接 #

bash
# 启动代理
pscale connect my-database main
# Ready! Connect to my-database at 127.0.0.1:3306

# 另一个终端连接
mysql -h 127.0.0.1 -P 3306 -u root my-database
javascript
// 使用本地代理连接
const connection = await mysql.createConnection({
  host: '127.0.0.1',
  port: 3306,
  user: 'root',
  database: 'my-database'
});

安全最佳实践 #

密码安全 #

text
┌─────────────────────────────────────────────────────────────┐
│                    密码安全建议                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ✅ 使用环境变量存储密码                                   │
│   ✅ 不同环境使用不同密码                                   │
│   ✅ 定期轮换密码                                           │
│   ✅ 使用最小权限原则                                       │
│   ✅ 监控密码使用情况                                       │
│                                                             │
│   ❌ 不要将密码提交到代码仓库                               │
│   ❌ 不要在日志中记录密码                                   │
│   ❌ 不要共享密码                                           │
│   ❌ 不要使用过期密码                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

SSL 配置 #

javascript
// 强制 SSL
const connection = await mysql.createConnection({
  host: 'aws.connect.psdb.cloud',
  user: 'abc123',
  password: 'pscale_pw_xxx',
  database: 'my-database',
  ssl: {
    rejectUnauthorized: true
  }
});

故障排查 #

连接超时 #

text
问题:连接超时
原因:
  - 区域选择不当
  - 网络问题
  - 防火墙限制

解决:
  1. 检查区域是否正确
  2. 测试网络连通性
  3. 检查防火墙规则
  4. 使用 CLI 代理

SSL 错误 #

text
问题:SSL 验证失败
原因:
  - SSL 配置不正确
  - 证书问题

解决:
  1. 确保使用 sslaccept=strict
  2. 检查 SSL 配置
  3. 更新客户端库

连接数超限 #

text
问题:连接被拒绝
原因:
  - 达到连接数限制
  - 连接池配置过大

解决:
  1. 减小连接池大小
  2. 检查连接泄漏
  3. 升级计划

下一步 #

现在你已经掌握了数据库连接,接下来学习 数据迁移,了解如何导入导出数据!

最后更新:2026-03-29