手动增量的复合键

use*_*545 9 mysql database

如何在多会话/事务环境中安全地将行插入包含带有(手动)增量键的主复合键的表中.

如何获取最新的递增值column_c,LAST_INSERT_ID()不返回所需的值.

我已经调查过SELECT FOR UPDATE ... INSERT,INSERT INTO SELECT但无法决定使用哪个.

在事务安全(锁定),隔离级别和性能方面实现这一目标的最佳方法是什么.

更新 - 另一个问题


假设两个事务/会话尝试同时插入相同的column_a,column_b对(示例1,1).我如何能;

  1. 按顺序执行插入查询.所述第一插入件(事务1)应导致的1,1,复合键1,和第二(交易2)1,1,2.我需要某种锁定机制

  2. 检索插入的column_c值.我可能需要利用变量?


表定义

CREATE TABLE `table` (
        `column_a` int(11) unsigned NOT NULL,
        `column_b` int(11) unsigned NOT NULL,
        `column_c` int(11) unsigned NOT NULL,
        PRIMARY KEY (column_a, column_b, column_c)
 ) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

示例数据

+----------+----------+----------+
| column_a | column_b | column_c |
+----------+----------+----------+
|        1 |        1 |        1 |
|        1 |        1 |        2 |
|        1 |        1 |        3 |
|        2 |        1 |        1 |
|        2 |        1 |        2 |
|        2 |        1 |        3 |
+----------+----------+----------+
Run Code Online (Sandbox Code Playgroud)

将插入带入选择查询

INSERT INTO `table` (`column_a`, `column_b`, `column_c`)
SELECT 2,1, IFNULL(MAX(`column_c`), 0) + 1 FROM `table` 
WHERE `column_a` = 2 and `column_b` = 1;
Run Code Online (Sandbox Code Playgroud)

Ric*_*mes 1

BEGIN;
SELECT @c := MAX(c) + 1
    FROM t
    WHERE a = ? AND b = ?
    FOR UPDATE;           -- important
if row found              -- in application code (or Stored Proc)
then
    INSERT INTO t (a,b,c)
        VALUES
        (?, ?, @c);
else
    INSERT INTO t (a,b,c)
        VALUES
        (?, ?, 1);
COMMIT;
Run Code Online (Sandbox Code Playgroud)

希望它将FOR UPDATE停止,直到它获得锁定和所需的c值。那么剩下的交易应该会顺利进行。

我认为设置并不transaction_isolation重要,但这值得研究。