> 文章列表 > Hive 事务和锁的功能测试

Hive 事务和锁的功能测试

Hive 事务和锁的功能测试

Hive 事务和锁的功能测试

Hive 的事务和锁,可以在会话级别设置。

1. 无事务、无锁的方式

各云厂商,如阿里云,百度云默认都采用此方案。如果不使用此方案,用户需要手动改配置。
此方案读写表都没有限制。任务的执行时间可以估计,不会出现长时间等待锁的情况。

1.1 普通表

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) stored as parquet;
  • 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;
select current_timestamp();
insert overwrite table t_web_salesselect ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务能同时运行。

1.2 分区

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet;
  • 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务能同时运行。

1.3 动态分区

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet;
  • 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;
select current_timestamp();
insert overwrite table t_web_sales select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk,mod(hash(ws_sold_time_sk),10) from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务能同时运行。

1.4. 事务表

创建表失败,只能用 DbTxnManager 的情况下使用事务表。

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as orc tblproperties('transactional'='true');

1.5 insert only 事务表

创建表失败,只能用 DbTxnManager 的情况下使用事务表。

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager;
set hive.support.concurrency=false;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet tblproperties('transactional'='true','transactional_properties'='insert_only');

2. DbTxnManager锁表的方案

DbTxnManager 是现有的方式配置,使用DbLockManager。

2.1 普通表

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) stored as parquet;
  • 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_salesselect ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务不能同时运行。

2.2 分区表

2.2.1 插入相同的分区

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet;
  • 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务不能同时运行。

  • 两个会话同时执行以下 insert into SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert into table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务可以同时运行。

2.2.2 插入不同的分区

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet;
  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230102')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务能同时运行。

2.2.3 一个SQL读分区,一个SQL 插入其他分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();select count(distinct ws_sold_time_sk) from t_web_sales where dt='20230102';
select current_timestamp();

可以看到两个任务不能同时运行。

2.3 动态分区

创建表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet;
  • 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk,mod(hash(ws_sold_time_sk),10) from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务可以同时运行。

2.4. 事务表

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as orc tblproperties('transactional'='true');

事务表更严格,抛出的异常种类更多。需要在 metastore 开启 compactor,容易 compactor 和普通任务的相互竞争,导致报错。社区的 bug 很多,有 bug 导致内存溢出。

2.4.1 插入相同的分区

  • insert overwrite 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务不能同时运行,并且抛出以下异常:

FAILED: Hive Internal Error: org.apache.hadoop.hive.ql.lockmgr.LockException(Transaction manager has aborted the transaction txnid:86949.  Reason: Aborting [txnid:86949,86950] due to a write conflict on test/t_web_sales/dt=20230101 committed by [txnid:86947,86949] u/u)
  • insert into 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert into table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务可以同时运行

2.4.2 插入不同的分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230102')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务能同时运行。

2.4.3 一个SQL读分区,一个SQL 插入其他分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();select count(distinct ws_sold_time_sk) from t_web_sales where dt='20230102';
select current_timestamp();

可以看到两个任务不能同时运行。

2.4.4 一个SQL读分区,一个SQL insert into 其他分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert into table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();select count(distinct ws_sold_time_sk) from t_web_sales where dt='20230102';
select current_timestamp();

可以看到两个任务可以同时运行。

2.5 insert only 事务表

只能用 DbTxnManager 的情况下使用事务表。数据格式可以是其他格式。对相同分区可以多个会话使用 insert 但是不能使用 insert overwrite.

create database if not exists test;
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;drop table if exists t_web_sales;
create table t_web_sales(ws_sold_time_sk bigint,ws_ship_date_sk bigint,ws_item_sk bigint) partitioned by (dt string) stored as parquet tblproperties('transactional'='true','transactional_properties'='insert_only');

2.5.1 插入相同的分区

  • insert overwrite 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales limit 10000;
select current_timestamp();

可以看到两个任务不能同时运行,并且抛出以下异常:

Hive Internal Error: org.apache.hadoop.hive.ql.lockmgr.LockException(Transaction manager has aborted the transaction txnid:86999.  Reason: Aborting [txnid:86999,87000] due to a write conflict on test/t_web_sales/dt=20230101 committed by [txnid:86997,86999] u/u)
  • insert into 两个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert into table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务可以同时运行

2.5.2 插入不同的分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230102')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();

可以看到两个任务能同时运行。

2.5.3 一个SQL读分区,一个SQL 插入其他分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert overwrite table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();select count(distinct ws_sold_time_sk) from t_web_sales where dt='20230102';
select current_timestamp();

可以看到两个任务不能同时运行。

2.5.4 一个SQL读分区,一个SQL insert into 其他分区

  • 第1个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();
insert into table t_web_sales partition(dt='20230101')select ws_sold_time_sk,ws_ship_date_sk,ws_item_sk from tpcds_bos_orc_30.web_sales;
select current_timestamp();
  • 第2个会话同时执行以下 SQL
use test;
set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.support.concurrency=true;
select current_timestamp();select count(distinct ws_sold_time_sk) from t_web_sales where dt='20230102';
select current_timestamp();

可以看到两个任务可以同时运行。