锁定 table 红移
Lock table redshift
如何在 redshift 中插入时对 table 进行真正的锁定,我认为是这样,但我不确定并且 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;
LOCK
有一个 documented behavior:它获得了 table 上的独占锁,因此其他会话或事务不能做 任何事情 到 table.
如果您想验证此行为,请按以下步骤操作:
- 打开与数据库的连接并针对您的测试调用
begin
和 lock
命令 table。
- 打开一个 second 连接到数据库,并尝试对那个 table.
做一个 select
- 等到 select returns 或您确信
LOCK
的行为符合记录。
- 在第一个会话中执行
rollback
,这样您就不会永久锁定 table。
更新
根据您的评论,我认为您对事务的工作原理存在误解:
- 当您开始一个事务时,Redshift 会分配一个事务 ID,并标记该事务更改的每一行。
- SELECTs 在事务中更新时读取 table 将看到“已提交数据的快照”(引用自上文 link ),而不是在事务中更新的行。
- INSERT/UPDATE/DELETE 尝试更新正在由事务更新的 table 将阻塞直到事务完成(参见 doc,并注意此行为与你会看到,比方说,MySQL).
- 当您 commit/rollback 一个交易时,任何 new SELECTs 将使用更新的数据。在事务期间启动的任何 SELECTs 将继续使用旧数据。
鉴于这些规则,几乎没有理由使用显式 LOCK 语句。您的示例更新 without the LOCK, 将在正在更新的 table 上放置写锁(因此保证没有其他查询可以同时更新它),并且将使用正在读取的 table 的快照。
如果您确实使用锁,您将在更新期间阻止任何试图从tableSELECT的查询。您可能认为这就是您想要的,以确保您的用户只看到最新的数据,但考虑到这一点,在更新之前启动的任何 SELECTs 仍然会看到旧数据。
我使用 LOCK 语句的 唯一 原因是如果您需要保持一组 table 之间的一致性(好吧,如果您陷入僵局,但你没有指出):
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 在 期间 开始的交易在交易完成之前不会真正执行。如果它发生在他们的工作日中间,您的用户可能不喜欢这样。
如何在 redshift 中插入时对 table 进行真正的锁定,我认为是这样,但我不确定并且 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;
LOCK
有一个 documented behavior:它获得了 table 上的独占锁,因此其他会话或事务不能做 任何事情 到 table.
如果您想验证此行为,请按以下步骤操作:
- 打开与数据库的连接并针对您的测试调用
begin
和lock
命令 table。 - 打开一个 second 连接到数据库,并尝试对那个 table. 做一个
- 等到 select returns 或您确信
LOCK
的行为符合记录。 - 在第一个会话中执行
rollback
,这样您就不会永久锁定 table。
select
更新
根据您的评论,我认为您对事务的工作原理存在误解:
- 当您开始一个事务时,Redshift 会分配一个事务 ID,并标记该事务更改的每一行。
- SELECTs 在事务中更新时读取 table 将看到“已提交数据的快照”(引用自上文 link ),而不是在事务中更新的行。
- INSERT/UPDATE/DELETE 尝试更新正在由事务更新的 table 将阻塞直到事务完成(参见 doc,并注意此行为与你会看到,比方说,MySQL).
- 当您 commit/rollback 一个交易时,任何 new SELECTs 将使用更新的数据。在事务期间启动的任何 SELECTs 将继续使用旧数据。
鉴于这些规则,几乎没有理由使用显式 LOCK 语句。您的示例更新 without the LOCK, 将在正在更新的 table 上放置写锁(因此保证没有其他查询可以同时更新它),并且将使用正在读取的 table 的快照。
如果您确实使用锁,您将在更新期间阻止任何试图从tableSELECT的查询。您可能认为这就是您想要的,以确保您的用户只看到最新的数据,但考虑到这一点,在更新之前启动的任何 SELECTs 仍然会看到旧数据。
我使用 LOCK 语句的 唯一 原因是如果您需要保持一组 table 之间的一致性(好吧,如果您陷入僵局,但你没有指出):
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 在 期间 开始的交易在交易完成之前不会真正执行。如果它发生在他们的工作日中间,您的用户可能不喜欢这样。