#39329·gitea

Costly chained queries involving `commit_status (sha, repo_id)`

Author: juan-ferrer-toribioCreated Sep 16, 2026Updated Sep 16, 2026
Labelstype/bug

Gitea Version

1.27.3

What happened?

In some unknown but frequent cases, gitea generates extremely costly/large queries against thecommit_status table containing hundreds (or thousands) of OR sha = ? conditions.

SELECT max( `index` ) as `index`, sha
FROM `commit_status`
WHERE (repo_id = ?) AND (sha=? OR ... /* hundreds/thousands */ OR sha=?)
GROUP BY context_hash, sha
ORDER BY max( `index` ) desc;

These queries end up consuming the MariaDB connection limit and/or resources, eventually causing it to fail with Too many connections.

MariaDB [(none)]> show processlist;
+------+-------+--------------------+-------+---------+------+--------------+------------------------------------------------------------------------------------------------------+----------+
| Id   | User  | Host               | db    | Command | Time | State        | Info                                                                                                 | Progress |
+------+-------+--------------------+-------+---------+------+--------------+------------------------------------------------------------------------------------------------------+----------+
|   59 | gitea | 10.243.4.106:46712 | gitea | Execute | 3709 | Sending data | SELECT max( `index` ) as `index`, sha FROM `commit_status` WHERE (repo_id = ?) AND (sha=? OR sha=? O |    0.000 |
...
| 5232 | gitea | 10.243.4.23:39440  | gitea | Execute |   51 | Sending data | SELECT max( `index` ) as `index`, sha FROM `commit_status` WHERE (repo_id = ?) AND (sha=? OR sha=? O |    0.000 |
| 5260 | root  | localhost          | NULL  | Query   |    0 | starting     | show processlist                                                                                     |    0.000 |
+------+-------+--------------------+-------+---------+------+--------------+------------------------------------------------------------------------------------------------------+----------+
151 rows in set (0.001 sec)

Adding an index on (repo_id, sha) improves a bit the execution of these queries, but doesn't solve the issue:

CREATE INDEX IDX_commit_status_repo_sha_FIX ON commit_status (repo_id, sha);

As a temporary workaround, maximum statement time could be limited for gitea DB user, but it could also limit other legitimate queries.

GRANT USAGE ON *.* TO 'gitea'@'%' WITH MAX_STATEMENT_TIME 30;

Structure of our commit_status table:

MariaDB [gitea]> SHOW CREATE TABLE commit_status\G
*************************** 1. row ***************************
       Table: commit_status
Create Table: CREATE TABLE `commit_status` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `index` bigint(20) DEFAULT NULL,
  `repo_id` bigint(20) DEFAULT NULL,
  `state` varchar(7) NOT NULL,
  `sha` varchar(64) NOT NULL,
  `target_url` text DEFAULT NULL,
  `description` text DEFAULT NULL,
  `context_hash` varchar(64) DEFAULT NULL,
  `context` text DEFAULT NULL,
  `creator_id` bigint(20) DEFAULT NULL,
  `created_unix` bigint(20) DEFAULT NULL,
  `updated_unix` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UQE_commit_status_repo_sha_index` (`index`,`repo_id`,`sha`),
  KEY `IDX_commit_status_index` (`index`),
  KEY `IDX_commit_status_repo_id` (`repo_id`),
  KEY `IDX_commit_status_sha` (`sha`),
  KEY `IDX_commit_status_context_hash` (`context_hash`),
  KEY `IDX_commit_status_created_unix` (`created_unix`),
  KEY `IDX_commit_status_updated_unix` (`updated_unix`),
  KEY `IDX_commit_status_repo_sha_FIX` (`repo_id`,`sha`)
) ENGINE=InnoDB AUTO_INCREMENT=339871 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_as_cs ROW_FORMAT=DYNAMIC
1 row in set (0.000 sec)

How are you running Gitea?

Kubernetes (official helm chart) with MariaDB 10.11.4