MySQL 命令行操作完整帮助文档

Scroll Down

MySQL 命令行操作完整帮助文档

📖 目录

  1. 快速导出CSV
  2. 数据导入MySQL
  3. 执行大文件SQL
  4. 常用维护命令
  5. 性能优化建议

1. 快速导出CSV

1.1 基础导出命令

# 基本格式
mysql -u用户名 -p密码 -D数据库名 -e "查询语句" > 输出文件.csv

# 示例:导出整个表
mysql -uroot -p123456 -Dmydb -e "SELECT * FROM users" > users.csv

# 示例:导出特定字段
mysql -uroot -p123456 -Dmydb -e "SELECT id, name, email FROM customers" > customers.csv

1.2 格式化CSV导出

# 方法1:使用sed格式化(标准CSV格式)
mysql -uroot -p123456 -Dmydb -e "SELECT * FROM table" | 
  sed 's/\t/","/g; s/^/"/; s/$/"/; s/\r//g;' > output.csv

# 方法2:使用tr替换制表符(简单CSV)
mysql -uroot -p123456 -Dmydb -e "SELECT * FROM table" | 
  tr '\t' ',' > output.csv

# 方法3:包含表头的格式化
mysql -uroot -p123456 -Dmydb --batch -e "SELECT * FROM table" | 
  sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > output.csv

1.3 使用INTO OUTFILE(高性能导出)

# 需要FILE权限,数据保存在MySQL服务器上
mysql -uroot -p123456 -Dmydb -e "
SELECT * FROM orders
INTO OUTFILE '/tmp/orders_export.csv'
FIELDS TERMINATED BY ',' 
ENCLOSED BY '\"'
LINES TERMINATED BY '\n';
"

# 导出到远程服务器的本地
mysql -uroot -p123456 -h远程IP -Dmydb -e "
SELECT * FROM orders
INTO OUTFILE '/tmp/orders.csv'
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
" && scp user@远程IP:/tmp/orders.csv ./local/

1.4 复杂查询导出

# 多表关联导出
mysql -uroot -p123456 -Dmydb -e "
SELECT u.id, u.name, o.order_date, o.total_amount
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.status = 'completed'
" > user_orders.csv

# 带条件导出
mysql -uroot -p123456 -Dmydb -e "
SELECT * FROM logs 
WHERE create_time > '2024-01-01' 
ORDER BY create_time DESC
" > recent_logs.csv

1.5 压缩导出

# 直接压缩
mysql -uroot -p123456 -Dmydb -e "SELECT * FROM large_table" | gzip > data.csv.gz

# 分步压缩
mysql -uroot -p123456 -Dmydb -e "SELECT * FROM large_table" > data.csv && gzip data.csv

# 使用pigz多线程压缩(更快)
mysql -uroot -p123456 -Dmydb -e "SELECT * FROM large_table" | pigz > data.csv.gz

1.6 分块导出大数据

#!/bin/bash
# 分页导出大表
LIMIT=100000
OFFSET=0
PAGE=1

while true; do
  mysql -uroot -p123456 -Dmydb -e "
    SELECT * FROM huge_table 
    LIMIT $LIMIT OFFSET $OFFSET
  " > "data_part_$PAGE.csv"
  
  # 检查是否还有数据
  if [ $(wc -l < "data_part_$PAGE.csv") -le 1 ]; then
    rm "data_part_$PAGE.csv"
    break
  fi
  
  OFFSET=$((OFFSET + LIMIT))
  PAGE=$((PAGE + 1))
done

2. 数据导入MySQL

2.1 使用LOAD DATA INFILE(高性能导入)

# 基本格式
mysql -uroot -p123456 -Dmydb -e "
LOAD DATA INFILE '/path/to/data.csv'
INTO TABLE target_table
FIELDS TERMINATED BY ',' 
ENCLOSED BY '\"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;  -- 忽略标题行
"

# 示例:导入用户数据
mysql -uroot -p123456 -Dmydb -e "
LOAD DATA INFILE '/tmp/users.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
ENCLOSED BY '\"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(id, name, email, created_at);
"

2.2 命令行管道导入

# CSV导入(使用sed处理格式)
cat data.csv | sed 's/","/\t/g; s/^"//; s/"$//' | 
mysql -uroot -p123456 -Dmydb -e "LOAD DATA LOCAL INFILE '/dev/stdin' INTO TABLE mytable"

# TSV文件直接导入
cat data.tsv | mysql -uroot -p123456 -Dmydb -e "
LOAD DATA LOCAL INFILE '/dev/stdin' 
INTO TABLE mytable
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
"

2.3 使用mysqlimport工具

# 基本格式
mysqlimport -u用户名 -p密码 --local 数据库名 文件名.csv

# 示例
mysqlimport -uroot -p123456 --local --fields-terminated-by=, --ignore-lines=1 mydb /tmp/users.csv

