mysql> create table hit_counter(
-> cnt int unsigned not null
-> ) engine=innodb;
mysql> update hit_counter set cnt=cnt+1;
問題在於,對於任何想要更新這一行的事務來說,這條記錄上都有乙個全域性的互斥鎖(mutex)。這會使得這些事務只能序列執行。要想獲得更高的併發更新效能,也可以將計數器儲存在多行中,每次隨機選擇一行進行更新。這樣做需要對計數器表進行如下修改:
mysql> create table hit_counter(
-> slot tinyint unsigned not null primary key,
-> cnt int unsigned not null
-> ) engine=innodb;
然後預先在這張表增加100行資料。現在選擇乙個隨機的槽(slot)進行更新:
mysql> update hit_counter set cnt=cnt+1
where slot=rand()*100;
要獲得統計結果,需要使用下面的聚合查詢:
select
sum(cnt) from hit_counter;
乙個常見的需求使每隔一段時間開始乙個新的計數器(例如每天乙個)。如果需要這麼做,則可以再簡單的修改一下表設計:
mysql> create table daily_hit_counter(-> day date not
null,-> slot tinyint unsgined not
null,-> cnt int unsigned not
null,-> primary key(day,slot)
-> ) engine=innodb;
在這個場景中,可以不用像前面的例子那樣預先生成行,而用on duplicate key update代替:
mysql> insert into daily_hit_counter(day, slot, cnt)
-> values(current_date, rand()*100,1)
->
on duplicate key update cnt=cnt+1
如果希望減少表的行數,以避免表變得太大,可以寫乙個週期執行的任務,合併所有結果到0號槽,並且刪除所有其他的槽:
mysql> update daily_hit_counter as c
-> inner join (
->
select day, sum(cnt) as cnt min(slot) as mslot
-> from daily_hit_counter
->
group
by day
-> ) as x using(day)
->
set c.cnt=
if(c.slot=x.mslot, x.cnt, 0),
-> c.slot=
if(c.slot=x.mslot,0 ,c.slot);
mysql> delete from daily_hit_counter where slot<>
0and cnt=
0;
MySQL 計數器表
計數器表的建立 create table hit counter cnt int unsigned not null engine innodb update hit counter set cnt cnt 1 問題在於,對於任何想要更新這一行的事務來說,這條記錄上都有乙個全域性的互斥鎖 mutex...
計數器設計
最近看到一篇文章說要實現乙個計數器的功能,於是通過思索,設計了乙個靈活可用性高的物件計數器。裡面閃爍著 很多的火花。template class object counter object counter private static int m count template int object ...
mysql計數 mysql實現計數器
本文 如果是在非常高的併發之下,還是建議用記憶體資料庫redis去實現計數的功能。如果不是那麼高的併發,用表實現就可以。drop table access counter create table access counter cnt int unsigned not null insert int...