peewee,mysql 和自动递增 id
peewee, mysql and auto incrementing id
我在带有 unique=True
字段的 peewee ORM 中有模型。我像这样将数据保存到我的 MySQL 数据库中:
try:
model.save()
except IntegrityError: # do not save if it's already in db
pass
但是当 peewee 试图保存已经在数据库中的数据时,MySQL 递增 id 并且 ids 顺序被破坏。如何避免这种行为?
这是我正在尝试保存的模型:
class FeedItem(Model):
vendor = ForeignKeyField(Vendor, to_field='name')
url = CharField(unique=True)
title = CharField()
pub = DateTimeField()
rating = IntegerField(default=0)
img = CharField(default='null')
def construct(self, vendor, url, title):
self.vendor = vendor
self.url = url
self.title = title
self.pub = datetime.now()
self.save()
class Meta:
database = db
我正在保存它:
for article in feedparser.parse(vendor.feed)['items']:
try:
entry = FeedItem()
entry.construct(vendor.name, article.link, article.title)
except IntegrityError:
pass
MySQL increments id and ids order is broken. How to avoid this behavior?
你不知道。
数据库生成的标识符不在您的控制范围内。它是由数据库生成的。不能保证所有标识符都必须是连续的且没有间隙,只是它们是唯一的。有许多事情会导致该序列中不存在数字,例如:
- 一条记录被删除。
- 尝试插入一条记录,它生成了一个 ID,但在生成该 ID 后插入以某种方式失败。
- 记录作为未提交事务的一部分被插入。
- 作为数据库引擎内部优化的一部分,在内存中生成了一组 ID,但在使用这些 ID 之前引擎已关闭。
- 插入了带有显式 ID 的记录,导致自动递增功能重新调整为新值。
可能还有更多我没有考虑的。但关键是您根本无法控制该值,而是由数据库引擎控制。
如果您想控制该值,请不要使用 autoincrement
。但请注意,这会带来一大堆您需要解决的其他问题,而 autoincrement
会为您解决这些问题。或者您必须切换到 GUID 而不是整数,这本身可能会导致您需要考虑的其他注意事项。
我不确定这是否有效,但您可以尝试类似的方法:
try:
with database.atomic():
model.save()
except IntegrityError:
pass # Model already exists.
通过包装在 atomic()
中,代码将在事务中执行(如果您已经在事务中,则执行保存点)。这可能会导致 ID 序列保持完整。
不过,我同意 David 的回答,即这实际上是一个数据库细节,不应成为您的应用程序逻辑的一部分。如果您需要单调递增的 ID,您应该自己实现。
我在带有 unique=True
字段的 peewee ORM 中有模型。我像这样将数据保存到我的 MySQL 数据库中:
try:
model.save()
except IntegrityError: # do not save if it's already in db
pass
但是当 peewee 试图保存已经在数据库中的数据时,MySQL 递增 id 并且 ids 顺序被破坏。如何避免这种行为?
这是我正在尝试保存的模型:
class FeedItem(Model):
vendor = ForeignKeyField(Vendor, to_field='name')
url = CharField(unique=True)
title = CharField()
pub = DateTimeField()
rating = IntegerField(default=0)
img = CharField(default='null')
def construct(self, vendor, url, title):
self.vendor = vendor
self.url = url
self.title = title
self.pub = datetime.now()
self.save()
class Meta:
database = db
我正在保存它:
for article in feedparser.parse(vendor.feed)['items']:
try:
entry = FeedItem()
entry.construct(vendor.name, article.link, article.title)
except IntegrityError:
pass
MySQL increments id and ids order is broken. How to avoid this behavior?
你不知道。
数据库生成的标识符不在您的控制范围内。它是由数据库生成的。不能保证所有标识符都必须是连续的且没有间隙,只是它们是唯一的。有许多事情会导致该序列中不存在数字,例如:
- 一条记录被删除。
- 尝试插入一条记录,它生成了一个 ID,但在生成该 ID 后插入以某种方式失败。
- 记录作为未提交事务的一部分被插入。
- 作为数据库引擎内部优化的一部分,在内存中生成了一组 ID,但在使用这些 ID 之前引擎已关闭。
- 插入了带有显式 ID 的记录,导致自动递增功能重新调整为新值。
可能还有更多我没有考虑的。但关键是您根本无法控制该值,而是由数据库引擎控制。
如果您想控制该值,请不要使用 autoincrement
。但请注意,这会带来一大堆您需要解决的其他问题,而 autoincrement
会为您解决这些问题。或者您必须切换到 GUID 而不是整数,这本身可能会导致您需要考虑的其他注意事项。
我不确定这是否有效,但您可以尝试类似的方法:
try:
with database.atomic():
model.save()
except IntegrityError:
pass # Model already exists.
通过包装在 atomic()
中,代码将在事务中执行(如果您已经在事务中,则执行保存点)。这可能会导致 ID 序列保持完整。
不过,我同意 David 的回答,即这实际上是一个数据库细节,不应成为您的应用程序逻辑的一部分。如果您需要单调递增的 ID,您应该自己实现。