【问题标题】:MySQL transaction and triggersMySQL 事务和触发器
【发布时间】:2010-11-15 12:42:10
【问题描述】:

嘿伙计们,这是我无法弄清楚的一个。我们在数据库中有一个表,PHP 在其中插入记录。我创建了一个触发器来计算要插入的值。计算的值应该是唯一的。但是,有时我在表中的几行有完全相同的数字。数字是年月日的组合和当天的订单号。我认为插入的单个操作是原子的,并且在事务进行时表被锁定。我需要计算的值是唯一的...服务器是 5.0.88 版本。服务器是双核处理器的Linux CentOS 5。

这里是触发器:

CREATE TRIGGER bi_order_data BEFORE INSERT ON order_data
FOR EACH ROW BEGIN
  SET NEW.auth_code = get_auth_code();
END;

相应的例程如下所示:

CREATE FUNCTION `get_auth_code`() RETURNS bigint(20)
BEGIN
    DECLARE my_auth_code, acode BIGINT;
    SELECT MAX(d.auth_code) INTO my_auth_code
        FROM orders_data d
        JOIN orders o ON (o.order_id = d.order_id)
        WHERE DATE(NOW()) = DATE(o.date);

    IF my_auth_code IS NULL THEN
        SET acode = ((DATE_FORMAT(NOW(), "%y%m%d")) + 100000) * 10000 + 1;
    ELSE
        SET acode = my_auth_code + 1;
    END IF;
    RETURN acode;
END

【问题讨论】:

  • 你为什么不把时间包括到毫秒。或者取一个序列/自动递增的数字并添加它。
  • 我秒自增数,如果你不使用某种内部的计数器方法,你会有竞争条件的风险
  • 嗯...每一行都有一个唯一的自动增量编号。但是,计数的数字用于其他目的。订单被输入到表格中,然后精细状态机将其拾取并发送给遗留系统处理。然后,表中的顺序在通过精细状态机时会更改状态。旧系统支持所描述格式的 10 位数字。因此,添加自动增量将在总共 9999 个订单后停止系统...
  • ZaQ 是对的。只要您不依赖系统范围的自动增量/序列(对不起,我习惯了 Oracle 术语),您将始终在此过程中遇到竞争问题。我对 MySQL 不是很熟悉,但应该可以从某种系统范围的序列提供程序中获取下一个数字,而不是在代码中添加一个。
  • 单个语句是原子的,但它指的是实际查询。存储过程不是原子操作 - 它是一系列单独的原子操作。你需要一个事务和一些锁来保证你得到一个唯一的 MAX(d.auth_code)

标签: mysql sql stored-procedures triggers


【解决方案1】:

我以为单机操作 插入是原子的并且表被锁定 交易进行中

表被锁定(使用 MyISAM)或记录可能被锁定(使用 InnoDB),而不是两者。

由于您提到“事务”,我假设 InnoDB 正在使用中。 InnoDB 的优势之一是没有表锁,因此没有什么可以阻止多个触发器的主体同时执行并产生相同的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    相关资源
    最近更新 更多