2

场景:WAMP 服务器、InnoDB 表、自增唯一 ID 字段 [ INT(10)]、100+ 并发 SQL 请求。如果需要,也应该使用 VB.Net。

我的数据库有一个自动增量字段,用于为每个存储的新信息(服务订单)生成唯一的票证/协议号。

问题是这个数字必须每年重新设置。即它从000001/12 01/01/2012 00:00:00 开始直到最大值999999/12,然后在 01/01/2013 00:00:00 它必须重新开始000001/13

显然,它应该使用某种算法轻松完成,但是,我正在尝试找到一种更有效的方法来做到这一点。考虑:

  1. 它必须(?)使用自动增量,因为数据库有一些并发性(+100)。

  2. 每张票必须是唯一的。所以0000012012 年不等于0000012013 年。

  3. 它必须是自动的。(无需人工干预即可进行重置,或其他)

  4. 它应该是相当有效的。(监视程序应该每天检查数据库(?),但它似乎不是最好的解决方案,因为它会“失败”364 次,只有一次成功)。

我能想到的“最佳”方法是使用年份存储票号,例如:

12000001- 12999999(无论如何,它永远不应该达到 999.999)

然后监视程序应将自动增量字段设置13000000为 2013 年 1 月 1 日。

有什么建议么?

PS:感谢阅读... ;)

4

3 回答 3

1

因此,为了进一步参考,我采用了以下解决方案:

我确实在数据库上创建了n 个表(每年一个),只有一个自动增量字段负责生成每年的唯一 ID。

因此,考虑到事件日期,将新插入到相应的表中。之后,该算法将 last_inseted_id() 使用格式 000001/12 将该值存储到主表中。(票/年)

那是因为每年都必须有自己的计数器,因为即使当前日期已经是 2013 年,也会插入 2012 年的事件。

这样事件应该是可追溯的,不需要重置,并且很容易实现。

插入示例代码:

$eventdate="2012-11-30";
$eventyear="2012";
$sql = "INSERT INTO tbl$eventyear VALUES (NULL)";
mysql_query ($sql);
$sql = "LAST_INSERT_ID()";
$row = mysql_fetch_assoc(mysql_query($sql));
$eventID = $row(0)
$sql = "INSERT INTO tblMain VALUES ('$eventID/$eventYear', ... ";
mysql_query($sql)
于 2012-06-26T19:35:33.260 回答
0

MongoDB 使用与此非常相似的东西来编码日期、进程 id 和生成 id 的主机以及一些随机熵来创建 UUID。不是满足您对单调增加的要求的东西,而是一些有趣的东西来寻找一些关于方法的想法。

如果我正在实现它,我将创建一个简单的 ID 代理服务器,它将按日期执行逻辑处理,并为您描述的 id 创建一个唯一的 slug。只要你知道它是如何构造的,你就有原生的 MySql 等价物来让你的排序/分组工作,并且表示可以优雅地序列化这将工作。带有 UTC 日期字符串的东西,然后是作为字符串附加的单调序列。

Twitter 在实现自定义 ID 服务器Snowflake时,对自定义索引设计有一些有趣的见解。

生成不仅是简单整数而且还包含一些业务逻辑的 UUID 的代理端点的想法变得越来越普遍。

于 2012-06-19T15:53:32.013 回答
0

You can set up a combined PRIMARY KEY for both of the two columns ID and YEAR; this way you would only have one ID per year.

MySQL:

CREATE TABLE IF NOT EXISTS `ticket` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `year` YEAR NOT NULL DEFAULT '2012',
    `data` TEXT NOT NULL DEFAULT '',
    PRIMARY KEY (`id`, `year`)
)
ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci

UPDATE: (to the comment from @Paulo Bueno) How to reset the auto-increment-value could be found in the MySQL documentation: mysql> ALTER TABLE ticket AUTO_INCREMENT = 1;. If you also increase the default value of the year-column when resetting the auto-increment-value, you 'll have a continuous two-column primary key. But I think you still need some sort of trigger-program to execute the reset. Maybe a yearly cron-job, which is launching a batch-script to do so on each first of January.

UPDATE 2: OK, I've tested that right now and one can not set the auto-increment-value to a number lower than any existing ID in that specific column. My mistake – I thought it would work on combined primary keys…</del>

INSERT INTO `ticket` (`id`, `year`, `data`) VALUES
    (NULL , '2012', 'dtg htg het'),
    -- some more rows in 2012
);

-- this works of course
ALTER TABLE `ticket` CHANGE `year` `year` YEAR( 4 ) NOT NULL DEFAULT '2013';

-- this does not reset the auto-increment
ALTER TABLE `ticket` AUTO_INCREMENT = 1;

INSERT INTO `ticket` (`id`, `year`, `data`) VALUES
    (NULL , '2013', 'sadfadf asdf a'),
    -- some more rows in 2013
);
-- this will result in continously counted ID's

UPDATE 3: The MySQL-documentation page has a working example, which uses grouped primary keys on MyISAM table. They are using a table similar to the one above, but with reversed column-order, because one must not have auto-increment as first column. It seems this works only using MyISAM instead of InnoDB. If MyISAM still fits your needs, you don't need to reset the ID, but merely increase the year and still have a result as the one you've questioned for.

See: http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html (second example, after "For MyISAM and BDB tables you can specify AUTO_INCREMENT on a secondary column in a multiple-column index.")

于 2012-06-19T16:07:42.523 回答