DigVPS

MySQL

MySQL 相关资料

📘 MySQL 安装

Debian 自带仓库安装 MySQL

Debian 12(Bookworm)里提供的是 default-mysql-server,它实际安装的是 MariaDB 10.11 LTS。

terminal
#!/usr/bin/env bash
set -euo pipefail

# =========================================================
# Debian 12 一键安装 default-mysql-server(MariaDB)
# 默认行为:
# 1. 使用 Debian 自带仓库安装
# 2. 默认开启远程访问
# 3. 默认创建远程 root
# 4. 默认远程 root 密码:DigVPS.COM
# 5. 本机 root 可直接 mysql 登录
# 6. 可选:当前 sudo 用户本地直接 mysql 登录
# =========================================================

# ===== 默认参数 =====
ENABLE_REMOTE_ROOT="${ENABLE_REMOTE_ROOT:-1}"
REMOTE_ROOT_HOST="${REMOTE_ROOT_HOST:-%}"
REMOTE_ROOT_PASSWORD="${REMOTE_ROOT_PASSWORD:-DigVPS.COM}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
BIND_ADDRESS="${BIND_ADDRESS:-0.0.0.0}"
CREATE_LOCAL_SUDO_SOCKET_USER="${CREATE_LOCAL_SUDO_SOCKET_USER:-1}"

MYSQL_CNF="/etc/mysql/mariadb.conf.d/50-server.cnf"
TUNING_CNF="/etc/mysql/mariadb.conf.d/99-local-init.cnf"

# ===== 基础检查 =====
if [[ "${EUID}" -ne 0 ]]; then
  echo "请用 root 运行,或 sudo bash $0"
  exit 1
fi

source /etc/os-release

if [[ "${ID:-}" != "debian" || "${VERSION_ID:-}" != "12" ]]; then
  echo "本脚本仅支持 Debian 12,当前系统:${PRETTY_NAME:-unknown}"
  exit 1
fi

REAL_USER="${SUDO_USER:-}"

export DEBIAN_FRONTEND=noninteractive

echo "==> 清理之前残留的 Oracle MySQL APT 仓库配置(如果有)"
rm -f /etc/apt/sources.list.d/mysql.list
rm -f /usr/share/keyrings/mysql.gpg

echo "==> 更新 APT"
apt-get update

echo "==> 安装 default-mysql-server"
apt-get install -y default-mysql-server

echo "==> 启动并设置开机自启"
systemctl enable --now mariadb

echo "==> 等待数据库就绪"
for i in {1..30}; do
  if mysqladmin ping >/dev/null 2>&1; then
    break
  fi
  sleep 1
done

echo "==> 测试 root 本地登录"
if ! mysql -uroot -e "SELECT VERSION();" >/dev/null 2>&1; then
  echo "本地 root 无法登录,请检查服务:"
  echo "systemctl status mariadb --no-pager"
  exit 1
fi

echo "==> 配置监听地址和端口"
cp -a "${MYSQL_CNF}" "${MYSQL_CNF}.bak.$(date +%s)" || true

if grep -Eq '^[#[:space:]]*bind-address[[:space:]]*=' "${MYSQL_CNF}"; then
  sed -ri "s/^[#[:space:]]*bind-address[[:space:]]*=.*/bind-address = ${BIND_ADDRESS}/" "${MYSQL_CNF}"
else
  printf "\n[mysqld]\nbind-address = %s\n" "${BIND_ADDRESS}" >> "${MYSQL_CNF}"
fi

if grep -Eq '^[#[:space:]]*port[[:space:]]*=' "${MYSQL_CNF}"; then
  sed -ri "s/^[#[:space:]]*port[[:space:]]*=.*/port = ${MYSQL_PORT}/" "${MYSQL_CNF}"
else
  printf "port = %s\n" "${MYSQL_PORT}" >> "${MYSQL_CNF}"
fi

echo "==> 写入基础配置"
cat > "${TUNING_CNF}" <<'EOF'
[mysqld]

skip_name_resolve = 1

character-set-server = utf8mb4
collation-server = utf8mb4_general_ci

server_id = 1
log_bin = mysql-bin
binlog_format = ROW

expire_logs_days = 7
max_binlog_size = 1000M
sync_binlog = 1

innodb_file_per_table = 1
EOF

