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