-
还在为毕设画图焦头烂额?这款专为大学生打造的论文画图神器来救场! 上传代码即可智能解析,一键生成以下核心图表:ER图(实体关系图)系统架构图功能模块图时序图用例图数据流图业务流程图使用方法:打开🛰,搜索「毕设论文AI智能画图助手」上传你的项目代码选择需要生成的图表类型一键生成,直接导出使用适用场景:毕业设计论文课程设计报告项目文档编写系统设计说明让论文图表不再是噩梦,快来试试吧!
-
本文发出主要共同探讨目的。找出问题和其他,配置稳定到极限 非常遗憾PostgreSQL官方只支持流复制数据同步,不支持故障检测切换。所以需要第三方来实现。在网上寻找方案过程中发现 Postgresql 流复制/patroni/etcd 组合 这个方案用的挺多。PostgreSQL流复制(数据同步) - 官方Patroni - 第三方开源etcd - 第三方开源整体工作逻辑架构拓扑PostgreSQL + Patroni项目说明部署建议Patroni 与 PostgreSQL 同机部署,以便使用本地控制命令(如 pg_ctl promote),降低网络依赖与权限复杂度。节点规模最少 3 台,最多 9 个节点节点扩展影响从库数量增加会导致主库 WAL 发送压力上升、网络带宽消耗增加,并可能引起复制延迟(replication lag)上升,需合理规划规模。PostgreSQL 角色数据库引擎(负责数据存储与读写)Patroni 角色高可用控制器(负责集群管理、主从选举与故障切换)数据同步方式PostgreSQL 原生流复制(Streaming Replication)核心能力Leader 选举、健康检查、自动故障切换(Failover)、集群状态一致性维护切换机制通过 pg_ctl promote 或等价机制完成主库提升状态依赖依赖 DCS(如 etcd)进行分布式一致性协调与选举仲裁etcd 分布式配置存储(DCS)项目说明角色定位分布式配置存储(DCS),用于为 Patroni 提供一致性状态管理与选举仲裁能力。最少数量3 台最多数量5 台或 7 台(节点过多会增加 Raft 写入确认开销,影响性能;建议使用奇数节点以保证多数派选举效率。)部署建议建议独立部署 etcd,以避免与数据库资源竞争和故障耦合,保证 Raft 选举的稳定性与低延迟。核心职责作为 Patroni 的仲裁与状态存储组件,用于维护集群状态与 Leader 信息,并通过 Raft 协议保证一致性;同时需以集群方式部署以避免单点故障。HAProxy + Keepalived项目说明HAProxy 角色作为四层负载均衡组件,基于 Patroni 提供的健康检查 API 识别主备角色,实现写请求转发至主库、读请求分发至备库。HAProxy 数量2 台(主备模式)即可满足高可用需求Keepalived 角色通过 VRRP 为 HAProxy 提供 VIP,实现主备切换以避免单点故障Keepalived 部署建议和HAProxy 同机部署 方案1(不推荐)概率性逻辑缺陷非技术上无法实现服务器组件其他主 - 服务器-01PostgreSQL + Patroni + etcd(Leader)HAProxy实现读写分离,读负载均衡,识别后端健康节点不推荐etcd和其他组件混合原因纯硬件故障:主设备完全故障,etcd 立刻知道它的状态,其他节点快速接管,虽然中断但逻辑清晰。(此过程无问题)性能缺失:主节点还正常,但(CPU,RAM,DISK)资源占满,etcd 无法正常判断当前正常还是故障 → 进入逻辑混乱状态。后果:混乱导致脑裂、双主、数据冲突,恢复时间从分钟级变成小时级,且可能丢数据。(此过程会有问题)降低资源沾满导致混乱问题技巧(只能降低,无法彻底解决)通过postgresql.conf 配置限制使用内存上线80%通过一种手段限制postgresql数据库CPU使用上线到80%剩余20% 资源留给操作系统和patroni,etcd使用从 - 服务器-02PostgreSQL + Patroni + etcd(Follower)从 - 服务器-03PostgreSQL + Patroni + etcd(Follower)主 - 服务器-04HAProxy + Keepalived备 - 服务器-05HAProxy + Keepalived方案2(不推荐,比方案1优)服务器组件其他主 - 服务器-01PostgreSQL + PatroniHAProxy实现读写分离,读负载均衡,识别后端健康节点HAProxy 占用资源100% 机率比PostgreSQL少很多,所以这个组合比方案1靠谱 仍然存在HAProxy 资源100% 引起集群混乱概率仍需要通过一种手段把每个组件资源使用率限制不要让他占用100%影响其他组件从 - 服务器-02PostgreSQL + Patroni从 - 服务器-03PostgreSQL + PatroniLeader - 服务器-04etcdFollower - 服务器-05etcd + 主HAProxy + KeepalivedFollower - 服务器-06etcd + 备HAProxy + Keepalived方案3(强烈最低配推荐)服务器组件其他主 - 服务器-01PostgreSQL + PatroniHAProxy实现读写分离,读负载均衡,识别后端健康节点为什么PostgreSQL + Patroni 可以混合一台机器比如node1 当前主 Postgresql 引起资源占用 100% 导致 Patroni 无法工作,此时因为Patroni无法给etcd续约当前正常信号,所以集群认为故障直接切换到新节点提升主从 - 服务器-02PostgreSQL + Patroni从 - 服务器-03PostgreSQL + PatroniLeader - 服务器-04etcdFollower - 服务器-05etcdFollower - 服务器-06etcd主 - 服务器-07HAProxy + Keepalived备 - 服务器-08HAProxy + KeepalivedPostgreSQL 此案例服务器规划 HostnameIP组件操作系统数据库版本组件版本pgsql-node-01.itxinxi.net10.10.1.101PostgreSQL + PatroniRocky Linux9 64bitPostgreSQL v17.7Patroni v4.1.2pgsql-node-02.itxinxi.net10.10.1.102PostgreSQL + PatroniRocky Linux9 64bitPostgreSQL v17.7Patroni v4.1.2pgsql-node-03.itxinxi.net10.10.1.103PostgreSQL + PatroniRocky Linux9 64bitPostgreSQL v17.7Patroni v4.1.2etcd-node-01.itxinxi.net10.10.1.104etcdRocky Linux9 64bit-etcd v3.6.11etcd-node-02.itxinxi.net10.10.1.105etcdRocky Linux9 64bit-etcd v3.6.11etcd-node-03.itxinxi.net10.10.1.106etcdRocky Linux9 64bit-etcd v3.6.11haproxy-node-01.itxinxi.net10.10.1.107HAProxy + KeepalivedRocky Linux9 64bit-HAProxy 3.3.x / Keepalived v2.3.4haproxy-node-02.itxinxi.net10.10.1.108HAProxy + KeepalivedRocky Linux9 64bit-HAProxy 3.3.x / Keepalived v2.3.4PostgreSQL安装之后无需手动启动(Patroni 接管postgresql.conf配置参数,初始化,启动服务)[root@pgsql-node-01 ~]# dnf install -y gcc make readline-devel zlib-devel flex bison libxml2-devel libxslt-devel openssl-devel systemd-devel perl lz4-devel krb5-devel pam-devel[root@pgsql-node-01 ~]# wget https://ftp.postgresql.org/pub/source/v17.7/postgresql-17.7.tar.gz[root@pgsql-node-01 ~]# tar zxvf postgresql-17.7.tar.gz[root@pgsql-node-01 ~]# cd postgresql-17.7[root@pgsql-node-01 postgresql-17.7]# ./configure --prefix=/usr/local/postgresql --with-openssl --with-libxml --with-systemd --without-icu --with-lz4 --with-zstd --with-gssapi --with-pam[root@pgsql-node-01 postgresql-17.7]# make -j $(nproc)[root@pgsql-node-01 postgresql-17.7]# make install[root@pgsql-node-01 postgresql-17.7]# useradd postgres[root@pgsql-node-01 postgresql-17.7]# chown -R postgres:postgres /usr/local/postgresql/[root@pgsql-node-01 ~]# echo 'export PATH=/usr/local/postgresql/bin:$PATH' >> /etc/profile[root@pgsql-node-01 ~]# source /etc/profile[root@pgsql-node-01 ~]# psql -Vpsql (PostgreSQL) 17.7所有节点配置hosts[root@pgsql-node-01 ~]# vim /etc/hosts10.10.1.101 pgsql-node-01.itxinxi.net10.10.1.102 pgsql-node-02.itxinxi.net10.10.1.103 pgsql-node-03.itxinxi.net10.10.1.104 etcd-node-01.itxinxi.net10.10.1.105 etcd-node-02.itxinxi.net10.10.1.106 etcd-node-03.itxinxi.net10.10.1.107 haproxy-node-01.itxinxi.net10.10.1.108 haproxy-node-02.itxinxi.netPatroni 源码初始安装(在pgsql-node-01,02,03安装)[root@pgsql-node-01 ~]# wget https://files.pythonhosted.org/packages/14/84/1dea5b4a178d294e47ac4aa9c2b6727dc55fc4d1d292f2beac59a00b3838/patroni-4.1.2.tar.gz[root@pgsql-node-01 ~]# dnf install -y python3-devel postgresql-libs postgresql-devel[root@pgsql-node-01 ~]# cd patroni-4.1.2/[root@pgsql-node-01 patroni-4.1.2]# pip3 install wheel[root@pgsql-node-01 patroni-4.1.2]# pip3 install .[etcd3,psycopg2]patroni.yml 配置内容[root@pgsql-node-01 ~]# mkdir -p /usr/local/postgresql/logs /usr/local/postgresql/patroni/logs /usr/local/postgresql/ssl /usr/local/postgresql/patroni/ssl[root@pgsql-node-01 ~]# vim /usr/local/postgresql/patroni/patroni.yml# =====================================================# Patroni PostgreSQL HA 集群配置# 节点: pgsql-node-01.itxinxi.net (初始主节点)# =====================================================scope: postgres-clustername: pgsql-node-01.itxinxi.netnamespace: /service/# =====================================================# REST API 配置# =====================================================restapi: listen: 0.0.0.0:8008 connect_address: pgsql-node-01.itxinxi.net:8008# =====================================================# DCS 配置 (etcd)# =====================================================etcd3: hosts: - 'etcd-node-01.itxinxi.net:2379' - 'etcd-node-02.itxinxi.net:2379' - 'etcd-node-03.itxinxi.net:2379' protocol: http request_timeout: 30 connect_timeout: 10 host_check_interval: 15# =====================================================# Bootstrap 配置(仅首次初始化使用)# =====================================================bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 master_start_timeout: 300 maximum_lag_on_failover: 1048576 synchronous_mode: true synchronous_mode_strict: true synchronous_node_count: 1 postgresql: use_pg_rewind: true use_slots: true # ========== 集群全局参数(通过 DCS 管理)========== parameters: max_connections: 400 wal_level: replica max_wal_senders: 20 max_replication_slots: 15 # ========== 安全 ========== password_encryption: 'scram-sha-256' # ========== 内存配置 ========== shared_buffers: '8GB' # ========== 复制配置 ========== wal_keep_size: '4GB' # ========== 查询优化 ========== max_worker_processes: 16 pg_hba: - local replication replicator peer - local all all peer - host all all 127.0.0.1/32 scram-sha-256 - host replication replicator 10.10.1.0/24 scram-sha-256 - host all rewind 10.10.1.0/24 scram-sha-256 - host all all 0.0.0.0/0 scram-sha-256 initdb: - encoding: UTF8 - data-checksums - auth: scram-sha-256 - auth-host: scram-sha-256# =====================================================# PostgreSQL 运行时配置# =====================================================postgresql: listen: 0.0.0.0:5432 connect_address: pgsql-node-01.itxinxi.net:5432 data_dir: /usr/local/postgresql/data bin_dir: /usr/local/postgresql/bin pgpass: /usr/local/postgresql/.pgpass failover_priority: 100 authentication: replication: username: replicator password: '234234.com' superuser: username: postgres password: '123123.com' rewind: username: rewind password: '345345.com' parameters: # ========== 连接配置 ========== superuser_reserved_connections: 5 unix_socket_directories: '/tmp' # ========== 内存配置 ========== huge_pages: 'try' work_mem: '8MB' maintenance_work_mem: '512MB' wal_buffers: '16MB' effective_cache_size: '24GB' dynamic_shared_memory_type: 'posix' # ========== WAL 配置 ========== fsync: 'on' wal_log_hints: 'on' max_wal_size: '8GB' min_wal_size: '4GB' checkpoint_completion_target: 0.8 commit_delay: 0 commit_siblings: 5 # ========== 复制配置 ========== hot_standby: 'on' hot_standby_feedback: 'on' max_slot_wal_keep_size: '8GB' wal_sender_timeout: '30s' wal_receiver_timeout: '30s' synchronous_commit: 'on' # ========== 查询优化 ========== random_page_cost: 4.0 default_statistics_target: 200 effective_io_concurrency: 2 max_parallel_workers_per_gather: 2 # ========== 日志配置 ========== logging_collector: 'on' log_directory: '/usr/local/postgresql/logs' log_filename: 'postgresql-%a.log' log_truncate_on_rotation: 'on' log_rotation_age: '1d' log_rotation_size: 0 log_statement: 'ddl' log_line_prefix: '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' log_timezone: 'Asia/Shanghai' # ========== 时区 ========== timezone: 'Asia/Shanghai' lc_messages: 'en_US.UTF-8' lc_monetary: 'en_US.UTF-8' lc_numeric: 'en_US.UTF-8' lc_time: 'en_US.UTF-8' default_text_search_config: 'pg_catalog.english' tags: nofailover: false noloadbalance: false clonefrom: false nosync: false# =====================================================# Patroni 日志配置# =====================================================log: dir: /usr/local/postgresql/patroni/logs file_num: 10 file_size: 10485760 log_level: INFO format: '%(asctime)s %(levelname)s: %(message)s' date_format: '%Y-%m-%d %H:%M:%S'[root@pgsql-node-01 ~]# chown -R postgres:postgres /usr/local/postgresql/Patroni 自动启动设置(在pgsql-node-01,02,03)[root@pgsql-node-01 ~]# cat > /etc/systemd/system/patroni.service << 'EOF'[Unit]Description=Patroni - PostgreSQL High AvailabilityAfter=network-online.targetAfter=etcd.serviceWants=network-online.target[Service]Type=simpleUser=postgresGroup=postgresExecStart=/usr/local/bin/patroni /usr/local/postgresql/patroni/patroni.ymlExecReload=/bin/kill -HUP $MAINPID# ========== 重启策略 ==========Restart=on-failure # 异常退出时重启RestartSec=15 # 等待15秒后重启StartLimitInterval=300 # 5分钟内StartLimitBurst=5 # 最多重启5次# ========== 进程管理 ==========KillMode=process # 只杀Patroni,不杀PostgreSQLKillSignal=SIGTERMTimeoutStopSec=90# ========== 资源限制 ==========LimitNOFILE=65536 # 文件句柄限制LimitNPROC=65536 # 进程数限制# ========== 日志 ==========StandardOutput=journalStandardError=journalSyslogIdentifier=patroni[Install]WantedBy=multi-user.targetEOF[root@pgsql-node-01 ~]# systemctl daemon-reload[root@pgsql-node-01 ~]# systemctl start patroni[root@pgsql-node-01 ~]# systemctl enable patronietcd 源码初始安装(在pgsql-node-04,05,06安装)[root@etcd-node-01 ~]# wget https://github.com/etcd-io/etcd/releases/download/v3.6.11/etcd-v3.6.11-linux-amd64.tar.gz[root@etcd-node-01 ~]# tar zxvf etcd-v3.6.11-linux-amd64.tar.gz[root@etcd-node-01 ~]# mkdir -p /usr/local/etcd/{data,bin,logs,conf,wal}[root@etcd-node-01 ~]# cp -r etcd-v3.6.11-linux-amd64/* /usr/local/etcd/bin/[root@etcd-node-01 ~]# echo 'export PATH=/usr/local/etcd/bin:$PATH' >> /etc/profile[root@etcd-node-01 ~]# source /etc/profile[root@etcd-node-01 ~]# useradd -r etcd -s /sbin/nologin[root@etcd-node-01 ~]# chmod 700 /usr/local/etcd/data /usr/local/etcd/wal[root@etcd-node-01 ~]# touch /usr/local/etcd/conf/etcd_conf.yml[root@etcd-node-01 ~]# chown -R etcd:etcd /usr/local/etcd/[root@etcd-node-01 ~]# vim /usr/local/etcd/conf/etcd_conf.yml# etcd 服务器配置文件# 节点的人类可读名称name: 'etcd-node-01.itxinxi.net'# 数据目录路径data-dir: /usr/local/etcd/data# 专用 wal 目录路径wal-dir: /usr/local/etcd/wal# 触发磁盘快照的已提交事务数snapshot-count: 10000# 心跳间隔时间(毫秒)heartbeat-interval: 100# 选举超时时间(毫秒)election-timeout: 1000# 当后端大小超过给定配额时触发告警。0 表示使用默认配额quota-backend-bytes: 8589934592# 用于监听节点间通信的 URL 列表,逗号分隔listen-peer-urls: http://0.0.0.0:2380# 用于监听客户端通信的 URL 列表,逗号分隔listen-client-urls: http://0.0.0.0:2379# 保留的快照文件最大数量(0 表示无限制)max-snapshots: 5# 保留的 wal 文件最大数量(0 表示无限制)max-wals: 5# 跨域资源共享的源白名单,逗号分隔cors:# 向集群其他成员广播的该节点对等点 URL 列表,需要是逗号分隔的列表initial-advertise-peer-urls: http://etcd-node-01.itxinxi.net:2380# 向公众广播的该节点客户端 URL 列表,需要是逗号分隔的列表advertise-client-urls: http://etcd-node-01.itxinxi.net:2379# 用于引导集群的发现 URLdiscovery:# 有效值包括 'exit'、'proxy'discovery-fallback: 'proxy'# 用于访问发现服务的 HTTP 代理discovery-proxy:# 用于引导初始集群的 DNS 域名discovery-srv:# 用于引导的初始集群配置的逗号分隔字符串# 示例: initial-cluster: "infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"initial-cluster: 'etcd-node-01.itxinxi.net=http://etcd-node-01.itxinxi.net:2380,etcd-node-02.itxinxi.net=http://etcd-node-02.itxinxi.net:2380,etcd-node-03.itxinxi.net=http://etcd-node-03.itxinxi.net:2380'# 引导期间的初始集群令牌initial-cluster-token: 'patroni-cluster'# 初始集群状态:new(新建集群)/ existing(加入现有集群)initial-cluster-state: 'new'# 拒绝会导致法定人数丢失的重配置请求strict-reconfig-check: false# 通过 HTTP 服务器启用运行时性能分析数据enable-pprof: true# 有效值包括 'on'、'readonly'、'off'proxy: 'off'# 端点保持在失败状态的时间(毫秒)proxy-failure-wait: 5000# 端点刷新间隔时间(毫秒)proxy-refresh-interval: 30000# 拨号超时时间(毫秒)proxy-dial-timeout: 1000# 写入超时时间(毫秒)proxy-write-timeout: 5000# 读取超时时间(毫秒)proxy-read-timeout: 0# client-transport-security:# # 客户端服务器 TLS 证书文件路径# cert-file:# # # 客户端服务器 TLS 密钥文件路径# key-file:# # # 启用客户端证书认证# client-cert-auth: false# # # 客户端服务器 TLS 受信任的 CA 证书文件路径# trusted-ca-file:# # # 使用生成的证书进行客户端 TLS# auto-tls: false# peer-transport-security:# # 节点间服务器 TLS 证书文件路径# cert-file:# # # 节点间服务器 TLS 密钥文件路径# key-file:# # # 启用节点间客户端证书认证# client-cert-auth: false# # # 节点间服务器 TLS 受信任的 CA 证书文件路径# trusted-ca-file:# # # 使用生成的证书进行节点间 TLS# auto-tls: false# # # 节点间认证允许的 CN# allowed-cn:# # # 节点间认证允许的 TLS 主机名# allowed-hostname:# 自签名证书的有效期,单位为年self-signed-cert-validity: 1# etcd 的日志级别log-level: infologger: zaplog-outputs: [/usr/local/etcd/logs/etcd.log]# 启用日志轮换enable-log-rotation: truelog-rotation-config-json: '{"maxsize":100, "maxage":30, "maxbackups":10}'# 强制创建一个新的单成员集群force-new-cluster: falseauto-compaction-mode: periodicauto-compaction-retention: "24h"# 限制 etcd 使用特定的 TLS 密码套件# cipher-suites: [# TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,# TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384# ]# 限制 etcd 使用特定的 TLS 协议版本# tls-min-version: 'TLS1.2'# tls-max-version: 'TLS1.3'etcd 自动启动(在pgsql-node-04,05,06)[root@etcd-node-01 ~]# vim /etc/systemd/system/etcd.service[Unit]Description=etcd key-value storeAfter=network-online.targetWants=network-online.target[Service]Type=simpleUser=etcdGroup=etcdExecStart=/usr/local/etcd/bin/etcd --config-file=/usr/local/etcd/conf/etcd_conf.ymlRestart=on-failureRestartSec=10LimitNOFILE=65536[Install]WantedBy=multi-user.target[root@etcd-node-01 ~]# systemctl daemon-reload[root@etcd-node-01 ~]# systemctl start etcd[root@etcd-node-01 ~]# systemctl enable etcd到此 PostgreSQL + Patroni + etcd 部署结束 检查下来所有数据同步,故障切换,集群状态工作一切正常。
-
华为云数据库使用云盘时,io调度器None、mq-deadline、kyber、bfg如何选择?
-
在数据库的实际使用与运维过程中,事务一致性、数据安全、性能优化与高可用始终是绕不开的核心问题。围绕这些目标,数据库在事务机制、日志系统、复制架构、存储引擎以及执行引擎等方面构建了一整套复杂而精巧的设计。本文结合近期发布的一系列数据库技术详解文章,对这些关键知识点进行系统性梳理,并附上对应原文链接,方便深入阅读与查阅。一、事务与一致性机制事务是数据库可靠性的基础,直接决定了数据是否正确、是否可恢复。• 二阶段提交详解从 prepare 与 commit 两个阶段解析事务提交过程,是理解 MySQL 内部事务一致性与分布式事务的关键基础。👉 https://bbs.huaweicloud.com/forum/thread-0213201683537376122-1-1.html• 大事务问题详解详细分析大事务带来的锁竞争、Undo 膨胀、主从延迟等问题,并给出规避思路。👉 https://bbs.huaweicloud.com/forum/thread-0235200485163366077-1-1.html• 乐观锁详解通过版本号或时间戳实现并发控制,适用于读多写少场景,是高并发系统的重要设计手段。👉 https://bbs.huaweicloud.com/forum/thread-02127200485311762072-1-1.html二、日志系统与复制架构日志和复制机制是数据库实现高可用与数据安全的核心能力。• binlog 格式详解详解 statement、row、mixed 三种 binlog 格式及其优缺点,是理解复制和数据恢复的基础。👉 https://bbs.huaweicloud.com/forum/thread-02117201683398976115-1-1.html• 主从复制详解从整体流程出发,解析主库、从库之间的数据同步机制,是读写分离与容灾架构的基础。👉 https://bbs.huaweicloud.com/forum/thread-02126201683495089112-1-1.html• 并行复制详解重点讲解并行复制的原理与实现方式,解决高并发场景下的主从延迟问题。👉 https://bbs.huaweicloud.com/forum/thread-02126201683453788111-1-1.html三、存储引擎内部实现理解 InnoDB 内部结构,有助于从根本上分析性能问题。• Buffer Pool 详解深入解析 Buffer Pool 的工作机制,是理解数据库性能瓶颈和 IO 行为的核心知识点。👉 https://bbs.huaweicloud.com/forum/thread-02117200485209435070-1-1.html• 页分裂和页合并详解通过 B+ 树页结构分析索引在插入、删除过程中的变化,解释索引性能波动的原因。👉 https://bbs.huaweicloud.com/forum/thread-0250200485261693071-1-1.html四、执行引擎与 SQL 性能SQL 的执行效率,很大程度取决于执行计划和 Join 策略。• 驱动表详解解释 Join 执行顺序的选择原则,是 SQL 优化中非常关键但容易被忽视的点。👉 https://bbs.huaweicloud.com/forum/thread-0250200485042254070-1-1.html• Hash Join 详解介绍 Hash Join 的执行原理及适用场景,是理解现代数据库执行引擎的重要内容。👉 https://bbs.huaweicloud.com/forum/thread-0213200485103249073-1-1.html五、数据库在线变更能力在生产环境中,数据库必须支持不停机演进。• Online DDL 详解讲解表结构在线变更的实现方式,帮助在不中断业务的情况下完成数据库演进。👉 https://bbs.huaweicloud.com/forum/thread-0250201683581719127-1-1.html总结通过以上这些主题,可以从多个层面理解数据库的整体运行逻辑:• 事务与锁机制,保障数据一致性• 日志与复制,确保数据安全与高可用• 存储结构,决定性能上限• 执行引擎,影响 SQL 执行效率• Online DDL,支撑业务持续演进当这些知识点被系统性串联起来,数据库不再只是一个“黑盒”,而是一个可以分析、可以调优、可以预判行为的系统。
-
我有个SQL查询用了多个OR条件,比如WHERE status='A' OR status='B' OR status='C',发现走不了索引,改成IN也一样,这种情况应该怎么优化?
-
查询的时候需要对JSON字段里的某个属性做过滤,比如WHERE data->>'status' = 'active',但发现完全不走索引,JSONB字段应该怎么建索引才能提高查询效率?
-
我们的系统有个实时数据大屏,需要展示各种统计数据,但每次刷新都要执行几十条聚合查询,数据库压力很大,有没有什么好的优化方案?物化视图适合这种场景吗?
-
问题描述这是关于MySQL DDL操作的常见面试题面试官通过这个问题考察你对Online DDL的理解通常会追问Online DDL的实现原理和适用场景核心答案Online DDL是MySQL 5.6引入的特性,允许在不锁表的情况下执行DDL操作:主要特点支持并发DML操作减少锁表时间提高系统可用性优化用户体验实现方式使用临时表增量数据同步原子性切换自动回滚机制详细解析1. Online DDL原理Online DDL通过临时表和增量同步实现无锁表修改:-- 查看DDL执行状态 SHOW PROCESSLIST; -- 监控DDL进度 SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING'; 执行流程:准备阶段:创建临时表复制表结构记录DDL操作准备增量同步执行阶段:应用DDL到临时表同步增量数据记录DML操作维护数据一致性提交阶段:原子性切换表清理临时表完成DDL操作释放资源2. Online DDL支持的操作Online DDL支持多种DDL操作,但不同操作的支持程度不同:-- 添加索引(Online) ALTER TABLE table_name ADD INDEX index_name (column_name), ALGORITHM=INPLACE, LOCK=NONE; -- 修改列类型(可能需要锁表) ALTER TABLE table_name MODIFY COLUMN column_name new_type, ALGORITHM=INPLACE, LOCK=SHARED; 支持的操作:完全支持:添加/删除二级索引修改索引名修改列默认值修改列名部分支持:添加列删除列修改列类型修改表选项不支持:修改主键修改字符集修改行格式修改存储引擎3. Online DDL的优缺点Online DDL具有明显的优势和限制,需要根据场景选择:-- 优化Online DDL SET GLOBAL innodb_online_alter_log_max_size = 1073741824; SET GLOBAL innodb_sort_buffer_size = 67108864; 优缺点分析:优点:减少锁表时间支持并发DML提高系统可用性优化用户体验缺点:执行时间较长占用额外空间可能影响性能部分操作不支持常见追问Q1: Online DDL如何保证数据一致性?A:使用临时表增量数据同步原子性切换自动回滚机制Q2: 什么情况下不适合使用Online DDL?A:大表修改主键修改字符集修改存储引擎修改Q3: 如何优化Online DDL性能?A:选择合适的算法调整缓冲区大小控制并发操作监控执行进度扩展知识监控命令-- 查看DDL执行状态 SHOW PROCESSLIST; -- 监控DDL进度 SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING'; -- 查看表状态 SHOW TABLE STATUS LIKE 'table_name'; 优化参数-- 优化Online DDL innodb_online_alter_log_max_size = 1G innodb_sort_buffer_size = 64M innodb_read_io_threads = 8 innodb_write_io_threads = 8 实际应用示例场景一:添加索引-- Online方式添加索引 ALTER TABLE orders ADD INDEX idx_customer_id (customer_id), ALGORITHM=INPLACE, LOCK=NONE; -- 查看执行进度 SHOW PROCESSLIST; 场景二:修改列类型-- 修改列类型(可能需要锁表) ALTER TABLE users MODIFY COLUMN age INT UNSIGNED, ALGORITHM=INPLACE, LOCK=SHARED; -- 监控执行状态 SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING'; 面试要点基础概念Online DDL定义支持的操作类型执行流程数据一致性保证性能优化参数配置算法选择监控方法问题诊断实战经验场景选择问题处理优化策略最佳实践
-
问题描述这是关于MySQL事务机制的常见面试题面试官通过这个问题考察你对事务一致性的理解通常会追问二阶段提交的必要性和实现细节核心答案二阶段提交(2PC)是保证分布式事务一致性的协议,分为准备阶段和提交阶段:准备阶段(Prepare)协调者询问参与者是否可以提交参与者执行事务但不提交参与者返回准备结果提交阶段(Commit)协调者根据参与者反馈决定提交或回滚参与者执行最终操作完成事务提交或回滚详细解析1. 为什么需要二阶段提交二阶段提交解决了分布式事务的一致性问题,特别是在MySQL中协调Redo log和Binlog的写入:具体例子:假设有一个转账事务,需要同时更新账户表和交易记录表。在MySQL中,这个事务涉及两个关键日志:Redo log:记录InnoDB存储引擎的物理变更Binlog:记录MySQL Server层的逻辑变更如果不使用二阶段提交,可能会出现以下问题:如果先写Redo log后写Binlog,当Binlog写入失败时,主库已经提交,但从库无法同步,导致主从不一致如果先写Binlog后写Redo log,当Redo log写入失败时,主库回滚,但从库已经同步,同样导致主从不一致二阶段提交通过以下步骤解决这个问题:准备阶段:写入Redo log,标记为prepare状态写入Binlog两个日志都写入成功才算准备完成提交阶段:如果准备阶段成功,将Redo log标记为commit状态如果准备阶段失败,进行回滚确保两个日志要么都提交,要么都回滚这样,即使发生故障:如果Redo log是prepare状态,检查Binlog是否完整如果Binlog完整,提交事务如果Binlog不完整,回滚事务保证主从数据的一致性2. 二阶段提交流程二阶段提交是分布式事务的核心机制,确保数据一致性:-- 查看事务状态 SHOW ENGINE INNODB STATUS; -- 监控二阶段提交 SHOW GLOBAL STATUS LIKE 'Innodb_2pc%'; 执行流程:准备阶段:协调者发送prepare请求参与者执行事务操作写入undo日志返回准备结果提交阶段:协调者收集所有响应决定提交或回滚发送最终指令参与者执行操作完成阶段:清理事务信息释放资源返回结果3. 二阶段提交的优缺点二阶段提交具有明显的优势和劣势,需要权衡使用:-- 优化二阶段提交 SET GLOBAL innodb_flush_log_at_trx_commit = 2; SET GLOBAL sync_binlog = 0; 优缺点分析:优点:保证数据一致性支持故障恢复实现简单直观广泛支持缺点:性能开销大同步阻塞单点故障超时处理复杂常见追问Q1: 二阶段提交如何保证一致性?A:准备阶段验证可行性提交阶段统一决策所有节点同步执行支持故障恢复Q2: 二阶段提交的性能问题如何解决?A:优化日志写入减少同步等待使用异步复制批量处理事务Q3: 如何处理二阶段提交的故障?A:超时机制重试策略人工干预自动恢复扩展知识监控命令-- 查看事务状态 SHOW ENGINE INNODB STATUS; -- 监控二阶段提交 SHOW GLOBAL STATUS LIKE 'Innodb_2pc%'; -- 查看事务日志 SHOW BINARY LOGS; SHOW BINLOG EVENTS; 优化参数-- 优化二阶段提交 innodb_flush_log_at_trx_commit = 2 sync_binlog = 0 innodb_support_xa = 1 innodb_use_native_aio = 1 实际应用示例场景一:优化二阶段提交性能-- 配置文件设置 [mysqld] innodb_flush_log_at_trx_commit = 2 sync_binlog = 0 innodb_support_xa = 1 innodb_use_native_aio = 1 -- 动态设置 SET GLOBAL innodb_flush_log_at_trx_commit = 2; SET GLOBAL sync_binlog = 0; 场景二:处理二阶段提交故障-- 查看未完成事务 SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'PREPARED'; -- 手动提交事务 XA COMMIT 'transaction_id'; -- 手动回滚事务 XA ROLLBACK 'transaction_id'; 面试要点基础概念二阶段提交定义执行流程一致性保证故障处理性能优化参数配置日志优化并发控制批量处理实战经验故障诊断性能调优监控方案应急预案
-
问题描述这是关于MySQL复制机制的常见面试题面试官通过这个问题考察你对主从复制原理的理解通常会追问复制延迟的原因和解决方案核心答案MySQL主从复制过程:主库写入事务提交时写入binlog记录所有数据变更操作使用不同格式记录(STATEMENT/ROW/MIXED)从库复制从库IO线程读取主库binlog写入从库relay logSQL线程执行relay log中的操作延迟原因主库写入压力大从库执行能力不足网络延迟大事务执行详细解析1. 主从复制过程MySQL主从复制是基于binlog的异步复制,包含三个线程:-- 查看主从复制状态 SHOW SLAVE STATUS\G -- 查看复制线程 SHOW PROCESSLIST; 复制流程:主库写入过程:事务提交时写入binlog记录操作类型(INSERT/UPDATE/DELETE)记录操作数据(STATEMENT/ROW格式)从库复制过程:IO线程:连接主库,读取binlog写入relay logSQL线程:执行relay log中的操作复制格式:STATEMENT:记录SQL语句ROW:记录行数据变化MIXED:混合模式2. 复制延迟原因复制延迟是主从复制常见问题,主要原因包括:-- 查看复制延迟 SELECT TIMESTAMPDIFF(SECOND, MASTER_POS_WAIT('mysql-bin.000001', 1234), NOW()) AS delay_seconds; 延迟原因:主库因素:写入压力大大事务执行binlog写入延迟主库性能瓶颈从库因素:硬件资源不足SQL执行效率低单线程执行从库负载高网络因素:网络带宽不足网络延迟高网络不稳定3. 延迟解决方案针对复制延迟,有多种解决方案,需要根据具体情况选择:-- 优化从库配置 SET GLOBAL slave_parallel_workers = 8; SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; 解决方案:主库优化:优化大事务控制写入频率使用MIXED格式调整binlog参数从库优化:提升硬件配置启用并行复制优化SQL执行调整参数配置网络优化:提升网络带宽优化网络架构使用专线连接监控网络状态常见追问Q1: 主从复制的原理是什么?A:基于binlog的异步复制主库记录变更,从库重放三个线程协作完成支持多种复制格式Q2: 如何监控复制延迟?A:使用SHOW SLAVE STATUS监控Seconds_Behind_Master使用pt-heartbeat工具自定义监控脚本Q3: 大事务如何处理?A:拆分大事务使用分批处理优化事务逻辑调整事务隔离级别扩展知识复制监控命令-- 查看复制状态 SHOW SLAVE STATUS\G -- 查看复制线程 SHOW PROCESSLIST; -- 查看binlog信息 SHOW BINARY LOGS; SHOW BINLOG EVENTS; -- 查看复制延迟 SELECT TIMESTAMPDIFF(SECOND, MASTER_POS_WAIT('mysql-bin.000001', 1234), NOW()) AS delay_seconds; 优化参数配置-- 主库配置 sync_binlog = 1 binlog_format = MIXED binlog_group_commit_sync_delay = 100 binlog_group_commit_sync_no_delay_count = 10 -- 从库配置 slave_parallel_workers = 8 slave_parallel_type = LOGICAL_CLOCK slave_pending_jobs_size_max = 1073741824 实际应用示例场景一:优化大事务-- 原始大事务 BEGIN; INSERT INTO large_table SELECT * FROM source_table; COMMIT; -- 优化后分批处理 SET @batch_size = 1000; SET @offset = 0; WHILE @offset < (SELECT COUNT(*) FROM source_table) DO INSERT INTO large_table SELECT * FROM source_table LIMIT @offset, @batch_size; SET @offset = @offset + @batch_size; END WHILE; 场景二:并行复制配置-- 配置文件设置 [mysqld] slave_parallel_workers = 8 slave_parallel_type = LOGICAL_CLOCK slave_pending_jobs_size_max = 1G -- 动态设置 SET GLOBAL slave_parallel_workers = 8; SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_pending_jobs_size_max = 1073741824; 面试要点基础概念主从复制原理复制线程作用复制格式区别延迟监控方法性能优化参数配置优化大事务处理并行复制配置监控方案设计实战经验延迟问题诊断优化方案实施监控体系建设应急预案制定
-
问题描述这是关于MySQL复制机制的常见面试题面试官通过这个问题考察你对并行复制原理的理解通常会追问各个版本的并行复制实现方式和优化策略核心答案MySQL并行复制的演进历程:MySQL 5.6基于库级别的并行复制不同库的事务可以并行执行简单但并行度有限MySQL 5.7基于组提交的并行复制同一组提交的事务可以并行执行提高了并行度MySQL 8.0基于WriteSet的并行复制无冲突事务可以并行执行最高效的并行复制详细解析1. MySQL 5.6并行复制MySQL 5.6实现了基于库级别的并行复制,并行度有限:-- 查看并行复制配置 SHOW VARIABLES LIKE 'slave_parallel_workers'; -- 设置并行复制工作线程数 SET GLOBAL slave_parallel_workers = 4; 实现原理:库级别并行:不同数据库的事务可以并行执行同一数据库的事务串行执行通过数据库名判断是否可以并行工作线程:配置多个工作线程每个线程处理不同库的事务线程间通过协调器协调限制因素:单库事务无法并行跨库事务可能冲突并行度受库数量限制2. MySQL 5.7并行复制MySQL 5.7实现了基于组提交的并行复制,提高了并行度:-- 查看并行复制配置 SHOW VARIABLES LIKE 'slave_parallel_type'; SHOW VARIABLES LIKE 'slave_parallel_workers'; -- 设置并行复制类型和工作线程数 SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_parallel_workers = 8; 实现原理:组提交机制:同一组提交的事务可以并行执行通过事务提交时间判断是否可以并行使用逻辑时钟(LOGICAL_CLOCK)标记事务组并行度提升:不再受限于库级别同一库的事务可以并行并行度显著提高优化策略:调整组提交大小优化工作线程数监控并行复制延迟3. MySQL 8.0并行复制MySQL 8.0实现了基于WriteSet的并行复制,最高效的并行复制:-- 查看并行复制配置 SHOW VARIABLES LIKE 'binlog_transaction_dependency_tracking'; SHOW VARIABLES LIKE 'slave_parallel_type'; SHOW VARIABLES LIKE 'slave_parallel_workers'; -- 设置WriteSet并行复制 SET GLOBAL binlog_transaction_dependency_tracking = 'WRITESET'; SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_parallel_workers = 16; 实现原理:WriteSet机制:记录事务修改的数据行通过WriteSet判断事务冲突无冲突事务可以并行执行并行度优化:更细粒度的并行控制更高的并行度更低的复制延迟性能提升:减少事务冲突提高并行效率优化资源利用常见追问Q1: 各个版本并行复制的区别是什么?A:5.6:库级别并行,简单但并行度低5.7:组提交并行,提高了并行度8.0:WriteSet并行,最高效的并行复制主要区别在于并行粒度和实现机制Q2: 如何优化并行复制性能?A:合理设置工作线程数选择合适的并行复制类型监控并行复制延迟优化主库事务提交策略Q3: 并行复制可能带来什么问题?A:事务顺序可能改变可能存在数据一致性问题需要更多的系统资源配置复杂度增加扩展知识并行复制监控命令-- 查看并行复制状态 SHOW SLAVE STATUS\G -- 查看并行复制工作线程 SHOW PROCESSLIST; -- 查看并行复制延迟 SELECT TIMESTAMPDIFF(SECOND, MASTER_POS_WAIT('mysql-bin.000001', 1234), NOW()) AS delay_seconds; 优化参数配置-- MySQL 5.6配置 slave_parallel_workers = 4 -- MySQL 5.7配置 slave_parallel_type = LOGICAL_CLOCK slave_parallel_workers = 8 binlog_group_commit_sync_delay = 100 binlog_group_commit_sync_no_delay_count = 10 -- MySQL 8.0配置 binlog_transaction_dependency_tracking = WRITESET slave_parallel_type = LOGICAL_CLOCK slave_parallel_workers = 16 实际应用示例场景一:MySQL 5.7并行复制配置-- 配置文件设置 [mysqld] slave_parallel_type = LOGICAL_CLOCK slave_parallel_workers = 8 binlog_group_commit_sync_delay = 100 binlog_group_commit_sync_no_delay_count = 10 -- 动态设置 SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_parallel_workers = 8; SET GLOBAL binlog_group_commit_sync_delay = 100; SET GLOBAL binlog_group_commit_sync_no_delay_count = 10; 场景二:MySQL 8.0 WriteSet并行复制-- 配置文件设置 [mysqld] binlog_transaction_dependency_tracking = WRITESET slave_parallel_type = LOGICAL_CLOCK slave_parallel_workers = 16 transaction_write_set_extraction = XXHASH64 -- 动态设置 SET GLOBAL binlog_transaction_dependency_tracking = 'WRITESET'; SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_parallel_workers = 16; SET GLOBAL transaction_write_set_extraction = 'XXHASH64'; 面试要点基础概念并行复制的定义各个版本的实现方式并行复制原理性能影响因素性能优化参数配置优化监控方法问题诊断最佳实践实战经验配置实践问题处理优化策略版本选择
-
问题描述这是关于MySQL日志系统的常见面试题面试官通过这个问题考察你对binlog格式的理解通常会追问各种格式的特点、适用场景和配置方法核心答案binlog的三种主要格式:STATEMENT格式记录SQL语句日志量小可能存在主从不一致(如使用NOW()、RAND()等函数)ROW格式记录行数据变化日志量大主从数据一致支持所有隔离级别MIXED格式混合使用STATEMENT和ROW智能选择格式平衡日志量和一致性详细解析1. STATEMENT格式STATEMENT格式记录SQL语句,日志量最小:-- 查看当前binlog格式 SHOW VARIABLES LIKE 'binlog_format'; -- 设置binlog格式为STATEMENT SET GLOBAL binlog_format = 'STATEMENT'; 主从不一致的原因:函数依赖:NOW()、RAND()等函数在主从执行时结果可能不同UUID()、USER()等函数在主从执行时值不同触发器依赖:触发器中的函数调用可能导致主从不一致触发器中的变量值在主从可能不同存储过程依赖:存储过程中的变量值在主从可能不同存储过程中的函数调用结果可能不同隔离级别限制:在REPEATABLE READ隔离级别下不能使用STATEMENT格式因为可能导致主从不一致2. ROW格式ROW格式记录行数据变化,保证数据一致性:-- 设置binlog格式为ROW SET GLOBAL binlog_format = 'ROW'; -- 查看binlog事件 SHOW BINLOG EVENTS IN 'mysql-bin.000001'; 一致性保证:记录实际数据:记录修改前后的完整行数据不依赖SQL语句的执行结果支持所有隔离级别:可以在REPEATABLE READ下使用不会出现主从不一致函数处理:记录函数执行后的结果主从执行结果一致3. MIXED格式MIXED格式智能选择格式,平衡性能和一致性:-- 设置binlog格式为MIXED SET GLOBAL binlog_format = 'MIXED'; -- 查看binlog配置 SHOW VARIABLES LIKE 'binlog%'; 智能选择规则:使用ROW格式的情况:涉及不确定函数(如NOW())涉及触发器或存储过程涉及临时表涉及UUID()等函数使用STATEMENT格式的情况:简单的INSERT/UPDATE/DELETE不涉及不确定函数不涉及触发器或存储过程常见追问Q1: 为什么STATEMENT格式会导致主从不一致?A:函数依赖:NOW()、RAND()等函数在主从执行时间不同触发器依赖:触发器中的变量值在主从可能不同存储过程依赖:存储过程中的变量值在主从可能不同隔离级别限制:REPEATABLE READ下不能使用STATEMENT格式Q2: 在REPEATABLE READ隔离级别下应该使用哪种格式?A:必须使用ROW格式STATEMENT格式会导致主从不一致MIXED格式在不确定情况下会使用ROW格式ROW格式可以保证数据一致性Q3: 如何避免主从不一致?A:使用ROW格式记录实际数据变化避免使用不确定函数合理设置隔离级别监控主从同步状态扩展知识binlog监控命令-- 查看binlog状态 SHOW MASTER STATUS; -- 查看binlog文件 SHOW BINARY LOGS; -- 查看binlog事件 SHOW BINLOG EVENTS IN 'mysql-bin.000001'; -- 查看主从同步状态 SHOW SLAVE STATUS\G优化参数配置-- binlog格式设置(RR隔离级别必须使用ROW) binlog_format = ROW -- binlog缓存大小 binlog_cache_size = 32768 -- binlog文件大小 max_binlog_size = 100M -- 事务隔离级别 transaction_isolation = REPEATABLE-READ 实际应用示例场景一:配置ROW格式(RR隔离级别)-- 配置文件设置 [mysqld] binlog_format = ROW binlog_row_image = FULL sync_binlog = 1 transaction_isolation = REPEATABLE-READ -- 动态设置 SET GLOBAL binlog_format = 'ROW'; SET GLOBAL binlog_row_image = 'FULL'; SET GLOBAL sync_binlog = 1; SET GLOBAL transaction_isolation = 'REPEATABLE-READ'; 场景二:监控主从同步-- 检查主从同步状态 SHOW SLAVE STATUS\G -- 检查主从延迟 SELECT TIMESTAMPDIFF(SECOND, MASTER_POS_WAIT('mysql-bin.000001', 1234), NOW()) AS delay_seconds; 面试要点基础概念binlog格式的定义各种格式的特点主从不一致的原因隔离级别限制性能优化格式选择策略参数配置优化监控方法问题诊断实战经验配置实践问题处理优化策略最佳实践
-
问题描述这是关于数据库并发控制的常见面试题面试官通过这个问题考察你对乐观锁机制的理解通常会追问乐观锁的实现方式、适用场景和与悲观锁的区别核心答案乐观锁的核心机制:无锁机制不直接加锁基于版本号或时间戳读操作不阻塞冲突检测更新时检查版本版本不一致则失败需要重试机制适用场景读多写少冲突概率低响应时间要求高实现方式版本号控制时间戳控制CAS操作详细解析1. 乐观锁原理乐观锁是基于版本控制的并发控制机制,不直接加锁:-- 版本号控制示例 CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(100), version INT DEFAULT 0, quantity INT ); -- 更新时检查版本 UPDATE products SET quantity = quantity - 1, version = version + 1 WHERE id = 1 AND version = 1; 2. 实现方式乐观锁的主要实现方式:-- 时间戳控制示例 CREATE TABLE orders ( id INT PRIMARY KEY, status VARCHAR(20), update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 更新时检查时间戳 UPDATE orders SET status = 'PAID' WHERE id = 1 AND update_time = '2025-05-20 10:00:00'; 3. 冲突处理处理并发冲突的策略:-- 重试机制示例 BEGIN; SELECT version, quantity FROM products WHERE id = 1; -- 业务逻辑处理 UPDATE products SET quantity = quantity - 1, version = version + 1 WHERE id = 1 AND version = @current_version; COMMIT; 常见追问Q1: 乐观锁和悲观锁的区别是什么?A:乐观锁:不直接加锁,通过版本控制实现悲观锁:直接加锁,阻塞其他事务乐观锁适合读多写少场景悲观锁适合写多读少场景Q2: 乐观锁的实现方式有哪些?A:版本号控制:使用version字段时间戳控制:使用update_time字段CAS操作:使用原子操作状态标记:使用状态字段Q3: 乐观锁的优缺点是什么?A:优点:并发性能好,无死锁风险缺点:需要重试机制,可能产生ABA问题适用场景:读多写少,冲突概率低不适用场景:写多读少,冲突概率高扩展知识乐观锁监控命令-- 查看表结构 DESC table_name; -- 查看版本字段 SELECT version FROM table_name WHERE id = 1; -- 查看更新历史 SELECT * FROM table_name WHERE id = 1; 优化参数配置-- 设置重试次数 SET @max_retries = 3; -- 设置重试间隔 SET @retry_interval = 1000; 实际应用示例场景一:库存扣减-- 乐观锁实现库存扣减 DELIMITER // CREATE PROCEDURE decrease_stock(IN product_id INT, IN quantity INT) BEGIN DECLARE retry_count INT DEFAULT 0; DECLARE success BOOLEAN DEFAULT FALSE; WHILE retry_count < 3 AND NOT success DO BEGIN DECLARE current_version INT; DECLARE current_quantity INT; -- 获取当前版本和库存 SELECT version, quantity INTO current_version, current_quantity FROM products WHERE id = product_id FOR UPDATE; -- 检查库存是否足够 IF current_quantity >= quantity THEN -- 更新库存和版本 UPDATE products SET quantity = quantity - quantity, version = version + 1 WHERE id = product_id AND version = current_version; SET success = TRUE; ELSE SET success = FALSE; END IF; END; IF NOT success THEN SET retry_count = retry_count + 1; DO SLEEP(1); END IF; END WHILE; END // DELIMITER ; 场景二:订单状态更新-- 乐观锁实现订单状态更新 DELIMITER // CREATE PROCEDURE update_order_status(IN order_id INT, IN new_status VARCHAR(20)) BEGIN DECLARE retry_count INT DEFAULT 0; DECLARE success BOOLEAN DEFAULT FALSE; WHILE retry_count < 3 AND NOT success DO BEGIN DECLARE current_time TIMESTAMP; -- 获取当前时间戳 SELECT update_time INTO current_time FROM orders WHERE id = order_id; -- 更新订单状态 UPDATE orders SET status = new_status, update_time = CURRENT_TIMESTAMP WHERE id = order_id AND update_time = current_time; SET success = ROW_COUNT() > 0; END; IF NOT success THEN SET retry_count = retry_count + 1; DO SLEEP(1); END IF; END WHILE; END // DELIMITER ; 面试要点基础概念乐观锁的定义和原理与悲观锁的区别实现方式适用场景性能优化重试机制设计版本控制策略冲突处理方案监控指标分析实战经验实现方法问题诊断优化策略最佳实践
-
问题描述这是关于MySQL InnoDB存储引擎页管理的常见面试题面试官通过这个问题考察你对InnoDB存储结构的理解通常会追问页分裂和页合并的触发条件、影响和优化策略核心答案页分裂和页合并的核心机制:页分裂机制数据页空间不足时触发将原页数据分为两部分创建新页并调整指针页合并机制相邻页空间利用率低时触发合并相邻页的数据释放空闲页空间性能影响页分裂导致性能下降页合并优化空间利用影响索引维护效率优化策略合理设置填充因子优化插入顺序定期维护表空间详细解析1. 页分裂机制页分裂是InnoDB处理数据增长的重要机制,当数据页空间不足时触发:-- 查看页分裂统计 SHOW GLOBAL STATUS LIKE 'Innodb_page_splits'; -- 查看页空间使用情况 SHOW TABLE STATUS LIKE 'table_name'; 2. 页合并机制页合并是InnoDB优化空间利用的机制,当相邻页空间利用率低时触发:-- 查看页合并统计 SHOW GLOBAL STATUS LIKE 'Innodb_page_merges'; -- 查看表空间碎片 SHOW TABLE STATUS LIKE 'table_name'; 3. 性能监控监控页分裂和页合并的频率和影响:-- 查看页操作统计 SHOW GLOBAL STATUS LIKE 'Innodb_pages%'; -- 查看索引统计信息 SHOW INDEX FROM table_name; 常见追问Q1: 页分裂的触发条件是什么?A:数据页空间不足(默认16KB)插入数据导致页溢出更新数据导致页空间不足索引页分裂(B+树结构要求)Q2: 页合并的触发条件是什么?A:相邻页空间利用率低于阈值删除操作导致页空间利用率低更新操作导致页空间利用率低系统空闲时自动触发Q3: 如何优化页分裂和页合并?A:合理设置填充因子(innodb_fill_factor)优化数据插入顺序定期进行表空间维护监控页分裂和合并频率扩展知识页分裂和页合并监控命令-- 查看页操作统计 SHOW GLOBAL STATUS LIKE 'Innodb_pages%'; -- 查看表空间使用情况 SHOW TABLE STATUS LIKE 'table_name'; -- 查看索引统计信息 SHOW INDEX FROM table_name; 优化参数配置-- 填充因子设置 innodb_fill_factor = 100 -- 页分裂阈值 innodb_page_size = 16384 -- 合并阈值 innodb_merge_threshold = 50 实际应用示例场景一:监控页分裂和页合并-- 监控页分裂频率 SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'Innodb_page_splits'; -- 监控页合并频率 SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'Innodb_page_merges'; -- 计算页分裂率 SELECT (page_splits / (page_splits + page_merges)) * 100 as split_rate FROM ( SELECT variable_value as page_splits FROM information_schema.global_status WHERE variable_name = 'Innodb_page_splits' ) AS splits, ( SELECT variable_value as page_merges FROM information_schema.global_status WHERE variable_name = 'Innodb_page_merges' ) AS merges; 场景二:优化页分裂和页合并-- 优化前:默认配置 innodb_fill_factor = 100 innodb_page_size = 16384 -- 优化后:根据业务特点调整 innodb_fill_factor = 80 innodb_merge_threshold = 40 面试要点基础概念页分裂的定义和触发条件页合并的定义和触发条件页管理的基本原理性能影响分析性能优化填充因子设置插入顺序优化表空间维护监控指标分析实战经验监控方法优化策略问题诊断最佳实践
推荐直播
-
华为云码道 × 仓颉编程:工程化AI编码探索2026/05/27 周三 19:00-21:00
刘俊杰-华为云仓颉语言专家/李炎-华为云码道技术专家/王智鹏-OpenCangjie开源社区发起人
本场直播围绕华为云仓颉语言与华为云码道的深度结合,展示华为云智能编程从零基础到高效落地的完整生态能力。以华为云码道为引擎,仓颉语言为载体,带给大家日常提效、趣味创新到极速量产的开发体验。
即将直播
热门标签