mysqldump、myisam 和读取本地

mysqldump、myisam 和读取本地

当使用 --lock-tables 针对使用 MyISAM 表的数据库运行 mysqldump 时,文档指出每个表都使用 READ LOCAL 锁定。据我了解,READ LOCAL 允许来自其他会话的并发插入。

我对此有几个疑问。

使用 READ LOCAL 时,其他会话无法执行的唯一操作是 TRUNCATE、UPDATE 和 DELETE。如果表中没有“漏洞”,则其他会话在使用 READ LOCAL 锁定的表上可以正常执行 INSERTS 和 SELECTS。这是正确的假设吗?

在使用 mysqldump 进行备份的情况下,由于允许并发插入并且表被顺序锁定(多个表备份),那么是什么阻止了关系表变得不一致?表转储是否包含可能在发出 LOCK TABLE 后添加的数据?

感谢您的时间。

答案1

我认为您的假设是正确的。我刚刚进行了测试以确认,READ LOCAL 允许来自其他会话的并发 INSERT,这些 INSERT 在调用 UNLOCK TABLE 之前对锁定会话不可见。在持有 READ LOCAL 锁时,UPDATE、TRUNCATE 和 DELETE 会被阻止。我没有测试漏洞情况。

关于引用完整性,mysqldump 的 --lock-tables 选项(从 5.1 开始默认启用,不确定早期版本是否启用)在转储数据之前使用单个 LOCK TABLES 语句一次性锁定数据库中的所有表,因此它不可能对数据产生不一致的看法。您可以通过打开常规查询日志并运行 mysqldump 来确认这一点。

但是,请注意手册页中的这一点:

      Please note that when dumping multiple databases, --lock-tables locks tables for each database
      separately. Therefore, this option does not guarantee that the tables in the dump file are logically
      consistent between databases. Tables in different databases may be dumped in completely different
      states.

此外,我知道您可能意识到了这一点,但如果您担心参照完整性,MyISAM 可能不是正确的存储引擎。

下面是我用来确认你的假设的简单代码:

第一节

create database testing;
use testing;
create table t1 (a int not null, primary key(a));
insert into t1 values (1),(2),(3),(4),(5),(6);
select * from t1;
lock tables t1 read local;

第二节

use testing;
insert into t1 values (7);
-- Shows row with a=7
select * from t1;

第一节

-- Does not show row with a=7
select * from t1;

第二节

   -- Blocked
   update t1 set a=8 where a=2;

希望有所帮助。

答案2

文档中根本没有明确说明这一点。我认为这里发生的事情是,这LOCK TABLE导致会话只读取表被锁定时存在的行或字节或任何内容,而不管表实际的大小。行可以继续插入到表中,但只能在表的末尾,即表的锁定部分之后。

相关内容