echo "==> 重启 MariaDB"
systemctl restart mariadb
sleep 2

echo "==> 确保 root 本地仍可登录"
mysql -uroot -e "SELECT USER(), CURRENT_USER(), VERSION();"

if [[ "${CREATE_LOCAL_SUDO_SOCKET_USER}" == "1" && -n "${REAL_USER}" && "${REAL_USER}" != "root" ]]; then
  echo "==> 为 sudo 用户创建本地免密账号:${REAL_USER}"
  mysql -uroot <<SQL
CREATE USER IF NOT EXISTS '${REAL_USER}'@'localhost' IDENTIFIED VIA unix_socket;
GRANT ALL PRIVILEGES ON *.* TO '${REAL_USER}'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
SQL
fi

if [[ "${ENABLE_REMOTE_ROOT}" == "1" ]]; then
  echo "==> 开启远程 root"
  mysql -uroot <<SQL
CREATE USER IF NOT EXISTS 'root'@'${REMOTE_ROOT_HOST}' IDENTIFIED BY '${REMOTE_ROOT_PASSWORD}';
ALTER USER 'root'@'${REMOTE_ROOT_HOST}' IDENTIFIED BY '${REMOTE_ROOT_PASSWORD}';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'${REMOTE_ROOT_HOST}' WITH GRANT OPTION;
FLUSH PRIVILEGES;
SQL
fi

echo "==> 最终检查"
mysql -uroot -e "SELECT VERSION();"
mysql -uroot -e "SELECT User,Host,plugin FROM mysql.user ORDER BY User,Host;"

cat <<EOF

================ 安装完成 ================

已安装:
  default-mysql-server(Debian 12 实际为 MariaDB)

本机 root 登录:
  mysql
或:
  sudo mysql

服务名:
  systemctl status mariadb

远程访问:
  已默认开启

监听地址:
  ${BIND_ADDRESS}

端口:
  ${MYSQL_PORT}

远程 root:
  root@${REMOTE_ROOT_HOST}

远程 root 默认密码:
  ${REMOTE_ROOT_PASSWORD}

远程登录命令:
  mysql -h 服务器IP -P ${MYSQL_PORT} -uroot -p

注意:
1. 还需要放行防火墙/安全组的 ${MYSQL_PORT}
2. 当前默认密码是公开口令,装完强烈建议立刻修改
3. 建议把 REMOTE_ROOT_HOST 改成固定管理 IP,不要长期使用 %

==========================================
EOF

MySQL 官方社区版

terminal
#!/usr/bin/env bash
set -e

ROOT_PASSWORD=${ROOT_PASSWORD:-DigVPS.COM}
REPL_USER=${REPL_USER:-repl}
REPL_PASSWORD=${REPL_PASSWORD:-DigVPS-Repl}

APT_PKG=mysql-apt-config_0.8.36-1_all.deb
APT_URL=https://dev.mysql.com/get/${APT_PKG}

CONF=/etc/mysql/mysql.conf.d/99-digvps.cnf

echo "=============================="
echo " DigVPS MySQL Installer"
echo "=============================="

if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit
fi

echo "Installing dependencies..."
apt update
apt install -y wget gnupg lsb-release debconf-utils ca-certificates

echo "Downloading MySQL APT repo..."
wget -qO /tmp/${APT_PKG} ${APT_URL}

echo "Configuring MySQL repository..."

cat <<EOF | debconf-set-selections
mysql-apt-config mysql-apt-config/select-server select mysql-innovation
mysql-apt-config mysql-apt-config/select-product select Ok
EOF

dpkg -i /tmp/${APT_PKG} || apt -f install -y

echo "Installing MySQL..."
apt update
DEBIAN_FRONTEND=noninteractive apt install -y mysql-server

SERVER_ID=$((RANDOM % 10000 + 1))

echo "Writing MySQL config..."

cat > ${CONF} <<EOF
[mysqld]

bind-address=0.0.0.0

server-id=${SERVER_ID}

log_bin=mysql-bin
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
binlog_format=ROW
binlog_row_image=FULL
relay_log=relay-bin

gtid_mode=ON
enforce_gtid_consistency=ON

slow_query_log=ON
slow_query_log_file=/var/log/mysql/mysql-slow.log
long_query_time=2

skip_name_resolve

innodb_buffer_pool_size=512M
innodb_redo_log_capacity=512M
EOF

