显示标签为“MySQL”的博文。显示所有博文
显示标签为“MySQL”的博文。显示所有博文

2026年3月2日星期一

每个 PXC 节点都需要安装 XtraBackup 吗?

Percona 论坛中经常出现的一个问题:Percona XtraDB Cluster (PXC) 中的每个节点都需要安装 XtraBackup 吗? 这是一个合理的问题,尤其是在管理混合环境或试图最小化某些节点上的软件占用时。以下是实际机制和测试所确认的内容。

简短答案(但请继续阅读)

这取决于你希望该节点做什么。 这里的细微差别非常重要,因此值得详细说明 PXC 中 State Snapshot Transfer (SST) 的工作原理,以及 XtraBackup 在给定节点上的存在——或缺失——为什么重要。

PXC 中 SST 的快速复习

当一个新节点加入 Percona XtraDB Cluster,或者一个现有节点宕机时间过长以至于 Incremental State Transfer (IST) 不再可能时,集群会执行 State Snapshot Transfer (SST)。这本质上是捐献节点向加入节点的全量数据复制。

PXC 支持多种 SST 方法,在 my.cnf 中配置:

[mysqld]
wsrep_sst_method = xtrabackup-v2

可用的 SST 方法包括:

  • xtrabackup-v2 — PXC 的推荐方法,使用 Percona XtraBackup;执行 SST 时不会长时间锁定捐献节点
  • clone — PXC 8.0.22+ 中可用,使用 MySQL 内置的 Clone Plugin;消除了 SST 对 XtraBackup 的依赖
  • mysqldump — 较慢且在传输期间锁定捐献节点;不推荐用于生产环境
  • rsync — 要求捐献节点在传输期间为只读,阻塞写入;也不推荐用于活跃集群

xtrabackup-v2 方法历来是默认方法,并在现有部署中广泛使用,正是因为它在传输期间保持捐献节点可用于写入。其他旧方法可能会阻塞捐献节点的写入,这在生产集群中通常是不可接受的。请注意,Percona 越来越推荐在 PXC 8.0.22 及更高版本的新安装中使用 clone 方法,因为它消除了 SST 层对外部工具的依赖。

XtraBackup 需要安装在哪里?

当触发使用 xtrabackup-v2 的 SST 时,捐献节点和加入节点都需要安装 XtraBackup 并可访问。以下是为什么两侧都需要的原因:

``````html
  • 捐赠者 运行 XtraBackup 来流式传输快照数据到外部
  • 加入者 运行 XtraBackup — 具体来说是 xbstream 和 xbcrypt 工具 — 来接收并应用这些流式传输的数据

如果加入者节点没有安装 XtraBackup,并且您尝试使用 xtrabackup-v2 将其加入集群,SST 将失败。加入者上的错误日志通常会显示类似以下内容:

[ERROR] WSREP: Failed to read 'ready <addr>' from: wsrep_sst_xtrabackup-v2
...
wsrep_sst_xtrabackup-v2: line 522: xbstream: command not found
[ERROR] WSREP: SST failed: 2 (No such file or directory)

这是一个明确且无歧义的失败模式。如果 xbstream 在加入者上不存在,SST 将无法完成。

那些永远不会成为加入者的节点呢?

从技术上讲,如果一个节点将始终充当捐赠者并且永远不需要从头重新加入集群,您可以说它只需要在捐赠者角色下安装 XtraBackup。然而,在实际操作中,任何节点都可能成为加入者 — 在崩溃后、计划维护后,或从网络分区恢复后。没有可靠的方法可以保证一个节点永远不需要接收 SST。

这里的实用指导很简单:在每个 PXC 节点上无一例外地安装 XtraBackup。 安装它的开销微乎其微。而在计划外中断期间 SST 失败的成本则不然。

Clone 插件替代方案(PXC 8.0.22+)

从 PXC 8.0.22 开始,Percona 添加了对 MySQL Clone Plugin 作为 SST 方法的支持。值得了解这一点,因为它完全消除了 SST 对 XtraBackup 的依赖:

[mysqld]
wsrep_sst_method = clone

使用 clone 方法时,所有节点必须加载 Clone 插件:

INSTALL PLUGIN clone SONAME 'mysql_clone.so';
SHOW PLUGINS WHERE Name = 'clone';
+-------+--------+-------+----------------+---------+
| Name  | Status | Type  | Library        | License |
+-------+--------+-------+----------------+---------+
| clone | ACTIVE | CLONE | mysql_clone.so | GPL     |
+-------+--------+-------+----------------+---------+

clone 方法是一个很好的标准化选项,无需将 XtraBackup 作为 SST 依赖。不过,无论您选择哪种 SST 方法,XtraBackup 对于您的 外部备份策略 仍然具有真正价值。SST 是一种集群同步机制 — 它不是备份,也不应被当作备份对待。

检查当前的 SST 配置

您可以使用以下命令验证当前的 SST 方法和 Galera 相关设置:

SHOW VARIABLES LIKE 'wsrep_sst_method';
+------------------+---------------+
| Variable_name    | Value         |
+------------------+---------------+
| wsrep_sst_method | xtrabackup-v2 |
+------------------+---------------+

检查集群状态并确认哪个节点可能充当捐赠者:

SHOW STATUS LIKE 'wsrep_local_state_comment';
+---------------------------+--------+
| Variable_name             | Value  |
+---------------------------+--------+
| wsrep_local_state_comment | Synced |
+---------------------------+--------+
SHOW STATUS LIKE 'wsrep_connected';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| wsrep_connected | ON    |
+-----------------+-------+
SHOW STATUS LIKE 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| wsrep_cluster_size | 3     |
+--------------------+-------+

实际观察

直接处理 PXC 环境时值得注意的几点:

``````html
  • XtraBackup 的版本必须与您的 PXC 版本匹配。使用 XtraBackup 2.x 与 PXC 8.0 会导致 SST 失败。请使用 Percona XtraBackup 8.0 与 PXC 8.0,并在任何升级后确认版本对齐。
  • 即使您切换到 clone SST 方法,也要保留安装 XtraBackup,用于计划备份。您的备份策略与 SST 方法是独立的关注点,应分别处理。
  • wsrep_sst_donor 变量允许您指定首选捐赠节点,这对于将 SST 引导远离最繁忙或延迟最敏感的成员非常有用。
  • 如果您在 PXC 旁边运行 Percona Toolkit,请注意您特定 PXC 版本中 DDL replication 的工作方式 — Total Order Isolation (TOI) 与 Rolling Schema Upgrade (RSU) 的行为不同,在生产环境中运行架构更改之前值得专门查看。

总结

直接回答问题:如果您使用 xtrabackup-v2 作为 SST 方法 — 这在许多现有 PXC 部署中仍是默认方法 — 那么是的,每个集群成员都需要安装 XtraBackup。 任何节点都可能根据情况成为捐赠节点或加入节点,使用此方法时两种角色都需要 XtraBackup。

如果您使用 PXC 8.0.22 或更高版本,并希望在 SST 层消除该依赖,Clone Plugin 方法是一个可行的替代方案,并且是 Percona 越来越推荐的新部署选择。如果您是从头开始,PXC 8.4 LTS 是当前长期支持版本,也是新安装的推荐目标。即使使用 clone 进行 SST,XtraBackup 仍是实际备份任务的正确工具。

不要为了节省选定节点上的几兆字节磁盘空间而跳过 XtraBackup。此决定最终导致的 SST 失败不是值得的权衡。

资源

2026年2月22日星期日

MySQL + Neo4j 用于 AI 工作负载:为什么关系型数据库仍然重要

所以我想是时候记录一下如何使用你已经熟悉的数据库为 AI 代理构建持久内存了。不是向量数据库 - 而是 MySQL 和 Neo4j。

这不是理论。我每天都在使用这种架构,在多个项目中处理 AI 代理内存。这是真正有效的 schema 和查询模式。

架构

AI 代理需要两种类型的内存:

  • 结构化内存 - 发生了什么、何时、为什么 (MySQL)
  • 模式内存 - 什么与什么相连 (Neo4j)

向量数据库适用于相似性搜索。它们不适合跟踪工作流状态或决策历史。为此,你需要 ACID 事务和正确的关系。

MySQL Schema

这是 AI 代理持久内存的实际 schema:

-- Architecture decisions the AI made
CREATE TABLE architecture_decisions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    project_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    decision TEXT NOT NULL,
    rationale TEXT,
    alternatives_considered TEXT,
    status ENUM('accepted', 'rejected', 'pending') DEFAULT 'accepted',
    decided_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    tags JSON,
    INDEX idx_project_date (project_id, decided_at),
    INDEX idx_status (status)
) ENGINE=InnoDB;

-- Code patterns the AI learned
CREATE TABLE code_patterns (
    id INT AUTO_INCREMENT PRIMARY KEY,
    project_id INT NOT NULL,
    category VARCHAR(50) NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    code_example TEXT,
    language VARCHAR(50),
    confidence_score FLOAT DEFAULT 0.5,
    usage_count INT DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_project_category (project_id, category),
    INDEX idx_confidence (confidence_score)
) ENGINE=InnoDB;

-- Work session tracking
CREATE TABLE work_sessions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    session_id VARCHAR(255) UNIQUE NOT NULL,
    project_id INT NOT NULL,
    started_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    ended_at DATETIME,
    summary TEXT,
    context JSON,
    INDEX idx_project_session (project_id, started_at)
) ENGINE=InnoDB;

