首页 > 解决方案 > 锁表红移

问题描述

插入红移时如何对表进行真正的锁定,我认为是这样,但我不确定并且aws文档始终为零输入

begin;lock table sku_stocks;insert into sku_stocks select facility_alias_id, facility_name, CAST( item_name AS bigint), description, CAST( prod_type AS smallint ), total_available, total_allocated from tp_sku_stocks;

标签: sqlamazon-web-servicesamazon-redshiftamazon-redshift-spectrum

解决方案


LOCK有一个记录在案的行为:它在表上获得一个排他锁,因此没有其他会话或事务可以对表做任何事情

如果您希望验证此行为,请按以下步骤操作:

  1. 打开到数据库的连接并针对您的测试表调用beginand命令。lock
  2. 打开到数据库的第二个连接,并尝试select对该表执行操作。
  3. 等到选择返回或您确信其LOCK行为符合记录。
  4. 在第一个会话中执行 a rollback,这样您就不会永久锁定表。

更新

根据您的评论,我认为您对交易的工作方式有误解:

  • 当您启动事务时,Redshift 会分配一个事务 ID,并标记该事务更改的每一行。
  • 在事务中更新表时读取表的 SELECT 将看到“已提交数据的快照”(引用来自上面的链接),而不是事务中正在更新的行。
  • 尝试更新由事务更新的表的 INSERT/UPDATE/DELETE 将阻塞,直到事务完成(请参阅doc,并注意此行为与您从 MySQL 中看到的有所不同)。
  • 当您提交/回滚事务时,任何的 SELECT 都将使用更新的数据。在事务期间启动的任何 SELECT 将继续使用旧数据。

鉴于这些规则,几乎没有理由使用显式 LOCK 语句。您的示例更新,没有 LOCK,将在正在更新的表上放置一个写锁(因此保证没有其他查询可以同时更新它),并将使用它正在读取的表的快照。

如果您确实使用了 LOCK,您将阻止在更新期间尝试从表中进行 SELECT 的任何查询。您可能认为这是您想要的,以确保您的用户只能看到最新数据,但考虑到这一点,在更新之前启动的任何 SELECT 仍将看到旧数据。

我会使用 LOCK 语句的唯一原因是如果您需要保持一组表之间的一致性(好吧,如果您遇到死锁,但您没有指出这一点):

begin;
lock TABLE1;
lock TABLE2;
lock TABLE3;
copy TABLE1 from ...
update TABLE2 select ... from TABLE1
update TABLE3 select ... from TABLE2
commit;

在这种情况下,您要确保 TABLE1、TABLE2 和 TABLE3 始终保持一致:针对其中任何一个的查询将显示相同的信息。但是请注意,在锁定之前启动的 SELECTS 将成功,并在任何更新之前显示数据。并且在事务期间启动的 SELECT 直到事务完成才会真正执行。如果它发生在工作日中间,您的用户可能不喜欢这种情况。


推荐阅读