echo "Validating MySQL config..."
mysqld --validate-config

echo "Starting MySQL..."
systemctl enable mysql
systemctl restart mysql

echo "Waiting MySQL ready..."

for i in {1..30}; do
  if mysqladmin ping >/dev/null 2>&1; then
    break
  fi
  sleep 1
done

echo "Configuring users..."

mysql --protocol=socket -uroot <<EOF

ALTER USER 'root'@'localhost' IDENTIFIED WITH auth_socket;

CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY '${ROOT_PASSWORD}';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

CREATE USER IF NOT EXISTS '${REPL_USER}'@'%' IDENTIFIED BY '${REPL_PASSWORD}';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO '${REPL_USER}'@'%';

FLUSH PRIVILEGES;

EOF

echo
echo "=============================="
echo " MySQL Installed Successfully"
echo "=============================="

mysql -V

echo
echo "Local login:"
echo "mysql"
echo
echo "Remote login:"
echo "mysql -h SERVER_IP -u root -p"
echo "Password: ${ROOT_PASSWORD}"

echo
echo "Replication user:"
echo "User: ${REPL_USER}"
echo "Password: ${REPL_PASSWORD}"

echo
echo "Master status:"
mysql -e "SHOW BINARY LOG STATUS" -E || true

📘 MySQL 二进制日志格式

结合视频教程食用 油管 B站

基于段的格式

conf
# mysql 5.7之前默认格式
binlog_format=STATEMENT

优点

  • 基于段日志记录的是 SQL 语句,所以日志记录量相对较小,节约磁盘及网络 I/O
  • 并不强制要求主从数据库的表定义完全相同
  • 相比于基于行的复制方式更为灵活

缺点

  • 必须要记录上下文信息保证语句在从服务器上执行的结果和在主服务器上相同,但是一些特定函数,如 UUID(),user() 这样非确定性函数还是无法复制。
  • 对于存储过程,触发器,自定义函数进行的修改也可能造成数据不一致。
  • 相比基于行的复制方式在从执行时需要更多的行锁。

演示

mysql
# 显示当前格式
MariaDB [(none)]> show variables like 'binlog_format';

# 设定为段格式
MariaDB [(none)]> set session binlog_format=statement;

# 刷新 binlog 产生新文件便于观察
MariaDB [(none)]> flush logs;

# 创建新的数据库和表
MariaDB [(none)]> create database digvps;
MariaDB [(none)]> use digvps;
MariaDB [digvps]> create table user(id int,name varchar(10));

# 插入数据更新数据
MariaDB [digvps]> insert into user values(1,'pang'),(2,'bb');
MariaDB [digvps]> update user set name='pangge' where id =1;

# 查看 binlog 日志
root@master:~# cd /var/lib/mysql/
root@master:/var/lib/mysql# mysqlbinlog mysql-bin.000002

基于行的格式

conf
# mysql 5.7 之后的默认格式
binlog_format=ROW

优点

  • Row 格式可以避免 MySQL 复制中出现的主从不一致问题,记录的是增删改查的每一行的数据更改
  • 对每一行数据的修改比基于段的复制高效,减少从库锁的使用。
  • 误操作的时候还可以通过分析二进制日志,对日志中记录的数据修改操作进行反向处理来达到恢复数据的目的。

缺点

  • 记录的日志量加大 binlog_row_image =FULL|MINIMAL|NOBLOB
  • 要求主从数据库的表结构相同,否则可能会终端复制
  • 无法在从库单独执行触发器

演示

full - 记录整行数据(所有列)

mysql
# 设置日志格式为 row
MariaDB [digvps]> set session binlog_format=row;
MariaDB [digvps]> show variables like 'binlog_format';
MariaDB [digvps]> flush logs;
MariaDB [digvps]> show variables like 'binlog_row_image';

# 做些操作
## 创建表
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  `url` varchar(20) DEFAULT NULL,
  `intro` text DEFAULT NULL,
  PRIMARY KEY (`id`)
)
## 添加数据
MariaDB [digvps]> insert into user values(3,'cc','一二三四五,上山打老虎');
## 删除操作
MariaDB [digvps]> delete from user where id=1;

# 查看日志
root@master:/var/lib/mysql# mysqlbinlog -vv mysql-bin.000004

minimal - 只记录必要的列

