0%

Hive锁介绍-翻译自官方文档

在数据库中,并发性支持是必须的,而且它们的用例也很容易理解。至少,我们希望尽可能支持并发的读和写。添加一个机制来发现已获得的当前锁是很有用的。没有立即添加API来显式获取任何锁的需求,因此所有锁都是隐式获得的。以下锁定模式将在hive中定义(注意,不需要意图锁)。

1
2
共享(S)
独占(X)

顾名思义,可以同时获得多个共享锁,而X锁可以阻止所有其他锁。
兼容性矩阵如下:

对于某些操作,锁在本质上是分层的——例如,对于某些分区操作,表也被锁定(以确保在创建新分区时不能删除表)。

锁定模式下获取的合理性如下:

对于非分区表,锁模式非常直观。读取表时,获取一个S锁,而所有其他操作(插入表、alter table等其他操作)获得一个X锁。

对于分区表,其思想如下:

在执行读操作时,获取表和相关分区的 ‘S’ 锁。对于所有其他操作,在分区上执行“X”锁。但是,如果更改只适用于较新的分区,则在表上获得“S”锁,而如果更改适用于所有分区,则在表上获得“X”锁。因此,旧分区可以被读取和写入,而新的分区则被转换为RCFile。每当一个分区被锁定在任何模式时,它的所有父级都被锁在“S”模式中。

基于此,为操作获得的锁如下:

为了避免死锁,这里提出了一个非常简单的方案。所有要锁定的对象都是按字母顺序排序的,然后获取所需的模式锁。请注意,在某些情况下,可能不知道对象列表——例如,在动态分区的情况下,正在修改的分区列表在编译时是未知的——因此,列表的生成是保守的。由于分区的数量可能不知道,所以应该将一个专用锁(但目前不是由于hive -3509 bug)放在表上,或者是已知的前缀。

将添加两个新的可配置参数来决定锁的重试次数和每次重试之间的等待时间。如果重试的次数真的很高,它会导致一个活锁。看看ZooKeeper,看看如何使用ZooKeeper api实现读写锁。请注意,锁请求将被拒绝,而不是等待。现有的锁将被释放,所有的锁将在重试间隔后重试。

上面列出的不会按照指定的方式工作,因为锁的等级性。

表T的“S”锁指定如下:

  • 调用create()创建具有路径名的节点“/ warehouse/T/ read—”。这是协议后面使用的锁节点。确保设置顺序和临时标志。
  • 在锁定节点上调用getChildren(),而无需设置观察标志。
  • 如果有一个以“write -”开头的路径名的孩子,以及一个较低的序列数,那么这个锁就不能被获取。删除第一步中创建的节点并返回。
  • 否则,锁就被授予了。

表T的“X”锁定如下:

  • 调用create()创建具有路径名的节点“/ warehouse/T/ write—”。这是协议后面使用的锁节点。确保设置顺序和临时标志。
  • 在锁定节点上调用getChildren(),而无需设置观察标志。
  • 如果有一个以“读-”或“写-”开头的路径名的孩子,并以较低的序列号开始,就不能获得锁。删除第一步中创建的节点并返回。
  • 否则,锁就被授予了。

默认的Hive行为不会更改,并发也不受支持。
您可以通过将以下变量设置为false来关闭并发性: hive.support.concurrency.

您可以通过发出以下命令查看表中的锁:

1
2
3
4
SHOW LOCKS <TABLE_NAME>;
SHOW LOCKS <TABLE_NAME> EXTENDED;
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>);
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>) EXTENDED;

点我了解Hive锁定的配置属性