Php 同一表中的两个递增列

Php 同一表中的两个递增列,php,mysql,mariadb,Php,Mysql,Mariadb,我有一个表,其中包含多个公司的发票,每个公司都需要有自己的递增发票编号系统 id | invoiceId | companyId -------------------------- 1 | 1 | 1 2 | 2 | 1 3 | 1 | 2 4 | 1 | 3 我希望用一个与此类似的独特复合键来实现这一点,但似乎用InnoDB是不可能的 我需要在插入后立即返回新ID,如果我尝试用PHP实现这一点,我会担心创建竞争条件 是

我有一个表,其中包含多个公司的发票,每个公司都需要有自己的递增发票编号系统

id | invoiceId | companyId
--------------------------
1  | 1         | 1
2  | 2         | 1
3  | 1         | 2
4  | 1         | 3
我希望用一个与此类似的独特复合键来实现这一点,但似乎用InnoDB是不可能的

我需要在插入后立即返回新ID,如果我尝试用PHP实现这一点,我会担心创建竞争条件

是我创建触发器的最佳选择,如果是,会是什么样子?我没有使用触发器的经验,我对插入后使用
触发器的研究让我担心:

限制

不能在视图上创建后触发器。您不能更新 新的价值观。不能更新旧值


感谢您的建议

除了获取下一个值之外,您还需要添加一个唯一的索引。下一个值最好通过使用触发器查询表或通过事务中的某个过程来获得。在这种情况下,视图上的触发器备注不相关


唯一索引位于companyId上,需要invoiceId来防止在同一公司上运行的两个插入进程添加发票,然后这两个插入进程都可以使用相同的invoiceId结束。更好的是,当您切换到InnoDB时,您可以使用事务:然后,实际上同时启动的两个进程可以从事务隔离中受益,因此它们将被序列化,您将返回两个唯一的递增发票ID,而无需处理代码中的唯一索引异常。

据我所知,mysql的最后一个id是基于连接的,而不是全局的,并且在进程之间共享

使用这个简单的脚本,我验证了我的顾虑

(注意,这是codeigniter语法,但相对容易理解)

我在10秒内访问了两次以下功能(在不同的浏览器窗口中)

有趣的是,我没有得到“2”作为两个答案,而是得到了1和2。这在查看底层函数时更有意义

function insert_id()
{
    return @mysqli_insert_id($this->conn_id);
}
这解决了返回的ID,您的竞争条件是基础查询的产物,基本上是“selectmax(invoiceId)WHERE companyID=X”,并向其添加+1,然后插入它

这应该可以在插入之前使用表锁,但是这取决于您希望该表每秒更新多少次


注意在持久连接上,最后一个插入id可能会有不同的工作方式,我没有测试过。

您可以创建一个增量表,例如,
userid int,increment int
,但是使用myisam,您必须执行一个完整的表锁来安全地更新该值。至少在innodb中,您有行级锁。实际上,您希望在表上使用“插入前”触发器,这样警告看起来就不相关了。@GordonLinoff谢谢,这给了我一个新的视角。我会调查的
function insert_id()
{
    return @mysqli_insert_id($this->conn_id);
}