mysql
# 日志存储设置为 minimal
MariaDB [digvps]> set session binlog_row_image=minimal;

# 更新数据
MariaDB [digvps]> update user set name='name 2' where id =2;

noblob - 和 FULL 类似,但不记录 BLOB / TEXT 列

mysql
# 日志存储设置为 noblob
set session binlog_row_image=noblob;

# 更新数据
MariaDB [digvps]> update user set name='name 2' where id =2;

混合日志格式

根据 SQL 语句由系统决定在基于段和基于行的日志格式中进行选择

conf
binlog_format=MIXED

📘 主从同步

介绍

主从同步解决了什么问题

  • 实现在不通服务器上的数据分布
  • 实现数据读取的负载均衡
  • 增强了数据安全性
  • 实现数据库高可用和故障切换

注意事项

  • binlog 记录了所有对 MySQL 数据库的修改事件,包括增删改查事件和对表结构的修改事件,对于回滚或者其他原因未成功执行的事件不会记录。

MySQL复制拓扑

复制的本质是 Source 把事务写入 binary log,然后 Replica 读取并应用这些事件。

                +--------------------+
                |     Source DB      |
                | (Primary/Master)   |
                +--------------------+
                        |
                        | 1. 写入 binlog
                        v
                +--------------------+
                |    Binary Log      |
                |   mysql-bin.xxx    |
                +--------------------+
                        |
                        | 2. 发送 binlog event
                        v
        +-------------------------------------+
        |        Replica IO Thread            |
        |   (从 Source 拉取 binlog event)      |
        +-------------------------------------+
                        |
                        | 3. 写入 relay log
                        v
                +--------------------+
                |      Relay Log     |
                |   relay-log.xxx    |
                +--------------------+
                        |
                        | 4. SQL Thread
                        v
                +--------------------+
                |     Replica DB     |
                |    应用 SQL 变更    |
                +--------------------+

📘 基于日志点的复制

结合视频教程食用 油管 B站

优点

  • 是 MySQL 最早支持的复制技术,Bug 相对较少。
  • 对 SQL 查询没有任何限制
  • 故障处理比较容易

缺点

  • 故障转移时重新获取新主库的二进制文件偏移量比较困难。

建立复制账号

在 主库(Source) 执行:

terminal
CREATE USER 'repl'@'38.255.16.190' IDENTIFIED BY 'digvps.com';

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'38.255.16.190';

FLUSH PRIVILEGES;

配置文件

配置主数据库服务器

conf
# 日志的名字,以mysql-bin开头
log_bin = mysql-bin

# 动态参数,可以用 set 命令设置,但是记得需要及时在配置文件中修改,否则下次启动就。。。
# 在整个群集中,这个 id 必须是唯一的
server_id = 1

配置从数据库服务器

conf
log_bin = mysql-bin
server_id = 2
# 配置中继日志名,这里注意,默认情况下是主机名,如果运维改了机器名字就。。。
relay_log = mysql-relay-bin
# 可选,开启这个参数可以把中继日志记录到本机的二进制日志,这样可以进行链路复制,其他服务器可以从从服务器同步数据。
log_slave_update = on 
# 可选,禁止写操作
read_only = on

初始化从服务器数据

备份主库

terminal
mysqldump --single-transaction --master-data --triggers  --routines --all-databases > all.sql
xtrabackup --slave-info

拷贝到从库

terminal
scp all.sql root@38.255.16.190:/root

从库还原数据

terminal
root@silver:~# mysql < all.sql

主库获取 binlog 位置

从刚才的备份文件中找到 MASTER_LOG_FILE和MASTER_LOG_POS

从库配置复制

mysql
-- 创建
CHANGE MASTER TO
  MASTER_HOST='38.255.16.139',
  MASTER_USER='repl',
  MASTER_PASSWORD='digvps.com',
  MASTER_LOG_FILE='mysql-bin.000005',
  MASTER_LOG_POS=3255;

-- 查看状态

SHOW MASTER STATUS;
show slave status \G;

-- 启动
START SLAVE;

-- 查看进程