-- Pitfalls to avoid (learned from mistakes)
CREATE TABLE pitfalls (
    id INT AUTO_INCREMENT PRIMARY KEY,
    project_id INT NOT NULL,
    category VARCHAR(50),
    title VARCHAR(255) NOT NULL,
    description TEXT,
    how_to_avoid TEXT,
    severity ENUM('critical', 'high', 'medium', 'low'),
    encountered_count INT DEFAULT 1,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_project_severity (project_id, severity)
) ENGINE=InnoDB;

外键。检查约束。正确的索引。这是关系型数据库擅长的领域。

查询模式

这是实际为 AI 代理内存查询的方式:

-- Get recent decisions for context
SELECT title, decision, rationale, decided_at
FROM architecture_decisions
WHERE project_id = ?
  AND decided_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
ORDER BY decided_at DESC
LIMIT 10;

-- Find high-confidence patterns
SELECT category, name, description, code_example
FROM code_patterns
WHERE project_id = ?
  AND confidence_score >= 0.80
ORDER BY usage_count DESC, confidence_score DESC
LIMIT 20;

-- Check for known pitfalls before implementing
SELECT title, description, how_to_avoid
FROM pitfalls
WHERE project_id = ?
  AND category = ?
  AND severity IN ('critical', 'high')
ORDER BY encountered_count DESC;

-- Track session context across interactions
SELECT context
FROM work_sessions
WHERE session_id = ?
ORDER BY started_at DESC
LIMIT 1;

这些是直截了当的 SQL 查询。EXPLAIN 显示索引使用完全符合预期。没有惊喜。

Neo4j 层

MySQL 处理结构化数据。Neo4j 处理关系:

// Create nodes for decisions
CREATE (d:Decision {
  id: 'dec_123',
  title: 'Use FastAPI',
  project_id: 1,
  embedding: [0.23, -0.45, ...]  // Vector for similarity
})

// Create relationships
CREATE (d1:Decision {id: 'dec_123', title: 'Use FastAPI'})
CREATE (d2:Decision {id: 'dec_45', title: 'Used Flask before'})
CREATE (d1)-[:SIMILAR_TO {score: 0.85}]->(d2)
CREATE (d1)-[:CONTRADICTS]->(d3:Decision {title: 'Avoid frameworks'})

// Query: Find similar past decisions
MATCH (current:Decision {id: $decision_id})
MATCH (current)-[r:SIMILAR_TO]-(similar:Decision)
WHERE r.score > 0.80
RETURN similar.title, r.score
ORDER BY r.score DESC

// Query: What outcomes followed this pattern?
MATCH (d:Decision)-[:LEADS_TO]->(o:Outcome)
WHERE d.title CONTAINS 'Redis'
RETURN d.title, o.type, o.success_rate

它们如何协同工作

流程如下所示:

  1. AI 代理生成内容或做出决策
  2. 将结构化数据存储到 MySQL(什么、何时、为什么、完整上下文)
  3. 生成嵌入,向量存储到 Neo4j,并与相似项目建立关系
  4. 下次会话:Neo4j 找到相关的相似决策
  5. MySQL 提供这些决策的完整细节

MySQL 是真相之源。Neo4j 是模式查找器。

为什么不只用向量数据库?

我见过团队试图仅用 Pinecone 或 Weaviate 构建 AI 代理内存。但效果不佳,因为:

向量数据库擅长:

  • 找到与查询相似的文档
  • 语义搜索 (RAG)
  • “类似这样的东西”

向量数据库不擅长:

  • “我们 3 月 15 日决定了什么?”
  • “显示导致中断的决策”
  • “这个工作流的当前状态是什么?”
  • “哪些模式置信度 > 0.8 且使用次数 > 10?”

这些查询需要结构化过滤、连接和事务。这是关系型数据库的领域。

MCP 和未来

模型上下文协议 (MCP) 正在标准化 AI 系统处理上下文的方式。早期的 MCP 实现正在发现我们早已知道的事情:你需要结构化存储和图关系两者兼备。

``````html

MySQL 处理 MCP 的“resources”和“tools”目录。Neo4j 处理上下文项之间的“relationships”。Vector embeddings 只是拼图中的一块。

生产环境说明

当前运行此架构的系统:

  • MySQL 8.0, 48 tables, ~2GB data
  • Neo4j Community, ~50k nodes, ~200k relationships
  • Query latency: MySQL <10ms, Neo4j <50ms
  • Backup: Standard mysqldump + neo4j-admin dump
  • Monitoring: Same Percona tools I've used for years

运营复杂度低,因为这些是成熟的数据库,具有良好理解的运营模式。

何时使用什么

Use CaseDatabase
Workflow state, decisions, audit trailMySQL/PostgreSQL
Pattern detection, similarity, relationshipsNeo4j
Semantic document search (RAG)Vector DB (optional)

从 MySQL 开始用于状态管理。当需要模式识别时添加 Neo4j。只有在实际进行语义文档检索时才添加 vector DB。

总结

AI 代理需要持久化内存。不仅仅是 vector database 中的 embeddings - 结构化、关系型、时序内存,带有模式识别。

MySQL 处理结构化状态。Neo4j 处理图关系。它们共同提供 vector databases 单独无法提供的功能。

不要为了 AI 工作负载而放弃关系型数据库。为每个任务使用正确的工具,那就是将两者结合使用。

有关此架构的 AI 代理视角,参见 3k1o 的配套文章。

2025年7月4日星期五

MySQL分析:使用AI驱动的CLI工具

MySQL分析:使用AI驱动的CLI工具

本文是 https://anothermysqldba.blogspot.com/2025/07/mysql-analysis-with-ai-powered-cli-tool.html 的中文翻译版。

作为MySQL DBA,我们经常在Linux终端窗口中工作。我们也喜欢可用的免费选项。这篇文章展示了一种方法,让我们可以在终端窗口中使用AI驱动的工具。你可以更新使用其他直接的AI提供商,但我将此示例设置为使用aimlapi.com,因为它免费提供有限使用的多个AI模型到你的终端,或者以很低的成本进行更多测试。

注:我不是AIMLAPI的付费发言人或任何其他身份 - 这只是一个简单的例子来突出这个想法。

问题

你正在查看一个有数百个表的遗留数据库,每个表都有复杂的关系和多年前做出的可疑设计决策。通常的过程包括:

  • 手动架构检查
  • 交叉引用文档(如果存在)
  • 运行多个EXPLAIN查询
  • 查阅最佳实践指南
  • 征求同事的第二意见

这需要时间,经常会遗漏一些东西。

基于CLI的方法

我们可以直接从CLI利用AI做很多事情。帮助MySQL分析只是这种方法如何与我们日常数据库任务配合的一个例子。通过将MySQL的原生功能与AI模型结合,全部通过简单的命令行界面访问,我们可以在不离开终端的情况下获得洞察。AIMLAPI提供对100多个AI模型的有限使用免费访问,使这种方法变得可行。对于更集中的测试,成本仍然非常合理。

工具:AIMLAPI CLI

所以这里有一个bash脚本,通过单一界面提供对100多个AI模型的访问:

#!/bin/bash
# 可访问100多个AI模型的AIMLAPI CLI工具
# 文件: ~/.local/bin/aiml

# 配置
DEFAULT_MODEL=${AIMLAPI_DEFAULT_MODEL:-"gpt-4o"}
MAX_TOKENS=${AIMLAPI_MAX_TOKENS:-2000}
TEMPERATURE=${AIMLAPI_TEMPERATURE:-0.7}
BASE_URL="https://api.aimlapi.com"
ENDPOINT="v1/chat/completions"

# 输出颜色代码
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # 无颜色

# 打印彩色输出的函数
print_info() { echo -e "${BLUE}[信息]${NC} $1"; }
print_success() { echo -e "${GREEN}[成功]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[警告]${NC} $1"; }
print_error() { echo -e "${RED}[错误]${NC} $1"; }
print_model() { echo -e "${PURPLE}[模型]${NC} $1"; }

# 热门模型快捷方式
declare -A MODEL_SHORTCUTS=(
    # OpenAI模型
    ["gpt4"]="gpt-4o"
    ["gpt4o"]="gpt-4o"
    ["gpt4mini"]="gpt-4o-mini"
    ["o1"]="o1-preview"
    ["o3"]="openai/o3-2025-04-16"
    
    # Claude模型  
    ["claude"]="claude-3-5-sonnet-20241022"
    ["claude4"]="anthropic/claude-sonnet-4"
    ["opus"]="claude-3-opus-20240229"
    ["haiku"]="claude-3-5-haiku-20241022"
    ["sonnet"]="claude-3-5-sonnet-20241022"
    
    # DeepSeek模型
    ["deepseek"]="deepseek-chat"
    ["deepseek-r1"]="deepseek/deepseek-r1"
    ["reasoner"]="deepseek-reasoner"
    
    # Google模型
    ["gemini"]="gemini-2.0-flash"
    ["gemini2"]="gemini-2.0-flash"
    ["gemini15"]="gemini-1.5-pro"
    
    # Meta Llama模型
    ["llama"]="meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo"
    ["llama405b"]="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo"
    
    # Qwen模型
    ["qwen"]="qwen-max"
    ["qwq"]="Qwen/QwQ-32B"
    
    # Grok模型
    ["grok"]="x-ai/grok-beta"
    ["grok3"]="x-ai/grok-3-beta"
    
    # 专业模型
    ["coder"]="Qwen/Qwen2.5-Coder-32B-Instruct"
)

