Search code examples
mysqlauto-incrementmultiple-columns

How do I resolve or avoid need for MySQL with multiple AUTO INCREMENT columns?


I have put a lot of effort into my database design, but I think I am now realizing I made a major mistake.

Background: (Skip to 'Problem' if you don't need background.)

The DB supports a custom CMS layer for a website template. Users of the template are limited to turning pages on and off, but not creating their own 'new' pages. Further, many elements are non editable.

Therefore, if a page has a piece of text I want them to be able to edit, I would have 'manually' assigned a static ID to it:

<h2><%= CMS.getDataItemByID(123456) %></h2>

Note: The scripting language is not relevant to this question, but the design forces each table to have unique column names. Hence the convention of 'TableNameSingular_id' for the primary key etc.

The scripting language would do a lookup on these tables to find the string.

mysql> SELECT * FROM CMSData WHERE CMSData_data_id = 123456;
+------------+-----------------+-----------------------------+
| CMSData_id | CMSData_data_id | CMSData_CMSDataType_type_id |
+------------+-----------------+-----------------------------+
|          1 |          123456 |                           1 |
+------------+-----------------+-----------------------------+

mysql> SELECT * FROM CMSDataTypes WHERE CMSDataType_type_id = 1;
+----------------+---------------------+-----------------------+------------------------+
| CMSDataType_id | CMSDataType_type_id | CMSDataType_type_name | CMSDataType_table_name |
+----------------+---------------------+-----------------------+------------------------+
|              1 |                   1 | String                | CMSStrings             |
+----------------+---------------------+-----------------------+------------------------+

mysql> SELECT * FROM CMSStrings WHERE CMSString_CMSData_data_id=123456;
+--------------+---------------------------+----------------------------------+
| CMSString_id | CMSString_CMSData_data_id | CMSString_string                 |
+--------------+--------------------------------------------------------------+
|            1 |                    123456 | The answer to the universe is 42.|
+--------------+---------------------------+----------------------------------+

The rendered text would then be:

<h2>The answer to the universe is 42.</h2>

This works great for 'static' elements, such as the example above. I used the exact same method for other data types such as file specifications, EMail Addresses, Dates, etc.

However, it fails for when I want to allow the User to dynamically generate content.

For example, there is an 'Events' page and they will be dynamically created by the User by clicking 'Add Event' or 'Delete Event'.

An Event table will use keys to reference other tables with the following data items:

Data Item:  Table:
--------------------------------------------------
Date        CMSDates
Title       CMSStrings (As show above)
Description CMSTexts   (MySQL TEXT data type.)
--------------------------------------------------

Problem:

That means, each time an Event is created, I need to create the following rows in the CMSData table;

+------------+-----------------+-----------------------------+
| CMSData_id | CMSData_data_id | CMSData_CMSDataType_type_id |
+------------+-----------------+-----------------------------+
|          x |               y |                           6 | (Event)
|        x+1 |             y+1 |                           5 | (Date)
|        x+2 |             y+2 |                           1 | (Title)
|        x+3 |             y+3 |                           3 | (Description)
+------------+-----------------+-----------------------------+

But, there is the problem. In MySQL, you can have only 1 AUTO INCREMENT field.

If I query for the highest value of CMSData_data_id and just add 1 to it, there is a chance there is a race condition, and someone else grabs it first.

How is this issue typically resolved - or avoided in the first place?

Thanks,

Eric


Solution

  • The id should be meaningless, except to be unique. Your design should work no matter if the block of 4 ids is contiguous or not.

    Redesign your implementation to add the parts separately, not as a block of 4. Doing so should simplify things overall, and improve your scalability.