热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MySQL和INTauto_increment字段-MySQLandINTauto_incrementfields

ImdevelopinginLAMP(Linux+Apache+MySQL+PHP)sinceIremembermyself.Butonequestionwasbuggin

I'm developing in LAMP (Linux+Apache+MySQL+PHP) since I remember myself. But one question was bugging me for years now. I hope you can help me to find an answer and point me into the right direction. Here is my challenge:

我正在开发LAMP (Linux+Apache+MySQL+PHP),因为我记得自己。但是有一个问题困扰了我很多年。我希望你能帮我找到一个答案,给我指明正确的方向。这是我的挑战:

Say, we are creating a community website, where we allow our users to register. The MySQL table where we store all users would look then like this:

比如,我们正在创建一个社区网站,我们允许用户注册。我们存储所有用户的MySQL表是这样的:

CREATE TABLE `users` (
  `uid` int(2) unsigned NOT NULL auto_increment COMMENT 'User ID',
  `name` varchar(20) NOT NULL,
  `password` varchar(32) NOT NULL COMMENT 'Password is saved as a 32-bytes hash, never in plain text',
  `email` varchar(64) NOT NULL,
  `created` int(11) unsigned NOT NULL default '0' COMMENT 'Timestamp of registration',
  `updated` int(11) unsigned NOT NULL default '0' COMMENT 'Timestamp of profile update, e.g. change of email',
  PRIMARY KEY  (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

So, from this snippet you can see that we have a unique and automatically incrementing for every new user 'uid' field. As on every good and loyal community website we need to provide users with possibility to completely delete their profile if they want to cancel their participation in our community.

因此,从这段代码中,您可以看到,对于每个新用户“uid”字段,我们都有一个惟一的并自动递增的值。在每一个好的和忠诚的社区网站上,我们需要为用户提供完全删除他们的个人资料的可能性,如果他们想取消他们对我们社区的参与。

Here comes my problem. Let's say we have 3 registered users: Alice (uid = 1), Bob (uid = 2) and Chris (uid = 3). Now Bob want to delete his profile and stop using our community. If we delete Bob's profile from the 'users' table then his missing 'uid' will create a gap which will be never filled again. In my opinion it's a huge waste of uid's. I see 3 possible solutions here:

我的问题来了。假设我们有3个注册用户:Alice (uid = 1)、Bob (uid = 2)和Chris (uid = 3),现在Bob想删除他的个人资料,停止使用我们的社区。如果我们从“用户”表中删除Bob的个人资料,那么他丢失的“uid”将产生一个永远不会被再次填充的空白。在我看来,这是对uid的巨大浪费。我看到了3个可能的解决方案:

1) Increase the capacity of the 'uid' field in our table from SMALLINT (int(2)) to, for example, BIGINT (int(8)) and ignore the fact that some of the uid's will be wasted.

1)将我们表中“uid”字段的容量从SMALLINT (int(2))增加到,例如,BIGINT (int(8)),忽略一些uid的将被浪费的事实。

2) introduce the new field 'is_deleted', which will be used to mark deleted profiles (but keep them in the table, instead of deleting them) to re-utilize their uid's for newly registered users. The table will look then like this:

2)引入新的字段“is_deleted”,该字段将用于标记已删除的概要文件(但是要将它们保存在表中,而不是删除它们),以便重新利用它们的uid来针对新注册的用户。这个表格看起来是这样的:

CREATE TABLE `users` (
  `uid` int(2) unsigned NOT NULL auto_increment COMMENT 'User ID',
  `name` varchar(20) NOT NULL,
  `password` varchar(32) NOT NULL COMMENT 'Password is saved as a 32-bytes hash, never in plain text',
  `email` varchar(64) NOT NULL,
  `is_deleted` int(1) unsigned NOT NULL default '0' COMMENT 'If equal to "1" then the profile has been deleted and will be re-used for new registrations',
  `created` int(11) unsigned NOT NULL default '0' COMMENT 'Timestamp of registration',
  `updated` int(11) unsigned NOT NULL default '0' COMMENT 'Timestamp of profile update, e.g. change of email',
  PRIMARY KEY  (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

3) Write a script to shift all following user records once a previous record has been deleted. E.g. in our case when Bob (uid = 2) decides to remove his profile, we would replace his record with the record of Chris (uid = 3), so that uid of Chris becomes qual to 2 and mark (is_deleted = '1') the old record of Chris as vacant for the new users. In this case we keep the chronological order of uid's according to the registration time, so that the older users have lower uid's.

3)编写一个脚本,以便在删除之前的记录之后转移所有跟随的用户记录。如在我们的示例中,当鲍勃(uid = 2)决定取消他的形象,我们将取代他的记录与记录的克里斯(uid = 3),所以克里斯就等于2的uid和马克(is_deleted = ' 1 ')老克里斯作为新用户空的记录。在这种情况下,我们根据注册时间来保持uid的时间顺序,以便老用户的uid更少。

Please, advice me now which way is the right way to handle the gaps in the auto_increment fields. This is just one example with users, but such cases occur very often in my programming experience.

现在请建议我用哪种方式来处理auto_increment字段中的间隔。这只是用户的一个例子,但是这种情况经常发生在我的编程经验中。

Thanks in advance!

提前谢谢!

5 个解决方案

#1


2  

definitely not the moving user ids idea - that will kill you or your mysql server at some point. lets say you have 1,000,000 users and user 2 gets deleted - you had to shift 999,999 records one down... as simple as the query would be it would still lock your db for a while. also i think that messes with your auto_increment value which is set on each insert for each table. insert -> AI+1 -> insert -> AI+1 -> delete -> AI stays the same... if you would shift all the ID's the next auto_increment value would still be 1,000,001 which would now leave 1,000,000 empty.

绝对不是移动用户id的想法——这会在某个时候杀死你或你的mysql服务器。假设您有1,000,000个用户,而user 2被删除——您必须将999,999条记录向下移动1条……查询的简单之处在于,它仍然会在一段时间内锁定您的db。另外,我认为这会与auto_increment值混淆,该值设置在每个表的每个insert上。插入-> AI+1 ->插入-> AI+1 ->删除-> AI保持不变…如果您将所有的ID转换为下一个auto_increment值,则仍然是1000001,现在将会留下1,000,000个空值。

i say unsigned BIGINT and ignore it - cause if you come even close to the limit of bigint you have many other problems to solve ;)

我说unsigned BIGINT然后忽略它——因为如果你接近BIGINT的极限你还有很多其他的问题要解决;)

#2


1  

I wrote a simple PHP function to "fill" auto_increment gaps caused by "delete" queries and set the correct "next auto_increment" value.

我编写了一个简单的PHP函数来“填充”由“delete”查询引起的“auto_increment”间隔,并设置正确的“next auto_increment”值。

function mysql_fix_aigap($table,$column){

$fix_aigap=1;

$query_results=mysql_query("select * from $table");

while($row=mysql_fetch_array($query_results)){

mysql_query("update $table set `$column`='$fix_aigap' where `$column` like {$row[$column]};");

$fix_aigap=$fix_aigap+1;

  }

mysql_query("alter table `$table` AUTO_INCREMENT =$fix_aigap");

}

and call it with:

并称之为:

mysql_fix_aigap("gapped_table_to_be_fixed","column"); //"users" and "uid" in your case.

(This script assumes that you are already connected to the server and you have selected the database!)

(此脚本假设您已经连接到服务器,并且已经选择了数据库!)

And this was the technical answer.

这就是技术上的答案。

In my honest opinion, I wouldn't recommend to assign a "variable" uid to the username, it's the non-schizophrenical way! (id=identity)

老实说,我不建议给用户名分配“变量”uid,这是一种非精神分裂的方式!(id =身份)

t.

t。

#3


0  

First of all; why do you think it's a "waste" of uids? I mean, it's just an integer (or BIGINT), this aren't the 70's anymore.

首先;为什么你认为这是对uid的“浪费”?我的意思是,它只是一个整数(或BIGINT),这已经不是70了。