MariaDB [digvps]> show processlist;
+----+-------------+-----------+--------+-----------+------+--------------------------------------------------------+------------------+----------+
| Id | User        | Host      | db     | Command   | Time | State                                                  | Info             | Progress |
+----+-------------+-----------+--------+-----------+------+--------------------------------------------------------+------------------+----------+
| 33 | root        | localhost | digvps | Query     |    0 | starting                                               | show processlist |    0.000 |
| 35 | system user |           | NULL   | Slave_SQL |   94 | Slave has read all relay log; waiting for more updates | NULL             |    0.000 |
+----+-------------+-----------+--------+-----------+------+--------------------------------------------------------+------------------+----------+

📘 基于 GTID 的复制

GTID 既全局事务 ID,其保证为每一个在主数据库上提交的事务在复制群集中可以生成一个唯一的 ID

GTID=source_id:transaction_id

从库会把已执行事务的 GTID 值发给主库,主库会发送未执行事务的 GTID 值,同一个事务只在指定的从库执行一次。

建立复制账号

在 主库(Source) 执行:

terminal
CREATE USER 'repl'@'38.255.16.190' IDENTIFIED BY 'digvps.com';

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'38.255.16.190';

FLUSH PRIVILEGES;

# 可选,修改密码
ALTER USER 'repl'@'38.255.16.190' IDENTIFIED BY 'digvps.com';

如已建立,可以检查下

mysql
-- 查看用户
SELECT user,host,plugin FROM mysql.user;

-- 查看授权
show grants for repl@'%';

主从服务器配置

配置主数据库服务器

conf
# 日志的名字,以mysql-bin开头
log_bin = mysql-bin

# 动态参数,可以用 set 命令设置,但是记得需要及时在配置文件中修改,否则下次启动就。。。
# 在整个群集中,这个 id 必须是唯一的
server_id = 1

# 必须
gtid_mode = ON

# 禁止执行那些“无法生成 GTID 或可能破坏 GTID 一致性”的 SQL。
## 这样的话一些语句无法使用,例如 CREATE TABLE … SELECT ,必须先定义表。又或者  CREATE TEMPORARY TABLE 等。。。
enforce_gtid_consistency=ON

配置从数据库服务器

conf
log_bin = mysql-bin
server_id = 2

# 集群中每台服务器都要开启 gtid_mode
gtid_mode = ON
enforce_gtid_consistency=ON

# 配置中继日志名,这里注意,默认情况下是主机名,如果运维改了机器名字就。。。
relay_log = mysql-relay-bin

# 可选,开启这个参数可以把中继日志记录到本机的二进制日志,这样可以进行链路复制,其他服务器可以从从服务器同步数据。
log_slave_update = on 

# 可选,禁止写操作
read_only = on

初始化从服务器数据

备份主库

terminal
mysqldump \
--single-transaction \
--quick \
--source-data=2 \
--triggers \
--routines \
--events \
--set-gtid-purged=ON \
--all-databases \
> all.sql

拷贝到从库

terminal
scp all.sql root@38.255.16.190:/root

从库还原数据

terminal
root@silver:~# mysql < all.sql

启动基于 GTID 的复制

mysql
-- 创建
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='38.255.16.139',
  SOURCE_USER='repl',
  SOURCE_PASSWORD='digvps.com',
  SOURCE_AUTO_POSITION=1,
  GET_SOURCE_PUBLIC_KEY=1;

-- 启动复制
START REPLICA;

-- 停止复制
STOP REPLICA;

-- 查看状态
SHOW REPLICA STATUS\G

-- 可选,查更细的 worker 错误
SELECT WORKER_ID, LAST_ERROR_NUMBER, LAST_ERROR_MESSAGE
FROM performance_schema.replication_applier_status_by_worker
WHERE LAST_ERROR_NUMBER <> 0\G

CREATE USER IF NOT EXISTS 'repl'@'38.255.16.190' IDENTIFIED BY 'digvps.com';

-- 可选,跳过 GTID
STOP REPLICA;

SET GTID_NEXT='c5a56417-1e87-11f1-9b73-fa163ec99a28:13';
BEGIN;
COMMIT;
SET GTID_NEXT='AUTOMATIC';

START REPLICA;

-- 查看进程
show processlist;

并行复制(Parallel Replication)

mysql
STOP REPLICA;

-- 控制 SQL 线程的并发 worker 数量。
SHOW VARIABLES LIKE 'replica_parallel_workers';
SET GLOBAL replica_parallel_workers = 4;

