Java 用户是否可能同时获得相同的唯一生成ID?

Java 用户是否可能同时获得相同的唯一生成ID?,java,mysql,Java,Mysql,我制作了一个简单的java程序,可以使用日期作为前缀,增量数字作为后缀生成ID,如150801其中15是年份,08是月份,01是增量数字。由于每个用户都将数据保存在数据库中并获得一个唯一的生成ID,因此如果两个或多个用户同时保存数据,用户是否可能获得相同的生成ID?解决此问题的一个简单方法是使用自动增量列让数据库跟踪您的唯一标识符 沿着以下几行创建表格: CREATE TABLE your_table ( id BIGINT NOT NULL AUTO_INCREMENT,

我制作了一个简单的java程序,可以使用日期作为前缀,增量数字作为后缀生成ID,如
150801
其中
15
是年份,
08
是月份,
01
是增量数字。由于每个用户都将数据保存在数据库中并获得一个唯一的生成ID,因此如果两个或多个用户同时保存数据,用户是否可能获得相同的生成ID?

解决此问题的一个简单方法是使用自动增量列让数据库跟踪您的唯一标识符

沿着以下几行创建表格:

CREATE TABLE your_table (
     id BIGINT NOT NULL AUTO_INCREMENT,
     username CHAR(30) NOT NULL,
     ... other fields go here ...
     PRIMARY KEY (id)
)

若您的应用程序是多线程的,那个么答案是肯定的。在数据库中的ID上设置唯一约束,将不会插入具有相同ID的两个用户。但是,我建议使用另一个ID生成器,它将生成比您的ID更多的唯一ID。

首先,处理增量号的代码应该是线程安全的,否则多个用户可以具有相同的后缀

此外,考虑到此表单的标识符,这意味着每个月只有99个唯一增量编号,即每个月99个唯一标识符。这可能足以满足您的要求,但不太可能


您应该考虑使用类生成标识符。

需要某种锁定机制来防止同时用户获得相同的ID。

有几种方法可以实现这一点:

  • 如果您遇到约束冲突,请使ID列唯一并使用新编号重试
  • 使用数据库提供的数字生成器(Oracle序列、MS SQL Server的自动增量等)
  • 创建一个保存序列值的表,并在读取时锁定该值(使用SELECT xxx FOR UPDATE…)
  • 您可以使用Java的类创建值作为唯一标识符。如果以后需要,您将能够从生成的UUID获取时间戳

    UUID.randomUUID().toString()
    
    如果需要,您可以在稍后的一品脱时间从该字符串获取时间戳。

    我已经使用MySQL触发器生成了我需要的格式的唯一ID

    CREATE TABLE mytable(
       id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0',
       name VARCHAR(20)
    );
    
    以下是触发器脚本:

    DELIMITER $$
    CREATE TRIGGER table1_trigger
    BEFORE INSERT ON table1
    FOR EACH ROW
    BEGIN
    DECLARE postfix INT(4) ZEROFILL;
    DECLARE newID varchar(10);
    
    SET @prefix = DATE_FORMAT(CURDATE(),'%y%m');
    SET @wlike = CONCAT(@prefix, '%');
    SET @previous_id = (SELECT id FROM table1 WHERE id LIKE @wlike ORDER BY id DESC LIMIT 1);
    SET postfix = CAST(SUBSTRING(@previous_id, 5, 8) AS SIGNED);
    
    IF postfix != 9999 THEN
      SET postfix = postfix + 1;
    END IF;
    
    SET NEW.id = CONCAT(@prefix, postfix);
    END$$
    DELIMITER;
    

    我建议您看看这里:。对于您的id,它实际上取决于您如何增加索引,它是线程安全的吗?这在很大程度上取决于生成的id是如何生成的。您必须告诉我们它是如何生成的,以便我们能够回答。@MichaelLaffargue它不是线程安全的。我不使用UUID,因为长度太长,并且没有遵循我需要的格式。我不打算使用数据库自动增量函数,因为它没有遵循所需的ID格式。@AkashahAmin您指定的格式每月只处理100个新用户。你几乎肯定要改变它。这是一个很好的解决方案。是的,你说得对。我已经将其更改为5位数作为后缀,因此每月最多可以限制为99999个唯一id。我还发现,您可以使用数据库触发器生成具有所需格式的唯一id,可以在此基础上读取。很快我会发布答案。竖起大拇指!不,您肯定不会从该字符串获取时间戳。UUID的随机版本()不包含任何时间戳。只有一些具有嵌入的时间戳。即便如此,提取时间戳也将是对UUID的滥用。UUID从未打算用作日期-时间通信设备。我以前已经想过使用UUID,但UUID长度太长。所以我决定创建自己的ID生成器。