Secondly, the performance loss you get if you implement one of your suggested options is far greater than the spatial loss you get from "wasting" uids. If some user deletes his profile, at worst, every user that registered after him gets a new id, so you have to update very, very much records...

其次,如果您实现了建议的选项之一,那么您的性能损失将远远大于“浪费”uid带来的空间损失。如果某个用户删除了他的个人资料,最坏的情况是,每个在他之后注册的用户都得到了一个新的id,所以你必须更新非常非常多的记录……

I must admit, when I just started programming I remember having to get used to gaps in auto-increment columns. But you will have to accept them, move on, and just let them exist...

我必须承认,当我刚开始编程时,我记得我不得不习惯自动增量列中的空白。但是你必须接受他们,继续前进,让他们存在……

#4


0  

I'd just ignore the gaps and ensure you have as large a range of ids as needed. The gaps do no real harm. Trying to fix them up by updating data might introduce broken relationships that are more trouble.

我将忽略这些空白,并确保在需要的时候有大量的id。这些差距不会造成真正的伤害。试图通过更新数据来修复它们可能会导致更麻烦的关系破裂。

By the way in MySQL INT(2) the 2 specifies the maximum display width, but doesn't affect the amount of storage. INT(8) uses the same storage as INT(2) - use BIGINT as you imply.

顺便说一下,在MySQL INT(2)中,2指定了最大显示宽度,但不影响存储的数量。INT(8)使用与INT(2)相同的存储—使用BIGINT,如您所暗示的。

#5


0  

The maximum value of an unsigned int is 4,294,967,295. The current population of the internet is approximately 1.8 billion people. I'd recommend using an unsigned int for your purposes and don't worry about gaps in your sequence.

无符号整数的最大值为4,294,967,295。目前的互联网人口约为18亿。出于您的目的,我建议您使用无符号int,不要担心序列中的间隔。

On a philosophical note: Donald Knuth once said "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil".

从哲学的角度来看:Donald Knuth曾经说过“我们应该忘记小的效率,大约97%的时候是这样的:过早的优化是所有邪恶的根源”。


推荐阅读
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文讨论了在使用Git进行版本控制时,如何提供类似CVS中自动增加版本号的功能。作者介绍了Git中的其他版本表示方式,如git describe命令,并提供了使用这些表示方式来确定文件更新情况的示例。此外,文章还介绍了启用$Id:$功能的方法,并讨论了一些开发者在使用Git时的需求和使用场景。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • 本文提供了关于数据库设计的建议和注意事项,包括字段类型选择、命名规则、日期的加入、索引的使用、主键的选择、NULL处理、网络带宽消耗的减少、事务粒度的控制等方面的建议。同时还介绍了使用Window Functions进行数据处理的方法。通过遵循这些建议,可以提高数据库的性能和可维护性。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
  • Summarize function is doing alignment without timezone ?
    Hi.Imtryingtogetsummarizefrom00:00otfirstdayofthismonthametric, ... [详细]
  • 玩转直播系列之消息模块演进(3)
    一、背景即时消息(IM)系统是直播系统重要的组成部分,一个稳定的,有容错的,灵活的,支持高并发的消息模块是影响直播系统用户体验的重要因素。IM长连接服务在直播系统有发挥着举足轻重的 ... [详细]
  • 起因由于我录制过一个小程序的课程,里面有消息模板的讲解。最近有几位同学反馈官方要取消消息模板,使用订阅消息。为了方便大家容易学 PythonFlask构建微信小程序订餐系统 课程。 ... [详细]
  • 生产环境下JVM调优参数的设置实例
     正文前先来一波福利推荐: 福利一:百万年薪架构师视频,该视频可以学到很多东西,是本人花钱买的VIP课程,学习消化了一年,为了支持一下女朋友公众号也方便大家学习,共享给大家。福利二 ... [详细]
  • 工作用可能会用到会话分组:Message是消息实体对象,里面有toId和fromId指明接收方ID和发送方Id,通过组合形式“12-22-”为map的key其中Mess ... [详细]
author-avatar
mobiledu2502905727
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有