我四处寻找锁定整个数据库的解决方案,到目前为止我发现的唯一一个是FLUSH TABLES WITH READ LOCK。
这对于备份来说很好,但不幸的是,当我使用模式更改修补数据库时,我不能使用它来阻止对数据库的其他访问。如果我运行ALTER TABLE
after FLUSH TABLES WITH READ LOCK
,我会收到以下消息:
无法执行查询,因为您有一个冲突的读锁
有没有办法在我修补数据库时阻止其他数据库连接临时访问数据库?
我不想主动拒绝其他连接,我只想让它们“暂停”直到修补完成(几秒钟)。
我怎样才能做到这一点?
您应该能够使用一条语句锁定您打算更改(或以其他方式想要隔离,以修改触发器)的所有表,并且您的会话将在您进行更改时保持锁定,直到您释放锁定。
例如,我这里有 3 个表,t1、t2 和 t3。我将对 t2 和 t3 进行更改,我将使用 t1 来说明我是否实际上仍然持有 t2 和 t3 上的锁。
获取 t2 和 t3 上的写锁。每当您
lock table
隐式释放任何其他表锁时,您都必须将它们全部锁定在一起。您的会话将阻塞,直到您获得所有锁定,然后您的提示返回。表 t2 已锁定,我可以更改它。
我也可以访问 t3 (恰好是空的):
但是,我没有锁定 t1,所以我什至无法从中选择。当您持有一个或多个表锁时,您只能访问您拥有锁的表。
现在,测试在 t2 上创建一个简单的触发器,它仍然被锁定。
哈!这是一个错字:我错误地说“在 t1 上插入后”而不是“t2”,服务器阻止我触摸我没有锁定的表,而我持有其他锁。但是,如果我输入正确,我可以修改我实际锁定的表上的触发器。
毕竟,我可以通过从 t2 和 t3 中进行选择来确认我仍然对它们进行了锁定,并且我还可以通过尝试触摸我知道我没有锁定的表来确认我对“某物”有锁定,( t1 再次):
更改完成,释放您最初获得的所有锁。
想到的唯一警告是,如果在更改表时出现相当严重的错误(不是语法错误,而是像 IO 错误、数据损坏和操作系统权限这样的低级错误),则该表可能会被隐式解锁。 .事实上,正如我所提到的,你必须在一个语句中获得所有的表锁,因为下一个
LOCK TABLE
将解锁你已经锁定的任何东西。尝试访问您锁定的表的其他线程应该阻塞,直到您完成或失去连接,这将隐式释放锁定,因为它们与您的连接/会话相关联。