MySQL触发器为auto_increment索引生成哈希

时间:2013-06-07 13:16:51

标签: mysql triggers

我正在尝试创建一个生成并存储auto_increment索引的哈希的触发器,但我尝试过的所有解决方案都不起作用:

DELIMITER //
CREATE TRIGGER insertTable1 AFTER INSERT ON Table1
FOR EACH ROW 
   BEGIN
     SET NEW.hash = calc_hash_udf(NEW.id);
   END //
DELIMITER ;;

它说我无法在NEW之后修改INSERT,而INSERT之前我没有修改auto_increment值:

错误1442(HY000):无法更新存储的函数/触发器中的表'Table1',因为它已被调用此存储函数/触发器的语句使用。

1 个答案:

答案 0 :(得分:5)

在插入行之后,您无法再修改的值。因此,SET NEW.column仅适用于BEFORE触发器。

此外,您无法使用常规UPDATE because

  

存储的函数或触发器无法修改已经存在的表   被调用的语句用于(读或写)   功能或触发器。

最后,在BEFORE INSERT触发器中,尚未生成AUTO_INCREMENT值,NEW.id0

技巧:在BEFORE触发器中,手动检查表定义中的下一个AUTO_INCREMENT值:

警告:这仅适用于MyISAM,而不适用于InnoDB

假设如果innodb_autoinc_lock_mode = 0它可以与InnoDB一起使用,但我无法确定。

DELIMITER //    

    CREATE TRIGGER insertTable1 BEFORE INSERT ON Table1 FOR EACH ROW
    BEGIN
        DECLARE next_ai INT;
        SELECT auto_increment INTO next_ai
          FROM information_schema.tables
          WHERE table_schema=DATABASE() AND table_name = 'Table1';
        SET NEW.hash = calc_hash_udf(next_ai);
    END //

DELIMITER ;

[编辑1]

至于这种方法的并发证明属性,我可以说:

  • 使用MyISAM,只有表锁可用,安全性显而易见:任何INSERT / UPDATE / {{1获取对表的独占锁定并且不会发生并发访问。

  • 使用InnoDB,这不太明显。对于“traditional lock mode”,手册说:

  

InnoDB使用一种称为表级AUTO-INC锁的特殊锁   插入带有AUTO_INCREMENT列的表。这种锁通常是   持有到声明的末尾

我认为在这种情况下这是安全的。

我不熟悉这些概念,所以我无法确定。这看起来确实很可疑。

[编辑2]

我使用innodb_autoinc_lock_mode的不同设置运行以下测试:

创建表t(     ai INT AUTO_INCREMENT PRIMARY KEY,     trigval INT,     旗帜BOOL );

表格上的触发器使用上述方法DELETE

在一个事务中,长INSERT由:

生成
SET NEW.trigval = next_ai

在第二次交易中,我不断发表以下声明:

INSERT INTO t SELECT null, null, 0 FROM (SELECT * FROM a_very_big_table) AS tmp;

最后,我搜索了差异:

INSERT INTO t VALUES (null, null, 1);

SELECT * FROM t WHERE ai <> trigval; (“传统”)似乎是安全的。插入到表中的任何并发尝试都将被锁定,直到完成长innodb_autoinc_lock_mode = 0

但是,我没想到,使用模式INSERT(默认值)和1,这种方法明显错误2按步骤更新。这是我得到的结果:

+-------+---------+------+
| ai    | trigval | flag |
+-------+---------+------+
|     3 |       4 |    0 |
|     5 |       8 |    0 |
|     9 |      16 |    0 |
|    17 |      32 |    0 |
|    33 |      64 |    0 |
|    65 |     128 |    0 |
...