# 常用参数
mysqlimport -uroot -p123456 \
  --local \
  --fields-terminated-by=, \
  --fields-enclosed-by='"' \
  --lines-terminated-by='\n' \
  --ignore-lines=1 \
  --columns="id,name,email" \
  mydb /tmp/data.csv

2.4 导入压缩文件

# 解压并导入
gunzip -c data.csv.gz | mysql -uroot -p123456 -Dmydb -e "
LOAD DATA LOCAL INFILE '/dev/stdin'
INTO TABLE mytable
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
"

# 一步完成
zcat data.csv.gz | sed '1d' | mysql -uroot -p123456 -Dmydb -e "
LOAD DATA LOCAL INFILE '/dev/stdin'
INTO TABLE mytable
FIELDS TERMINATED BY ','
"

2.5 导入时数据转换

# 导入时修改数据
mysql -uroot -p123456 -Dmydb -e "
LOAD DATA INFILE '/tmp/data.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(@col1, @col2, @col3)
SET 
  id = NULL,  -- 自增ID
  name = UPPER(@col1),
  email = LOWER(@col2),
  age = @col3 * 1,  -- 类型转换
  created_at = NOW();
"

2.6 导入前预处理脚本

#!/bin/bash
# 预处理并导入
INPUT_FILE="data.csv"
TEMP_FILE="$(mktemp)"

# 清理数据
cat "$INPUT_FILE" | \
  sed 's/\"\"/\\\"\"/g' | \  # 处理双引号
  iconv -f GBK -t UTF-8//IGNORE | \  # 转换编码
  grep -v '^#' > "$TEMP_FILE"  # 移除注释行

# 导入清理后的数据
mysql -uroot -p123456 -Dmydb -e "
LOAD DATA LOCAL INFILE '$TEMP_FILE'
INTO TABLE mytable
FIELDS TERMINATED BY ',' 
ENCLOSED BY '\"'
LINES TERMINATED BY '\n'
"

# 清理临时文件
rm "$TEMP_FILE"

3. 执行大文件SQL

3.1 基础执行方式

# 方法1:直接执行
mysql -uroot -p123456 -Dmydb < large_file.sql

# 方法2:使用source命令
mysql -uroot -p123456
mysql> USE mydb;
mysql> SOURCE /path/to/large_file.sql;

# 方法3:带进度显示
pv large_file.sql | mysql -uroot -p123456 -Dmydb

3.2 分割大文件执行

# 按文件大小分割
split -l 10000 large_file.sql chunk_

# 依次执行分割文件
for file in chunk_*; do
  echo "Processing $file..."
  mysql -uroot -p123456 -Dmydb < "$file"
  rm "$file"
done

3.3 使用mysqlslap测试性能

# 测试SQL文件执行性能
mysqlslap -uroot -p123456 \
  --concurrency=50 \
  --iterations=10 \
  --query=large_file.sql \
  --create-schema=mydb \
  --verbose

3.4 分批次执行大事务

#!/bin/bash
# 分批次执行大更新
BATCH_SIZE=10000
MAX_ID=$(mysql -uroot -p123456 -Dmydb -N -e "SELECT MAX(id) FROM huge_table")
BATCHES=$(( (MAX_ID + BATCH_SIZE - 1) / BATCH_SIZE ))

for ((i=0; i<BATCHES; i++)); do
  OFFSET=$((i * BATCH_SIZE))
  echo "Processing batch $((i+1))/$BATCHES..."
  
  mysql -uroot -p123456 -Dmydb <<EOF
    START TRANSACTION;
    UPDATE huge_table 
    SET status = 'processed'
    WHERE id BETWEEN $OFFSET AND $((OFFSET + BATCH_SIZE - 1))
      AND status = 'pending';
    COMMIT;
EOF
  
  sleep 1  # 避免锁竞争
done

3.5 执行时监控进度

#!/bin/bash
# 带进度监控的执行
SQL_FILE="large_update.sql"
TOTAL_LINES=$(wc -l < "$SQL_FILE")
PROGRESS_FILE="/tmp/mysql_progress"

# 使用awk添加进度信息
awk -v total="$TOTAL_LINES" '
{
  # 每1000行输出一次进度
  if (NR % 1000 == 0) {
    printf "Progress: %.2f%% (%d/%d)\n", (NR/total)*100, NR, total > "/dev/stderr"
  }
  print $0
}
' "$SQL_FILE" | mysql -uroot -p123456 -Dmydb --show-warnings

3.6 使用pt-online-schema-change(在线修改大表)

# 安装percona工具包后使用
pt-online-schema-change \
  --user=root \
  --password=123456 \
  --host=localhost \
  --database=mydb \
  --table=huge_table \
  --alter="ADD COLUMN new_column INT NULL" \
  --execute \
  --no-drop-old-table

3.7 并行执行多个SQL文件

#!/bin/bash
# 并行执行脚本
SQL_DIR="/path/to/sql/files"
MAX_JOBS=4  # 最大并行数

