In my MariaDB I have two tables project
and issue
, the issue
table contains all issues created for all projects
create table if not exists Project(
id integer PRIMARY KEY auto_increment,
`name` varchar(200) NOT NULL
);
create table if not exists Issue(
id integer PRIMARY KEY AUTO_INCREMENT,
project_id integer,
issue_number integer,
content text,
FOREIGN KEY (project_id)
REFERENCES Project(id)
);
The issue_number
is per project and starts always from 1, how can increment it by 1 and resolve concurrent insert problems?
I can’t use select max(issue_number) + 1 from Issue where project_id=X
to determine the new value because could be stale
4
Answers
You could calculate the field
issue_number
, there is no need to store it:or you could store it when you need the actual value of
issue_number
often….You could use a subquery for this. In it you get the maximum issue number for a project and then you insert the issue row with a number that’s one higher. Something like this:
There’s no change that the issue number will go stale because you perform the subquery and insert in one SQL statement.
To make this query performant I recommend to create an index on the combination of the
project_id
andissue_number
columns:Note that we have to use the
AS I
alias to prevent MySQL from saying: "ERROR: Table ‘Issue ‘ is specified twice, both as a target for ‘INSERT’ and as a separate source for data.".To ensure that the issue_number column increments correctly and avoids concurrent insert problems, you can use a combination of triggers and sequences in MariaDB. Here’s an approach to achieve this:
Create a Sequence:
First, create a sequence to generate unique numbers for the issue_number column. Sequences are designed to handle concurrent access and guarantee unique values.
CREATE SEQUENCE issue_number_sequence START WITH 1;
Use a Trigger:
Next, create a trigger that automatically sets the issue_number when inserting a new row into the Issue table. This trigger will use the sequence to generate the next value for issue_number based on the project_id.
DELIMITER //
CREATE TRIGGER before_issue_insert
BEFORE INSERT ON Issue
FOR EACH ROW
BEGIN
SET NEW.issue_number = NEXT VALUE FOR issue_number_sequence;
END;
//
DELIMITER ;
With this setup, whenever a new row is inserted into the Issue table, the trigger before_issue_insert will automatically set the issue_number to the next value from the issue_number_sequence based on the current project_id. This approach ensures that issue_number increments correctly and avoids concurrent insert problems.
Note: Make sure to adjust the sequence and trigger names, as well as any other specifics, based on your database schema and requirements.
One way is to create another table,
IssueSequence
, that serves as a SEQUENCE table capable of holding the last Issue key created on a project basis.