get database write lock timeout问题处理手册
背景
使用 starrocks 过程中我们偶尔会遇到 ‘get database write lock timeout’ 类似的报错,通常是因为库级别有很多的写入任务引起的。下面我们简单说下如果使用过程中遇到此类问题该如何处理。
问题分析
这是由于历史的设计原因,我们在访问 starrocks 的元数据时,通过持有一把 DB 级的大锁来保证元数据读写访问的一致性,这个方式的优缺点都很明显。优点是实现简单,正确性也有保障,缺点是锁的粒度太粗,会导致无关的操作产生锁竞争(lock contention),降低执行效率,后续版本我们会优化此类锁问题,尽量避免粗粒度的锁占用太多资源
解决方式
-
将库级别的导入频次降低。减少单位时间的写入次数。
针对不同的导入方式分别调整导入间隔,降低写入频次,具体load参数参考
导入问题 too many tablet version解决方法
避免使用jdbc insert数据或者insert into values方式写入数据,使用微批导入的数据的方式,单表建议写入间隔5s+(1 并发 )
-
库中表数量很多的时拆分为多个库
由于锁是DB级别的,因此当DB级别锁竞争比较大时,常见于库有很多表(比如上千表)且均有不低的写入频次时,可以考虑将表分库,也能缓解此类问题
- 可使用工具批量导出建表语句
使用说明
python olapdump.py [--host HOST] [--port PORT] [--user USER] [--password PASSWORD] [--database DATABASE]
example: python olapdump.py -h 127.0.0.1 -P 9030 -u root -d dtest > dump.sql
- 新建库表,并迁移数据
## 新建database
create database newdata
## 新建table 具体迁移表建表语句采用上述工具dump的sql
CREATE TABLE `test` (
`k1` int(11) NULL COMMENT "",
`k2` varchar(20) NULL COMMENT ""
) ENGINE=OLAP
DUPLICATE KEY(`k1`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`k1`) BUCKETS 20
PROPERTIES (
"replication_num" = "3",
"in_memory" = "false",
"storage_format" = "DEFAULT",
"enable_persistent_index" = "false"
);
## 将原表数据写入新表
insert into newdata.test select * from data.test
- 修改导入任务中的表名
离线例行任务可以将导入任务中的表名 data.test 替换为 newdata.test 并重启任务。
实时任务需要在迁移数据前暂停任务,迁移写入完成后,从上次的消费点往新表去写,下面以routine load为例:
-
PAUSE ROUTINE LOAD FOR test1; 暂停routine load作业
-
SHOW ROUTINE LOAD FOR test1;查看并记录当前消费的offset,如下有4个partitions{0,1,2,3}
“0”:4492297965表示partition 0消费进度为4492297965
DataSourceProperties: {"0":4492297965,"1":2633828643,"2":4492269032,"3":2633828635}
- 新建任务并继续之前的消费进度
新建任务在from kafka中指定消费的offset,需要注意的是,任务记录offset值是消费到的数据,新建一个任务继续消费的话指定的offset需要手动加1,否则会出现部分数据重复消费的情况。如pause时消费进度为"0":4492297965,则重新消费需要从4492297966开始消费,示例如下
FROM KAFKA
("kafka_broker_list" = "broker1:9092,broker2:9092,broker3:9092",
"kafka_topic" = "my_topic",
"kafka_partitions" = "0,1,2,3",
"kafka_offsets" = "4492297966,2633828644,4492269033,2633828636");
- 确认新建任务消费正常后,将之前旧表的消费任务stop即可