9

我编写了一个备份 shell 脚本来执行 mysqldump。

mysqldump -u$BACKUP_USER -p$BACKUP_PASS --flush-logs --lock-tables $DB_NAME > $SQL_FILE

我的数据库的存储引擎是 MyISAM。所以我不能使用--single-transaction选项。mysqldump 进程中--lock-tables唯一锁定一张表。我的 MySQL 实例中有很多数据库,我不想使用--lock-all-tables,它会锁定我服务器中运行的所有数据库。那么,如何同时锁定一个 mysql 数据库中的所有表以便我可以转储它?

4

3 回答 3

8

到目前为止,这不是最漂亮的解决方案,但这有效。我有同样的需求,这是我的解决方案,稍作修改以匹配您的变量名。我假设您在 Linux 上运行 MySQL,因为这在很大程度上依赖于 shell BASH 语义。如果你在 Windows 上,这可能行不通。

# Mysql script to lock all tables in one DB
# (such as to get a consistent export dump of one database)

MYSQLCMD="mysql -u$BACKUP_USER -p$BACKUP_PASS -A"

function lock_db {
  [ -e "/tmp/mysql-db-lock-${1}" ] && rm "/tmp/mysql-db-lock-${1}"
  mkfifo "/tmp/mysql-db-lock-${1}"
  (
    (
      echo "SELECT CONCAT( 'LOCK TABLES '
             , GROUP_CONCAT(CONCAT('\`',table_name,'\`'),' WRITE')
             , ';'
             ) AS \"-- Statement to lock tables\"
      FROM information_schema.tables
      WHERE table_schema='${1}'
      ORDER BY table_name;
      " | $MYSQLCMD
      echo "\! cat '/tmp/mysql-db-lock-${1}' >/dev/null"
      echo 'UNLOCK TABLES;'
    ) | $MYSQLCMD -D"${1}"
    rm "/tmp/mysql-db-lock-${1}"
  ) &
}

function unlock_db {
  >"/tmp/mysql-db-lock-${1}"
}

# Lock one database, all tables
lock_db $DB_NAME

# Verify locks have been placed
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD

# Do whatever here that you needed the locked db for
mysqldump -u$BACKUP_USER -p$BACKUP_PASS $DB_NAME > $SQL_FILE

# Release locks
unlock_db $DB_NAME

# Verify locks released
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD
于 2013-09-11T22:28:54.030 回答
5

这就是我的做法。它应该适用于所有情况,因为它使用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 !"

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

mysqldump使用此手动后台锁定而不是使用选项--single-transaction和有两个优点--lock-tables

  1. 如果您混合了 MyISAM/InnoDB 表,这将锁定所有内容。
  2. 除了mysqldump在同一锁定期间,您还可以运行其他命令。例如,当在主节点上设置复制时,它很有用,因为您需要SHOW MASTER STATUS;在您创建的转储的确切状态下(在解锁数据库之前)获取二进制日志位置,以便能够创建复制从属节点。
于 2016-03-04T15:04:22.130 回答
4

你应该看看这个选项。

FLUSH TABLES WITH READ LOCK

关闭所有打开的表并使用全局读锁锁定所有数据库的所有表。这是获取备份的一种非常方便的方法...

http://dev.mysql.com/doc/refman/5.0/en/flush.html

于 2012-12-27T06:55:30.130 回答