
# 热点行更新
#### 操作场景
数据库中频繁被增删改查的记录被称为热点行。热点行常见于秒杀抢购、演唱会门票预订、热门路线火车票预订等场景。由于事务对数据更新时，需要持有行锁，同一时刻内只能有一个事务更新热点行，其他事务只能等待行锁释放后才能继续执行，导致热点行更新的性能存在瓶颈，并且传统的分库分表策略在提升性能方面效果有限。
云数据库 TaurusDB支持热点行更新优化，您可以通过手动指定或者自动识别的方式开启热点行更新。热点行更新开启后可以大幅度提升热点行的更新性能。
#### 原理介绍
TaurusDB热点行更新的架构如下图所示：分为Fold计算、Counter_hash，Group_hash三部分。
- Fold：是SQL标识，基于表、主键、唯一键或隔离级别等因素计算，能同时支持多种隔离级别。
- Counter_hash：用于实现热点行的自动判断，由Counter组成，Counter用于统计热点行SQL的执行次数。根据该类SQL的执行频率自动识别为热点。
- Group_hash：热点行的实际实现部分，由多个Hotspot group组成。每个Hotspot group对应一个热点行，每个Hotspot group由多个batch组成，交替为热点行提供批量提交服务。
图1热点行更新原理图   
![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000002556987691.png "点击放大")
#### 约束与限制
- TaurusDB实例的内核版本为2.0.54.240600及以上时支持使用该功能。内核版本的查询方法请参见[如何查看云数据库 TaurusDB实例的版本号](https://support.huaweicloud.com/taurusdb_faq/taurusdb_faq_0141.html)。
- 热点行更新优化需满足以下全部条件，不满足时将执行普通UPDATE：
  - 仅支持 InnoDB表。
  
  - 单条UPDATE语句的SET子句只能修改一个列，多列更新不适用。
  
  - 表上不能定义 BEFORE或 AFTER UPDATE触发器。
  
  - 不支持多表 UPDATE（如 UPDATE t1 JOIN t2 ...），即使带 HOTSPOT 标记也不生效。
  
  - WHERE条件中只能使用主键或唯一索引的等值匹配，并且只能更新单条记录，WHERE等值覆盖所选索引的全部列。
  
  - 不允许修改任何索引列（含主键、唯一索引、二级索引）。
  
  - 仅对增量值为整数常量的加减操作生效，与列类型无关。
    表1热点行更新示例 
    | 语句                        | 是否生效 | 原因       |
    |:---|:---|:---|
    | c = c + 1                 | 是    | -        |
    | c = c + 1.5 或 c = c + 0.1 | 否    | 增量非整数常量。 |
       
    
  
  - 只允许对热点行记录进行两个元素的加减操作，且书写顺序上的第一个操作数与等号左侧相等并满足唯一索引等约束，不允许赋值操作。
    表2热点行更新示例 
    | 语句            | 是否生效 | 原因             |
    |:---|:---|:---|
    | c = c + 2     | 是    | -              |
    | c = d + 1     | 否    | 第一个操作数与等号左侧不同。 |
    | c = 1 + c     | 否    | 操作数顺序错误。       |
    | c = c + 1 + 1 | 否    | 超过两个操作数。       |
       
    
  
  - 必须在隐式事务中使用，即 AUTOCOMMIT为ON，且不能在BEGIN/COMMIT显式事务中使用。
  
  - 需显式使用HOTSPOT标记，或开启自动检测（rds_hotspot_auto_detection_threshold 设为非0且rds_hotspot设置ON）。
  
  - 只对RC级别生效。
  
  - 无法在stored function、trigger中使用，否则将对客户端报如下错误：
    ```
    HOTSPOT hints can not be used in stored function or trigger.
    ```
    
   
- 行为变更：一个hotspot事务组内，除了执行失败或者在更新阶段killed的事务外，其他事务被按批次集中提交，集中记录redo log和undo log，只能集中提交或者回滚，无法单独回滚。每个批次提交的事务个数为几十到几百个不等。
  异常处理：
  - 提交阶段异常中断（如进程被 kill）：整批回滚，包括已成功但尚未提交的事务。
  
  - 单个事务约束失败或值超限：该事务被剔除，不影响同批其他事务提交。
    
 
#### 参数说明
表3参数说明 
| **参数名称**                                  | **参数说明**                                                                                         |
|:---|:---|
| rds_hotspot                               | 热点行更新优化开关。将其设置为ON将启用热点行更新优化。                                                                     |
| rds_hotspot_follower_wait_commit_interval | 热点行更新follower事务等待leader事务日志持久化时，进入阻塞前的睡眠时间。单位：微秒。对日志持久化速度慢的实例，建议调大。对于持久化快速的实例，建议设置为0，不休眠直接阻塞。    |
| rds_hotspot_leader_wait_follower_interval | 热点行更新leader事务等待follower更新记录的时间单位。单位：微秒。低并发适当调低可以避免性能下降。高并发适当调高可以提升性能。当QPS超过20w时，建议将该值设置为100或者更大。 |
| rds_hotspot_auto_detection_threshold      | 热点行更新的自动识别功能开关。设置为0表示不启用自动识别功能。设置为非0表示热点行更新的识别阈值。当某个符合热点行要求的行每秒更新次数超过阈值时将启动热点行更新功能。              |
| rds_hotspot_batch_size_lower_limit        | 每批热点事务大小的建议最小值。每个batch尽可能达到该大小。但是，这并不是严格保证的。当leader发现所有需要等待的follower都已经到达时，batch就进入提交状态。         |
| rds_hotspot_max_memory_size               | 热点行更新中group和counter占用的内存上限。当group或counter占用内存超过限制时，将分别清空其占用的内存（申请新内存时触发）。                        |
| rds_hotspot_enable_time_statistics        | 是否开启热点行更新的时间相关的状态统计功能。将其设置为ON以启用该功能。                                                             |
   
#### 状态说明
表4状态说明 
| **状态**                            | **说明**                                                                                                                                       |
|:---|:---|
| Hotspot_total_trx                 | 使用hotspot总事务数。                                                                                                                               |
| Hotspot_update_errors             | 更新阶段出错的热点行更新事务，这些出错的事务只会自己更新失败，不会影响其他热点行更新事务的提交。                                                                                             |
| Hotspot_trx_rollbacked            | 更新阶段完成，但是在提交时队长（leader）决定回滚的事务数量。 一条更新语句分两个阶段，更新阶段和提交阶段。当队长（leader）决定回滚时，所有组员（follower）跟着一起回滚。 |
| Hotspot_trx_committed             | 提交成功的热点行更新事务数量。                                                                                                                              |
| Hotspot_batch_size                | 热点行更新事务分批次提交。该值表示当前批次热点行更新事务的数量。                                                                                                             |
| Hotspot_batch_wait_time           | 热点行更新按批次持有锁和提交事务。此时间为当前热点行更新批次等待上一批次释放锁的时间，单位微秒。                                                                                             |
| Hotspot_leader_wait_follower_time | 在一个批次中leader需要等待follower完成记录更新，此时间为当前批次leader等待follower的时间，单位微秒。                                                                             |
| Hotspot_leader_total_time         | 当前批次leader的热点行更新事务总时间，单位微秒。                                                                                                                  |
| Hotspot_follower_total_time       | 当前批次某一个follower的热点行更新事务总时间，单位微秒。                                                                                                             |
| Hotspot_follower_wait_commit_time | 在一个批次中follower需要等待leader持久化日志，此时间为当前批次某一个follower等待leader持久化日志的时间，单位微秒。                                                                      |
| Hotspot_group_counts              | 每个热点行更新对应一个组，组内事务分批次提交。该值为使用热点行更新的组数。                                                                                                        |
| Hotspot_counter_counts            | counter用于自动判断热点行更新。当counter中的统计值满足要求时，将会创建group使用热点行更新。该值为counter的总数。                                                                        |
   
#### 新增关键字
新增标记语句的关键字如下：
表5新增关键字 
| 关键字           | 描述              |
|:---|:---|
| HOTSPOT       | 表示开启热点更新功能。     |
| NOT_MORE_THAN | 可选项。表示目标值不大于某值。 |
| NOT_LESS_THAN | 可选项。表示目标值不小于某值。 |
   
上述关键字放置在SQL语句末尾。HOTSPOT必须在最前面，NOT_MORE_THAN和NOT_LESS_THAN没有位置前后的要求。
例如：假设table_name是表名，id是主键列，c是int类型列，那么支持以下语法：
```
UPDATE table_name SET c=c+1 where id=10 HOTSPOT;
UPDATE table_name SET c=c+1 where id=10 HOTSPOT NOT_MORE_THAN 100; // c值不大于100
UPDATE table_name SET c=c-1 where id=10 HOTSPOT NOT_LESS_THAN 0;   // c值不小于0
UPDATE table_name SET c=c+1 where id=10 HOTSPOT NOT_MORE_THAN 100 NOT_LESS_THAN 0; // c值不大于100，不小于0
UPDATE table_name SET c=c+1 where id=10 HOTSPOT NOT_LESS_THAN 0 NOT_MORE_THAN 100; // c值不大于100，不小于0
```
当超过NOT_MORE_THAN或者NOT_LESS_THAN的限制时，会向客户端报如下错误：
```
HOTSPOT field value exceeds limit
```
#### 使用示例
1. 创建表，准备数据。
   ```
   CREATE TABLE test.hotspot1 (
     `id` int NOT NULL primary key,
     `c` int NOT NULL DEFAULT '0'
   ) ENGINE=InnoDB;
   INSERT INTO test.hotspot1 VALUES (1, 1);
   ```
   
2. 打开热点行更新开关。
   ```
   SET GLOBAL rds_hotspot = ON;
   ```
   
3. 修改隔离级别，AUTOCOMMIT。
   ```
   SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
   SET SESSION AUTOCOMMIT = ON;
   ```
   
4. 发起带HOTSPOT关键字的更新。
   ```
   UPDATE test.hotspot1 SET c=c+1 WHERE id=1 HOTSPOT;
   ```
   
5. 检查热点行更新状态。
   ```
   SHOW STATUS like "%hotspot%";
   ```
   
 
#### 性能测试
- 测试环境 实例规格：8U32GB、32U128GB
  ECS规格：32U64GB
  测试环境：华北-北京四
  测试工具：sysbench-1.0.18
  数据模型：
  - 1张表，1条数据。
  
  - 8张表，每张表1条数据。
   
- 参数配置 rds_hotspot=ON
  transaction_isolation=READ-COMMITTED
  max_prepared_stmt_count=1048576
  rds_global_sql_log_bin=OFF
  
- 测试方法 测试所需数据表定义：
  ```
  CREATE TABLE sbtest (id int NOT NULL AUTO_INCREMENT,k int NOT NULL DEFAULT '0',PRIMARY KEY (id));
  ```
  测试语句：
  ```
  UPDATE sbtest%u SET k=k+1 WHERE id=1 hotspot;
  ```
  
- 测试场景和测试结果 测试场景1：8U32GB实例单个热点行更新
  测试结果：所有并发均有不同程度提升，64并发及以下并发提升不明显，128并发及以上并发提升明显，最高提升9.26倍。
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000001981020924.png "点击放大")
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000002017700341.png "点击放大")
  测试场景2：32U128GB实例单个热点行更新
  测试结果：128并发及以上并发提升明显，最高提升639倍。
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000002017820849.png "点击放大")
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000001981180644.png "点击放大")
  测试场景3：32U128GB实例8个热点行更新
  测试结果：256及以下并发无提升，512及以上并发提升效果明显，最高提升78倍。
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000001981020932.png "点击放大")
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb/figure/zh-cn_image_0000002017700345.png "点击放大")
  
 
