关于主键管理
提到主键管理,我能联想到几点:
1. 使用数据库自增主键很方便,但不推荐使用,移植性和灵活性大大降底,比如只能在插入记录后获取主键值,
相对而言,很多人更推荐自管理主键的方式,下面就忽略自增主键的讨论吧
2. 使用 UUID 作为主键非常方便,JAVA简单的 API 调用就可以生成 UUID(也可以考虑使用第 3 方类库生成 UUID),并且全球唯一,在集群环境中或其它复杂环境中使用都很方便,但经过查阅相关资料,发现一些劣势,一是生成 UUID 的效率不高,并发量大的情况下很明显,二是用 UUID 作为表的主键,等数据量大了之后,会严重影响 SELECT 和 INSERT 的效率。
虽然没尝试过用 UUID 作主键,但看了些文章后就被吓到了(我基本还是用关系型数据库的)
3. 一个常用的主键管理方案是,用一张表来维护所有的主键/值,在应用层生成下个 ID 值,经常见到这种代码:getNextSequence(key)。为了避免与数据库的频繁交互,一般加个缓存,一次取多个 sequence,偶然情况下会有少许的浪费。
针对集群环境,了解一点,有一种办法是每个结点生成 sequence 时使步进(step)错位,这样可以避免冲突。
4. 我自己寻思的一种方法,不使用数据库的自增主键特性,在应用启动的时刻,初始化/收集所有需要主键管理的表的最大主键值(maxId)并保存到内存中(针对 int/long 类型),然后使用 AtomicInteger 或 AtomicLong 实现递增,除了初始化阶段外,不需要为了主键管理而去和数据库打交道,而且 AtomicInteger 的并发效率更高吧?这种方式实战不多,有没有朋友提点建议?
5. 我发现有些应用,生成 ID 的时机非常早。比如新增一条记录,在进入到新增界面时,ID 就生成了,如果你未提交并且关闭浏览器窗口,会提示什么“数据会丢失”、“是否确认关闭窗口”等信息。这里我有几个疑问,希望了解的朋友给讲讲。
a). ID 这么早生成有什么特殊的应用场景吗?为要这么急?
b). 进入新建页面->不提交->关闭窗口,这样操作就要浪费一个 ID,这个影响不严重吗?恶意用户频率过高的浪费ID呢?或者干脆写个 HTTP 交互的程序暴ID呢?是我想得太多了,还是想歪了?请高手讲解如何正确使用这种方式。
说的不对的,谢谢指正,如果大家有好的主键管理方案,希望能让我学学。。
[该贴被edison87915于2014-09-17 08:54修改过]