问题:当我在数据库中使用自动递增主键时,这种情况时有发生:
我想存一份10件的订单。所订购的物品属于订单。因此,我存储订单,向数据库询问最后插入的id (这在并发性方面很危险,对吗?),然后用外键(order_id)存储这10项。
所以我总是要做:
插入..。
last_inserted_id = db.lastInsertId();
插入..。插入..。插入..。
我相信这会阻止我在几乎所有需要外键的插入情况下使用事务。
所以..。这里有一些解决方案,我不知道它们是否真的很好:
A)不要使用auto_increment密钥!使用键表?键表将有两个字段:table_name, next_key。每次我需要一个键来插入一个新的数据集时,我首先通过访问一个特殊的静态next_key类方法来请求这个KeyGenerator。这做了一个选择和更新,如果可能的话,在一个事务(这会起作用吗?)。当然,我会要求每个受影响的桌子。接下来,我可以在一个事务中插入我的整个对象图,而无需与数据库玩乒乓游戏,在我事先知道键之前。
B)对密钥使用GUUID / UUID算法吗?--假设它们在世界范围内是非常独特的,而且它们很大。我是说. L_A_R_G_E因此,大量的记忆会进入这些巨大的钥匙。索引会很难,对吧?数据检索对数据库来说将是一个痛苦--至少我想--整数键处理起来要快得多。另一方面,这些也提供了一些安全性:访问者不能再通过增量id参数来迭代所有订单或所有用户或所有图片。
C)坚持使用auto_incremented键吗? Ok,如果是这样的话,那么上面示例中描述的事务呢?我该怎么解决呢?也许首先插入一个Ghost行,然后用一个UPDATE +n插入一个事务?
D)还有什么?
发布于 2009-12-30 10:43:18
在存储订单时,需要进行事务处理,以防止只将一半产品添加到数据库中的情况。
根据数据库和连接器的不同,最后一个insert-id函数返回的值可能与事务无关。例如,使用MySQL,mysql_insert_id从该特定客户端返回最后一个查询的标识符(不受其他客户端并发执行的操作的影响)。
发布于 2009-12-30 10:43:17
你用的是哪个数据库?
是的,通常插入一个记录,然后尝试再次选择它以查找自动生成的键是错误的,特别是当您使用表查询中的朴素select max(id)时。这是因为当两个线程正在创建记录时,max( id )可能实际上不会返回当前线程使用的最后一个id。
避免这种情况的一种方法是在数据库中创建一个序列。从您的代码中选择sequence.NextValue,然后使用该值来执行您的插入(或者您可以创建一个更复杂的SQL语句来完成这个选择和插入的一次执行)。序列是原子/线程安全的。
在MySQL中,您可以从执行结果中请求最后插入的id,我相信这将始终给出正确的答案。
发布于 2009-12-30 10:41:45
Server支持标识(Transact-SQL),它应该处理事务问题和并发问题。
我会说坚持auto_increment.
https://stackoverflow.com/questions/1979495
复制相似问题