# 解析模型快捷方式的函数
resolve_model() {
    local model="$1"
    if [[ -n "${MODEL_SHORTCUTS[$model]}" ]]; then
        echo "${MODEL_SHORTCUTS[$model]}"
    else
        echo "$model"
    fi
}

# 使用jq创建JSON载荷的函数,确保正确转义
create_json_payload() {
    local model="$1"
    local prompt="$2"
    local system_prompt="$3"
    
    local temp_file=$(mktemp)
    echo "$prompt" > "$temp_file"
    
    if [ -n "$system_prompt" ]; then
        jq -n --arg model "$model" \
              --rawfile prompt "$temp_file" \
              --arg system "$system_prompt" \
              --argjson max_tokens "$MAX_TOKENS" \
              --argjson temperature "$TEMPERATURE" \
              '{
                model: $model,
                messages: [{role: "system", content: $system}, {role: "user", content: $prompt}],
                max_tokens: $max_tokens,
                temperature: $temperature
              }'
    else
        jq -n --arg model "$model" \
              --rawfile prompt "$temp_file" \
              --argjson max_tokens "$MAX_TOKENS" \
              --argjson temperature "$TEMPERATURE" \
              '{
                model: $model,
                messages: [{role: "user", content: $prompt}],
                max_tokens: $max_tokens,
                temperature: $temperature
              }'
    fi
    
    rm -f "$temp_file"
}

# 调用AIMLAPI的函数
call_aimlapi() {
    local prompt="$1"
    local model="$2"
    local system_prompt="$3"
    
    if [ -z "$AIMLAPI_API_KEY" ]; then
        print_error "AIMLAPI_API_KEY未设置"
        return 1
    fi
    
    model=$(resolve_model "$model")
    
    local json_file=$(mktemp)
    create_json_payload "$model" "$prompt" "$system_prompt" > "$json_file"
    
    local response_file=$(mktemp)
    local http_code=$(curl -s -w "%{http_code}" -X POST "${BASE_URL}/${ENDPOINT}" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $AIMLAPI_API_KEY" \
        --data-binary @"$json_file" \
        -o "$response_file")
    
    if [ "$http_code" -ne 200 ] && [ "$http_code" -ne 201 ]; then
        print_error "HTTP错误 $http_code"
        cat "$response_file" >&2
        rm -f "$json_file" "$response_file"
        return 1
    fi
    
    local content=$(jq -r '.choices[0].message.content // empty' "$response_file" 2>/dev/null)
    
    if [ -z "$content" ]; then
        content=$(jq -r '.choices[0].text // .message.content // .content // empty' "$response_file" 2>/dev/null)
    fi
    
    if [ -z "$content" ]; then
        local error_msg=$(jq -r '.error.message // .error // empty' "$response_file" 2>/dev/null)
        if [ -n "$error_msg" ]; then
            echo "API错误: $error_msg"
        else
            echo "错误: 无法解析API响应"
        fi
    else
        echo "$content"
    fi
    
    rm -f "$json_file" "$response_file"
}

# 带参数解析的主函数
main() {
    local model="$DEFAULT_MODEL"
    local system_prompt=""
    local prompt=""
    local piped_input=""
    
    if [ -p /dev/stdin ]; then
        piped_input=$(cat)
    fi
    
    # 解析参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -m|--model)
                model="$2"
                shift 2
                ;;
            -s|--system)
                system_prompt="$2"
                shift 2
                ;;
            *)
                prompt="$*"
                break
                ;;
        esac
    done
    
    # 处理输入
    if [ -n "$piped_input" ] && [ -n "$prompt" ]; then
        prompt="$prompt

要分析的数据如下:
$piped_input"
    elif [ -n "$piped_input" ]; then
        prompt="请分析这些数据:

$piped_input"
    elif [ -z "$prompt" ]; then
        echo "用法: aiml [选项] \"提示\""
        echo "       命令 | aiml [选项]"
        exit 1
    fi
    
    local resolved_model=$(resolve_model "$model")
    print_info "正在查询 $resolved_model..."
    
    local response=$(call_aimlapi "$prompt" "$model" "$system_prompt")
    
    echo ""
    print_model "来自 $resolved_model 的响应:"
    echo "----------------------------------------"
    echo "$response" 
    echo "----------------------------------------"
}

# 检查依赖项
check_dependencies() {
    command -v curl >/dev/null 2>&1 || { print_error "需要curl但未安装。"; exit 1; }
    command -v jq >/dev/null 2>&1 || { print_error "需要jq但未安装。"; exit 1; }
}

check_dependencies
main "$@"

这个脚本通过简单的快捷方式如claude4、gpt4、grok3等提供对各种AI模型的访问。AIMLAPI为所有这些模型提供有限使用的免费访问,额外测试的成本合理。适合想要在不超出预算的情况下进行实验的DBA。

脚本功能

脚本包含全面的帮助。aiml --help显示的内容如下:

AIMLAPI CLI工具 - 访问100多个AI模型
=======================================
用法: aiml [选项] "提示"
     命令 | aiml [选项]
核心选项:
  -m, --model 模型          要使用的模型 (默认: gpt-4o)
  -t, --tokens 数字         最大令牌数 (默认: 2000)
  -T, --temperature 浮点数  温度 0.0-2.0 (默认: 0.7)
  -s, --system 提示         模型行为的系统提示
输入/输出选项:
  -f, --file 文件           从文件读取提示
  -o, --output 文件         将响应保存到文件
  -r, --raw                 原始输出 (无格式/颜色)
信息选项:
  -l, --list               列出热门模型快捷方式
  --get-models             从API获取所有可用模型
  -c, --config             显示当前配置
  -v, --verbose            启用详细输出
  -d, --debug              显示调试信息
  -h, --help               显示此帮助
基本示例:
  aiml "解释量子计算"
  aiml -m claude "审查这段代码"
  aiml -m deepseek-r1 "逐步解决这个数学问题"
  aiml -m grok3 "AI的最新发展是什么?"
  aiml -m coder "优化这个Python函数"
管道示例:
  ps aux | aiml "分析这些进程"
  netstat -tuln | aiml "解释这些网络连接"
  cat error.log | aiml -m claude "诊断这些错误"
  git diff | aiml -m coder "审查这些代码更改"
  df -h | aiml "分析磁盘使用情况并建议清理"
文件操作:
  aiml -f prompt.txt -o response.txt
  aiml -f large_dataset.csv -m llama405b "分析这些数据"
  cat script.py | aiml -m coder -o review.md "代码审查"
模型类别和快捷方式:
  OpenAI:     gpt4, gpt4mini, o1, o3
  Claude:     claude, opus, haiku, sonnet, claude4
  DeepSeek:   deepseek, deepseek-r1, reasoner
  Google:     gemini, gemini2, gemma
  Meta:       llama, llama3, llama4, llama405b
  Qwen:       qwen, qwen2, qwq
  Grok:       grok, grok3, grok3mini
  编程:       coder, codestral
高级用法:
  aiml -m claude -s "你是安全专家" "审计这段代码"
  aiml -m deepseek-r1 -t 3000 "复杂推理任务"
  aiml -v -m grok3 "带详细日志的详细查询"
  aiml -d "调试模式以解决API问题"
模型发现:
  aiml -l                   # 显示热门快捷方式
  aiml --get-models         # 从API获取所有可用模型
  aiml --config             # 显示当前配置
环境变量:
  AIMLAPI_API_KEY          - 您的AIMLAPI密钥 (必需)
  AIMLAPI_DEFAULT_MODEL    - 默认模型 (可选)
  AIMLAPI_MAX_TOKENS       - 默认最大令牌数 (可选)
  AIMLAPI_TEMPERATURE      - 默认温度 (可选)
专业提示:
  • 使用 coder 进行编程任务和代码审查
  • 使用 deepseek-r1 进行复杂推理和数学问题
  • 使用 claude4 进行详细分析和长篇内容
  • 使用 grok3 获取当前事件和实时信息
  • 使用 gpt4mini 进行快速问题以节省API成本
  • 直接管道命令输出: 命令 | aiml "分析这个"
  • 使用 -v 获取详细输出以查看正在使用的模型
  • 使用 --get-models 查看所有100多个可用模型

通过简单界面访问100多个AI模型!

示例:City表