-- 并发复制策略。
-- DATABASE 按数据库并发,LOGICAL_CLOCK 按事务依赖并发
SHOW VARIABLES LIKE 'replica_parallel_type';
SET GLOBAL replica_parallel_type = 'LOGICAL_CLOCK';
START REPLICA;

📘 半同步复制(Semi-Sync Replication)

概念

主库提交事务时,至少有一个从库收到 binlog 才返回成功。

普通复制:

client
  ↓
master commit
  ↓
返回客户端
  ↓
replica 收到 binlog

半同步复制:至少一个 replica 收到 binlog

client
  ↓
master commit
  ↓
发送 binlog
  ↓
replica ACK
  ↓
master 返回客户端

两种提交模式

mysql
-- 控制参数
SHOW VARIABLES LIKE 'rpl_semi_sync_source_wait_point';

AFTER_SYNC(默认,推荐)

先同步,再提交,主库 crash 时,至少有一个从库拥有完整事务。

client
  │
  │ commit
  ▼
master 写 binlog
  │
  ▼
发送给 replica
  │
  ▼
replica 写入 relay log
  │
  ▼
replica ACK
  │
  ▼
master commit
  │
  ▼
返回客户端

AFTER_COMMIT

先提交,再等待 ACK。如果这时 master crash,replica 还没收到 binlog,就可能事务已经返回客户端但从库没有。

client
  │
  │ commit
  ▼
master 写 binlog
  │
  ▼
master commit
  │
  ▼
返回客户端
  │
  ▼
发送给 replica
  │
  ▼
replica ACK

配置

主库配置

mysql
-- 查看插件
SHOW PLUGINS;
     
-- 安装半同步插件
-- 如果没看到 semisync_source 和 semisync_replica
INSTALL PLUGIN rpl_semi_sync_source
SONAME 'semisync_source.so';

-- 开启半同步
SET GLOBAL rpl_semi_sync_source_enabled = ON;
    
-- 设置至少一个从库确认
SET GLOBAL rpl_semi_sync_source_wait_for_replica_count = 1;
    
-- 设置等待 ACK 的时间
SET GLOBAL rpl_semi_sync_source_timeout = 1000

-- 验证
-- 验证是否启用成功
SHOW STATUS LIKE 'Rpl_semi_sync_source_status';
-- 查看当前有多少从库参与:
SHOW STATUS LIKE 'Rpl_semi_sync_source_clients';
conf
plugin_load_add = semisync_source.so
rpl_semi_sync_source_enabled = ON
rpl_semi_sync_source_wait_for_replica_count = 1
rpl_semi_sync_source_timeout = 1000

从库配置

mysql
-- 安装插件
INSTALL PLUGIN rpl_semi_sync_replica
SONAME 'semisync_replica.so';

-- 启用半同步
SET GLOBAL rpl_semi_sync_replica_enabled = ON;
    
-- 重启复制
STOP REPLICA;
START REPLICA;

-- 验证
-- 验证是否启用成功
SHOW STATUS LIKE 'Rpl_semi_sync_replica_status';
conf
plugin_load_add = semisync_replica.so
rpl_semi_sync_replica_enabled = ON

📘 查询优化

设置参数

mysql
-- 启动停止记录慢查询日志
show variables like 'slow_query_log'
set global slow_query_log on
     
-- 指定记录了慢查询日志的存储路径及文件
show variables like 'slow_query_log_file'
     
-- 是否记录未适用索引的 SQL
show variables like 'log_queries_not_using_indexes'
set global log_queries_not_using_indexes on

-- 指定记录慢查询日志 SQL 执行时间的阈值
show variables like 'long_query_time'

查看慢查询语句

通过工具

terminal
# 安装  percona-toolkit 
apt update
apt install percona-toolkit -y

# 看最慢 SQL:
pt-query-digest --limit=20 /srv/data/mysql/slow.log

通过 SQL

mysql
SELECT id,user,host,DB,command,time,state,info
from information_schema.PROCESSLIST
where TIME >=60
mysql
SELECT
  DIGEST_TEXT,
  COUNT_STAR AS exec_count,
  ROUND(SUM_TIMER_WAIT/1000000000000,2) AS total_sec,
  ROUND(AVG_TIMER_WAIT/1000000000000,4) AS avg_sec,
  SUM_ROWS_SENT,
  SUM_ROWS_EXAMINED
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
  LIMIT 10;