之前因?yàn)闀r(shí)間匆忙,大區(qū)里產(chǎn)生唯一ID只是簡(jiǎn)單寫(xiě)了一個(gè)方法,今天趁著有時(shí)間,把里面一些過(guò)程寫(xiě)出來(lái),也算是個(gè)總結(jié)。 首先說(shuō)說(shuō)需求,現(xiàn)在游戲里數(shù)據(jù)庫(kù)為了分散熱點(diǎn),都采用分表方式,以前那種一張表AUTO_INCREMENT的方式顯然不行了,那么將唯一ID放到業(yè)務(wù)進(jìn)程里可行嗎?這個(gè)也不好,因?yàn)楝F(xiàn)在后臺(tái)都是多個(gè)部署,每個(gè)進(jìn)程可以保證ID唯一,但是存到數(shù)據(jù)庫(kù)的時(shí)候就可能重復(fù),所以我們還是得在DB上做文章。 因此就有了上篇文章的解決方案,單獨(dú)一張表,這張表的作用就是專(zhuān)門(mén)產(chǎn)生唯一ID,而且為多個(gè)業(yè)務(wù)提供唯一ID,多進(jìn)程情況下也不需要鎖表,效率比較高,是不是很像設(shè)計(jì)模式里的工廠(chǎng)。接著我來(lái)分析下這張表。我們?cè)賮?lái)看看表結(jié)構(gòu)和用法
create table SeqTab (
iSeqNo bigint(20) not null default 0, //表示唯一ID
iSeqType int(11) not null default 0, //表示業(yè)務(wù)ID
primary key(iSeqNo,iSeqType));
insert into SeqTab values(0,1); //初始化,假設(shè)一個(gè)業(yè)務(wù)編號(hào)為1
update SeqTab set iSeqNo=last_insert_id(iSeqNo+1) where iSeqType=1;
select last_insert_id(); //這兩句是獲取一個(gè)業(yè)務(wù)的唯一ID,供業(yè)務(wù)進(jìn)程使用。 其實(shí)說(shuō)到這張表,關(guān)鍵是說(shuō)LAST_INSERT_ID()這個(gè)方法。它有兩種形式LAST_INSERT_ID(),LAST_INSERT_ID(expr)。 這個(gè)東西的特點(diǎn)是,1.屬于每個(gè)CONNECTION,CONNECTION之間相互不會(huì)影響 2.不屬于某個(gè)具體的表 3.返回最后一次INSERT AUTO_INCREMENT的值 4.假如以此使用INSERT插入 多行數(shù)據(jù),只返回第一行數(shù)據(jù)產(chǎn)生的值 5.如果你UPDATE某個(gè)AUTO_INCREMENT的值,不會(huì)影響LAST_INSERT_ID()返回值 LAST_INSERT_ID(expr)與LAST_INSERT_ID()稍有不同,首先它返回expr的值,其次它的返回值會(huì)記錄在LAST_INSERT_ID()。 我們這里主要使用到了第一和第二個(gè)特點(diǎn),每個(gè)進(jìn)程并發(fā)執(zhí)行update SeqTab set iSeqNo=last_insert_id(iSeqNo+1) where iSeqType=1;,就獲取屬于進(jìn)程自己的iSeqNo并且記錄在 LAST_INSERT_ID中,通過(guò)第二句取出該值。 接著我們?cè)诒容^下其他一些辦法。 第一種是直接一張表,里面有一個(gè)ID字段,設(shè)置成AUTO_INCREMENT。這個(gè)的問(wèn)題是每個(gè)業(yè)務(wù)ID不是連續(xù)的,是離散的。 第二種是使用GUID或者UUID,但是這個(gè)問(wèn)題我個(gè)人覺(jué)得是效率上的差異,字符串沒(méi)有數(shù)字的效率好,另外數(shù)字ID今后也可以拼接一些區(qū)信息,之后跨區(qū)的時(shí)候可以方便獲取對(duì)象是哪個(gè)區(qū)的.
posted on 2012-12-06 23:01
梨樹(shù)陽(yáng)光 閱讀(2221)
評(píng)論(2) 編輯 收藏 引用 所屬分類(lèi):
數(shù)據(jù)庫(kù)