<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>数据库 on heyaohua's Blog</title><link>https://blog.heyaohua.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/</link><description>Recent content in 数据库 on heyaohua's Blog</description><image><title>heyaohua's Blog</title><url>https://blog.heyaohua.com/og-image.png</url><link>https://blog.heyaohua.com/og-image.png</link></image><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 09 Oct 2025 12:15:00 +0800</lastBuildDate><atom:link href="https://blog.heyaohua.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/index.xml" rel="self" type="application/rss+xml"/><item><title>MySQL→PostgreSQL 主从架构迁移方案（读写分离版）</title><link>https://blog.heyaohua.com/posts/2025/10/mysql-to-postgresql-migration-rw/</link><pubDate>Thu, 09 Oct 2025 12:15:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2025/10/mysql-to-postgresql-migration-rw/</guid><description>目标：用 PostgreSQL 的 WAL + Streaming Replication 实现“写走主、读走从”，并提供生产可用的高可用与连接层方案，附配置模板与运维脚本示例。适配 PostgreSQL 16/17/18。</description><content:encoded><![CDATA[<blockquote>
<p>目标：用 PostgreSQL 的 WAL + Streaming Replication 实现“写走主、读走从”，并提供生产可用的高可用与连接层方案，附配置模板与运维脚本示例。适配 PostgreSQL 16/17/18。</p>
</blockquote>
<hr>
<h2 id="1-架构总览">1. 架构总览</h2>
<h3 id="11-基础拓扑最小可用">1.1 基础拓扑（最小可用）</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>App(写) ─────────►  Primary(主)
</span></span><span style="display:flex;"><span>                ╲
</span></span><span style="display:flex;"><span>                 ╲ WAL Stream
</span></span><span style="display:flex;"><span>                  ╲
</span></span><span style="display:flex;"><span>App(读) ───────────► Standby1(从)
</span></span><span style="display:flex;"><span>                   ► Standby2(从)
</span></span></code></pre></div><ul>
<li>写请求：直连主库。</li>
<li>读请求：直连从库（或通过中间层，见 §4）。</li>
<li>主从：物理复制（Streaming Replication），异步或半同步可选。</li>
</ul>
<h3 id="12-生产级拓扑推荐">1.2 生产级拓扑（推荐）</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>               +-------------------+
</span></span><span style="display:flex;"><span>               |    pgbouncer      |  连接池（减少连接抖动）
</span></span><span style="display:flex;"><span>               +-------------------+
</span></span><span style="display:flex;"><span>                        │
</span></span><span style="display:flex;"><span>                 +--------------+
</span></span><span style="display:flex;"><span>                 |   Pgpool-II  |  SQL解析级读写分离/健康检查/故障转移脚本
</span></span><span style="display:flex;"><span>                 +--------------+
</span></span><span style="display:flex;"><span>                     │     │
</span></span><span style="display:flex;"><span>                (Write)   (Read)
</span></span><span style="display:flex;"><span>                     │     │
</span></span><span style="display:flex;"><span>                   Primary  ──┬── Standby1
</span></span><span style="display:flex;"><span>                              └── Standby2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        +-------------------+
</span></span><span style="display:flex;"><span>        | Patroni + etcd    |  主从编排/自动故障切换/仲裁
</span></span><span style="display:flex;"><span>        +-------------------+
</span></span></code></pre></div><ul>
<li>可替换 Pgpool-II 为 HAProxy（协议层转发）+ 应用侧读写分离（双 DSN）。</li>
<li>可替换 Patroni 为 repmgr 或手工脚本（风险更高）。</li>
</ul>
<hr>
<h2 id="2-版本与参数基线">2. 版本与参数基线</h2>
<ul>
<li>推荐版本：PostgreSQL 17（当前成熟稳定）或 18（新项目/前瞻特性）。</li>
<li>最小参数：</li>
<li><code>wal_level = replica</code>（或 <code>logical</code> 若需逻辑复制）</li>
<li><code>max_wal_senders</code> ≥ 从库数 + 维护冗余（例如 10）</li>
<li><code>wal_keep_size</code>：按网络/故障时间留足（例如 512MB~2GB）</li>
<li><code>archive_mode = on</code> + <code>archive_command</code>（若做增量备份/回放）</li>
<li>半同步：<code>synchronous_commit = on</code> + <code>synchronous_standby_names = 'FIRST 1 (standby1, standby2)'</code></li>
</ul>
<hr>
<h2 id="3-数据层主从复制配置模板物理复制">3. 数据层：主从复制配置模板（物理复制）</h2>
<h3 id="31-主库-postgresqlconf">3.1 主库 <code>postgresql.conf</code></h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 基础
</span></span><span style="display:flex;"><span>listen_addresses = &#39;*&#39;
</span></span><span style="display:flex;"><span>port = 5432
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 复制/WAL
</span></span><span style="display:flex;"><span>wal_level = replica
</span></span><span style="display:flex;"><span>max_wal_senders = 10
</span></span><span style="display:flex;"><span>max_wal_size = 4GB
</span></span><span style="display:flex;"><span>min_wal_size = 1GB
</span></span><span style="display:flex;"><span>wal_keep_size = 1024MB
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 半同步（可选）
</span></span><span style="display:flex;"><span># synchronous_commit = on
</span></span><span style="display:flex;"><span># synchronous_standby_names = &#39;FIRST 1 (standby1, standby2)&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 性能观测（推荐开启）
</span></span><span style="display:flex;"><span>shared_preload_libraries = &#39;pg_stat_statements&#39;
</span></span><span style="display:flex;"><span>pg_stat_statements.max = 10000
</span></span><span style="display:flex;"><span>pg_stat_statements.track = all
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 归档（如采用 pgBackRest 则由其接管）
</span></span><span style="display:flex;"><span># archive_mode = on
</span></span><span style="display:flex;"><span># archive_command = &#39;test ! -f /var/backup/%f &amp;&amp; cp %p /var/backup/%f&#39;
</span></span></code></pre></div><h3 id="32-主库-pg_hbaconf">3.2 主库 <code>pg_hba.conf</code></h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 允许业务访问
</span></span><span style="display:flex;"><span>host    all             appuser         10.0.0.0/16           scram-sha-256
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 允许复制连接（repl 角色）
</span></span><span style="display:flex;"><span>host    replication     repl            10.0.0.0/16           scram-sha-256
</span></span></code></pre></div><h3 id="33-创建复制用户">3.3 创建复制用户</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">ROLE</span> repl <span style="color:#ff79c6">WITH</span> REPLICATION LOGIN PASSWORD <span style="color:#f1fa8c">&#39;REPLACE_WITH_REPL_PASSWORD&#39;</span>;
</span></span></code></pre></div><h3 id="34-从库基线拉起pg_basebackup">3.4 从库基线拉起（pg_basebackup）</h3>
<blockquote>
<p>在 Standby 节点执行：</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>pg_basebackup -h 10.0.0.10 -p 5432 -U repl \
</span></span><span style="display:flex;"><span>  -D /var/lib/postgresql/17/data -X stream -C -S standby1_slot -R -P
</span></span></code></pre></div><ul>
<li><code>-R</code>：自动写入 <code>standby.signal</code> 与 <code>primary_conninfo</code>。</li>
<li><code>-C -S standby1_slot</code>：自动创建复制槽，防止 WAL 丢失。</li>
<li>多个从库请使用不同 slot 名称：<code>standby2_slot</code> 等。</li>
</ul>
<h3 id="35-启动与验证">3.5 启动与验证</h3>
<ul>
<li>启动从库后，在主库查看：</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> pid, application_name, client_addr, <span style="color:#ff79c6">state</span>, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsn
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">FROM</span> pg_stat_replication;
</span></span></code></pre></div><ul>
<li>从库延迟：</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> now() <span style="color:#ff79c6">-</span> pg_last_xact_replay_timestamp() <span style="color:#ff79c6">AS</span> standby_delay;
</span></span></code></pre></div><h3 id="36-延迟从库防误删回滚保护可选">3.6 延迟从库（防误删回滚保护，可选）</h3>
<p>从库 <code>postgresql.auto.conf</code> 增加：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>recovery_min_apply_delay = &#39;5min&#39;
</span></span></code></pre></div><hr>
<h2 id="4-连接层读写分离方案">4. 连接层：读写分离方案</h2>
<h3 id="41-pgpool-iisql-解析级自动区分读写">4.1 Pgpool-II（SQL 解析级，自动区分读/写）</h3>
<h4 id="核心优点">核心优点</h4>
<ul>
<li>会解析 SQL 并将 SELECT 分发到从库，将 写语句 路由到主库；</li>
<li>内置健康检查、自动跟随主库（<code>follow_primary_command</code>），可脚本化故障切换；</li>
<li>与 pgbouncer 叠加实现“连接池 + 读写分离”。</li>
</ul>
<h4 id="411-pgpoolconf-样例核心片段">4.1.1 <code>pgpool.conf</code> 样例（核心片段）</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 监听
</span></span><span style="display:flex;"><span>listen_addresses = &#39;0.0.0.0&#39;
</span></span><span style="display:flex;"><span>port = 9999
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 后端节点（node_id 从 0 开始）
</span></span><span style="display:flex;"><span>backend_hostname0 = &#39;10.0.0.10&#39;   # primary
</span></span><span style="display:flex;"><span>backend_port0     = 5432
</span></span><span style="display:flex;"><span>backend_weight0   = 1
</span></span><span style="display:flex;"><span>backend_flag0     = &#39;ALWAYS_PRIMARY&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>backend_hostname1 = &#39;10.0.0.11&#39;   # standby1
</span></span><span style="display:flex;"><span>backend_port1     = 5432
</span></span><span style="display:flex;"><span>backend_weight1   = 1
</span></span><span style="display:flex;"><span>backend_flag1     = &#39;ALLOW_TO_FAILOVER&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>backend_hostname2 = &#39;10.0.0.12&#39;   # standby2
</span></span><span style="display:flex;"><span>backend_port2     = 5432
</span></span><span style="display:flex;"><span>backend_weight2   = 1
</span></span><span style="display:flex;"><span>backend_flag2     = &#39;ALLOW_TO_FAILOVER&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 读写分离与负载
</span></span><span style="display:flex;"><span>load_balance_mode = on                 # 允许 SELECT 负载到从库
</span></span><span style="display:flex;"><span>statement_level_load_balance = on      # 语句级平衡（谨慎与事务特性）
</span></span><span style="display:flex;"><span>replication_mode = off                 # 非多主
</span></span><span style="display:flex;"><span>master_slave_mode = on
</span></span><span style="display:flex;"><span>master_slave_sub_mode = &#39;stream&#39;       # Streaming Replication
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 健康检查
</span></span><span style="display:flex;"><span>health_check_period = 5
</span></span><span style="display:flex;"><span>health_check_timeout = 3
</span></span><span style="display:flex;"><span>health_check_user = &#39;pgpool&#39;           # 仅用于健康检查的低权账号
</span></span><span style="display:flex;"><span>health_check_password = &#39;***&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 主从跟随（当主切换时，更新路由）
</span></span><span style="display:flex;"><span>follow_primary_command = &#39;/usr/local/bin/pgpool-follow-primary %d %h %p %D %m %H %M %P %r %R&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 会话保持与函数黑名单（避免副作用语句被当作读）
</span></span><span style="display:flex;"><span>black_function_list = &#39;nextval,setval&#39;
</span></span><span style="display:flex;"><span>white_function_list = &#39;&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 日志
</span></span><span style="display:flex;"><span>log_per_node_statement = off
</span></span><span style="display:flex;"><span>log_statement = off
</span></span></code></pre></div><h4 id="412-pool_hbaconf">4.1.2 <code>pool_hba.conf</code></h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>host    all     all     10.0.0.0/16     scram-sha-256
</span></span></code></pre></div><h4 id="413-pcpconf">4.1.3 <code>pcp.conf</code></h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>admin:SCRAM-SHA-256$&lt;hash&gt;
</span></span></code></pre></div><h4 id="414-典型运维脚本占位">4.1.4 典型运维脚本占位</h4>
<ul>
<li><code>pgpool-follow-primary</code>：当检测到新主库后，自动调整后端主从角色并重载。</li>
<li><code>failover_streaming</code>：在主库失效时，触发预设的 Promote（若未用 Patroni）。</li>
</ul>
<blockquote>
<p>注：Pgpool-II 与 prepared statements / 长事务 叠加时需评估；对强一致读，可将关键读强制走主（应用层或 <code>app_name</code> 路由）。</p>
</blockquote>
<h3 id="42-haproxy--pgbouncer轻量级">4.2 HAProxy + pgbouncer（轻量级）</h3>
<ul>
<li>策略：对应用提供两个 DSN：</li>
<li>写：<code>haproxy-write:5432</code>（仅指向主库或 Patroni 的主 VIP）</li>
<li>读：<code>haproxy-read:5432</code>（轮询多个从库）</li>
<li>HAProxy 核心示例：</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>frontend pg_write
</span></span><span style="display:flex;"><span>  bind *:5000
</span></span><span style="display:flex;"><span>  default_backend pg_primary
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>backend pg_primary
</span></span><span style="display:flex;"><span>  option tcp-check
</span></span><span style="display:flex;"><span>  server primary 10.0.0.10:5432 check
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frontend pg_read
</span></span><span style="display:flex;"><span>  bind *:5001
</span></span><span style="display:flex;"><span>  default_backend pg_standbys
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>backend pg_standbys
</span></span><span style="display:flex;"><span>  balance roundrobin
</span></span><span style="display:flex;"><span>  option tcp-check
</span></span><span style="display:flex;"><span>  server s1 10.0.0.11:5432 check
</span></span><span style="display:flex;"><span>  server s2 10.0.0.12:5432 check
</span></span></code></pre></div><ul>
<li>pgbouncer：建议 transaction 池化模式，注意与 <code>server_reset_query</code> 配置，避免事务泄漏。</li>
</ul>
<hr>
<h2 id="5-高可用patroni--etcd推荐">5. 高可用：Patroni + etcd（推荐）</h2>
<h3 id="51-部署要点">5.1 部署要点</h3>
<ul>
<li>各节点运行 Patroni，使用 etcd（或 Consul）存储集群状态；</li>
<li>Patroni 负责：</li>
<li>主从编排、健康检查、自动 promote；</li>
<li>维护 <code>postgresql.conf</code> 与复制参数；</li>
<li>提供 REST API（供 HAProxy/keepalived 识别主）。</li>
</ul>
<h3 id="52-patroni-样例配置etcpatronipg01yml">5.2 Patroni 样例配置（<code>/etc/patroni/pg01.yml</code>）</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>scope: pg-cluster
</span></span><span style="display:flex;"><span>name: pg01
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>restapi:
</span></span><span style="display:flex;"><span>  listen: 0.0.0.0:8008
</span></span><span style="display:flex;"><span>  connect_address: 10.0.0.10:8008
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>etcd:
</span></span><span style="display:flex;"><span>  hosts: 10.0.0.20:2379,10.0.0.21:2379,10.0.0.22:2379
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>postgresql:
</span></span><span style="display:flex;"><span>  listen: 0.0.0.0:5432
</span></span><span style="display:flex;"><span>  connect_address: 10.0.0.10:5432
</span></span><span style="display:flex;"><span>  data_dir: /var/lib/postgresql/17/data
</span></span><span style="display:flex;"><span>  bin_dir: /usr/lib/postgresql/17/bin
</span></span><span style="display:flex;"><span>  parameters:
</span></span><span style="display:flex;"><span>    wal_level: replica
</span></span><span style="display:flex;"><span>    max_wal_senders: 10
</span></span><span style="display:flex;"><span>    wal_keep_size: 1024MB
</span></span><span style="display:flex;"><span>    shared_preload_libraries: pg_stat_statements
</span></span><span style="display:flex;"><span>  authentication:
</span></span><span style="display:flex;"><span>    replication:
</span></span><span style="display:flex;"><span>      username: repl
</span></span><span style="display:flex;"><span>      password: REPLACE_WITH_REPL_PASSWORD
</span></span><span style="display:flex;"><span>    superuser:
</span></span><span style="display:flex;"><span>      username: postgres
</span></span><span style="display:flex;"><span>      password: REPLACE_WITH_SUPERUSER_PASSWORD
</span></span><span style="display:flex;"><span>  pg_hba:
</span></span><span style="display:flex;"><span>  - host all all 0.0.0.0/0 scram-sha-256
</span></span><span style="display:flex;"><span>  - host replication repl 0.0.0.0/0 scram-sha-256
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>synchronous_mode: false   # 如需半同步置 true，并配置 standby 优先级
</span></span></code></pre></div><ul>
<li>其他节点将 <code>name</code> 与 <code>connect_address</code> 对应修改即可。</li>
</ul>
<h3 id="53-与-haproxy-集成识别主">5.3 与 HAProxy 集成（识别主）</h3>
<p>HAProxy 可基于 Patroni REST 的 <code>/master</code> endpoint 进行后端切换，或以 tag 端口代理当前主。</p>
<hr>
<h2 id="6-运维脚本与常见操作">6. 运维脚本与常见操作</h2>
<h3 id="61-手工主从切换无-patroni-场景">6.1 手工主从切换（无 Patroni 场景）</h3>
<ol>
<li>在待升主的从库执行 Promote：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>pg_ctl -D /var/lib/postgresql/17/data promote
</span></span></code></pre></div><ol>
<li>调整应用/中间件连接到新主。</li>
<li>原主修复后以从库身份重拉：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>pg_ctl -D /var/lib/postgresql/17/data stop
</span></span><span style="display:flex;"><span>rm -rf /var/lib/postgresql/17/data/*
</span></span><span style="display:flex;"><span>pg_basebackup -h NEW_PRIMARY -U repl -D /var/lib/postgresql/17/data -X stream -R -P -C -S oldprimary_slot
</span></span><span style="display:flex;"><span>pg_ctl -D /var/lib/postgresql/17/data start
</span></span></code></pre></div><h3 id="62-创建查看复制槽">6.2 创建/查看复制槽</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 创建逻辑槽（如需逻辑复制）
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> <span style="color:#ff79c6">*</span> <span style="color:#ff79c6">FROM</span> pg_create_logical_replication_slot(<span style="color:#f1fa8c">&#39;app_slot&#39;</span>, <span style="color:#f1fa8c">&#39;pgoutput&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 查看复制槽
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> slot_name, slot_type, active, restart_lsn <span style="color:#ff79c6">FROM</span> pg_replication_slots;
</span></span></code></pre></div><h3 id="63-只读事务强一致读在主库">6.3 只读事务（强一致读在主库）</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">BEGIN</span> <span style="color:#ff79c6">READ</span> <span style="color:#ff79c6">ONLY</span>;  <span style="color:#6272a4">-- 强制在主库读（通过路由或角色策略）
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> ...;
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">COMMIT</span>;
</span></span></code></pre></div><hr>
<h2 id="7-监控与告警">7. 监控与告警</h2>
<h3 id="71-关键视图">7.1 关键视图</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 主库查看复制
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> <span style="color:#ff79c6">*</span> <span style="color:#ff79c6">FROM</span> pg_stat_replication;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- WAL 生成量
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> date_trunc(<span style="color:#f1fa8c">&#39;hour&#39;</span>, now()) <span style="color:#ff79c6">AS</span> ts,
</span></span><span style="display:flex;"><span>       pg_wal_lsn_diff(pg_current_wal_lsn(), <span style="color:#f1fa8c">&#39;0/0&#39;</span>)<span style="color:#ff79c6">/</span><span style="color:#bd93f9">1024</span><span style="color:#ff79c6">/</span><span style="color:#bd93f9">1024</span><span style="color:#ff79c6">/</span><span style="color:#bd93f9">1024</span> <span style="color:#ff79c6">AS</span> wal_gb;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 从库延迟
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> now() <span style="color:#ff79c6">-</span> pg_last_xact_replay_timestamp() <span style="color:#ff79c6">AS</span> standby_delay;
</span></span></code></pre></div><h3 id="72-prometheus-exporter建议">7.2 Prometheus Exporter（建议）</h3>
<ul>
<li><code>postgres_exporter</code>：抓取一般指标</li>
<li><code>pgbouncer_exporter</code>、<code>pgpool2_exporter</code>（若使用）</li>
<li>告警建议：</li>
<li><code>standby_delay &gt; 5s/30s/60s</code> 分级；</li>
<li><code>replication_state != streaming</code></li>
<li><code>replication_slot_inactive</code> &amp; WAL 堆积</li>
</ul>
<hr>
<h2 id="8-备份与恢复">8. 备份与恢复</h2>
<h3 id="81-工具选型">8.1 工具选型</h3>
<ul>
<li>pgBackRest（推荐）：全量/增量/差异、并行、校验、保留策略、S3 对接；</li>
<li><code>pg_basebackup</code> + WAL 归档：适合轻量场景。</li>
</ul>
<h3 id="82-pgbackrest-最小配置示例片段">8.2 pgBackRest 最小配置示例（片段）</h3>
<p><code>/etc/pgbackrest/pgbackrest.conf</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>[global]
</span></span><span style="display:flex;"><span>repo<span style="color:#bd93f9">1</span>-path=/var/lib/pgbackrest
</span></span><span style="display:flex;"><span>repo<span style="color:#bd93f9">1</span>-retention-full=<span style="color:#bd93f9">7</span>
</span></span><span style="display:flex;"><span>start-fast=y
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[pg]
</span></span><span style="display:flex;"><span>pg<span style="color:#bd93f9">1</span>-path=/var/lib/postgresql/<span style="color:#bd93f9">17</span>/data
</span></span><span style="display:flex;"><span>pg<span style="color:#bd93f9">1</span>-port=<span style="color:#bd93f9">5432</span>
</span></span></code></pre></div><ul>
<li>调度：<code>pgbackrest backup --type=full|diff|incr</code></li>
<li>恢复：<code>pgbackrest restore --type=time --target='2025-10-08 12:00:00'</code></li>
</ul>
<hr>
<h2 id="9-逻辑复制可选按表级跨版本">9. 逻辑复制（可选：按表级/跨版本）</h2>
<h3 id="91-主库发布publication">9.1 主库发布（publication）</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> PUBLICATION mypub <span style="color:#ff79c6">FOR</span> <span style="color:#ff79c6">TABLE</span> <span style="color:#ff79c6">public</span>.users, <span style="color:#ff79c6">public</span>.orders;
</span></span></code></pre></div><h3 id="92-从库订阅subscription">9.2 从库订阅（subscription）</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> SUBSCRIPTION mysub
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">CONNECTION</span> <span style="color:#f1fa8c">&#39;host=10.0.0.10 dbname=app user=repl password=REPLACE_WITH_REPL_PASSWORD&#39;</span>
</span></span><span style="display:flex;"><span>  PUBLICATION mypub;
</span></span></code></pre></div><blockquote>
<p>适用：选择性同步、跨版本/异构聚合、CDC 下游（Kafka/ETL）。</p>
</blockquote>
<hr>
<h2 id="10-应用侧改造要点从-mysql-迁移">10. 应用侧改造要点（从 MySQL 迁移）</h2>
<ul>
<li>自增主键：改为 <code>GENERATED BY DEFAULT AS IDENTITY</code>；</li>
<li>UPSERT：<code>INSERT ... ON CONFLICT (key) DO UPDATE</code>；</li>
<li>读写分离：强一致读上主（关键交易/下单等），弱一致读走从；</li>
<li>事务隔离：PostgreSQL 默认 <code>READ COMMITTED</code>，必要时用 <code>REPEATABLE READ</code>；</li>
<li>SQL 差异：<code>LIMIT/OFFSET</code>、<code>BOOLEAN</code>、<code>text/varchar</code>、<code>ILIKE</code> 等；</li>
<li>连接池：强烈建议使用 pgbouncer（transaction 模式）。</li>
</ul>
<hr>
<h2 id="11-交付清单可直接使用改造">11. 交付清单（可直接使用/改造）</h2>
<ul>
<li>数据层：<code>postgresql.conf</code>、<code>pg_hba.conf</code> 基线模板（§3）</li>
<li>初始化：<code>pg_basebackup</code> 命令（§3.4）</li>
<li>验证脚本：<code>pg_stat_replication</code>/延迟检查 SQL（§3.5、§7）</li>
<li>中间层：Pgpool-II 样例（§4.1）或 HAProxy 样例（§4.2）</li>
<li>高可用：Patroni 示例（§5.2）</li>
<li>故障切换：Promote/重拉流程（§6.1）</li>
<li>备份：pgBackRest 样例（§8.2）</li>
</ul>
<hr>
<h2 id="12-风险与最佳实践">12. 风险与最佳实践</h2>
<ul>
<li>WAL 保留不足：务必使用复制槽或足够的 <code>wal_keep_size</code>，防止从库追不上；</li>
<li>读写错路由：关键读务必走主；Pgpool 解析有边界，建议灰度与压测；</li>
<li>长事务：阻塞 VACUUM，导致膨胀与复制延迟；监控 <code>pg_stat_activity</code>；</li>
<li>半同步权衡：开启会增加写延迟；金融交易强一致可 <code>FIRST 1</code> 策略；</li>
<li>备份演练：每季度至少一次异地恢复演练；</li>
<li>版本升级：用 <code>pg_upgrade --check</code> 预检测，读 release notes。</li>
</ul>
<hr>
<h2 id="13-附docker-compose演示用">13. 附：Docker Compose（演示用）</h2>
<blockquote>
<p>仅供演示，生产请改为有状态存储 + 独立网络与安全策略。</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">version</span>: <span style="color:#f1fa8c">&#39;3.8&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">primary</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">image</span>: postgres:17
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">POSTGRES_PASSWORD</span>: REPLACE_WITH_SUPERUSER_PASSWORD
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f1fa8c">&#39;5432:5432&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>      - primary_data:/var/lib/postgresql/data
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">standby1</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">image</span>: postgres:17
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">depends_on</span>:
</span></span><span style="display:flex;"><span>      - primary
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">POSTGRES_PASSWORD</span>: REPLACE_WITH_SUPERUSER_PASSWORD
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">command</span>: &gt;<span style="color:#f1fa8c">
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">      bash -lc &#34;pg_basebackup -h primary -U postgres -D /var/lib/postgresql/data -R -P &amp;&amp; docker-entrypoint.sh postgres&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>      - standby1_data:/var/lib/postgresql/data
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">primary_data</span>: {}
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">standby1_data</span>: {}
</span></span></code></pre></div><hr>
<h3 id="结语">结语</h3>
<p>本方案覆盖“写主读从”的完整链路：复制 → 连接层 → 高可用 → 备份 → 监控。可按你现网规模裁剪。如需，我可以基于你的主机清单/网段/端口策略，生成一套可直接上线的配置包（含脚本与 Ansible 角色）。</p>
]]></content:encoded></item><item><title>PostgreSQL Docker 部署常见问题与解决方案</title><link>https://blog.heyaohua.com/posts/2025/10/postgresql-docker-faq/</link><pubDate>Thu, 09 Oct 2025 12:05:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2025/10/postgresql-docker-faq/</guid><description>汇总在使用 Docker 部署 PostgreSQL（含 PostGIS、pgvector、TimescaleDB）过程中常见的问题及可操作的解决方案，涵盖构建、扩展、连接、权限、性能与数据等方面。</description><content:encoded><![CDATA[<p>汇总在使用 Docker 部署 PostgreSQL（含 PostGIS、pgvector、TimescaleDB）过程中常见的问题及可操作的解决方案，涵盖构建、扩展、连接、权限、性能与数据等方面。</p>
<hr>
<h2 id="目录">目录</h2>
<ul>
<li>构建问题</li>
<li>扩展问题</li>
<li>连接问题</li>
<li>权限问题</li>
<li>性能问题</li>
<li>数据问题</li>
<li>调试技巧</li>
<li>预防措施</li>
<li>获取帮助</li>
</ul>
<hr>
<h2 id="构建问题">构建问题</h2>
<h3 id="q1-docker-构建时出现-lsb_release-command-not-found">Q1: Docker 构建时出现 &ldquo;lsb_release: command not found&rdquo;</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>/bin/sh: 1: lsb_release: command not found
</span></span><span style="display:flex;"><span>/bin/sh: 1: apt-key: command not found
</span></span></code></pre></div><p>原因分析：
在 Debian/Ubuntu 基础镜像中，<code>lsb_release</code> 和 <code>apt-key</code> 命令可能不存在或已被弃用。</p>
<p>解决方案：改用从源码编译的方式安装 TimescaleDB：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 不使用包管理器安装，改为源码编译</span>
</span></span><span style="display:flex;"><span>RUN <span style="color:#8be9fd;font-style:italic">cd</span> /tmp <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    git clone https://github.com/timescale/timescaledb.git <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">cd</span> timescaledb <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    git checkout 2.13.0 <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    ./bootstrap <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">cd</span> build <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make install
</span></span></code></pre></div><h3 id="q2-编译时出现-gssapigssapih-no-such-file-or-directory">Q2: 编译时出现 &ldquo;gssapi/gssapi.h: No such file or directory&rdquo;</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>fatal error: gssapi/gssapi.h: No such file or directory
</span></span></code></pre></div><p>原因分析：缺少 GSSAPI 开发库，TimescaleDB 编译需要 Kerberos 相关依赖。</p>
<p>解决方案：在 Dockerfile 中添加必要的依赖包：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>RUN apt-get update <span style="color:#ff79c6">&amp;&amp;</span> apt-get install -y <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    build-essential <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    postgresql-server-dev-15 <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    cmake <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    git <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    wget <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    ca-certificates <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    libkrb5-dev <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    libgssapi-krb5-2 <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">&amp;&amp;</span> rm -rf /var/lib/apt/lists/*
</span></span></code></pre></div><hr>
<h2 id="扩展问题">扩展问题</h2>
<h3 id="q3-pgvector-出现段错误-segmentation-fault">Q3: pgvector 出现段错误 (Segmentation Fault)</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>server closed the connection unexpectedly
</span></span><span style="display:flex;"><span>This probably means the server terminated abnormally
</span></span><span style="display:flex;"><span>before or while processing the request.
</span></span></code></pre></div><p>原因分析：</p>
<ul>
<li>pgvector 最新版本可能与 PostgreSQL 15 存在兼容性问题</li>
<li>编译环境或依赖版本不匹配</li>
</ul>
<p>解决方案：使用稳定的预编译版本：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 使用 pgvector 0.5.1 版本，避免段错误</span>
</span></span><span style="display:flex;"><span>RUN <span style="color:#8be9fd;font-style:italic">cd</span> /tmp <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    wget https://github.com/pgvector/pgvector/archive/v0.5.1.tar.gz <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    tar -xzf v0.5.1.tar.gz <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">cd</span> pgvector-0.5.1 <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make install
</span></span></code></pre></div><h3 id="q4-timescaledb-扩展创建失败">Q4: TimescaleDB 扩展创建失败</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">ERROR</span>: could not load library &#34;timescaledb&#34;:
</span></span><span style="display:flex;"><span>shared_preload_libraries not configured
</span></span></code></pre></div><p>原因分析：TimescaleDB 需要在 PostgreSQL 启动时预加载。</p>
<p>解决方案：在 Dockerfile 中配置预加载库：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>RUN echo &#34;shared_preload_libraries = &#39;timescaledb&#39;&#34; &gt;&gt; /usr/share/postgresql/postgresql.conf.sample
</span></span></code></pre></div><h3 id="q5-postgis-扩展版本不匹配">Q5: PostGIS 扩展版本不匹配</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">ERROR</span>: extension &#34;postgis&#34; has no installation candidate
</span></span></code></pre></div><p>原因分析：PostgreSQL 版本与 PostGIS 包版本不匹配。</p>
<p>解决方案：明确指定对应版本的包：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>RUN apt-get install -y \
</span></span><span style="display:flex;"><span>    postgresql-15-postgis-3 \
</span></span><span style="display:flex;"><span>    postgresql-15-postgis-3-scripts
</span></span></code></pre></div><hr>
<h2 id="连接问题">连接问题</h2>
<h3 id="q6-ide-连接提示-connection-refused">Q6: IDE 连接提示 &ldquo;Connection refused&rdquo;</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>connection to server at &#34;localhost&#34; (::1), port 5432 failed: Connection refused
</span></span></code></pre></div><p>原因分析：</p>
<ul>
<li>端口映射不正确</li>
<li>服务未完全启动</li>
<li>防火墙阻止连接</li>
</ul>
<p>解决方案：</p>
<ol>
<li>检查端口映射：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker port postgres-all-extensions
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 应该显示: 5432/tcp -&gt; 0.0.0.0:5432</span>
</span></span></code></pre></div><ol>
<li>确认服务状态：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker ps
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 检查容器是否正常运行</span>
</span></span></code></pre></div><ol>
<li>等待服务完全启动：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker logs postgres-all-extensions
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看启动日志，确认数据库已就绪</span>
</span></span></code></pre></div><h3 id="q7-密码认证失败">Q7: 密码认证失败</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">FATAL</span>: password authentication failed for user &#34;postgres&#34;
</span></span></code></pre></div><p>原因分析：</p>
<ul>
<li>数据目录已存在，使用了旧密码初始化</li>
<li>环境变量未正确加载</li>
<li>pg_hba.conf 配置问题</li>
</ul>
<p>解决方案：</p>
<ol>
<li>清理旧数据重新初始化：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose down
</span></span><span style="display:flex;"><span>sudo rm -rf ./data/pgdata/*
</span></span><span style="display:flex;"><span>docker-compose up -d
</span></span></code></pre></div><ol>
<li>检查环境变量：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> postgres-all-extensions env | grep POSTGRES
</span></span></code></pre></div><ol>
<li>验证 .env 文件格式：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 确保 .env 文件在正确位置且格式正确
</span></span><span style="display:flex;"><span>POSTGRES_PASSWORD=your_password
</span></span></code></pre></div><hr>
<h2 id="权限问题">权限问题</h2>
<h3 id="q8-数据目录权限错误">Q8: 数据目录权限错误</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>initdb: error: could not create directory &#34;/var/lib/postgresql/data&#34;: Permission denied
</span></span></code></pre></div><p>原因分析：宿主机目录权限不正确，PostgreSQL 容器无法写入。</p>
<p>解决方案：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 修改目录权限</span>
</span></span><span style="display:flex;"><span>sudo chown -R 999:999 ./data/pgdata
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 或者删除目录让 Docker 自动创建</span>
</span></span><span style="display:flex;"><span>sudo rm -rf ./data/pgdata
</span></span></code></pre></div><h3 id="q9-配置文件权限问题">Q9: 配置文件权限问题</h3>
<p>问题描述：容器启动时无法读取配置文件。</p>
<p>解决方案：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 确保配置文件可读
</span></span><span style="display:flex;"><span>chmod 644 config/postgresql.conf
</span></span><span style="display:flex;"><span>chmod 644 config/pg_hba.conf
</span></span></code></pre></div><hr>
<h2 id="性能问题">性能问题</h2>
<h3 id="q10-容器启动缓慢">Q10: 容器启动缓慢</h3>
<p>问题描述：Docker 容器启动时间过长。</p>
<p>原因分析：</p>
<ul>
<li>数据库初始化需要时间</li>
<li>扩展安装和配置耗时</li>
<li>系统资源不足</li>
</ul>
<p>解决方案：</p>
<ol>
<li>增加启动等待时间：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 等待更长时间再进行连接测试
</span></span><span style="display:flex;"><span>sleep 15 &amp;&amp; docker exec postgres-all-extensions psql -U postgres -c &#34;SELECT 1;&#34;
</span></span></code></pre></div><ol>
<li>优化 Docker 资源分配：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 在 docker-compose.yml 中添加资源限制
</span></span><span style="display:flex;"><span>deploy:
</span></span><span style="display:flex;"><span>  resources:
</span></span><span style="display:flex;"><span>    limits:
</span></span><span style="display:flex;"><span>      memory: 2G
</span></span><span style="display:flex;"><span>    reservations:
</span></span><span style="display:flex;"><span>      memory: 1G
</span></span></code></pre></div><h3 id="q11-查询性能差">Q11: 查询性能差</h3>
<p>问题描述：数据库查询响应缓慢。</p>
<p>解决方案：</p>
<ol>
<li>调整 PostgreSQL 配置：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 增加共享缓冲区
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">ALTER</span> <span style="color:#ff79c6">SYSTEM</span> <span style="color:#ff79c6">SET</span> shared_buffers <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;256MB&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 调整工作内存
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">ALTER</span> <span style="color:#ff79c6">SYSTEM</span> <span style="color:#ff79c6">SET</span> work_mem <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;4MB&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 重载配置
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> pg_reload_conf();
</span></span></code></pre></div><ol>
<li>创建适当的索引：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 为向量查询创建索引
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">INDEX</span> <span style="color:#ff79c6">ON</span> items <span style="color:#ff79c6">USING</span> ivfflat (embedding vector_cosine_ops);
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 为时序数据创建索引
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">INDEX</span> <span style="color:#ff79c6">ON</span> sensor_data (time <span style="color:#ff79c6">DESC</span>);
</span></span></code></pre></div><hr>
<h2 id="数据问题">数据问题</h2>
<h3 id="q12-数据持久化失败">Q12: 数据持久化失败</h3>
<p>问题描述：容器重启后数据丢失。</p>
<p>原因分析：</p>
<ul>
<li>卷映射配置错误</li>
<li>数据目录路径不正确</li>
</ul>
<p>解决方案：确认 docker-compose.yml 中的卷配置：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>volumes:
</span></span><span style="display:flex;"><span>  - ./data/pgdata:/var/lib/postgresql/data
</span></span></code></pre></div><h3 id="q13-数据库版本不兼容">Q13: 数据库版本不兼容</h3>
<p>问题描述：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">FATAL</span>: database files are incompatible with server
</span></span></code></pre></div><p>原因分析：数据目录由不同版本的 PostgreSQL 创建。</p>
<p>解决方案：</p>
<ol>
<li>备份数据：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> postgres-old pg_dumpall -U postgres &gt; backup.sql
</span></span></code></pre></div><ol>
<li>清理数据目录：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo rm -rf ./data/pgdata/*
</span></span></code></pre></div><ol>
<li>重新启动并恢复：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose up -d
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 等待启动完成后</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> -i postgres-all-extensions psql -U postgres &lt; backup.sql
</span></span></code></pre></div><hr>
<h2 id="调试技巧">调试技巧</h2>
<h3 id="查看详细日志">查看详细日志</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 查看容器日志</span>
</span></span><span style="display:flex;"><span>docker logs postgres-all-extensions -f
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看 PostgreSQL 日志</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> postgres-all-extensions tail -f /var/log/postgresql/postgresql.log
</span></span></code></pre></div><h3 id="进入容器调试">进入容器调试</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 进入容器</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> -it postgres-all-extensions bash
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看进程状态</span>
</span></span><span style="display:flex;"><span>ps aux | grep postgres
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 检查扩展安装</span>
</span></span><span style="display:flex;"><span>psql -U postgres -c <span style="color:#f1fa8c">&#34;\dx&#34;</span>
</span></span></code></pre></div><h3 id="网络连接测试">网络连接测试</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 测试端口连通性</span>
</span></span><span style="display:flex;"><span>telnet localhost <span style="color:#bd93f9">5432</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 使用 Docker 网络测试</span>
</span></span><span style="display:flex;"><span>docker run --rm --network host postgres:15 pg_isready -h localhost -p <span style="color:#bd93f9">5432</span>
</span></span></code></pre></div><hr>
<h2 id="预防措施">预防措施</h2>
<ol>
<li>定期备份：建立自动化备份策略</li>
<li>监控日志：定期检查错误日志</li>
<li>版本管理：记录使用的具体版本号</li>
<li>测试环境：在生产部署前充分测试</li>
<li>文档更新：及时更新配置和问题解决方案</li>
</ol>
<hr>
<h2 id="获取帮助">获取帮助</h2>
<p>如遇到本文未涵盖的问题：</p>
<ol>
<li>查看官方文档：</li>
<li>PostgreSQL 官方文档</li>
<li>PostGIS 文档</li>
<li>pgvector GitHub</li>
<li></li>
</ol>
<p>TimescaleDB 文档</p>
<ol start="6">
<li></li>
</ol>
<p>社区支持：</p>
<ol start="7">
<li>PostgreSQL 邮件列表</li>
<li>Stack Overflow</li>
<li></li>
</ol>
<p>GitHub Issues</p>
<ol start="10">
<li></li>
</ol>
<p>日志分析：</p>
<ol start="11">
<li>详细记录错误信息</li>
<li>提供完整的错误日志</li>
<li>说明环境配置信息</li>
</ol>
]]></content:encoded></item><item><title>PostgreSQL Docker 部署指南</title><link>https://blog.heyaohua.com/posts/2025/10/postgresql-docker-deployment-guide/</link><pubDate>Thu, 09 Oct 2025 12:00:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2025/10/postgresql-docker-deployment-guide/</guid><description>本指南详细介绍如何使用 Docker 部署一个包含 PostGIS、pgvector 和 TimescaleDB 扩展的 PostgreSQL 15 数据库。该方案解决了扩展兼容性问题，特别是 pgvector 的段错误问题。</description><content:encoded><![CDATA[<p>本指南详细介绍如何使用 Docker 部署一个包含 PostGIS、pgvector 和 TimescaleDB 扩展的 PostgreSQL 15 数据库。该方案解决了扩展兼容性问题，特别是 pgvector 的段错误问题。</p>
<h2 id="项目结构">项目结构</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>PgSQL/
</span></span><span style="display:flex;"><span>├── .env                          # 环境变量配置
</span></span><span style="display:flex;"><span>├── Dockerfile                    # PostgreSQL 镜像构建文件
</span></span><span style="display:flex;"><span>├── docker-compose.yml            # Docker Compose 配置
</span></span><span style="display:flex;"><span>├── README.md                     # 项目说明
</span></span><span style="display:flex;"><span>├── config/                       # 配置文件目录
</span></span><span style="display:flex;"><span>│   ├── pg_hba.conf              # 客户端认证配置
</span></span><span style="display:flex;"><span>│   └── postgresql.conf          # PostgreSQL 主配置
</span></span><span style="display:flex;"><span>├── data/                        # 数据持久化目录
</span></span><span style="display:flex;"><span>│   └── pgdata/                  # PostgreSQL 数据目录
</span></span><span style="display:flex;"><span>├── init-scripts/                # 初始化脚本
</span></span><span style="display:flex;"><span>│   └── 01-install-extensions.sql # 扩展安装脚本
</span></span><span style="display:flex;"><span>├── logs/                        # 日志目录
</span></span><span style="display:flex;"><span>└── test-examples.sql            # 测试示例
</span></span></code></pre></div><h2 id="快速开始">快速开始</h2>
<h3 id="1-环境准备">1. 环境准备</h3>
<p>确保系统已安装：</p>
<ul>
<li>Docker</li>
<li>Docker Compose</li>
</ul>
<h3 id="2-克隆或创建项目目录">2. 克隆或创建项目目录</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir -p ~/Server/PgSQL
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">cd</span> ~/Server/PgSQL
</span></span></code></pre></div><h3 id="3-配置环境变量">3. 配置环境变量</h3>
<p>创建 <code>.env</code> 文件：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># PostgreSQL 数据库配置
</span></span><span style="display:flex;"><span>POSTGRES_DB=devdb
</span></span><span style="display:flex;"><span>POSTGRES_USER=postgres
</span></span><span style="display:flex;"><span>POSTGRES_PASSWORD=your_secure_password
</span></span><span style="display:flex;"><span>POSTGRES_PORT=5432
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 注意：请修改 POSTGRES_PASSWORD 为您的实际密码
</span></span><span style="display:flex;"><span># 建议使用强密码，包含大小写字母、数字和特殊字符
</span></span></code></pre></div><h3 id="4-构建镜像">4. 构建镜像</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker build -t postgres-all-extensions:latest .
</span></span></code></pre></div><h3 id="5-启动服务">5. 启动服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose up -d
</span></span></code></pre></div><h3 id="6-验证安装">6. 验证安装</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 检查容器状态</span>
</span></span><span style="display:flex;"><span>docker ps
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 连接数据库验证扩展</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> postgres-all-extensions psql -U postgres -d devdb -c <span style="color:#f1fa8c">&#34;SELECT extname, extversion FROM pg_extension WHERE extname IN (&#39;timescaledb&#39;, &#39;postgis&#39;, &#39;vector&#39;) ORDER BY extname;&#34;</span>
</span></span></code></pre></div><h2 id="详细配置说明">详细配置说明</h2>
<h3 id="dockerfile-解析">Dockerfile 解析</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>FROM postgres:15
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 安装系统依赖</span>
</span></span><span style="display:flex;"><span>RUN apt-get update <span style="color:#ff79c6">&amp;&amp;</span> apt-get install -y <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    build-essential <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    postgresql-server-dev-15 <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    cmake <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    git <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    wget <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    ca-certificates <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    postgresql-15-postgis-3 <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    postgresql-15-postgis-3-scripts <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    libkrb5-dev <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    libgssapi-krb5-2 <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">&amp;&amp;</span> rm -rf /var/lib/apt/lists/*
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 安装 pgvector (预编译版本，避免段错误)</span>
</span></span><span style="display:flex;"><span>RUN <span style="color:#8be9fd;font-style:italic">cd</span> /tmp <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    wget https://github.com/pgvector/pgvector/archive/v0.5.1.tar.gz <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    tar -xzf v0.5.1.tar.gz <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">cd</span> pgvector-0.5.1 <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make install
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 安装 TimescaleDB (从源码编译)</span>
</span></span><span style="display:flex;"><span>RUN <span style="color:#8be9fd;font-style:italic">cd</span> /tmp <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    git clone https://github.com/timescale/timescaledb.git <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">cd</span> timescaledb <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    git checkout 2.13.0 <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    ./bootstrap <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">cd</span> build <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make <span style="color:#ff79c6">&amp;&amp;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>    make install
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 配置 PostgreSQL</span>
</span></span><span style="display:flex;"><span>RUN <span style="color:#8be9fd;font-style:italic">echo</span> <span style="color:#f1fa8c">&#34;shared_preload_libraries = &#39;timescaledb&#39;&#34;</span> &gt;&gt; /usr/share/postgresql/postgresql.conf.sample
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 复制初始化脚本</span>
</span></span><span style="display:flex;"><span>COPY init-scripts/ /docker-entrypoint-initdb.d/
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXPOSE <span style="color:#bd93f9">5432</span>
</span></span></code></pre></div><h3 id="docker-compose-配置">Docker Compose 配置</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">version</span>: <span style="color:#f1fa8c">&#39;3.8&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">postgres-all-extensions</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">image</span>: postgres-all-extensions:latest
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">container_name</span>: postgres-all-extensions
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">POSTGRES_DB</span>: ${POSTGRES_DB}
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">POSTGRES_USER</span>: ${POSTGRES_USER}
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">POSTGRES_PASSWORD</span>: ${POSTGRES_PASSWORD}
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f1fa8c">&#34;5432:5432&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>      - ./data/pgdata:/var/lib/postgresql/data
</span></span><span style="display:flex;"><span>      - ./config/postgresql.conf:/etc/postgresql/postgresql.conf
</span></span><span style="display:flex;"><span>      - ./config/pg_hba.conf:/etc/postgresql/pg_hba.conf
</span></span><span style="display:flex;"><span>      - ./logs:/var/log/postgresql
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">networks</span>:
</span></span><span style="display:flex;"><span>      - postgres-network
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">restart</span>: unless-stopped
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">healthcheck</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">test</span>: [<span style="color:#f1fa8c">&#34;CMD-SHELL&#34;</span>, <span style="color:#f1fa8c">&#34;pg_isready -U postgres&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">interval</span>: 30s
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">timeout</span>: 10s
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">retries</span>: <span style="color:#bd93f9">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">networks</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">postgres-network</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">driver</span>: bridge
</span></span></code></pre></div><h2 id="扩展功能测试">扩展功能测试</h2>
<h3 id="postgis-测试">PostGIS 测试</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 创建几何数据
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> ST_AsText(ST_MakePoint(<span style="color:#ff79c6">-</span><span style="color:#bd93f9">71</span>.<span style="color:#bd93f9">064544</span>, <span style="color:#bd93f9">42</span>.<span style="color:#bd93f9">28787</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 空间查询示例
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">TABLE</span> locations (
</span></span><span style="display:flex;"><span>    id <span style="color:#8be9fd;font-style:italic">SERIAL</span> <span style="color:#ff79c6">PRIMARY</span> <span style="color:#ff79c6">KEY</span>,
</span></span><span style="display:flex;"><span>    name <span style="color:#8be9fd;font-style:italic">VARCHAR</span>(<span style="color:#bd93f9">100</span>),
</span></span><span style="display:flex;"><span>    geom GEOMETRY(POINT, <span style="color:#bd93f9">4326</span>)
</span></span><span style="display:flex;"><span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">INSERT</span> <span style="color:#ff79c6">INTO</span> locations (name, geom) <span style="color:#ff79c6">VALUES</span>
</span></span><span style="display:flex;"><span>(<span style="color:#f1fa8c">&#39;Boston&#39;</span>, ST_SetSRID(ST_MakePoint(<span style="color:#ff79c6">-</span><span style="color:#bd93f9">71</span>.<span style="color:#bd93f9">0589</span>, <span style="color:#bd93f9">42</span>.<span style="color:#bd93f9">3601</span>), <span style="color:#bd93f9">4326</span>));
</span></span></code></pre></div><h3 id="pgvector-测试">pgvector 测试</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 创建向量表
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">TABLE</span> items (
</span></span><span style="display:flex;"><span>    id <span style="color:#8be9fd;font-style:italic">SERIAL</span> <span style="color:#ff79c6">PRIMARY</span> <span style="color:#ff79c6">KEY</span>,
</span></span><span style="display:flex;"><span>    embedding VECTOR(<span style="color:#bd93f9">3</span>)
</span></span><span style="display:flex;"><span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 插入向量数据
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">INSERT</span> <span style="color:#ff79c6">INTO</span> items (embedding) <span style="color:#ff79c6">VALUES</span>
</span></span><span style="display:flex;"><span>(<span style="color:#f1fa8c">&#39;[1,2,3]&#39;</span>),
</span></span><span style="display:flex;"><span>(<span style="color:#f1fa8c">&#39;[4,5,6]&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 向量相似度查询
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> <span style="color:#ff79c6">*</span> <span style="color:#ff79c6">FROM</span> items <span style="color:#ff79c6">ORDER</span> <span style="color:#ff79c6">BY</span> embedding <span style="color:#ff79c6">&lt;-&gt;</span> <span style="color:#f1fa8c">&#39;[3,1,2]&#39;</span> <span style="color:#ff79c6">LIMIT</span> <span style="color:#bd93f9">5</span>;
</span></span></code></pre></div><h3 id="timescaledb-测试">TimescaleDB 测试</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#6272a4">-- 创建时序表
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">TABLE</span> sensor_data (
</span></span><span style="display:flex;"><span>    time TIMESTAMPTZ <span style="color:#ff79c6">NOT</span> <span style="color:#ff79c6">NULL</span>,
</span></span><span style="display:flex;"><span>    sensor_id <span style="color:#8be9fd;font-style:italic">INTEGER</span>,
</span></span><span style="display:flex;"><span>    temperature DOUBLE <span style="color:#ff79c6">PRECISION</span>,
</span></span><span style="display:flex;"><span>    humidity DOUBLE <span style="color:#ff79c6">PRECISION</span>
</span></span><span style="display:flex;"><span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 转换为超表
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> create_hypertable(<span style="color:#f1fa8c">&#39;sensor_data&#39;</span>, <span style="color:#f1fa8c">&#39;time&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4">-- 插入时序数据
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">INSERT</span> <span style="color:#ff79c6">INTO</span> sensor_data <span style="color:#ff79c6">VALUES</span>
</span></span><span style="display:flex;"><span>(NOW(), <span style="color:#bd93f9">1</span>, <span style="color:#bd93f9">23</span>.<span style="color:#bd93f9">5</span>, <span style="color:#bd93f9">65</span>.<span style="color:#bd93f9">2</span>),
</span></span><span style="display:flex;"><span>(NOW() <span style="color:#ff79c6">-</span> <span style="color:#8be9fd;font-style:italic">INTERVAL</span> <span style="color:#f1fa8c">&#39;1 hour&#39;</span>, <span style="color:#bd93f9">1</span>, <span style="color:#bd93f9">22</span>.<span style="color:#bd93f9">8</span>, <span style="color:#bd93f9">64</span>.<span style="color:#bd93f9">1</span>);
</span></span></code></pre></div><h2 id="连接配置">连接配置</h2>
<h3 id="ide-连接参数">IDE 连接参数</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Host: localhost
</span></span><span style="display:flex;"><span>Port: 5432
</span></span><span style="display:flex;"><span>Database: devdb (或 postgres)
</span></span><span style="display:flex;"><span>Username: postgres
</span></span><span style="display:flex;"><span>Password: [您在.env中设置的密码]
</span></span></code></pre></div><h3 id="命令行连接">命令行连接</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 使用 Docker 容器内的 psql</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> -it postgres-all-extensions psql -U postgres -d devdb
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 使用外部 psql (需要安装 PostgreSQL 客户端)</span>
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">PGPASSWORD</span><span style="color:#ff79c6">=</span>your_password psql -h localhost -p <span style="color:#bd93f9">5432</span> -U postgres -d devdb
</span></span></code></pre></div><h2 id="管理命令">管理命令</h2>
<h3 id="启动停止服务">启动/停止服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 启动服务</span>
</span></span><span style="display:flex;"><span>docker-compose up -d
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 停止服务</span>
</span></span><span style="display:flex;"><span>docker-compose down
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 重启服务</span>
</span></span><span style="display:flex;"><span>docker-compose restart
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看日志</span>
</span></span><span style="display:flex;"><span>docker-compose logs -f
</span></span></code></pre></div><h3 id="数据备份与恢复">数据备份与恢复</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 备份数据库</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> postgres-all-extensions pg_dump -U postgres devdb &gt; backup.sql
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 恢复数据库</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> -i postgres-all-extensions psql -U postgres devdb &lt; backup.sql
</span></span></code></pre></div><h3 id="性能监控">性能监控</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 查看容器资源使用</span>
</span></span><span style="display:flex;"><span>docker stats postgres-all-extensions
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看数据库连接</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> postgres-all-extensions psql -U postgres -c <span style="color:#f1fa8c">&#34;SELECT * FROM pg_stat_activity;&#34;</span>
</span></span></code></pre></div><h2 id="安全建议">安全建议</h2>
<ol>
<li>修改默认密码：确保在 <code>.env</code> 文件中设置强密码</li>
<li>网络安全：生产环境中限制 <code>pg_hba.conf</code> 的访问范围</li>
<li>数据加密：考虑启用 SSL/TLS 连接</li>
<li>定期备份：建立自动化备份策略</li>
<li>更新维护：定期更新 PostgreSQL 和扩展版本</li>
</ol>
<h2 id="版本信息">版本信息</h2>
<ul>
<li>PostgreSQL: 15.14</li>
<li>PostGIS: 3.6.0</li>
<li>pgvector: 0.5.1</li>
<li>TimescaleDB: 2.13.0</li>
</ul>
<h2 id="许可证">许可证</h2>
<p>本项目遵循 MIT 许可证。各个扩展遵循其各自的许可证条款。</p>
]]></content:encoded></item><item><title>WordPress 密码重置指南</title><link>https://blog.heyaohua.com/posts/2025/09/wordpress-password-reset/</link><pubDate>Mon, 08 Sep 2025 13:00:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2025/09/wordpress-password-reset/</guid><description>如果您有数据库访问权限，这是最快的方法：</description><content:encoded><![CDATA[<h2 id="-方法1通过数据库直接重置最快">🔑 方法1：通过数据库直接重置（最快）</h2>
<p>如果您有数据库访问权限，这是最快的方法：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 进入MySQL容器
</span></span><span style="display:flex;"><span>docker <span style="color:#ff79c6">exec</span> mysql_server mysql <span style="color:#ff79c6">-</span>u wordpress_user <span style="color:#ff79c6">-</span>p你的密码
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 在MySQL中执行以下命令
</span></span><span style="display:flex;"><span>USE wordpress_db;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 查看所有用户
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">SELECT</span> ID, user_login, user_email <span style="color:#ff79c6">FROM</span> wp_users;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 重置指定用户密码（这里以用户名 heyaohua 为例）
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">UPDATE</span> wp_users <span style="color:#ff79c6">SET</span> user_pass <span style="color:#ff79c6">=</span> MD5(<span style="color:#f1fa8c">&#39;新密码&#39;</span>) <span style="color:#ff79c6">WHERE</span> user_login <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;heyaohua&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 或者使用更安全的WordPress密码哈希
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">UPDATE</span> wp_users <span style="color:#ff79c6">SET</span> user_pass <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;$P$B7TBaFiTTExKUX8aWA.HyNEHKvZQ5P0&#39;</span> <span style="color:#ff79c6">WHERE</span> user_login <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;heyaohua&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 上面的哈希对应密码: REPLACE_WITH_NEW_PASSWORD
</span></span></code></pre></div><h2 id="-方法2通过wordpress文件重置">🔑 方法2：通过WordPress文件重置</h2>
<p>在WordPress根目录创建重置脚本：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#ff79c6">&lt;?</span>php
</span></span><span style="display:flex;"><span><span style="color:#6272a4">// 创建文件: reset_password.php
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">require_once</span>(<span style="color:#f1fa8c">&#39;wp-config.php&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">require_once</span>(<span style="color:#f1fa8c">&#39;wp-includes/wp-db.php&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">$user_login</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;heyaohua&#39;</span>;  <span style="color:#6272a4">// 替换为您的用户名
</span></span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">$new_password</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;REPLACE_WITH_NEW_PASSWORD&#39;</span>;  <span style="color:#6272a4">// 替换为新密码
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">$user</span> <span style="color:#ff79c6">=</span> get_user_by(<span style="color:#f1fa8c">&#39;login&#39;</span>, <span style="color:#8be9fd;font-style:italic">$user_login</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">if</span> (<span style="color:#8be9fd;font-style:italic">$user</span>) {
</span></span><span style="display:flex;"><span>    wp_set_password(<span style="color:#8be9fd;font-style:italic">$new_password</span>, <span style="color:#8be9fd;font-style:italic">$user</span><span style="color:#ff79c6">-&gt;</span><span style="color:#50fa7b">ID</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">echo</span> <span style="color:#f1fa8c">&#34;密码重置成功！用户: </span><span style="color:#f1fa8c">$user_login</span><span style="color:#f1fa8c">, 新密码: </span><span style="color:#f1fa8c">$new_password</span><span style="color:#f1fa8c">&#34;</span>;
</span></span><span style="display:flex;"><span>} <span style="color:#ff79c6">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">echo</span> <span style="color:#f1fa8c">&#34;用户不存在！&#34;</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">?&gt;</span>
</span></span></code></pre></div><p>使用方法：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#6272a4"># 在WordPress容器中创建文件
</span></span></span><span style="display:flex;"><span>docker exec wordpress_app bash <span style="color:#ff79c6">-</span>c <span style="color:#f1fa8c">&#34;cat &gt; /var/www/html/reset_password.php &lt;&lt; &#39;EOF&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&lt;?php
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">require_once(&#39;wp-config.php&#39;);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">require_once(&#39;wp-includes/wp-db.php&#39;);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">user_login = &#39;heyaohua&#39;;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">new_password = &#39;REPLACE_WITH_NEW_PASSWORD&#39;;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">user = get_user_by(&#39;login&#39;, </span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">user_login);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">if (</span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">user) {
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">    wp_set_password(</span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">new_password, </span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">user-&gt;ID);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">    echo &#39;密码重置成功！用户: &#39; . </span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">user_login . &#39;, 新密码: &#39; . </span><span style="color:#f1fa8c">\$</span><span style="color:#f1fa8c">new_password;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">} else {
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">    echo &#39;用户不存在！&#39;;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">}
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">EOF&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 通过浏览器访问执行
</span></span></span><span style="display:flex;"><span><span style="color:#6272a4"># http://localhost:8080/reset_password.php
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 执行完成后删除文件（重要！）
</span></span></span><span style="display:flex;"><span>docker exec wordpress_app rm <span style="color:#ff79c6">/</span><span style="color:#ff79c6">var</span><span style="color:#ff79c6">/</span>www<span style="color:#ff79c6">/</span>html<span style="color:#ff79c6">/</span>reset_password<span style="color:#ff79c6">.</span>php
</span></span></code></pre></div><h2 id="-方法3通过functionsphp临时添加管理员">🔑 方法3：通过functions.php临时添加管理员</h2>
<p>在当前主题的 <code>functions.php</code> 文件末尾添加：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#ff79c6">function</span> <span style="color:#50fa7b">add_temp_admin</span>(){
</span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">$user</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;temp_admin&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">$pass</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;REPLACE_WITH_TEMP_PASSWORD&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">$email</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;temp@example.com&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">if</span> (username_exists(<span style="color:#8be9fd;font-style:italic">$user</span>) <span style="color:#ff79c6">==</span> <span style="color:#ff79c6">null</span> <span style="color:#ff79c6">&amp;&amp;</span> email_exists(<span style="color:#8be9fd;font-style:italic">$email</span>) <span style="color:#ff79c6">==</span> <span style="color:#ff79c6">false</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#8be9fd;font-style:italic">$user_id</span> <span style="color:#ff79c6">=</span> wp_create_user(<span style="color:#8be9fd;font-style:italic">$user</span>, <span style="color:#8be9fd;font-style:italic">$pass</span>, <span style="color:#8be9fd;font-style:italic">$email</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#8be9fd;font-style:italic">$user</span> <span style="color:#ff79c6">=</span> <span style="color:#ff79c6">new</span> WP_User(<span style="color:#8be9fd;font-style:italic">$user_id</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#8be9fd;font-style:italic">$user</span><span style="color:#ff79c6">-&gt;</span><span style="color:#50fa7b">set_role</span>(<span style="color:#f1fa8c">&#39;administrator&#39;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>add_action(<span style="color:#f1fa8c">&#39;init&#39;</span>,<span style="color:#f1fa8c">&#39;add_temp_admin&#39;</span>);
</span></span></code></pre></div><p>执行方法：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#6272a4"># 编辑当前主题的functions.php
</span></span></span><span style="display:flex;"><span>docker exec wordpress_app bash <span style="color:#ff79c6">-</span>c <span style="color:#f1fa8c">&#34;echo &#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">function</span> <span style="color:#50fa7b">add_temp_admin</span>(){
</span></span><span style="display:flex;"><span>    \\\<span style="color:#8be9fd;font-style:italic">$user</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;temp_admin&#39;</span>;
</span></span><span style="display:flex;"><span>    \\\<span style="color:#8be9fd;font-style:italic">$pass</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;tempREPLACE_WITH_NEW_PASSWORD&#39;</span>;
</span></span><span style="display:flex;"><span>    \\\<span style="color:#8be9fd;font-style:italic">$email</span> <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;temp@example.com&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">if</span> (username_exists(\\\<span style="color:#8be9fd;font-style:italic">$user</span>) <span style="color:#ff79c6">==</span> <span style="color:#ff79c6">null</span> <span style="color:#ff79c6">&amp;&amp;</span> email_exists(\\\<span style="color:#8be9fd;font-style:italic">$email</span>) <span style="color:#ff79c6">==</span> <span style="color:#ff79c6">false</span>) {
</span></span><span style="display:flex;"><span>        \\\<span style="color:#8be9fd;font-style:italic">$user_id</span> <span style="color:#ff79c6">=</span> wp_create_user(\\\<span style="color:#8be9fd;font-style:italic">$user</span>, \\\<span style="color:#8be9fd;font-style:italic">$pass</span>, \\\<span style="color:#8be9fd;font-style:italic">$email</span>);
</span></span><span style="display:flex;"><span>        \\\<span style="color:#8be9fd;font-style:italic">$user</span> <span style="color:#ff79c6">=</span> <span style="color:#ff79c6">new</span> WP_User(\\\<span style="color:#8be9fd;font-style:italic">$user_id</span>);
</span></span><span style="display:flex;"><span>        \\\<span style="color:#8be9fd;font-style:italic">$user</span><span style="color:#ff79c6">-&gt;</span><span style="color:#50fa7b">set_role</span>(<span style="color:#f1fa8c">&#39;administrator&#39;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>add_action(<span style="color:#f1fa8c">&#39;init&#39;</span>,<span style="color:#f1fa8c">&#39;add_temp_admin&#39;</span>);<span style="color:#f1fa8c">&#34; &gt;&gt; /var/www/html/wp-content/themes/twentytwentyfour/functions.php&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 访问网站前台任意页面触发函数执行
</span></span></span><span style="display:flex;"><span><span style="color:#6272a4"># 然后用 temp_admin / tempREPLACE_WITH_NEW_PASSWORD 登录后台
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 登录后立即删除这段代码！
</span></span></span></code></pre></div><h2 id="-方法4通过邮箱重置需要邮件配置">🔑 方法4：通过邮箱重置（需要邮件配置）</h2>
<p>如果WordPress配置了邮件发送功能：</p>
<ol>
<li>访问 <code>http://localhost:8080/wp-login.php</code></li>
<li>点击&quot;忘记密码？&quot;</li>
<li>输入用户名或邮箱</li>
<li>检查邮箱中的重置链接</li>
</ol>
<h2 id="-方法5通过wp-cli推荐给开发者">🔑 方法5：通过WP-CLI（推荐给开发者）</h2>
<p>如果容器中安装了WP-CLI：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 安装WP-CLI（如果没有）</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> wordpress_app bash -c <span style="color:#f1fa8c">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">curl -O https://raw.githubusercontent.com/wp-cli/wp-cli/v2.8.1/bin/wp-cli.phar
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">chmod +x wp-cli.phar
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">mv wp-cli.phar /usr/local/bin/wp
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 重置密码</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> wordpress_app wp user update heyaohua --user_pass<span style="color:#ff79c6">=</span>REPLACE_WITH_NEW_PASSWORD --path<span style="color:#ff79c6">=</span>/var/www/html --allow-root
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 列出所有用户</span>
</span></span><span style="display:flex;"><span>docker <span style="color:#8be9fd;font-style:italic">exec</span> wordpress_app wp user list --path<span style="color:#ff79c6">=</span>/var/www/html --allow-root
</span></span></code></pre></div><h2 id="-安全建议">🛡️ 安全建议</h2>
<ol>
<li><strong>及时删除重置脚本</strong>：使用方法2后务必删除PHP重置文件</li>
<li><strong>更改默认密码</strong>：重置后立即登录并更改为强密码</li>
<li><strong>删除临时用户</strong>：使用方法3后删除临时管理员账户</li>
<li><strong>使用强密码</strong>：包含大小写字母、数字和特殊字符，至少8位</li>
</ol>
<h2 id="-快速重置命令">📱 快速重置命令</h2>
<p>最简单的数据库重置命令：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 重置为密码: REPLACE_WITH_NEW_PASSWORD
</span></span><span style="display:flex;"><span>docker <span style="color:#ff79c6">exec</span> mysql_server mysql <span style="color:#ff79c6">-</span>u wordpress_user <span style="color:#ff79c6">-</span>p你的密码 <span style="color:#ff79c6">-</span>e <span style="color:#f1fa8c">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">USE wordpress_db;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">UPDATE wp_users SET user_pass = MD5(&#39;REPLACE_WITH_NEW_PASSWORD&#39;) WHERE user_login = &#39;heyaohua&#39;;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> 重置为密码: REPLACE_WITH_NEW_PASSWORD
</span></span><span style="display:flex;"><span>docker <span style="color:#ff79c6">exec</span> mysql_server mysql <span style="color:#ff79c6">-</span>u wordpress_user <span style="color:#ff79c6">-</span>p你的密码 <span style="color:#ff79c6">-</span>e <span style="color:#f1fa8c">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">USE wordpress_db;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">UPDATE wp_users SET user_pass = MD5(&#39;REPLACE_WITH_NEW_PASSWORD&#39;) WHERE user_login = &#39;heyaohua&#39;;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&#34;</span>
</span></span></code></pre></div><h2 id="-注意事项">⚠️ 注意事项</h2>
<ol>
<li><strong>备份数据</strong>：重置前建议备份数据库</li>
<li><strong>检查用户名</strong>：确认用户名正确（区分大小写）</li>
<li><strong>清除缓存</strong>：重置后可能需要清除浏览器缓存</li>
<li><strong>安全性</strong>：生产环境中请使用更安全的密码哈希方法</li>
</ol>
<h2 id="-高级密码哈希">🔧 高级密码哈希</h2>
<h3 id="wordpress密码哈希生成">WordPress密码哈希生成</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#ff79c6">&lt;?</span>php
</span></span><span style="display:flex;"><span><span style="color:#6272a4">// 生成WordPress兼容的密码哈希
</span></span></span><span style="display:flex;"><span><span style="color:#ff79c6">require_once</span>(<span style="color:#f1fa8c">&#39;wp-includes/class-phpass.php&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">$wp_hasher</span> <span style="color:#ff79c6">=</span> <span style="color:#ff79c6">new</span> PasswordHash(<span style="color:#bd93f9">8</span>, <span style="color:#ff79c6">true</span>);
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">$password_hash</span> <span style="color:#ff79c6">=</span> <span style="color:#8be9fd;font-style:italic">$wp_hasher</span><span style="color:#ff79c6">-&gt;</span><span style="color:#50fa7b">HashPassword</span>(<span style="color:#f1fa8c">&#39;your_new_password&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">echo</span> <span style="color:#8be9fd;font-style:italic">$password_hash</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">?&gt;</span>
</span></span></code></pre></div><h3 id="在线密码哈希工具">在线密码哈希工具</h3>
<p>如果您需要生成WordPress兼容的密码哈希：</p>
<ol>
<li>访问 <a href="https://www.useotools.com/wordpress-password-hash-generator">WordPress密码哈希生成器</a></li>
<li>输入新密码</li>
<li>复制生成的哈希值</li>
<li>在数据库中更新 <code>user_pass</code> 字段</li>
</ol>
<h2 id="-紧急情况处理">🚨 紧急情况处理</h2>
<h3 id="完全锁定时的处理方法">完全锁定时的处理方法</h3>
<p>如果所有管理员账户都无法访问：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">#</span> <span style="color:#bd93f9">1</span>. 创建新的管理员用户
</span></span><span style="display:flex;"><span>docker <span style="color:#ff79c6">exec</span> mysql_server mysql <span style="color:#ff79c6">-</span>u wordpress_user <span style="color:#ff79c6">-</span>p你的密码 <span style="color:#ff79c6">-</span>e <span style="color:#f1fa8c">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">USE wordpress_db;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">INSERT INTO wp_users (user_login, user_pass, user_nicename, user_email, user_status)
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">VALUES (&#39;emergency_admin&#39;, MD5(&#39;emergency123&#39;), &#39;emergency_admin&#39;, &#39;emergency@example.com&#39;, 0);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> <span style="color:#bd93f9">2</span>. 获取新用户的ID
</span></span><span style="display:flex;"><span>docker <span style="color:#ff79c6">exec</span> mysql_server mysql <span style="color:#ff79c6">-</span>u wordpress_user <span style="color:#ff79c6">-</span>p你的密码 <span style="color:#ff79c6">-</span>e <span style="color:#f1fa8c">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">USE wordpress_db;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">SELECT ID FROM wp_users WHERE user_login = &#39;emergency_admin&#39;;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">#</span> <span style="color:#bd93f9">3</span>. 设置管理员权限（假设用户ID为5）
</span></span><span style="display:flex;"><span>docker <span style="color:#ff79c6">exec</span> mysql_server mysql <span style="color:#ff79c6">-</span>u wordpress_user <span style="color:#ff79c6">-</span>p你的密码 <span style="color:#ff79c6">-</span>e <span style="color:#f1fa8c">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">USE wordpress_db;
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">INSERT INTO wp_usermeta (user_id, meta_key, meta_value)
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">VALUES (5, &#39;wp_capabilities&#39;, &#39;a:1:{s:13:\&#34;</span>administrator\<span style="color:#f1fa8c">&#34;;b:1;}&#39;);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">INSERT INTO wp_usermeta (user_id, meta_key, meta_value)
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">VALUES (5, &#39;wp_user_level&#39;, &#39;10&#39;);
</span></span></span><span style="display:flex;"><span><span style="color:#f1fa8c">&#34;</span>
</span></span></code></pre></div><h2 id="-密码安全最佳实践">📊 密码安全最佳实践</h2>
<h3 id="强密码要求">强密码要求</h3>
<ol>
<li><strong>长度</strong>：至少12个字符</li>
<li><strong>复杂性</strong>：包含大小写字母、数字、特殊字符</li>
<li><strong>唯一性</strong>：不要重复使用其他账户的密码</li>
<li><strong>定期更换</strong>：建议每3-6个月更换一次</li>
</ol>
<h3 id="推荐的密码管理">推荐的密码管理</h3>
<ol>
<li><strong>使用密码管理器</strong>：如1Password、LastPass、Bitwarden</li>
<li><strong>启用双因素认证</strong>：安装WordPress 2FA插件</li>
<li><strong>限制登录尝试</strong>：使用Wordfence等安全插件</li>
<li><strong>定期安全审计</strong>：检查用户权限和登录日志</li>
</ol>
<hr>
<p>💡 <strong>提示</strong>：建议将此指南保存为书签，以备紧急情况使用。记住，安全第一，操作前务必备份！</p>
]]></content:encoded></item><item><title>MySQL与PostgreSQL全面对比与压测方案</title><link>https://blog.heyaohua.com/posts/2024/12/mysql-postgresql-comparison/</link><pubDate>Sun, 15 Dec 2024 10:00:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2024/12/mysql-postgresql-comparison/</guid><description>MySQL与PostgreSQL全面对比分析，包括核心技术差异、性能测试、Python操作示例及压测方案。帮助开发者选择适合业务场景的数据库系统。</description><content:encoded><![CDATA[<h2 id="一mysql与postgresql对比分析">一、MySQL与PostgreSQL对比分析</h2>
<h3 id="背景与概述">背景与概述</h3>
<p>MySQL长期因轻量和高性能占市场主导，PostgreSQL凭借先进特性和稳定性近年快速崛起，尤其在云原生和复杂业务需求场景中表现出色。</p>
<h3 id="核心技术对比">核心技术对比</h3>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>MySQL</th>
          <th>PostgreSQL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>数据一致性</td>
          <td>MVCC，读已提交隔离，异步复制</td>
          <td>完备MVCC，默认可重复读，逻辑/流复制</td>
      </tr>
      <tr>
          <td>SQL标准兼容与扩展</td>
          <td>支持有限，扩展围绕存储引擎</td>
          <td>几乎完整支持SQL标准，支持丰富扩展</td>
      </tr>
      <tr>
          <td>性能优化</td>
          <td>读写分离，高并发读优势</td>
          <td>并行查询，分区表，分布式支持日益完善</td>
      </tr>
  </tbody>
</table>
<h3 id="postgresql使用度超mysql原因">PostgreSQL使用度超MySQL原因</h3>
<ul>
<li>业务需求提升，复杂事务、分析需求增多</li>
<li>社区活跃，插件和扩展丰富</li>
<li>云服务快速支持，官方生态发展强劲</li>
<li>大型企业和专业领域采用增多</li>
</ul>
<h3 id="未来前景">未来前景</h3>
<table>
  <thead>
      <tr>
          <th>数据库</th>
          <th>优势场景</th>
          <th>未来发展方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MySQL</td>
          <td>简单高并发读写，Web应用</td>
          <td>高可用分布式，云原生集成</td>
      </tr>
      <tr>
          <td>PostgreSQL</td>
          <td>复杂事务，BI报表，地理空间</td>
          <td>原生分布式，多模扩展，SQL标准领先</td>
      </tr>
  </tbody>
</table>
<h2 id="二python数据库操作用例">二、Python数据库操作用例</h2>
<h3 id="原生驱动">原生驱动</h3>
<h4 id="mysql-pymysql">MySQL (PyMySQL)</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#ff79c6">import</span> pymysql
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>conn <span style="color:#ff79c6">=</span> pymysql<span style="color:#ff79c6">.</span>connect(host<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;localhost&#39;</span>, user<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;user&#39;</span>, password<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;password&#39;</span>, database<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;testdb&#39;</span>)
</span></span><span style="display:flex;"><span>cursor <span style="color:#ff79c6">=</span> conn<span style="color:#ff79c6">.</span>cursor()
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), email VARCHAR(100) UNIQUE)&#34;</span>)
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;INSERT INTO users (name, email) VALUES (</span><span style="color:#f1fa8c">%s</span><span style="color:#f1fa8c">, </span><span style="color:#f1fa8c">%s</span><span style="color:#f1fa8c">)&#34;</span>, (<span style="color:#f1fa8c">&#39;Alice&#39;</span>, <span style="color:#f1fa8c">&#39;alice@example.com&#39;</span>))
</span></span><span style="display:flex;"><span>conn<span style="color:#ff79c6">.</span>commit()
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;SELECT * FROM users&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">print</span>(cursor<span style="color:#ff79c6">.</span>fetchall())
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>close()
</span></span><span style="display:flex;"><span>conn<span style="color:#ff79c6">.</span>close()
</span></span></code></pre></div><h4 id="postgresql-psycopg2">PostgreSQL (psycopg2)</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#ff79c6">import</span> psycopg2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>conn <span style="color:#ff79c6">=</span> psycopg2<span style="color:#ff79c6">.</span>connect(host<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;localhost&#39;</span>, user<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;user&#39;</span>, password<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;password&#39;</span>, dbname<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;testdb&#39;</span>)
</span></span><span style="display:flex;"><span>cursor <span style="color:#ff79c6">=</span> conn<span style="color:#ff79c6">.</span>cursor()
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT, email TEXT UNIQUE)&#34;</span>)
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;INSERT INTO users (name, email) VALUES (</span><span style="color:#f1fa8c">%s</span><span style="color:#f1fa8c">, </span><span style="color:#f1fa8c">%s</span><span style="color:#f1fa8c">)&#34;</span>, (<span style="color:#f1fa8c">&#39;Bob&#39;</span>, <span style="color:#f1fa8c">&#39;bob@example.com&#39;</span>))
</span></span><span style="display:flex;"><span>conn<span style="color:#ff79c6">.</span>commit()
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;SELECT * FROM users&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">print</span>(cursor<span style="color:#ff79c6">.</span>fetchall())
</span></span><span style="display:flex;"><span>cursor<span style="color:#ff79c6">.</span>close()
</span></span><span style="display:flex;"><span>conn<span style="color:#ff79c6">.</span>close()
</span></span></code></pre></div><h3 id="orm-示例sqlalchemy">ORM 示例：SQLAlchemy</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#ff79c6">from</span> sqlalchemy <span style="color:#ff79c6">import</span> create_engine, Column, Integer, String
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">from</span> sqlalchemy.ext.declarative <span style="color:#ff79c6">import</span> declarative_base
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">from</span> sqlalchemy.orm <span style="color:#ff79c6">import</span> sessionmaker
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Base <span style="color:#ff79c6">=</span> declarative_base()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">class</span> <span style="color:#50fa7b">User</span>(Base):
</span></span><span style="display:flex;"><span>    __tablename__ <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;users&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">id</span> <span style="color:#ff79c6">=</span> Column(Integer, primary_key<span style="color:#ff79c6">=</span><span style="color:#ff79c6">True</span>)
</span></span><span style="display:flex;"><span>    name <span style="color:#ff79c6">=</span> Column(String(<span style="color:#bd93f9">100</span>))
</span></span><span style="display:flex;"><span>    email <span style="color:#ff79c6">=</span> Column(String(<span style="color:#bd93f9">100</span>), unique<span style="color:#ff79c6">=</span><span style="color:#ff79c6">True</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DATABASE_URL <span style="color:#ff79c6">=</span> <span style="color:#f1fa8c">&#39;postgresql+psycopg2://user:password@localhost:5432/testdb&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>engine <span style="color:#ff79c6">=</span> create_engine(DATABASE_URL)
</span></span><span style="display:flex;"><span>Session <span style="color:#ff79c6">=</span> sessionmaker(bind<span style="color:#ff79c6">=</span>engine)
</span></span><span style="display:flex;"><span>session <span style="color:#ff79c6">=</span> Session()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Base<span style="color:#ff79c6">.</span>metadata<span style="color:#ff79c6">.</span>create_all(engine)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>new_user <span style="color:#ff79c6">=</span> User(name<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;Carol&#39;</span>, email<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;carol@example.com&#39;</span>)
</span></span><span style="display:flex;"><span>session<span style="color:#ff79c6">.</span>add(new_user)
</span></span><span style="display:flex;"><span>session<span style="color:#ff79c6">.</span>commit()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>users <span style="color:#ff79c6">=</span> session<span style="color:#ff79c6">.</span>query(User)<span style="color:#ff79c6">.</span>all()
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">for</span> u <span style="color:#ff79c6">in</span> users:
</span></span><span style="display:flex;"><span>    <span style="color:#8be9fd;font-style:italic">print</span>(u<span style="color:#ff79c6">.</span>id, u<span style="color:#ff79c6">.</span>name, u<span style="color:#ff79c6">.</span>email)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>session<span style="color:#ff79c6">.</span>close()
</span></span></code></pre></div><h2 id="三数据库压测方案">三、数据库压测方案</h2>
<h3 id="压测总体流程">压测总体流程</h3>
<ol>
<li>环境准备：部署数据库和测试客户端</li>
<li>场景设计：包含OLTP、高并发读写、复杂查询等</li>
<li>基线测试：默认配置性能测量</li>
<li>参数调优：调整配置重复测试</li>
<li>结果分析：整理吞吐、延迟和资源利用数据</li>
<li>自动化脚本：支持快速复用</li>
</ol>
<h3 id="主要压测工具与命令示例">主要压测工具与命令示例</h3>
<h4 id="sysbenchmysql">Sysbench（MySQL）</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>sysbench oltp_read_write \
</span></span><span style="display:flex;"><span>  --db-driver=mysql \
</span></span><span style="display:flex;"><span>  --mysql-host=DB_HOST \
</span></span><span style="display:flex;"><span>  --mysql-user=testuser \
</span></span><span style="display:flex;"><span>  --mysql-password=secret \
</span></span><span style="display:flex;"><span>  --mysql-db=testdb \
</span></span><span style="display:flex;"><span>  --tables=10 \
</span></span><span style="display:flex;"><span>  --table-size=1000000 \
</span></span><span style="display:flex;"><span>  prepare
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sysbench oltp_read_write --threads=100 --time=300 run
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sysbench oltp_read_write cleanup
</span></span></code></pre></div><h4 id="pgbenchpostgresql">pgbench（PostgreSQL）</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>pgbench -h DB_HOST -U testuser -d testdb -i -s 1000
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pgbench -h DB_HOST -U testuser -d testdb -c 100 -T 300 -j 4
</span></span></code></pre></div><h3 id="自定义python异步压测示例">自定义Python异步压测示例</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#ff79c6">import</span> asyncio
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">import</span> aiomysql
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DB_CONFIG <span style="color:#ff79c6">=</span> <span style="color:#8be9fd;font-style:italic">dict</span>(host<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;DB_HOST&#39;</span>, user<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;testuser&#39;</span>, password<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;secret&#39;</span>, db<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#39;testdb&#39;</span>, minsize<span style="color:#ff79c6">=</span><span style="color:#bd93f9">10</span>, maxsize<span style="color:#ff79c6">=</span><span style="color:#bd93f9">100</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">async</span> <span style="color:#ff79c6">def</span> <span style="color:#50fa7b">task</span>(pool):
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">async</span> <span style="color:#ff79c6">with</span> pool<span style="color:#ff79c6">.</span>acquire() <span style="color:#ff79c6">as</span> conn:
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">async</span> <span style="color:#ff79c6">with</span> conn<span style="color:#ff79c6">.</span>cursor() <span style="color:#ff79c6">as</span> cur:
</span></span><span style="display:flex;"><span>            <span style="color:#ff79c6">await</span> cur<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;SELECT COUNT(*) FROM orders WHERE status=&#39;pending&#39;&#34;</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#ff79c6">await</span> cur<span style="color:#ff79c6">.</span>fetchone()
</span></span><span style="display:flex;"><span>            <span style="color:#ff79c6">await</span> cur<span style="color:#ff79c6">.</span>execute(<span style="color:#f1fa8c">&#34;UPDATE users SET last_login=NOW() WHERE id=</span><span style="color:#f1fa8c">%s</span><span style="color:#f1fa8c">&#34;</span>, (<span style="color:#bd93f9">1</span>,))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">async</span> <span style="color:#ff79c6">def</span> <span style="color:#50fa7b">run_load</span>(concurrency, duration):
</span></span><span style="display:flex;"><span>    pool <span style="color:#ff79c6">=</span> <span style="color:#ff79c6">await</span> aiomysql<span style="color:#ff79c6">.</span>create_pool(<span style="color:#ff79c6">**</span>DB_CONFIG)
</span></span><span style="display:flex;"><span>    end_time <span style="color:#ff79c6">=</span> asyncio<span style="color:#ff79c6">.</span>get_event_loop()<span style="color:#ff79c6">.</span>time() <span style="color:#ff79c6">+</span> duration
</span></span><span style="display:flex;"><span>    sem <span style="color:#ff79c6">=</span> asyncio<span style="color:#ff79c6">.</span>Semaphore(concurrency)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">async</span> <span style="color:#ff79c6">def</span> <span style="color:#50fa7b">worker</span>():
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">async</span> <span style="color:#ff79c6">with</span> sem:
</span></span><span style="display:flex;"><span>            <span style="color:#ff79c6">while</span> asyncio<span style="color:#ff79c6">.</span>get_event_loop()<span style="color:#ff79c6">.</span>time() <span style="color:#ff79c6">&lt;</span> end_time:
</span></span><span style="display:flex;"><span>                <span style="color:#ff79c6">await</span> task(pool)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">await</span> asyncio<span style="color:#ff79c6">.</span>gather(<span style="color:#ff79c6">*</span>[worker() <span style="color:#ff79c6">for</span> _ <span style="color:#ff79c6">in</span> <span style="color:#8be9fd;font-style:italic">range</span>(concurrency)])
</span></span><span style="display:flex;"><span>    pool<span style="color:#ff79c6">.</span>close()
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">await</span> pool<span style="color:#ff79c6">.</span>wait_closed()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>asyncio<span style="color:#ff79c6">.</span>run(run_load(concurrency<span style="color:#ff79c6">=</span><span style="color:#bd93f9">50</span>, duration<span style="color:#ff79c6">=</span><span style="color:#bd93f9">300</span>))
</span></span></code></pre></div><h2 id="四一体化压测脚本模板">四、一体化压测脚本模板</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#6272a4">#!/bin/bash
</span></span></span><span style="display:flex;"><span>DB_TYPE<span style="color:#ff79c6">=</span>${<span style="color:#bd93f9">1</span><span style="color:#ff79c6">:-</span>mysql}
</span></span><span style="display:flex;"><span>DB_HOST<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;127.0.0.1&#34;</span>
</span></span><span style="display:flex;"><span>DB_PORT_MYSQL<span style="color:#ff79c6">=</span><span style="color:#bd93f9">3306</span>
</span></span><span style="display:flex;"><span>DB_PORT_PG<span style="color:#ff79c6">=</span><span style="color:#bd93f9">5432</span>
</span></span><span style="display:flex;"><span>DB_USER<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;testuser&#34;</span>
</span></span><span style="display:flex;"><span>DB_PASS<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;secret&#34;</span>
</span></span><span style="display:flex;"><span>DB_NAME<span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;testdb&#34;</span>
</span></span><span style="display:flex;"><span>CONCURRENCY<span style="color:#ff79c6">=</span>(<span style="color:#bd93f9">10</span> <span style="color:#bd93f9">50</span> <span style="color:#bd93f9">100</span>)
</span></span><span style="display:flex;"><span>DURATION<span style="color:#ff79c6">=</span><span style="color:#bd93f9">120</span>
</span></span><span style="display:flex;"><span>SCALE<span style="color:#ff79c6">=</span><span style="color:#bd93f9">100</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">function</span> <span style="color:#50fa7b">bench_mysql</span>() {
</span></span><span style="display:flex;"><span>    sysbench oltp_read_write \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>threads<span style="color:#ff79c6">=</span>$<span style="color:#bd93f9">1</span> \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>time<span style="color:#ff79c6">=</span><span style="color:#8be9fd;font-style:italic">$DURATION</span> \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>db<span style="color:#ff79c6">-</span>driver<span style="color:#ff79c6">=</span>mysql \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>mysql<span style="color:#ff79c6">-</span>host<span style="color:#ff79c6">=</span><span style="color:#8be9fd;font-style:italic">$DB_HOST</span> \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>mysql<span style="color:#ff79c6">-</span>port<span style="color:#ff79c6">=</span><span style="color:#8be9fd;font-style:italic">$DB_PORT_MYSQL</span> \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>mysql<span style="color:#ff79c6">-</span>user<span style="color:#ff79c6">=</span><span style="color:#8be9fd;font-style:italic">$DB_USER</span> \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>mysql<span style="color:#ff79c6">-</span>password<span style="color:#ff79c6">=</span><span style="color:#8be9fd;font-style:italic">$DB_PASS</span> \
</span></span><span style="display:flex;"><span>        <span style="color:#ff79c6">--</span>mysql<span style="color:#ff79c6">-</span>db<span style="color:#ff79c6">=</span><span style="color:#8be9fd;font-style:italic">$DB_NAME</span> run <span style="color:#ff79c6">|</span> tee mysql_${<span style="color:#bd93f9">1</span>}c<span style="color:#ff79c6">.</span>log
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">function</span> <span style="color:#50fa7b">bench_pgsql</span>() {
</span></span><span style="display:flex;"><span>    pgbench <span style="color:#ff79c6">-</span>h <span style="color:#8be9fd;font-style:italic">$DB_HOST</span> <span style="color:#ff79c6">-</span>p <span style="color:#8be9fd;font-style:italic">$DB_PORT_PG</span> <span style="color:#ff79c6">-</span>U <span style="color:#8be9fd;font-style:italic">$DB_USER</span> <span style="color:#ff79c6">-</span>d <span style="color:#8be9fd;font-style:italic">$DB_NAME</span> <span style="color:#ff79c6">-</span>c $<span style="color:#bd93f9">1</span> <span style="color:#ff79c6">-</span>T <span style="color:#8be9fd;font-style:italic">$DURATION</span> <span style="color:#ff79c6">-</span>j $(nproc) <span style="color:#ff79c6">|</span> tee pg_${<span style="color:#bd93f9">1</span>}c<span style="color:#ff79c6">.</span>log
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">if</span> [[ <span style="color:#8be9fd;font-style:italic">$DB_TYPE</span> <span style="color:#ff79c6">==</span> <span style="color:#f1fa8c">&#34;pgsql&#34;</span> ]]; then
</span></span><span style="display:flex;"><span>    pgbench <span style="color:#ff79c6">-</span>h <span style="color:#8be9fd;font-style:italic">$DB_HOST</span> <span style="color:#ff79c6">-</span>p <span style="color:#8be9fd;font-style:italic">$DB_PORT_PG</span> <span style="color:#ff79c6">-</span>U <span style="color:#8be9fd;font-style:italic">$DB_USER</span> <span style="color:#ff79c6">-</span>d <span style="color:#8be9fd;font-style:italic">$DB_NAME</span> <span style="color:#ff79c6">-</span>i <span style="color:#ff79c6">-</span>s <span style="color:#8be9fd;font-style:italic">$SCALE</span>
</span></span><span style="display:flex;"><span>fi
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">for</span> c in <span style="color:#f1fa8c">&#34;</span><span style="color:#f1fa8c">${</span><span style="color:#8be9fd;font-style:italic">CONCURRENCY[@]</span><span style="color:#f1fa8c">}</span><span style="color:#f1fa8c">&#34;</span>; <span style="color:#ff79c6">do</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">if</span> [[ <span style="color:#8be9fd;font-style:italic">$DB_TYPE</span> <span style="color:#ff79c6">==</span> <span style="color:#f1fa8c">&#34;mysql&#34;</span> ]]; then
</span></span><span style="display:flex;"><span>        bench_mysql <span style="color:#8be9fd;font-style:italic">$c</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">else</span>
</span></span><span style="display:flex;"><span>        bench_pgsql <span style="color:#8be9fd;font-style:italic">$c</span>
</span></span><span style="display:flex;"><span>    fi
</span></span><span style="display:flex;"><span>done
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">echo</span> <span style="color:#f1fa8c">&#34;压测完成，查看 *_c.log 文件&#34;</span>
</span></span></code></pre></div><h2 id="五压测结果分析与扩展建议">五、压测结果分析与扩展建议</h2>
<ul>
<li>提取日志中的TPS、延迟等数据，生成CSV</li>
<li>使用图表工具（Excel，Grafana，Matplotlib）绘制性能曲线</li>
<li>根据业务需求调整读写比、复杂查询和分布式架构测试</li>
<li>可集成监控系统，实现实时资源指标采样</li>
</ul>
<p>以上内容系统梳理了MySQL与PostgreSQL的技术对比，Python数据库操作示例，以及一整套可执行的数据库压测方案与脚本，便于用户快速搭建测试环境，评估性能，指导优化与选型。</p>
]]></content:encoded></item><item><title>Redis Docker开发环境配置指南</title><link>https://blog.heyaohua.com/posts/2024/03/redis-docker-development-guide/</link><pubDate>Tue, 19 Mar 2024 12:00:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2024/03/redis-docker-development-guide/</guid><description>本文档详细介绍如何使用Docker搭建Redis开发环境，包括环境配置、启动方式、维护方法等内容。</description><content:encoded><![CDATA[<h1 id="redis-docker开发环境配置指南">Redis Docker开发环境配置指南</h1>
<p>本文档详细介绍如何使用Docker搭建Redis开发环境，包括环境配置、启动方式、维护方法等内容。</p>
<h2 id="目录结构">目录结构</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Redis_Docker/
</span></span><span style="display:flex;"><span>├── .env                # 环境变量配置文件
</span></span><span style="display:flex;"><span>├── README.md          # 项目说明文档
</span></span><span style="display:flex;"><span>├── config/            # 配置文件目录
</span></span><span style="display:flex;"><span>│   └── redis.conf    # Redis配置文件
</span></span><span style="display:flex;"><span>├── data/             # 数据存储目录
</span></span><span style="display:flex;"><span>└── logs/             # 日志文件目录
</span></span></code></pre></div><h2 id="配置文件说明">配置文件说明</h2>
<h3 id="1-docker-composeyml">1. docker-compose.yml</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">version</span>: <span style="color:#f1fa8c">&#39;3.8&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">redis</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">container_name</span>: redis-server
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">image</span>: redis:7.2
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f1fa8c">&#34;${REDIS_PORT}:6379&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>      - ./data:/data
</span></span><span style="display:flex;"><span>      - ./logs:/var/log/redis
</span></span><span style="display:flex;"><span>      - ./config/redis.conf:/usr/local/etc/redis/redis.conf
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">command</span>: redis-server /usr/local/etc/redis/redis.conf
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">environment</span>:
</span></span><span style="display:flex;"><span>      - TZ=Asia/Shanghai
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">networks</span>:
</span></span><span style="display:flex;"><span>      - redis-network
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">healthcheck</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">test</span>: [<span style="color:#f1fa8c">&#34;CMD&#34;</span>, <span style="color:#f1fa8c">&#34;redis-cli&#34;</span>, <span style="color:#f1fa8c">&#34;ping&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">interval</span>: 10s
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">timeout</span>: 5s
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">retries</span>: <span style="color:#bd93f9">5</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">start_period</span>: 5s
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">networks</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">redis-network</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">driver</span>: bridge
</span></span></code></pre></div><h3 id="2-env-环境变量配置">2. .env 环境变量配置</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># Redis 配置环境变量
</span></span><span style="display:flex;"><span>REDIS_PORT=6379           # Redis端口映射
</span></span><span style="display:flex;"><span>REDIS_PASSWORD=your_password  # Redis访问密码
</span></span></code></pre></div><h3 id="3-redisconf-主要配置">3. redis.conf 主要配置</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 网络设置
</span></span><span style="display:flex;"><span>bind 0.0.0.0
</span></span><span style="display:flex;"><span>port 6379
</span></span><span style="display:flex;"><span>protected-mode yes
</span></span><span style="display:flex;"><span>tcp-keepalive 300
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 基本设置
</span></span><span style="display:flex;"><span>databases 16
</span></span><span style="display:flex;"><span>loglevel notice
</span></span><span style="display:flex;"><span>logfile &#34;/var/log/redis/redis.log&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 内存设置
</span></span><span style="display:flex;"><span>maxmemory 256mb
</span></span><span style="display:flex;"><span>maxmemory-policy allkeys-lru
</span></span><span style="display:flex;"><span>maxmemory-samples 5
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 持久化设置
</span></span><span style="display:flex;"><span>save 900 1      # 900秒内至少1个键被修改
</span></span><span style="display:flex;"><span>save 300 10     # 300秒内至少10个键被修改
</span></span><span style="display:flex;"><span>save 60 10000   # 60秒内至少10000个键被修改
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># AOF设置
</span></span><span style="display:flex;"><span>appendonly yes
</span></span><span style="display:flex;"><span>appendfilename &#34;appendonly.aof&#34;
</span></span><span style="display:flex;"><span>appendfsync everysec
</span></span></code></pre></div><h2 id="使用说明">使用说明</h2>
<h3 id="1-启动服务">1. 启动服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 启动服务</span>
</span></span><span style="display:flex;"><span>docker-compose up -d
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看服务状态</span>
</span></span><span style="display:flex;"><span>docker-compose ps
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看日志</span>
</span></span><span style="display:flex;"><span>docker-compose logs redis
</span></span></code></pre></div><h3 id="2-连接redis">2. 连接Redis</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 使用容器内的redis-cli</span>
</span></span><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> redis redis-cli -a your_password
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 使用主机的redis-cli（如果已安装）</span>
</span></span><span style="display:flex;"><span>redis-cli -h localhost -p <span style="color:#bd93f9">6379</span> -a your_password
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 测试连接</span>
</span></span><span style="display:flex;"><span>redis-cli -h localhost -p <span style="color:#bd93f9">6379</span> -a your_password ping
</span></span></code></pre></div><h3 id="3-停止服务">3. 停止服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 停止服务</span>
</span></span><span style="display:flex;"><span>docker-compose down
</span></span></code></pre></div><h2 id="数据持久化">数据持久化</h2>
<p>Redis配置了双重持久化机制：</p>
<h3 id="1-rdb持久化">1. RDB持久化</h3>
<ul>
<li>文件位置：data/dump.rdb</li>
<li>自动保存策略：</li>
<li>900秒内至少1个键被修改</li>
<li>300秒内至少10个键被修改</li>
<li>60秒内至少10000个键被修改</li>
</ul>
<h3 id="2-aof持久化">2. AOF持久化</h3>
<ul>
<li>文件位置：data/appendonly.aof</li>
<li>同步策略：everysec（每秒同步）</li>
<li>重写策略：auto-aof-rewrite-percentage 100</li>
</ul>
<h2 id="性能优化">性能优化</h2>
<h3 id="1-内存配置">1. 内存配置</h3>
<ul>
<li>maxmemory：设置为256MB</li>
<li>maxmemory-policy：使用allkeys-lru策略</li>
<li>maxmemory-samples：设置为5</li>
</ul>
<h3 id="2-网络优化">2. 网络优化</h3>
<ul>
<li>tcp-keepalive：300秒</li>
<li>tcp-backlog：511</li>
</ul>
<h3 id="3-持久化优化">3. 持久化优化</h3>
<ul>
<li>appendfsync：everysec</li>
<li>no-appendfsync-on-rewrite：no</li>
</ul>
<h2 id="安全配置">安全配置</h2>
<h3 id="1-网络安全">1. 网络安全</h3>
<ul>
<li>protected-mode：启用</li>
<li>bind：0.0.0.0（允许所有IP访问）</li>
<li>requirepass：设置访问密码</li>
</ul>
<h3 id="2-客户端限制">2. 客户端限制</h3>
<ul>
<li>maxclients：10000</li>
<li>timeout：0（不自动断开空闲连接）</li>
</ul>
<h2 id="监控和维护">监控和维护</h2>
<h3 id="1-性能监控">1. 性能监控</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 查看服务器信息
</span></span><span style="display:flex;"><span>redis-cli -a your_password INFO
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 监控命令执行
</span></span><span style="display:flex;"><span>redis-cli -a your_password MONITOR
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 查看慢查询日志
</span></span><span style="display:flex;"><span>redis-cli -a your_password SLOWLOG GET
</span></span></code></pre></div><h3 id="2-内存分析">2. 内存分析</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 查看内存使用情况
</span></span><span style="display:flex;"><span>redis-cli -a your_password INFO memory
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 查看大键
</span></span><span style="display:flex;"><span>redis-cli -a your_password --bigkeys
</span></span></code></pre></div><h3 id="3-数据备份">3. 数据备份</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 手动触发RDB备份
</span></span><span style="display:flex;"><span>redis-cli -a your_password SAVE
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 异步触发RDB备份
</span></span><span style="display:flex;"><span>redis-cli -a your_password BGSAVE
</span></span></code></pre></div><h2 id="常见问题处理">常见问题处理</h2>
<h3 id="1-连接失败">1. 连接失败</h3>
<ul>
<li>检查密码是否正确</li>
<li>确认端口映射是否正确</li>
<li>验证Redis服务是否正常运行</li>
</ul>
<h3 id="2-内存问题">2. 内存问题</h3>
<ul>
<li>检查maxmemory设置</li>
<li>查看内存使用情况</li>
<li>考虑调整内存策略</li>
</ul>
<h3 id="3-持久化问题">3. 持久化问题</h3>
<ul>
<li>检查磁盘空间</li>
<li>查看AOF/RDB文件状态</li>
<li>确认写入权限</li>
</ul>
<h2 id="最佳实践">最佳实践</h2>
<h3 id="1-安全建议">1. 安全建议</h3>
<ul>
<li>使用强密码</li>
<li>限制可访问的IP</li>
<li>定期更新Redis版本</li>
</ul>
<h3 id="2-性能建议">2. 性能建议</h3>
<ul>
<li>合理设置内存上限</li>
<li>选择适当的持久化策略</li>
<li>监控慢查询</li>
</ul>
<h3 id="3-运维建议">3. 运维建议</h3>
<ul>
<li>定期备份数据</li>
<li>监控系统资源</li>
<li>保持日志分析</li>
</ul>
]]></content:encoded></item><item><title>PostgreSQL Docker开发环境配置指南</title><link>https://blog.heyaohua.com/posts/2024/03/postgresql-docker-development-guide/</link><pubDate>Tue, 19 Mar 2024 11:30:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2024/03/postgresql-docker-development-guide/</guid><description>本文档详细介绍如何使用Docker搭建PostgreSQL开发环境，包括环境配置、启动方式、维护方法等内容。</description><content:encoded><![CDATA[<h1 id="postgresql-docker开发环境配置指南">PostgreSQL Docker开发环境配置指南</h1>
<p>本文档详细介绍如何使用Docker搭建PostgreSQL开发环境，包括环境配置、启动方式、维护方法等内容。</p>
<h2 id="目录结构">目录结构</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>PgSQL_Docker/
</span></span><span style="display:flex;"><span>├── .env                  # 环境变量配置文件
</span></span><span style="display:flex;"><span>├── README.md            # 项目说明文档
</span></span><span style="display:flex;"><span>├── config/              # 配置文件目录
</span></span><span style="display:flex;"><span>│   ├── pg_hba.conf     # 访问控制配置
</span></span><span style="display:flex;"><span>│   └── postgresql.conf  # PostgreSQL主配置文件
</span></span><span style="display:flex;"><span>├── data/               # 数据存储目录
</span></span><span style="display:flex;"><span>└── logs/               # 日志文件目录
</span></span></code></pre></div><h2 id="配置文件说明">配置文件说明</h2>
<h3 id="1-docker-composeyml">1. docker-compose.yml</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">version</span>: <span style="color:#f1fa8c">&#39;3.8&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">postgres</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">container_name</span>: postgres-server
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">image</span>: postgres:15
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">environment</span>:
</span></span><span style="display:flex;"><span>      - POSTGRES_DB=${POSTGRES_DB}
</span></span><span style="display:flex;"><span>      - POSTGRES_USER=${POSTGRES_USER}
</span></span><span style="display:flex;"><span>      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f1fa8c">&#34;${POSTGRES_PORT}:5432&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>      - ./data:/var/lib/postgresql/data
</span></span><span style="display:flex;"><span>      - ./logs:/var/log/postgresql
</span></span><span style="display:flex;"><span>      - ./config/postgresql.conf:/etc/postgresql/postgresql.conf
</span></span><span style="display:flex;"><span>      - ./config/pg_hba.conf:/etc/postgresql/pg_hba.conf
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">command</span>: postgres -c &#39;config_file=/etc/postgresql/postgresql.conf&#39;
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">networks</span>:
</span></span><span style="display:flex;"><span>      - postgres-network
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">healthcheck</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">test</span>: [<span style="color:#f1fa8c">&#34;CMD-SHELL&#34;</span>, <span style="color:#f1fa8c">&#34;pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">interval</span>: 10s
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">timeout</span>: 5s
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">retries</span>: <span style="color:#bd93f9">5</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">start_period</span>: 10s
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">networks</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">postgres-network</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">driver</span>: bridge
</span></span></code></pre></div><h3 id="2-env-环境变量配置">2. .env 环境变量配置</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># PostgreSQL 配置环境变量
</span></span><span style="display:flex;"><span>POSTGRES_DB=test_db           # 数据库名称
</span></span><span style="display:flex;"><span>POSTGRES_USER=data           # 默认超级用户
</span></span><span style="display:flex;"><span>POSTGRES_PASSWORD=your_password  # 用户密码
</span></span><span style="display:flex;"><span>POSTGRES_PORT=5432          # 端口映射
</span></span></code></pre></div><h3 id="3-postgresqlconf-主要配置">3. postgresql.conf 主要配置</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># 连接设置
</span></span><span style="display:flex;"><span>listen_addresses = &#39;*&#39;
</span></span><span style="display:flex;"><span>port = 5432
</span></span><span style="display:flex;"><span>max_connections = 100
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 内存设置
</span></span><span style="display:flex;"><span>shared_buffers = 128MB
</span></span><span style="display:flex;"><span>work_mem = 4MB
</span></span><span style="display:flex;"><span>maintenance_work_mem = 64MB
</span></span><span style="display:flex;"><span>effective_cache_size = 512MB
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 写入设置
</span></span><span style="display:flex;"><span>wal_level = replica
</span></span><span style="display:flex;"><span>max_wal_size = 1GB
</span></span><span style="display:flex;"><span>min_wal_size = 80MB
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 日志设置
</span></span><span style="display:flex;"><span>log_destination = &#39;stderr&#39;
</span></span><span style="display:flex;"><span>logging_collector = on
</span></span><span style="display:flex;"><span>log_directory = &#39;/var/log/postgresql&#39;
</span></span><span style="display:flex;"><span>log_filename = &#39;postgresql-%Y-%m-%d_%H%M%S.log&#39;
</span></span><span style="display:flex;"><span>log_rotation_age = 1d
</span></span><span style="display:flex;"><span>log_rotation_size = 10MB
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 区域设置
</span></span><span style="display:flex;"><span>datestyle = &#39;iso, mdy&#39;
</span></span><span style="display:flex;"><span>timezone = &#39;UTC&#39;
</span></span><span style="display:flex;"><span>lc_messages = &#39;en_US.utf8&#39;
</span></span></code></pre></div><h3 id="4-pg_hbaconf-访问控制配置">4. pg_hba.conf 访问控制配置</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span># TYPE  DATABASE        USER            ADDRESS                 METHOD
</span></span><span style="display:flex;"><span>local   all            all                                     trust
</span></span><span style="display:flex;"><span>host    all            all             127.0.0.1/32           scram-sha-256
</span></span><span style="display:flex;"><span>host    all            all             ::1/128                scram-sha-256
</span></span><span style="display:flex;"><span>host    all            all             0.0.0.0/0              scram-sha-256
</span></span></code></pre></div><h2 id="使用说明">使用说明</h2>
<h3 id="1-启动服务">1. 启动服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 启动服务</span>
</span></span><span style="display:flex;"><span>docker-compose up -d
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看服务状态</span>
</span></span><span style="display:flex;"><span>docker-compose ps
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看日志</span>
</span></span><span style="display:flex;"><span>docker-compose logs postgres
</span></span></code></pre></div><h3 id="2-连接数据库">2. 连接数据库</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 使用超级用户连接</span>
</span></span><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> postgres psql -U data -d test_db
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看用户列表和权限</span>
</span></span><span style="display:flex;"><span><span style="color:#f1fa8c">\d</span>u
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看数据库列表</span>
</span></span><span style="display:flex;"><span><span style="color:#f1fa8c">\l</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 退出psql</span>
</span></span><span style="display:flex;"><span><span style="color:#f1fa8c">\q</span>
</span></span></code></pre></div><h3 id="3-停止服务">3. 停止服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 停止服务</span>
</span></span><span style="display:flex;"><span>docker-compose down
</span></span></code></pre></div><h2 id="用户和权限管理">用户和权限管理</h2>
<p>PostgreSQL使用角色（Role）概念来管理用户权限。在我们的配置中：</p>
<ol>
<li>通过<code>POSTGRES_USER</code>环境变量创建的用户（本例中为&quot;data&quot;）是超级用户，具有所有权限：</li>
<li>Superuser（超级用户权限）</li>
<li>Create role（创建角色权限）</li>
<li>Create DB（创建数据库权限）</li>
<li>Replication（复制权限）</li>
<li></li>
</ol>
<p>Bypass RLS（绕过行级安全性）</p>
<ol start="7">
<li></li>
</ol>
<p>创建新用户示例：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">CREATE</span> <span style="color:#ff79c6">ROLE</span> username <span style="color:#ff79c6">WITH</span> LOGIN PASSWORD <span style="color:#f1fa8c">&#39;password&#39;</span>;
</span></span></code></pre></div><ol>
<li>授予权限示例：</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>GRANT ALL PRIVILEGES ON DATABASE dbname TO username;
</span></span></code></pre></div><h2 id="数据备份和恢复">数据备份和恢复</h2>
<h3 id="备份数据">备份数据</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 备份整个数据库</span>
</span></span><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> postgres pg_dump -U data test_db &gt; backup.sql
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 备份特定表</span>
</span></span><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> postgres pg_dump -U data -t table_name test_db &gt; table_backup.sql
</span></span></code></pre></div><h3 id="恢复数据">恢复数据</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 恢复数据</span>
</span></span><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> -T postgres psql -U data test_db &lt; backup.sql
</span></span></code></pre></div><h2 id="性能优化建议">性能优化建议</h2>
<ol>
<li>内存配置</li>
<li><code>shared_buffers</code>: 建议设置为系统内存的25%</li>
<li><code>effective_cache_size</code>: 建议设置为系统内存的50%</li>
<li></li>
</ol>
<p><code>work_mem</code>: 根据并发连接数调整</p>
<ol start="5">
<li></li>
</ol>
<p>写入性能</p>
<ol start="6">
<li><code>wal_buffers</code>: 建议设置为16MB</li>
<li><code>checkpoint_timeout</code>: 可根据写入压力调整</li>
<li></li>
</ol>
<p><code>max_wal_size</code>: 根据磁盘空间调整</p>
<ol start="9">
<li></li>
</ol>
<p>连接池</p>
<ol start="10">
<li>建议使用pgBouncer等连接池管理工具</li>
<li>避免频繁创建新连接</li>
</ol>
<h2 id="常见问题处理">常见问题处理</h2>
<ol>
<li>容器无法启动</li>
<li>检查端口占用：<code>lsof -i :5432</code></li>
<li>检查配置文件权限</li>
<li></li>
</ol>
<p>查看错误日志：<code>docker-compose logs postgres</code></p>
<ol start="5">
<li></li>
</ol>
<p>连接失败</p>
<ol start="6">
<li>确认用户名和密码正确</li>
<li>检查pg_hba.conf配置</li>
<li></li>
</ol>
<p>验证网络连接</p>
<ol start="9">
<li></li>
</ol>
<p>性能问题</p>
<ol start="10">
<li>检查慢查询日志</li>
<li>使用EXPLAIN分析查询计划</li>
<li>优化索引和查询语句</li>
</ol>
<h2 id="安全建议">安全建议</h2>
<ol>
<li>密码安全</li>
<li>使用强密码</li>
<li>定期更换密码</li>
<li></li>
</ol>
<p>避免在命令行中明文输入密码</p>
<ol start="5">
<li></li>
</ol>
<p>网络安全</p>
<ol start="6">
<li>限制访问IP</li>
<li>使用SSL连接</li>
<li></li>
</ol>
<p>定期更新PostgreSQL版本</p>
<ol start="9">
<li></li>
</ol>
<p>权限控制</p>
<ol start="10">
<li>遵循最小权限原则</li>
<li>使用角色管理权限</li>
<li>启用行级安全性（RLS）</li>
</ol>
<h2 id="维护建议">维护建议</h2>
<ol>
<li>定期维护</li>
<li>执行VACUUM操作</li>
<li>更新统计信息</li>
<li></li>
</ol>
<p>检查日志文件大小</p>
<ol start="5">
<li></li>
</ol>
<p>监控</p>
<ol start="6">
<li>监控连接数</li>
<li>监控磁盘使用</li>
<li></li>
</ol>
<p>监控查询性能</p>
<ol start="9">
<li></li>
</ol>
<p>备份策略</p>
<ol start="10">
<li>定期备份</li>
<li>测试恢复流程</li>
</ol>
]]></content:encoded></item><item><title>MySQL Docker开发环境配置指南</title><link>https://blog.heyaohua.com/posts/2024/03/mysql-docker-development-guide/</link><pubDate>Tue, 19 Mar 2024 11:00:00 +0800</pubDate><guid>https://blog.heyaohua.com/posts/2024/03/mysql-docker-development-guide/</guid><description>重要配置说明： - - 容器异常退出时自动重启 - - 环境变量配置，支持从.env文件读取 - - 数据持久化配置，确保数据安全 - - 端口映射，允 …</description><content:encoded><![CDATA[<h1 id="如何使用docker启动mysql开发环境">如何使用Docker启动MySQL开发环境</h1>
<h2 id="目录结构">目录结构</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>MySQL_Docker/
</span></span><span style="display:flex;"><span>├── docker-compose.yml    # Docker Compose 配置文件
</span></span><span style="display:flex;"><span>├── .env                 # 环境变量配置
</span></span><span style="display:flex;"><span>├── config/
</span></span><span style="display:flex;"><span>│   └── my.cnf          # MySQL 配置文件
</span></span><span style="display:flex;"><span>├── data/               # MySQL 数据目录 (挂载)
</span></span><span style="display:flex;"><span>└── logs/               # MySQL 日志目录 (挂载)
</span></span></code></pre></div><h2 id="配置文件说明">配置文件说明</h2>
<h3 id="1-docker-composeyml-配置要点">1. docker-compose.yml 配置要点</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">version</span>: <span style="color:#f1fa8c">&#39;3.8&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">mysql</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">image</span>: mysql:8.0
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">container_name</span>: mysql-server
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">restart</span>: unless-stopped
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">MYSQL_ROOT_PASSWORD</span>: ${MYSQL_ROOT_PASSWORD:-root123}
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">MYSQL_DATABASE</span>: ${MYSQL_DATABASE:-testdb}
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">MYSQL_USER</span>: ${MYSQL_USER:-testuser}
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">MYSQL_PASSWORD</span>: ${MYSQL_PASSWORD:-testpass}
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f1fa8c">&#34;${MYSQL_PORT:-3306}:3306&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ff79c6">volumes</span>:
</span></span><span style="display:flex;"><span>      - ./data:/var/lib/mysql
</span></span><span style="display:flex;"><span>      - ./logs:/var/log/mysql
</span></span><span style="display:flex;"><span>      - ./config/my.cnf:/etc/mysql/conf.d/my.cnf
</span></span></code></pre></div><p><strong>重要配置说明：</strong></p>
<ul>
<li><code>restart: unless-stopped</code> - 容器异常退出时自动重启</li>
<li><code>environment</code> - 环境变量配置，支持从.env文件读取</li>
<li><code>volumes</code> - 数据持久化配置，确保数据安全</li>
<li><code>ports</code> - 端口映射，允许外部访问</li>
</ul>
<h3 id="2-mysql配置文件-mycnf-要点">2. MySQL配置文件 (my.cnf) 要点</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>[mysqld]
</span></span><span style="display:flex;"><span># 基本设置
</span></span><span style="display:flex;"><span>port = <span style="color:#bd93f9">3306</span>
</span></span><span style="display:flex;"><span>bind-address = <span style="color:#bd93f9">0.0</span>.<span style="color:#bd93f9">0.0</span>
</span></span><span style="display:flex;"><span>default-storage-engine = InnoDB
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 字符集设置（重要）
</span></span><span style="display:flex;"><span>character-set-server = utf<span style="color:#bd93f9">8</span>mb<span style="color:#bd93f9">4</span>
</span></span><span style="display:flex;"><span>collation-server = utf<span style="color:#bd93f9">8</span>mb<span style="color:#bd93f9">4</span>_unicode_ci
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 连接设置
</span></span><span style="display:flex;"><span>max_connections = <span style="color:#bd93f9">200</span>
</span></span><span style="display:flex;"><span>max_connect_errors = <span style="color:#bd93f9">10</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 缓冲区设置
</span></span><span style="display:flex;"><span>innodb_buffer_pool_size = <span style="color:#bd93f9">256</span>M
</span></span><span style="display:flex;"><span>innodb_log_file_size = <span style="color:#bd93f9">64</span>M
</span></span><span style="display:flex;"><span>innodb_log_buffer_size = <span style="color:#bd93f9">16</span>M
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span># 日志设置
</span></span><span style="display:flex;"><span>log-error = /var/log/mysql/error.log
</span></span><span style="display:flex;"><span>slow_query_log = <span style="color:#bd93f9">1</span>
</span></span><span style="display:flex;"><span>slow_query_log_file = /var/log/mysql/slow.log
</span></span><span style="display:flex;"><span>long_query_time = <span style="color:#bd93f9">2</span>
</span></span></code></pre></div><p><strong>配置注意事项：</strong></p>
<ol>
<li>字符集必须设置为utf8mb4，以支持完整的Unicode字符集</li>
<li>根据服务器内存调整缓冲区大小</li>
<li>开启慢查询日志便于性能优化</li>
<li>MySQL 8.0已不支持查询缓存（query_cache）相关配置</li>
</ol>
<h3 id="3-环境变量配置-env">3. 环境变量配置 (.env)</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>MYSQL_ROOT_PASSWORD=your_root_password
</span></span><span style="display:flex;"><span>MYSQL_DATABASE=your_database
</span></span><span style="display:flex;"><span>MYSQL_USER=your_user
</span></span><span style="display:flex;"><span>MYSQL_PASSWORD=your_password
</span></span><span style="display:flex;"><span>MYSQL_PORT=3306
</span></span></code></pre></div><p><strong>安全注意事项：</strong></p>
<ul>
<li>生产环境必须修改默认密码</li>
<li>.env文件不要提交到版本控制系统</li>
<li>定期更换密码</li>
<li>避免使用弱密码</li>
</ul>
<h2 id="启动和维护">启动和维护</h2>
<h3 id="启动服务">启动服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose up -d
</span></span></code></pre></div><h3 id="查看服务状态">查看服务状态</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose ps
</span></span></code></pre></div><h3 id="查看日志">查看日志</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 查看容器日志</span>
</span></span><span style="display:flex;"><span>docker-compose logs mysql
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看错误日志</span>
</span></span><span style="display:flex;"><span>tail -f logs/error.log
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6272a4"># 查看慢查询日志</span>
</span></span><span style="display:flex;"><span>tail -f logs/slow.log
</span></span></code></pre></div><h3 id="停止服务">停止服务</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose down
</span></span></code></pre></div><h2 id="常见问题处理">常见问题处理</h2>
<h3 id="1-容器无法启动或反复重启">1. 容器无法启动或反复重启</h3>
<ul>
<li>检查数据目录权限</li>
<li>查看错误日志（logs/error.log）</li>
<li>确认配置文件语法正确</li>
<li>验证端口是否被占用</li>
</ul>
<h3 id="2-连接失败">2. 连接失败</h3>
<ul>
<li>确认容器运行状态</li>
<li>检查端口映射</li>
<li>验证用户名密码</li>
<li>检查防火墙设置</li>
</ul>
<h3 id="3-性能问题">3. 性能问题</h3>
<ul>
<li>检查慢查询日志</li>
<li>调整缓冲区大小</li>
<li>优化索引</li>
<li>监控资源使用情况</li>
</ul>
<h2 id="数据备份建议">数据备份建议</h2>
<h3 id="1-使用docker-compose执行备份">1. 使用docker-compose执行备份</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> mysql mysqldump -u root -p database_name &gt; backup.sql
</span></span></code></pre></div><h3 id="2-自动备份脚本示例">2. 自动备份脚本示例</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#ff79c6">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">backup_dir</span><span style="color:#ff79c6">=</span><span style="color:#f1fa8c">&#34;backups&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">date_format</span><span style="color:#ff79c6">=</span><span style="color:#ff79c6">$(</span>date +%Y%m%d_%H%M%S<span style="color:#ff79c6">)</span>
</span></span><span style="display:flex;"><span>docker-compose <span style="color:#8be9fd;font-style:italic">exec</span> -T mysql mysqldump -u root -p database_name &gt; <span style="color:#f1fa8c">&#34;</span><span style="color:#f1fa8c">${</span><span style="color:#8be9fd;font-style:italic">backup_dir</span><span style="color:#f1fa8c">}</span><span style="color:#f1fa8c">/backup_</span><span style="color:#f1fa8c">${</span><span style="color:#8be9fd;font-style:italic">date_format</span><span style="color:#f1fa8c">}</span><span style="color:#f1fa8c">.sql&#34;</span>
</span></span></code></pre></div><h2 id="安全建议">安全建议</h2>
<ol>
<li>网络安全</li>
<li>限制端口访问</li>
<li>使用专用网络</li>
<li></li>
</ol>
<p>启用SSL/TLS加密</p>
<ol start="5">
<li></li>
</ol>
<p>账户安全</p>
<ol start="6">
<li>定期更换密码</li>
<li>限制用户权限</li>
<li></li>
</ol>
<p>删除未使用的账户</p>
<ol start="9">
<li></li>
</ol>
<p>数据安全</p>
<ol start="10">
<li>定期备份</li>
<li>加密敏感数据</li>
<li>监控异常访问</li>
</ol>
<h2 id="性能优化建议">性能优化建议</h2>
<ol>
<li>硬件资源</li>
<li>适当分配内存</li>
<li>使用SSD存储</li>
<li></li>
</ol>
<p>监控CPU使用率</p>
<ol start="5">
<li></li>
</ol>
<p>配置优化</p>
<ol start="6">
<li>调整缓冲池大小</li>
<li>优化日志设置</li>
<li></li>
</ol>
<p>配置合适的连接数</p>
<ol start="9">
<li></li>
</ol>
<p>查询优化</p>
<ol start="10">
<li>建立合适的索引</li>
<li>优化SQL语句</li>
<li>定期维护统计信息</li>
</ol>
]]></content:encoded></item></channel></rss>