# 使用GNU parallel并行执行
ls "$SQL_DIR"/*.sql | parallel -j $MAX_JOBS "
  echo 'Processing {}'
  mysql -uroot -p123456 -Dmydb < {} 2>&1 | tee {}.log
"

4. 常用维护命令

4.1 数据库备份与恢复

# 备份单个数据库
mysqldump -uroot -p123456 --single-transaction --routines mydb > mydb_backup.sql

# 备份所有数据库
mysqldump -uroot -p123456 --all-databases --single-transaction > all_dbs.sql

# 压缩备份
mysqldump -uroot -p123456 mydb | gzip > mydb_$(date +%Y%m%d).sql.gz

# 只备份结构
mysqldump -uroot -p123456 --no-data mydb > mydb_schema.sql

# 只备份数据
mysqldump -uroot -p123456 --no-create-info mydb > mydb_data.sql

# 恢复数据库
mysql -uroot -p123456 -Dmydb < backup.sql
gunzip -c backup.sql.gz | mysql -uroot -p123456 -Dmydb

4.2 数据库状态监控

# 查看进程列表
mysql -uroot -p123456 -e "SHOW PROCESSLIST;"

# 查看锁信息
mysql -uroot -p123456 -e "SHOW ENGINE INNODB STATUS\G"

# 查看表状态
mysql -uroot -p123456 -Dmydb -e "SHOW TABLE STATUS LIKE 'table_name';"

# 查看数据库大小
mysql -uroot -p123456 -e "
SELECT 
  table_schema AS 'Database',
  ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.tables 
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;
"

4.3 性能分析

# 开启慢查询日志分析
mysql -uroot -p123456 -e "
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
"

# 使用mysqldumpslow分析慢查询
mysqldumpslow -s t /var/log/mysql/slow.log | head -20

# 使用pt-query-digest(percona工具)
pt-query-digest /var/log/mysql/slow.log > slow_report.txt

5. 性能优化建议

5.1 导出优化

# 1. 使用INTO OUTFILE代替管道(性能最好)
# 2. 大表导出时添加索引条件减少锁表时间
# 3. 在从库上执行导出操作
# 4. 分批导出大数据,使用LIMIT和OFFSET

5.2 导入优化

# 1. 导入前禁用索引和外键约束
SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET AUTOCOMMIT = 0;

# 2. 使用LOAD DATA INFILE而不是INSERT
# 3. 导入后重新创建索引
ALTER TABLE table_name ENABLE KEYS;

# 4. 增大缓冲区大小
mysql --max_allowed_packet=1G --net_buffer_length=1000000

5.3 大文件SQL执行优化

# 1. 拆分大文件,分批执行
# 2. 关闭二进制日志
mysql --skip-log-bin

# 3. 增加超时时间
mysql --connect_timeout=3600 --net_read_timeout=3600

# 4. 使用事务包裹(适当大小)
START TRANSACTION;
-- 执行一批SQL
COMMIT;

5.4 配置文件优化

# my.cnf 相关配置
[mysqld]
# 导入导出相关
max_allowed_packet = 1G
innodb_buffer_pool_size = 4G
innodb_log_file_size = 1G
bulk_insert_buffer_size = 256M

# 连接相关
max_connections = 500
wait_timeout = 600
interactive_timeout = 600

# 查询缓存
query_cache_type = 0  # 对于频繁更新的大表建议关闭

📋 快速参考速查表

# 导出速查
mysql -uuser -p -Ddb -e "SELECT ..." > file.csv                  # 简单导出
mysql -uuser -p -Ddb -e "SELECT ..." | sed 's/\t/,/g' > file.csv # CSV格式化
mysqldump -uuser -p db table > backup.sql                        # 备份表

# 导入速查
mysql -uuser -p db < file.sql                                    # 执行SQL文件
mysqlimport -uuser -p --local db file.csv                        # 导入CSV
mysql -uuser -p -e "LOAD DATA INFILE 'file.csv' INTO TABLE ..."  # 高性能导入

# 实用管道组合
cat data.csv | grep -v 'NULL' | mysql -uuser -p -Ddb -e "LOAD DATA ..."  # 过滤后导入
mysql -uuser -p -Ddb -e "SELECT ..." | gzip > data.csv.gz                # 压缩导出
zcat backup.sql.gz | mysql -uuser -p db                                  # 压缩恢复

⚠️ 注意事项

  1. 权限要求INTO OUTFILE需要FILE权限,LOAD DATA需要INSERT权限
  2. 路径问题:确保MySQL对目标路径有读写权限
  3. 字符编码:统一使用UTF-8避免乱码
  4. 大文件处理:超过1GB的文件建议分割处理
  5. 生产环境:在从库上执行导出,避免影响主库性能
  6. 事务处理:大事务可能产生大量undo log,适当拆分

🔧 故障排查

# 查看错误日志
tail -f /var/log/mysql/error.log

# 查看当前连接状态
mysqladmin -uroot -p123456 processlist

# 检查表状态
mysqlcheck -uroot -p123456 --auto-repair --optimize mydb

# 查看导入导出错误
mysql -uroot -p123456 -e "SHOW WARNINGS;"