以下是如何通过实际MySQL表分析来演示这个工具的作用。我将使用三个不同的AI模型分析经典World数据库(来自https://dev.mysql.com/doc/index-other.html 示例数据库)的City表。

命令

mysql --login-path=klarson world -e "show create table City\G" | \
aiml --model claude4 "使用MySQL专家的观点分析这个表"

这个命令:

  1. 从MySQL提取表结构
  2. 通过管道发送到我们的AI工具
  3. 从Claude Sonnet 4获取分析

结果

Claude Sonnet 4分析

Claude 4提供了组织良好的分析:

优势:

  • 适合InnoDB效率的正确AUTO_INCREMENT主键
  • 维护引用完整性的外键约束
  • 适合常见查询的合适索引策略

发现的问题:

  • 存储效率低下: 对可变长度城市名称使用CHAR(35)浪费空间
  • 字符集限制: latin1字符集不适合国际城市名称
  • 次优索引: name_key索引仅覆盖前5个字符

建议的改进:

-- Claude建议的优化结构
CREATE TABLE `City` (
  `ID` int NOT NULL AUTO_INCREMENT,
  `Name` VARCHAR(35) NOT NULL,
  `CountryCode` CHAR(3) NOT NULL,
  `District` VARCHAR(20) NOT NULL,
  `Population` int UNSIGNED NOT NULL DEFAULT '0',
  PRIMARY KEY (`ID`),
  KEY `CountryCode` (`CountryCode`),
  KEY `name_idx` (`Name`),
  KEY `country_name_idx` (`CountryCode`, `Name`),
  KEY `population_idx` (`Population`),
  CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) 
    REFERENCES `Country` (`Code`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4080 
  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Grok 3 Beta分析

mysql --login-path=klarson world -e "show create table City\G" | \
aiml --model grok3 "使用MySQL专家的观点分析这个表"

Grok 3提供了详尽而详细的分析,涵盖:

技术深度分析:

  • 性能影响分析: 详细评估了部分索引限制
  • 存储引擎优势: 确认了InnoDB选择用于事务完整性
  • 数据类型优化: 带示例的详细节省空间建议

高级考虑:

  • 城市名称搜索的全文索引建议
  • 带特定命令的字符集迁移程序
  • 大数据集的分区策略

实施指南:

-- Grok的字符集迁移建议
ALTER TABLE City CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 全文索引建议
ALTER TABLE City ADD FULLTEXT INDEX name_fulltext (Name);

GPT-4o分析

mysql --login-path=klarson world -e "show create table City\G" | \
aiml --model gpt4 "使用MySQL专家的观点分析这个表"

GPT-4o专注于实用的、可直接执行的改进:

实用评估:

  • 验证了AUTO_INCREMENT主键设计
  • 确认了外键约束对数据完整性的好处
  • 识别了全球应用的字符集限制

ready-to-implement建议:

  • 用于立即优化的特定ALTER TABLE命令
  • 查询模式分析建议
  • 索引效果评估标准

多模型分析的力量

这种方法有价值的原因是获得三个不同的观点:

  1. Claude 4: 提供带有具体代码解决方案的详细结构化分析
  2. Grok 3: 提供带有高级优化策略的全面覆盖
  3. GPT-4o: 提供实用的、可直接执行的建议

每个模型都带来独特的优势:

  • 不同的焦点: 存储优化 vs 性能 vs 可维护性
  • 不同的深度级别: 从快速胜利到架构改进
  • 多样的分析风格: 结构化 vs 全面 vs 实用

超越MySQL:其他CLI示例

由于我们可以将任何命令输出通过管道传递给AI工具,这里有一些其他有用的示例:

系统管理

# 分析系统进程
ps aux | aiml "哪些进程使用了最多资源?"

# 检查磁盘使用情况
df -h | aiml "分析磁盘使用情况并建议清理"

# 网络连接
netstat -tuln | aiml "解释这些网络连接"

# 系统日志
tail -50 /var/log/syslog | aiml "这些日志中有令人担忧的错误吗?"

文件和目录分析

# 大文件
find /var -size +100M | aiml "按类型组织这些大文件"

# 权限问题
ls -la /etc/mysql/ | aiml "检查这些文件权限的安全性"

# 配置审查
cat /etc/mysql/my.cnf | aiml "审查这个MySQL配置"

日志分析

# Apache日志
tail -100 /var/log/apache2/error.log | aiml "总结这些Web服务器错误"

# 认证日志
grep "Failed password" /var/log/auth.log | aiml "分析这些失败的登录尝试"

重点是你可以通过管道传递几乎任何内容来获得快速分析,而无需离开终端。

实施工作流程

设置说明

1. 安装依赖项:

# 安装所需工具
sudo apt install curl jq mysql-client

# 创建脚本目录
mkdir -p ~/.local/bin

# 使脚本可执行
chmod +x ~/.local/bin/aiml

2. 配置API访问:

# 从https://aimlapi.com获取免费AIMLAPI密钥(有限使用的免费层)
export AIMLAPI_API_KEY="your-free-api-key-here"
echo 'export AIMLAPI_API_KEY="your-free-api-key-here"' >> ~/.bashrc

3. 测试设置:

# 验证配置
aiml --config

# 测试基本功能
echo "SELECT VERSION();" | aiml "解释这个SQL"

实用使用模式

快速表分析

# 分析特定表
mysql -e "SHOW CREATE TABLE users\G" mydb | \
aiml -m claude4 "分析这个MySQL表结构"

比较不同模型观点

# 获得同一个表的多个观点
TABLE_DDL=$(mysql -e "SHOW CREATE TABLE orders\G" ecommerce)

echo "$TABLE_DDL" | aiml -m claude4 "MySQL表分析"
echo "$TABLE_DDL" | aiml -m grok3 "性能优化审查" 
echo "$TABLE_DDL" | aiml -m gpt4 "实用改进建议"

分析多个表

# 数据库中所有表的快速分析
mysql -e "SHOW TABLES;" mydb | \
while read table; do
  echo "=== 分析 $table ==="
  mysql -e "SHOW CREATE TABLE $table\G" mydb | \
  aiml -m gpt4mini "快速评估这个表"
done

索引分析

# 审查索引使用和优化
mysql -e "SHOW INDEX FROM tablename;" database | \
aiml -m deepseek "为这个MySQL表建议索引优化"

查询性能分析

# 分析慢查询
mysql -e "SHOW PROCESSLIST;" | \
aiml -m grok3 "识别这些MySQL进程中的潜在性能问题"

为什么AIMLAPI使DBA能够做到这一点

合理成本的免费访问: AIMLAPI为100多个AI模型提供有限使用的免费访问,额外测试的价格非常合理。这使得想要在不承诺昂贵订阅的情况下进行实验的DBA成为完美选择。

模型多样性: 访问来自不同提供商(OpenAI、Anthropic、Google、Meta等)的模型意味着你可以获得不同的观点和专业领域。

无供应商锁定: 你可以试验不同的模型来找到最适合你特定需求的模型,而无需长期承诺。

终端原生: 保持在你舒适的Linux环境中,你已经在那里进行MySQL工作。

模型选择指南

不同的模型在MySQL分析的不同方面表现出色:

# 用于详细结构分析
aiml -m claude4 "全面的表结构审查"

# 用于性能导向分析  
aiml -m grok3 "性能优化建议"

# 用于快速实用建议
aiml -m gpt4 "立即可操作的改进"

# 用于关于权衡的复杂推理
aiml -m deepseek-r1 "复杂优化权衡分析"

# 用于成本效益的快速检查
aiml -m gpt4mini "简要表评估"

高级技术

自定义系统提示

将分析调整到你的特定环境:

# 电商焦点
aiml -m claude4 -s "你正在分析高流量电商网站的表" \
"审查这个表的可扩展性"

# 安全焦点
aiml -m grok3 -s "你是一个专注于安全的数据库分析师" \
"这个表结构的安全评估"

# 遗留系统焦点
aiml -m gpt4 -s "你正在帮助将遗留系统迁移到现代MySQL" \
"这个表的现代化建议"

自动报告

# 生成全面的数据库分析报告
DB_NAME="production_db"
REPORT_FILE="analysis_$(date +%Y%m%d).md"

echo "# $DB_NAME 数据库分析报告" > "$REPORT_FILE"
echo "生成于 $(date)" >> "$REPORT_FILE"

for table in $(mysql -Ns -e "SHOW TABLES;" "$DB_NAME"); do
  echo "" >> "$REPORT_FILE"
  echo "## 表: $table" >> "$REPORT_FILE"
  
  mysql -e "SHOW CREATE TABLE $table\G" "$DB_NAME" | \
  aiml -m claude4 "提供这个MySQL表的简洁分析" >> "$REPORT_FILE"
done

性能优化工作流程

# 全面的性能分析
mysql -e "SHOW CREATE TABLE heavy_table\G" db | \
aiml -m grok3 "性能瓶颈分析"

# 跟进索引建议
mysql -e "SHOW INDEX FROM heavy_table;" db | \
aiml -m deepseek "索引优化策略"

# 获取实施计划
aiml -m gpt4 "为这些优化创建逐步实施计划"

这种方法的实际好处

速度: 在几秒钟而不是几小时内获得专家级分析
多重视角: 不同的模型捕捉不同的问题
学习工具: 每次分析都能学到关于MySQL优化的新知识
成本效益: 由于AIMLAPI的免费层和合理定价,这种强大的分析是可访问的
一致性: 跨不同表和数据库的可重复分析
文档: 容易生成报告并与团队分享发现

获得最佳结果的提示

  1. 从结构开始: 总是从SHOW CREATE TABLE开始进行全面分析
  2. 使用具体提示: 你的请求越具体,分析就越好
  3. 比较模型: 不同的模型在不同方面表现出色 - 使用多重视角
  4. 验证建议: 总是在生产环境之前在开发环境中测试AI建议
  5. 迭代: 使用后续问题深入特定建议

今天开始

这种方法的美妙之处在于其简单性和成本效益。只需几个命令,你就可以:

  1. 从https://aimlapi.com获取免费的AIMLAPI密钥(包括免费层)
  2. 安装脚本(5分钟)
  3. 立即开始分析你的MySQL表
  4. 试验不同的模型以查看哪些最适合你的需求
  5. 将免费层用于常规分析,仅为集中测试付费

Windows用户(快速选项)

我不是Windows用户,但如果你需要在Windows上运行这个,最简单的方法是:

  1. 安装WSL2(Windows Linux子系统)
  2. 从Microsoft Store安装Ubuntu
  3. 在WSL2内遵循上述Linux设置

这为你提供了一个合适的Linux环境,脚本将完全按设计工作。

这不是要替换DBA专业知识 - 而是在保持在终端环境中的同时增强它。AI提供快速分析并捕捉你可能遗漏的东西,而你提供上下文并做出最终决定。

无论你是处理单个表还是拥有数百个表的复杂数据库,这个工作流程都能扩展以满足你的需求。由于AIMLAPI为额外使用提供合理成本的免费访问,你可以试验并找到你特定用例的完美组合,而无需预算担忧。


MySQL强大的内省功能与AI分析的结合为DBA创建了一个既实用又成本效益的工作流程。在你的下一个数据库优化项目中尝试一下 - 你可能会对出现的洞察感到惊讶,所有这些都在你舒适的终端环境中。

2020年3月16日星期一

MySQL和Docker ...一個簡單的設置

MySQL和Docker ...不是新概念,人們已經使用Docker已有一段時間了。 對於剛開始為此發展的人來說,可能會有一些障礙。

儘管MySQL在本地運行良好,但如果要在不同版本的MySQL上測試代碼,則很容易擁有多個版本是很好的。

多年來,一種選擇當然是Giuseppe Maxia的https://mysqlsandbox.net/ 。 這是一個非常有效的解決方案,能夠啟動多個實例並測試複製等。

在跨不同版本的MySQL進行測試時,Docker現在也是另一個經常使用的場景。 下面僅介紹一些步驟,以輕鬆安裝多個版本。 我使用OSX,因此這些示例適用於OSX。

您需要Docker才能啟動,當然,Docker Desktop是一個方便的工具,使您能夠輕鬆獲得訪問權限。

設置好Docker之後,就可以為MySQL準備好環境了。

在這裡,我創建了一個Docker文件夾,其中包含MySQL數據目錄,配置文件以及mysql-files目錄(如果需要)。

mkdir ~/Docker ;

mkdir ~/Docker/mysql_data;
mkdir ~/Docker/mysql-files;
mkdir ~/Docker/cnf;

現在在mysql_data


cd ~/Docker/mysql_data;
mkdir 8.0;
mkdir 5.7;
mkdir 5.6;
mkdir 5.5;


現在,我為該示例設置簡單的cnf文件。 要注意的主要事情是綁定地址。 這樣做是為了確保它對我們開放,使其可以在docker之外訪問MySQL。 您還可以注意到,對於每個MySQL docker實例,這些文件都可以用來設置其他配置信息。



cd ~/Docker/cnf;

cat my.8.0.cnf
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= /var/lib/mysql-files
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
bind-address = 0.0.0.0
port=3306
server-id=80


# Custom config should go here
!includedir /etc/mysql/conf.d/

cat my.5.7.cnf
[mysqld]
bind-address = 0.0.0.0
server-id=57
max_allowed_packet=32M

$ cat my.5.6.cnf
[mysqld]
bind-address = 0.0.0.0
server-id=56

$ cat my.5.5.cnf
[mysqld]
bind-address = 0.0.0.0
server-id=55


好的,現在我們已經設置了配置文件,我們需要構建docker。 生成命令要注意的幾件事。

--name我們為docker設置了一個命名引用。

在這裡,我們將配置文件,數據目錄和mysql-files目錄映射到docker。 這使我們可以輕鬆調整my.cnf文件等。
-v〜/ Docker / cnf / my.8.0.cnf:/etc/mysql/my.cnf
-v〜/ Docker / mysql_data / 8.0:/ var / lib / mysql
-v〜/ Docker / mysql文件:/ var / lib / mysql文件

我們希望能夠在docker之外訪問這些MySQL實例,因此我們需要相應地發布和映射端口。
-p 3306:3306這意味著3306在docker內部的3306本地
-p 3307:3306這意味著3307在docker內部3306本地
-p 3308:3306這意味著3308在docker內部3306本地
-p 3309:3306這意味著3309在docker內部3306本地

然後,我們還要傳遞幾個環境變量。
-e MYSQL_ROOT_HOST =%-e MYSQL_ROOT_PASSWORD = <在此處設置密碼>

所以放在一起...


docker run --restart always --name mysql8.0 -v ~/Docker/cnf/my.8.0.cnf:/etc/mysql/my.cnf -v ~/Docker/mysql_data/8.0:/var/lib/mysql -v ~/Docker/mysql-files:/var/lib/mysql-files -p 3306:3306 -d -e MYSQL_ROOT_HOST=% -e MYSQL_ROOT_PASSWORD=<set a password here> mysql:8.0

docker run --restart always --name mysql5.7 -v ~/Docker/cnf/my.5.7.cnf:/etc/mysql/my.cnf -v ~/Docker/mysql_data/5.7:/var/lib/mysql -v ~/Docker/mysql-files:/var/lib/mysql-files -p 3307:3306 -d -e MYSQL_ROOT_HOST=% -e MYSQL_ROOT_PASSWORD=<set a password here> mysql:5.7

docker run --restart always --name mysql5.6 -v ~/Docker/cnf/my.5.6.cnf:/etc/mysql/my.cnf -v ~/Docker/mysql_data/5.6:/var/lib/mysql -v ~/Docker/mysql-files:/var/lib/mysql-files -p 3308:3306 -d -e MYSQL_ROOT_HOST=% -e MYSQL_ROOT_PASSWORD=<set a password here> mysql:5.6

docker run --restart always --name mysql5.5 -v ~/Docker/cnf/my.5.5.cnf:/etc/mysql/my.cnf -v ~/Docker/mysql_data/5.5:/var/lib/mysql -v ~/Docker/mysql-files:/var/lib/mysql-files -p 3309:3306 -d -e MYSQL_ROOT_HOST=% -e MYSQL_ROOT_PASSWORD=<set a password here> mysql:5.5

每次執行以上命令後,您都應該返回一個ID。
示例:3cb07d7c21476fbf298648986208f3429ec664167d8eef7fed17bf9ee3ce6316

您可以通過Docker桌面輕鬆啟動/重新啟動和訪問每個Docker終端,或者只需記下相關ID即可通過終端執行。

Docker桌面還會顯示您傳遞的所有變量,以便您進行驗證。
當然,您也可以在此處訪問CLI,輕鬆停止或啟動或銷毀它。


$ docker exec -it 3cb07d7c21476fbf298648986208f3429ec664167d8eef7fed17bf9ee3ce6316 /bin/sh; exit
# mysql -p

如果Docker容器已經在運行,您現在可以通過localhost終端訪問MySQL。

$ mysql --host=localhost --protocol=tcp --port=3306 -p -u root

現在,如果您遇到任何訪問問題,請記住確保MySQL帳戶正確並且您的端口和映射正確。
  • 在“讀取初始通信數據包”時失去與MySQL服務器的連接
  • 錯誤1045(28000):用戶'root'@'192.168.0.5'的訪問被拒絕(使用密碼:是)

現在,您可以看到所有設備均已啟動並且可用,並且服務器ID與我們為每個cnf文件的eariler設置的設置匹配。

$ mysql --host=localhost --protocol=tcp --port=3306 -e "Select @@hostname, @@version, @@server_id "
+--------------+-----------+-------------+
| @@hostname | @@version | @@server_id |
+--------------+-----------+-------------+
| 58e9663afe8d | 8.0.19 | 80 |
+--------------+-----------+-------------+
$ mysql --host=localhost --protocol=tcp --port=3307 -e "Select @@hostname, @@version, @@server_id "
+--------------+-----------+-------------+
| @@hostname | @@version | @@server_id |
+--------------+-----------+-------------+
| b240917f051a | 5.7.29 | 57 |
+--------------+-----------+-------------+
$ mysql --host=localhost --protocol=tcp --port=3308 -e "Select @@hostname, @@version, @@server_id "
+--------------+-----------+-------------+
| @@hostname | @@version | @@server_id |
+--------------+-----------+-------------+
| b4653850cfe9 | 5.6.47 | 56 |
+--------------+-----------+-------------+
$ mysql --host=localhost --protocol=tcp --port=3309 -e "Select @@hostname, @@version, @@server_id "
+--------------+-----------+-------------+
| @@hostname | @@version | @@server_id |
+--------------+-----------+-------------+
| 22e169004583 | 5.5.62 | 55 |
+--------------+-----------+-------------+


2019年6月17日星期一

MySQL組複製

所以MySQL的組複製出來了MySQL 5.7。 現在已經有一段時間了,人們開始更多地詢問它。
下面是一個如何設置它的例子和一些痛點的例子,因為我用它來探討。
我使用三個不同的服務器,

服務器CENTOSA

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.02 sec)

vi my.cnf
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE

log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE

transaction_write_set_extraction=XXHASH64
group_replication_group_name="90d8b7c8-5ce1-490e-a448-9c8d176b54a8"
group_replication_start_on_boot=off
group_replication_local_address= "192.168.111.17:33061"
group_replication_group_seeds= "192.168.111.17:33061,192.168.111.89:33061,192.168.111.124:33061"
group_replication_bootstrap_group=off

mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER repl@'%' IDENTIFIED BY 'replpassword';
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;


CHANGE MASTER TO
MASTER_USER='repl',
MASTER_PASSWORD='replpassword'
FOR CHANNEL 'group_replication_recovery';


mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)


mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (3.11 sec)


mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)


mysql> SELECT * FROM performance_schema.replication_group_members \G

*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: 1ab30239-5ef6-11e9-9b4a-08002712f4b1
MEMBER_HOST: centosa
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.15
所以現在我們可以添加更多服務器。
服務器CENTOSB

vi my.cnf
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
server_id=2
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE

log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE


transaction_write_set_extraction=XXHASH64
group_replication_group_name="90d8b7c8-5ce1-490e-a448-9c8d176b54a8"
group_replication_start_on_boot=off
group_replication_local_address= "192.168.111.89:33061"
group_replication_group_seeds= "192.168.111.17:33061,192.168.111.89:33061,192.168.111.124:33061"
group_replication_bootstrap_group=off

mysql> CHANGE MASTER TO
MASTER_USER='repl',
MASTER_PASSWORD='replpassword'
FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> CHANGE MASTER TO GET_MASTER_PUBLIC_KEY=1;
Query OK, 0 rows affected (0.02 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (4.03 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ab30239-5ef6-11e9-9b4a-08002712f4b1 | centosa | 3306 | ONLINE | PRIMARY | 8.0.15 |
| group_replication_applier | 572ca2fa-5eff-11e9-8df9-08002712f4b1 | centosb | 3306 | RECOVERING | SECONDARY | 8.0.15 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
2 rows in set (0.00 sec)


服務器CENTOSC

vi my.cnf
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
server_id=3
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE

transaction_write_set_extraction=XXHASH64
group_replication_group_name="90d8b7c8-5ce1-490e-a448-9c8d176b54a8"
group_replication_start_on_boot=off
group_replication_local_address= "192.168.111.124:33061"
group_replication_group_seeds= "192.168.111.17:33061,192.168.111.89:33061,192.168.111.124:33061"
group_replication_bootstrap_group=off

mysql> CHANGE MASTER TO
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replpassword'
-> FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> CHANGE MASTER TO GET_MASTER_PUBLIC_KEY=1;
Query OK, 0 rows affected (0.02 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (3.58 sec)
mysql> SELECT * FROM performance_schema.replication_group_members \G
*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: 1ab30239-5ef6-11e9-9b4a-08002712f4b1
MEMBER_HOST: centosa
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.15

*************************** 2. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: 572ca2fa-5eff-11e9-8df9-08002712f4b1
MEMBER_HOST: centosb
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.15

*************************** 3. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: c5f3d1d2-8dd8-11e9-858d-08002773d1b6
MEMBER_HOST: centosc
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.15
3 rows in set (0.00 sec)


所以這一切都很棒,但並不總是意味著他們上網,他們通常可以坐在恢復模式。
到目前為止,我已經看到MySQL崩潰失敗,所以需要確保它穩定。
mysql> create database testcentosb;<br> ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement<br>
附註解決其中一些因素 -
mysql> START GROUP_REPLICATION;
ERROR 3094 (HY000): The START GROUP_REPLICATION command failed as the applier module failed to start.

mysql> reset slave all;
Query OK, 0 rows affected (0.03 sec)
- 然後從Change master命令重新開始
mysql> START GROUP_REPLICATION;
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.

[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error on opening a connection to 192.168.111.17:33061 on local port: 33061.'
[ERROR] [MY-011526] [Repl] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: c5f3d1d2-8dd8-11e9-858d-08002773d1b6:1-4 >
[ERROR] [MY-011522] [Repl] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'

https://ronniethedba.wordpress.com/2017/04/22/this-member-has-more-executed-transactions-than-those-present-in-the-group/


[ERROR] [MY-011620] [Repl] Plugin group_replication reported: 'Fatal error during the recovery process of Group Replication. The server will leave the group.'
[ERROR] [MY-013173] [Repl] Plugin group_replication reported: 'The plugin encountered a critical error and will abort: Fatal error during execution of Group Replication'

SELECT * FROM performance_schema.replication_connection_status\G


我的想法...
請記住,可以在單主模式或多節點中設置組複製
mysql> select @@group_replication_single_primary_mode\G
*************************** 1. row ***************************
@@group_replication_single_primary_mode: 1

mysql> create database testcentosb;
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
如果您寫入無主節點,您當然會收到錯誤。


group-replication-single-primary-mode = off < - 添加到cnf文件中。
mysql> SELECT * FROM performance_schema.replication_group_members;
+ --------------------------- + --------------------- ----------------- + ------------- ------------- + + ---- ---------- + ------------- + ---------------- +
| CHANNEL_NAME               | 會員ID                             | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+ --------------------------- + --------------------- ----------------- + ------------- ------------- + + ---- ---------- + ------------- + ---------------- +
| group_replication_applier | 1ab30239-5ef6-11e9-9b4a-08002712f4b1 | centosa     |         3306 | RECOVERING   | 主     | 8.0.15         |
| group_replication_applier | 572ca2fa-5eff-11e9-8df9-08002712f4b1 | centosb     |         3306 | 線上       | 主     | 8.0.15         |
| group_replication_applier | c5f3d1d2-8dd8-11e9-858d-08002773d1b6 | centosc     |         3306 | RECOVERING   | 主     | 8.0.15         |
+ --------------------------- + --------------------- ----------------- + ------------- ------------- + + ---- ---------- + ------------- + ---------------- +

3組(0.00秒)


現在,如果您使用Keepalived,MySQL路由器,ProxySQL等來處理您的流量,以便在發生故障轉移時自動翻轉。 當我停止主要時,我們可以從下面看到它立即失敗了。

mysql> SELECT * FROM performance_schema.replication_group_members ;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ab30239-5ef6-11e9-9b4a-08002712f4b1 | centosa | 3306 | ONLINE | PRIMARY | 8.0.15 |
| group_replication_applier | 572ca2fa-5eff-11e9-8df9-08002712f4b1 | centosb | 3306 | ONLINE | SECONDARY | 8.0.15 |
| group_replication_applier | c5f3d1d2-8dd8-11e9-858d-08002773d1b6 | centosc | 3306 | ONLINE | SECONDARY | 8.0.15 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)

[root@centosa]# systemctl stop mysqld

mysql> SELECT * FROM performance_schema.replication_group_members ;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 572ca2fa-5eff-11e9-8df9-08002712f4b1 | centosb | 3306 | ONLINE | PRIMARY | 8.0.15 |
| group_replication_applier | c5f3d1d2-8dd8-11e9-858d-08002773d1b6 | centosc | 3306 | ONLINE | SECONDARY | 8.0.15 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
2 rows in set (0.00 sec)

[root@centosa]# systemctl start mysqld
[root@centosa]# mysql
mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (3.34 sec)

mysql> SELECT * FROM performance_schema.replication_group_members ;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ab30239-5ef6-11e9-9b4a-08002712f4b1 | centosa | 3306 | RECOVERING | SECONDARY | 8.0.15 |
| group_replication_applier | 572ca2fa-5eff-11e9-8df9-08002712f4b1 | centosb | 3306 | ONLINE | PRIMARY | 8.0.15 |
| group_replication_applier | c5f3d1d2-8dd8-11e9-858d-08002773d1b6 | centosc | 3306 | ONLINE | SECONDARY | 8.0.15 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)


現在復蘇仍然是一個問題,因為它不會簡單地加入。 不得不再次審查所有帳戶和步驟,但我最終確實得到了它。

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ab30239-5ef6-11e9-9b4a-08002712f4b1 | centosa | 3306 | ONLINE | SECONDARY | 8.0.15 |
| group_replication_applier | 572ca2fa-5eff-11e9-8df9-08002712f4b1 | centosb | 3306 | ONLINE | PRIMARY | 8.0.15 |
| group_replication_applier | c5f3d1d2-8dd8-11e9-858d-08002773d1b6 | centosc | 3306 | ONLINE | SECONDARY | 8.0.15 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)


我需要對此進行更多測試,因為我還沒有100%銷售,因為我仍然傾向於Galera複製。

感興趣的URL


  • https://dev.mysql.com/doc/refman/8.0/en/group-replication.html
  • https://dev.mysql.com/doc/refman/8.0/en/group-replication-deploying-in-single-primary-mode.html
  • http://datacharmer.blogspot.com/2017/01/mysql-group-replication-vs-multi-source.html
  • https://dev.mysql.com/doc/refman/8.0/en/group-replication-launching.html
  • https://dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-instances.html
  • https://dev.mysql.com/doc/refman/8.0/en/group-replication-adding-instances.html
  • https://ronniethedba.wordpress.com/2017/04/22/how-to-setup-mysql-group-replication/
  • https://www.digitalocean.com/community/tutorials/how-to-configure-mysql-group-replication-on-ubuntu-16-04
  • https://dev.mysql.com/doc/refman/8.0/en/group-replication-options.html#sysvar_group_replication_group_seeds
  • https://bugs.mysql.com/bug.php?id=90534
  • https://www.percona.com/blog/2017/02/24/battle-for-synchronous-replication-in-mysql-galera-vs-group-replication/
  • https://lefred.be/content/mysql-group-replication-is-sweet-but-can-be-sour-if-you-misunderstand-it/
  • https://www.youtube.com/watch?v=IfZK-Up03Mw
  • https://mysqlhighavailability.com/mysql-group-replication-a-quick-start-guide/
  • 2019年6月4日星期二

    Max_connections 214 4.15.0-46-generic#49-Ubuntu

    因此,max_connections從my.cnf文件中設置的值下降到214的問題在Ubuntu上已經存在了一段時間。

    作為一個例子,它在2015年被注意到



    我最近又碰到了這個,並通過以下步驟解決了。


    # cp /lib/systemd/system/mysql.service /etc/systemd/system/
    # cd /etc/systemd/system/
    # vi mysql.service

    LimitNOFILE=infinity
    LimitMEMLOCK=infinity

    # systemctl daemon-reload
    # systemctl restart mysql


    完成這些步驟後,MySQL連接在my.cnf文件中的給定參數處穩定。

    2019年4月15日星期一

    簡單的KeepaliveD設置

    因此,keepalived已經存在了很長一段時間......但是對許多人來說這仍然是一個謎。
    所以這是一個非常簡單的例子,說明keepalived如何與MySQL一起工作。 希望這可以幫助那些有疑問的人。

    我們將有一個簡單的主設備到奴隸設置。 意思是..我們寫一個,除非我們故障轉移到第二個事件。

    1 - 安裝keepalived


    #yum搜索keepalived
    keepalived .x86_64:負載均衡器和高可用性服務

      僅限名稱和摘要匹配,對所有內容使用“全部搜索”。
    #yum -y install keepalived

    你現在應該有一個配置文件

    #ls -ltr /etc/keepalived/keepalived.conf  

    保留原件,因為你總是備份..右....
    #cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.orig

    因此,您需要找出可用於虛擬IP的ipaddress。 我為這個例子選擇了192.168.0.123。

    接下來,我們將設置一個腳本用於我們的新配置文件。

    我在這裡做的一些事情......
    我在/ etc / keepalived中留下了一個.cnf文件,用於keepalived和一個日誌。
    這使得示例變得簡單,因此您可以執行此操作或使用您自己的cnf文件。

    一個腳本:

    cat /etc/keepalived/keepalived_check.sh  
    #!/斌/慶典

    #monitor mysql status

    #如果這個節點mysql死了

    #並且它的奴隸還活著,然後停止它的keepalived。 另一個節點將綁定IP。



    export MYSQL_HOME = / etc / keepalived /

    export PATH = $ MYSQL_HOME / bin:$ PATH



    的MySQL =“/ USR / bin中/ MySQL的”

    中mysqladmin =“的/ usr /斌/中mysqladmin”

    delay_file =“$ MYSQL_HOME / slave_delay_second.log”

    slave_host = $ 1





    ALIVE = $($ mysqladmin --defaults-file = $ MYSQL_HOME / .my.localhost.cnf   ping | grep alive | wc -l);

    REMOTEALIVE = $($ mysqladmin --defaults-file = $ MYSQL_HOME / .my.remotehost.cnf   ping | grep alive | wc -l);



    如果[[$ ALIVE -ne 1]]

    然後

    #echo“MySQL已關閉”

            如果[[$ REMOTEALIVE -eq 1]]

            然後

    #         迴聲“關機保持活力”

                systemctl停止keepalived  

    #       echo“keepalived stop”

            科幻

    #其他

    #echo“MySQL正在上升”

    #日期

    科幻



    退出0 #all done

    新的配置文件

    cat /etc/keepalived/keepalived.conf
    global_defs {



          notification_email {

            anothermysqldba@gmail.com  

          }



          notification_email_from anothermysqldba@gmail.com  

          smtp_server localhost

          smtp_connect_timeout 30



          }







    vrrp_script check_mysql {

       腳本“/etc/keepalived/keepalived_check.sh”

       間隔2

       重量2

    }







    vrrp_instance VI_1 {



          國家MASTER

          接口enp0s8   #<---什麼界面名稱包含您的真實IP / sbin / ifconfig

            #在ip link show中找到

          virtual_router_id 51

          優先級101

          advert_int 1

          nopreempt不同   #僅在較高優先級節點上需要

          認證{

            auth_type PASS

            auth_pass 1111

          }





          track_script {

            check_mysql

          }



          virtual_ipaddress {

            192.168.0.123  

          }




    }



    這一切都很棒但是有效嗎......

    所以我們有2個主機

    [root @ centosa keepalived] #hostname

    centosa

    [root @ centosb keepalived] #hostname
    centosb

    啟動keepalived

    [root @ centosa keepalived] #systemctl status keepalived
    ●keepalived.service - LVS和VRRP高可用性監視器
       已加載:已加載(/usr/lib/systemd/system/keepalived.service;已禁用;供應商預設:已禁用)
       活動:不活動(死機)
    [root @ centosa keepalived] #systemctl restart keepalived
    [root @ centosa keepalived] #systemctl status keepalived
    ● keepalived.service - LVS和VRRP高可用性監視器
       已加載:已加載(/usr/lib/systemd/system/keepalived.service;已禁用;供應商預設:已禁用)
        活動: 活動(運行)

    [root @ centosa keepalived] #ssh 192.168.0.123'hostname'
    root@192.168.0.123的密碼:  

    centosa

    證明連接工作已經完成

    [root @ centosa keepalived] #mysql --defaults-file = .my.remotehost.cnf --host = 192.168.0.101   -e“select @@ hostname”
    + ------------ +
    | @@ hostname |
    + ------------ +
    | centosb     |
    + ------------ +
    [root @ centosa keepalived] #mysql --defaults-file = .my.remotehost.cnf --host = 192.168.0.102   -e“select @@ hostname”
    + ------------ +
    | @@ hostname |
    + ------------ +
    | centosa     |
    + ------------ +

    仔細檢查它是否正在運行......

    [root @ centosa keepalived] #systemctl status keepalived | grep活躍
        活動: 活躍  

    [root @ centosb keepalived] #systemctl status keepalived | grep活躍
        活動: 活躍  

    測試當前VIP ..停止mysql並觀看相同的VIP更改主機...

    [root @ centosa keepalived] #mysql --defaults-file = .my.remotehost.cnf --host = 192.168.0.123   -e“select @@ hostname”
    + ------------ +
    | @@ hostname |
    + ------------ +
    | centosa     |
    + ------------ +
    [root @ centosa keepalived] #systemctl stop mysqld  
    [root @ centosa keepalived] #mysql --defaults-file = .my.remotehost.cnf --host = 192.168.0.123   -e“select @@ hostname”
    + ------------ +
    | @@ hostname |
    + ------------ +
    | centosb     |
    + ------------ +

    2014年12月19日星期五

    一個MySQL分區和SUBPARTITION示例

    Original post: http://anothermysqldba.blogspot.com/2014/12/a-mysql-partition-and-subpartition.html

    因此,這是一個如何建立一個分區和MySQL的一個SUBPARTITION只是一個簡單的例子。 這裡的概念是,你必須在一個時間字段無數值表中的數據。 你可能有分佈在很多年(最有可能的,你做的)數據。 所以這個分區數據的一種方法是通過一年來排序,但隨後也即每年分區內按月份排序。 

    以下是你可以用考慮一個例子。 

    考慮到測試表。 你的表當然有更多的領域。 

    CREATE TABLE `t1` ( 
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `date_time` datetime DEFAULT NOW(), 
    PRIMARY KEY (`id`) 
    ) ENGINE=InnoDB; 


    首先,我將填充測試表隨機值的DATE_TIME領域。 

    delimiter // 
    CREATE PROCEDURE populate_t1( IN rowsofdata INT ) 
    BEGIN 

    SET @A = 1; 
    SET @B = 25 - @A; 

    WHILE rowsofdata > 0 DO 
    SELECT FLOOR( @A + (RAND() * @B )) INTO @randvalue; 
    INSERT INTO t1 
    SELECT NULL, NOW() - INTERVAL @randvalue MONTH; 
    SET rowsofdata = rowsofdata - 1; 
    END WHILE; 
    END// 
    delimiter ; 
    call populate_t1(1000); 


    檢查,看看我結束了什麼樣的價值觀為: 

    > SELECT COUNT(*) FROM t1 WHERE date_time BETWEEN '2012-01-01 00:00:00' AND '2013-01-01 00:00:00'\G 
    *************************** 1. row *************************** 
    COUNT(*): 43 
    1 row in set (0.00 sec) 

    > SELECT COUNT(*) FROM t1 WHERE date_time BETWEEN '2013-01-01 00:00:00' AND '2014-01-01 00:00:00'\G 
    *************************** 1. row *************************** 
    COUNT(*): 529 
    1 row in set (0.00 sec) 

    > SELECT COUNT(*) FROM t1 WHERE date_time BETWEEN '2014-01-01 00:00:00' AND NOW() \G
    *************************** 1. row *************************** 
    COUNT(*): 428 
    1 row in set (0.00 sec) 


    現在,我可以改變表,所以我可以通過分區添加我的分區,然後測試值計數。 

    ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY (`id`,`date_time`), LOCK=SHARED; 
    ALTER TABLE t1 
    PARTITION BY RANGE( YEAR(date_time) ) 
    SUBPARTITION BY HASH(MONTH(date_time) ) ( 

    PARTITION p2012 VALUES LESS THAN (2013) ( 
    SUBPARTITION dec_2012, 
    SUBPARTITION jan_2012, 
    SUBPARTITION feb_2012, 
    SUBPARTITION mar_2012, 
    SUBPARTITION apr_2012, 
    SUBPARTITION may_2012, 
    SUBPARTITION jun_2012, 
    SUBPARTITION jul_2012, 
    SUBPARTITION aug_2012, 
    SUBPARTITION sep_2012, 
    SUBPARTITION oct_2012, 
    SUBPARTITION nov_2012 
    ), 

    PARTITION p2013 VALUES LESS THAN (2014) ( 
    SUBPARTITION dec_2013, 
    SUBPARTITION jan_2013, 
    SUBPARTITION feb_2013, 
    SUBPARTITION mar_2013, 
    SUBPARTITION apr_2013, 
    SUBPARTITION may_2013, 
    SUBPARTITION jun_2013, 
    SUBPARTITION jul_2013, 
    SUBPARTITION aug_2013, 
    SUBPARTITION sep_2013, 
    SUBPARTITION oct_2013, 
    SUBPARTITION nov_2013 

    ), 
    PARTITION p2014 VALUES LESS THAN (2015) ( 
    SUBPARTITION dec_2014, 
    SUBPARTITION jan_2014, 
    SUBPARTITION feb_2014, 
    SUBPARTITION mar_2014, 
    SUBPARTITION apr_2014, 
    SUBPARTITION may_2014, 
    SUBPARTITION jun_2014, 
    SUBPARTITION jul_2014, 
    SUBPARTITION aug_2014, 
    SUBPARTITION sep_2014, 
    SUBPARTITION oct_2014, 
    SUBPARTITION nov_2014 
    ), 

    PARTITION pmax VALUES LESS THAN MAXVALUE ( 
    SUBPARTITION dec_max, 
    SUBPARTITION jan_max, 
    SUBPARTITION feb_max, 
    SUBPARTITION mar_max, 
    SUBPARTITION apr_max, 
    SUBPARTITION may_max, 
    SUBPARTITION jun_max, 
    SUBPARTITION jul_max, 
    SUBPARTITION aug_max, 
    SUBPARTITION sep_max, 
    SUBPARTITION oct_max, 
    SUBPARTITION nov_max 
    ) 
    ); 


    我型我秀創建表非常不同了。 

    > show create table t1; 
    CREATE TABLE `t1` ( 
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `date_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`,`date_time`) 
    ) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=latin1 
    /*!50100 PARTITION BY RANGE ( YEAR(date_time)) 
    SUBPARTITION BY HASH (MONTH(date_time)) 
    (PARTITION p2012 VALUES LESS THAN (2013) 
    (SUBPARTITION dec_2012 ENGINE = InnoDB, 
    SUBPARTITION jan_2012 ENGINE = InnoDB, 
    SUBPARTITION feb_2012 ENGINE = InnoDB, 
    SUBPARTITION mar_2012 ENGINE = InnoDB, 
    SUBPARTITION apr_2012 ENGINE = InnoDB, 
    SUBPARTITION may_2012 ENGINE = InnoDB, 
    SUBPARTITION jun_2012 ENGINE = InnoDB, 
    SUBPARTITION jul_2012 ENGINE = InnoDB, 
    SUBPARTITION aug_2012 ENGINE = InnoDB, 
    SUBPARTITION sep_2012 ENGINE = InnoDB, 
    SUBPARTITION oct_2012 ENGINE = InnoDB, 
    SUBPARTITION nov_2012 ENGINE = InnoDB), 
    PARTITION p2013 VALUES LESS THAN (2014) 
    (SUBPARTITION dec_2013 ENGINE = InnoDB, 
    SUBPARTITION jan_2013 ENGINE = InnoDB, 
    SUBPARTITION feb_2013 ENGINE = InnoDB, 
    SUBPARTITION mar_2013 ENGINE = InnoDB, 
    SUBPARTITION apr_2013 ENGINE = InnoDB, 
    SUBPARTITION may_2013 ENGINE = InnoDB, 
    SUBPARTITION jun_2013 ENGINE = InnoDB, 
    SUBPARTITION jul_2013 ENGINE = InnoDB, 
    SUBPARTITION aug_2013 ENGINE = InnoDB, 
    SUBPARTITION sep_2013 ENGINE = InnoDB, 
    SUBPARTITION oct_2013 ENGINE = InnoDB, 
    SUBPARTITION nov_2013 ENGINE = InnoDB), 
    PARTITION p2014 VALUES LESS THAN (2015) 
    (SUBPARTITION dec_2014 ENGINE = InnoDB, 
    SUBPARTITION jan_2014 ENGINE = InnoDB, 
    SUBPARTITION feb_2014 ENGINE = InnoDB, 
    SUBPARTITION mar_2014 ENGINE = InnoDB, 
    SUBPARTITION apr_2014 ENGINE = InnoDB, 
    SUBPARTITION may_2014 ENGINE = InnoDB, 
    SUBPARTITION jun_2014 ENGINE = InnoDB, 
    SUBPARTITION jul_2014 ENGINE = InnoDB, 
    SUBPARTITION aug_2014 ENGINE = InnoDB, 
    SUBPARTITION sep_2014 ENGINE = InnoDB, 
    SUBPARTITION oct_2014 ENGINE = InnoDB, 
    SUBPARTITION nov_2014 ENGINE = InnoDB), 
    PARTITION pmax VALUES LESS THAN MAXVALUE 
    (SUBPARTITION dec_max ENGINE = InnoDB, 
    SUBPARTITION jan_max ENGINE = InnoDB, 
    SUBPARTITION feb_max ENGINE = InnoDB, 
    SUBPARTITION mar_max ENGINE = InnoDB, 
    SUBPARTITION apr_max ENGINE = InnoDB, 
    SUBPARTITION may_max ENGINE = InnoDB, 
    SUBPARTITION jun_max ENGINE = InnoDB, 
    SUBPARTITION jul_max ENGINE = InnoDB, 
    SUBPARTITION aug_max ENGINE = InnoDB, 
    SUBPARTITION sep_max ENGINE = InnoDB, 
    SUBPARTITION oct_max ENGINE = InnoDB, 
    SUBPARTITION nov_max ENGINE = InnoDB)) 


    所以,我們還能指望我們的價值預期? 

    > SELECT count(*) FROM t1 PARTITION (p2012) \G 
    *************************** 1. row *************************** 
    count(*): 43 
    > SELECT count(*) FROM t1 PARTITION (p2013) \G 
    *************************** 1. row *************************** 
    count(*): 529 
    > SELECT count(*) FROM t1 PARTITION (p2014) \G 
    *************************** 1. row *************************** 
    count(*): 428 


    到目前為止好,所有的價值觀匹配了我們所收到的數量。 所以我們也可以算或每子分區中進行選擇。 


    > SELECT * FROM t1 PARTITION (dec_2012) limit 5; 
    +-----+---------------------+ 
    | id | date_time | 
    +-----+---------------------+ 
    | 59 | 2012-12-19 00:59:57 | 
    | 68 | 2012-12-19 00:59:58 | 
    | 93 | 2012-12-19 00:59:59 | 
    | 105 | 2012-12-19 00:59:59 | 
    | 111 | 2012-12-19 00:59:59 | 
    +-----+---------------------+ 

    > SELECT * FROM t1 PARTITION (jan_2013) limit 5; 
    +-----+---------------------+ 
    | id | date_time | 
    +-----+---------------------+ 
    | 6 | 2013-01-19 00:59:55 | 
    | 29 | 2013-01-19 00:59:56 | 
    | 55 | 2013-01-19 00:59:57 | 
    | 79 | 2013-01-19 00:59:58 | 
    | 100 | 2013-01-19 00:59:59 | 
    +-----+---------------------+ 

    > SELECT * FROM t1 PARTITION (jan_2014) limit 5; 
    +-----+---------------------+ 
    | id | date_time | 
    +-----+---------------------+ 
    | 16 | 2014-01-19 00:59:55 | 
    | 190 | 2014-01-19 01:00:04 | 
    | 191 | 2014-01-19 01:00:04 | 
    | 229 | 2014-01-19 01:00:05 | 
    | 234 | 2014-01-19 01:00:06 | 
    +-----+---------------------+ 

    > SELECT * FROM t1 PARTITION (jun_2014) limit 5; 
    +-----+---------------------+ 
    | id | date_time | 
    +-----+---------------------+ 
    | 13 | 2014-06-19 00:59:55 | 
    | 189 | 2014-06-19 01:00:04 | 
    | 221 | 2014-06-19 01:00:05 | 
    | 222 | 2014-06-19 01:00:05 | 
    | 238 | 2014-06-19 01:00:06 | 
    +-----+---------------------+ 

    > SELECT * FROM t1 PARTITION (dec_2013) limit 5; 
    +-----+---------------------+ 
    | id | date_time | 
    +-----+---------------------+ 
    | 50 | 2013-12-19 00:59:57 | 
    | 74 | 2013-12-19 00:59:58 | 
    | 98 | 2013-12-19 00:59:59 | 
    | 107 | 2013-12-19 00:59:59 | 
    | 167 | 2013-12-19 01:00:02 | 
    +-----+---------------------+ 


    這是偉大的,方便的,但是,當2015年或2016年左右出現什麼情況? 所有這些數據將在PMAX分區。 那麼,我們如何P2014和Pmax的在增加一個新的分區? 

    如果您在PMAX沒有數據,你可以刪除它並添加一個新的分區到年底。 但它也很容易重新組織的分區。 這將需要的PMAX分區,改變成我們新的分區。 


    ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( 
    PARTITION p2015 VALUES LESS THAN (2016) ( 
    SUBPARTITION dec_2015, 
    SUBPARTITION jan_2015, 
    SUBPARTITION feb_2015, 
    SUBPARTITION mar_2015, 
    SUBPARTITION apr_2015, 
    SUBPARTITION may_2015, 
    SUBPARTITION jun_2015, 
    SUBPARTITION jul_2015, 
    SUBPARTITION aug_2015, 
    SUBPARTITION sep_2015, 
    SUBPARTITION oct_2015, 
    SUBPARTITION nov_2015 
    ), 
    PARTITION pmax VALUES LESS THAN MAXVALUE ( 
    SUBPARTITION dec_max, 
    SUBPARTITION jan_max, 
    SUBPARTITION feb_max, 
    SUBPARTITION mar_max, 
    SUBPARTITION apr_max, 
    SUBPARTITION may_max, 
    SUBPARTITION jun_max, 
    SUBPARTITION jul_max, 
    SUBPARTITION aug_max, 
    SUBPARTITION sep_max, 
    SUBPARTITION oct_max, 
    SUBPARTITION nov_max 
    ) 
    ); 


    希望這可以幫助,好運。