在活动的系统上执行有效读写的最安全方法是mysqldump?


78

我不确定这是否是正确的,但我记得阅读过,如果您在linux中运行以下命令

mysqldump -u username -p database_name > backup_db.sql

在对数据库进行读写时,转储可能包含错误。

命令中是否有特定选项mysqldump来确保在实时系统上安全地完成此操作?我可以为用户禁用读/写功能几秒钟(数据库<50MB)

Answers:


82

所有数据都是InnoDB

这将为您提供数据的准确时间点快照:

mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

--single-transaction产生一个检查点,使转储在接收传入的更改时捕获该检查点之前的所有数据。这些传入的更改不会成为转储的一部分。这样可以确保所有表的时间点相同。

--routines 转储所有存储过程和存储函数

--triggers 为具有触发器的每个表转储所有触发器

所有数据都是MyISAM或InnoDB / MyISAM的混合

您将必须强加全局读取锁,执行mysqldump并释放全局锁

mysql -uuser -ppass -Ae"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
sleep 5
mysql -uuser -ppass -ANe"SHOW PROCESSLIST" | grep "SELECT SLEEP(86400)" > /tmp/proclist.txt
SLEEP_ID=`cat /tmp/proclist.txt | awk '{print $1}'`
echo "KILL ${SLEEP_ID};" > /tmp/kill_sleep.sql
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
mysql -uuser -ppass -A < /tmp/kill_sleep.sql

试试看 !!!

更新2012-06-22 08:12 EDT

由于您的总数据少于50MB,因此我有另一种选择。与其在后台启动SLEEP命令以保持全局读取锁定86400秒(即24小时)只是为了获取进程ID并杀死外部,我们不如尝试在mysql中而不是在OS中设置5秒超时:

SLEEP_TIMEOUT=5
SQLSTMT="FLUSH TABLES WITH READ LOCK; SELECT SLEEP(${SLEEP_TIMEOUT})"
mysql -uuser -ppass -Ae"${SQLSTMT}" &
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

对于非常小的数据库,这是一种更干净,更简单的方法。


1
5秒只是预防措施。您可以尝试使用较低的值。
RolandoMySQLDBA 2012年

1
Rolando-是ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query预期的错误消息吗?
user784637 2012年

1
是否所有MySQL数据都在mysqldump中输出?
RolandoMySQLDBA 2012年

1
我不确定错误消息。这只是一个猜测,但这可能来自单行脚本,该脚本杀死了我在第二个脚本中提到的用户定义的SLEEP函数调用。
RolandoMySQLDBA 2012年

1
试试我的新建议,看看是否顺利。希望不会有错误消息。
RolandoMySQLDBA 2012年

2
  • 对于InnoDB表,您应该使用该--single-transaction选项,如另一个答案中所述。
  • 对于MyISAM有--lock-tables

这里查看官方文档


1

如果要对MyISAM或混合表执行此操作,而又不会因锁定表而造成任何停机,则可以设置一个从数据库,并从那里获取快照。不幸的是,设置从数据库会导致导出实时数据库的停机时间,但是一旦运行该数据库,您应该能够锁定它的表,并使用其他人描述的方法进行导出。发生这种情况时,它将落后于主服务器,但不会阻止主服务器更新其表,并且在备份完成后会立即赶上。


1

这是我的方法。由于使用,它应该在所有情况下都有效FLUSH TABLES WITH READ LOCK

#!/bin/bash

DB=example
DUMP_FILE=export.sql

# Lock the database and sleep in background task
mysql -uroot -proot $DB -e "FLUSH TABLES WITH READ LOCK; DO SLEEP(3600);" &
sleep 3

# Export the database while it is locked
mysqldump -uroot -proot --opt $DB > $DUMP_FILE

# When finished, kill the previous background task to unlock
kill $! 2>/dev/null
wait $! 2>/dev/null

echo "Finished export, and unlocked !"

shell sleep命令只是为了确保在运行mysqldump之前执行运行mysql lock命令的后台任务。您可以将其减少到1秒,但仍然可以。将其增加到30秒,然后在那30秒内尝试将值插入另一个客户端的任何表中,您会看到它已被锁定。

使用此手动背景锁定有两个优点,而不是使用mysqldumpoptions --single-transaction--lock-tables

  1. 如果您混合使用MyISAM / InnoDB表,则这将锁定所有内容。
  2. mysqldump在相同的锁定期间,您还可以运行除以外的其他命令。例如,在主节点上设置复制时,这很有用,因为您需要获得二进制日志位置以及SHOW MASTER STATUS;创建的转储的确切状态(在解锁数据库之前),才能创建复制从属。


0

如果MYISAM表很大,并且需要不加锁地转储该表并避免高服务器负载,则可以使用以下脚本。

#!/bin/sh

my_user="user"
my_password="password"
my_db="vpn"
my_table="traffic"
my_step=100000

read -p "Dumping table ${my_db}.${my_table} to ${my_table}.sql?" yn
case $yn in
    [Yy]* ) break;;
    * ) echo "User cancel."; exit;;
esac

my_count=$(mysql $my_db -u $my_user -p$my_password -se "SELECT count(*) FROM $my_table")
my_count=$(($my_count + 0))

if [ ! $my_count ]
then
    echo "No records found"
    exit
fi

echo "Records in table ${my_db}.${my_table}: ${my_count}"

echo "" > $my_table.sql

max_progress=60

for (( limit=0; limit<=$my_count; limit+=$my_step )); do
    progress=$((max_progress * ( limit + my_step) / my_count))

    echo -ne "Dumping ["
    for ((i=0; i<$progress; i ++)); do
        echo -ne "#"
    done
    for ((; i<$max_progress; i ++)); do
        echo -ne "."
    done

    mysqldump -u $my_user -p$my_password --complete-insert --no-create-info --opt --where="1 limit $limit , $my_step" $my_db $my_table >> $my_table.sql
    echo "" >> $my_table.sql

    echo -ne "] $((100 * ( limit + my_step ) / my_count)) %"
    echo -ne "\r"

    sleep 1

done

echo -ne "\n"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.