精华内容
下载资源
问答
  • 假如我们的mysql有一个计数器,而这个计数器需要我们重新统计,怎么办呢?应用场景,比如说有一个商场,每卖一个产品都产生一个流水,然后我们需要知道每笔流水是该产品第几次出售的,这样说可能不明白,我拿一个...

    假如我们的mysql有一个计数器,而这个计数器需要我们重新统计,怎么办呢?

    应用场景,比如说有一个商场,每卖一个产品都产生一个流水,然后我们需要知道每笔流水是该产品第几次出售的,这样说可能不明白,我拿一个详细的数据举例吧。

    recordID,productID,productType,sellDate,counter

    1, 1, 1, '2010-1-15 15:20:10' 0

    2, 1, 2, '2010-1-15 15:20:10' 1

    3, 2, 1, '2010-1-15 15:20:10' 0

    4, 2, 1, '2010-1-15 15:20:10' 1

    上面这个数据是一些撒气数据,包括记录的流水号,产品的编号,产品的类型,销售的时间,计数器。一般来说,计数器我们首先我会想到自增,但这而肯定是不可能使用自增长的。

    我最初的时候,尝使用这样的代码:update t_product set t_counter = (select max(counter) from t_product where productid = 1 and productType = 1) + 1 where where productid = 1 and productType = 1

    但是mysql报错,上网一查,mysql不支持这种写法,呵呵,我对mysql完全不熟悉。记得以前在sql server用过游标,然后也试试查找游标,经过n次google与百度,最终搞定这个难题。

    我本身对mysql完全是个外行,就连注释也不知道怎么注释的,现在终于知道有三种写法的,而--的注释后面是要空一格的,所以代码写得性能什么的就不敢说了,只是实现了这个功能,希望对有同样需求的朋友有用。

    呵,还学到一点,declare只能写在最前面。

    看最终的代码:

    CREATE PROCEDURE p_resetCounter ()

    BEGIN

    DECLARE productID INT;

    DECLARE type INT;

    DECLARE tmpCount INT;

    DECLARE stopFlag int;

    #使用游标

    DECLARE cur cursor for SELECT COUNT(*), productID, productType FROM

    t_product GROUP BY productID, productType;

    DECLARE CONTINUE HANDLER FOR NOT FOUND set stopFlag=1; #如果找不到记录,则设置stopFlag=1

    #定义变量及创建临时表

    CREATE TEMPORARY TABLE tmp_Counter(

    recordID int not null,

    Counter int not null

    )TYPE = HEAP;

    #打开游标

    open cur;

    REPEAT

    fetch cur into tmpCount, productID, type;

    SET @id = -1;

    INSERT INTO tmp_Counter

    (SELECT recordID, (@id := @id + 1) counter

    from t_product WHERE productID = productID AND productType = type)

    ORDER BY ts_Date ASC;

    UNTIL stopFlag = 1

    END REPEAT;

    close cur; #关闭游标

    UPDATE t_product, tmp_Counter SET counter = tmp_Counter.Counter

    WHERE recordID = tmp_Counter.recordID;

    -- SELECT * FROM tmp_Counter;

    DROP TABLE tmp_Counter;#删除临时表

    END;

    注意:本文为我的独立博客镜像博客,自发表不再更新,原文可能随时被更新,敬请访问原文。同时,请大家不要在此评论,如果有什么看法,请点击这里:http://iove.net/1705/

    本文来自http://iove.net,欢迎转载,转载敬请保留相关链接,否则视为侵权,原文链接:http://iove.net/1705/

    展开全文
  • 只是你要严格控制userCount的更新,那就加行锁呗! select * from table where id=123456 and useCount ; update table set userCount = userCount + 1 where userCount = userCount and userCount ; InnoDB环境下...

    一张表 两个字段 一个id 一个useCount

    表里存了100个id 每个id对应自己的useCount

    业务场景是:当id每使用一次 useCount要加1。 当useCount大于1000时 这个id就不能在被使用了(换句话说 无法从数据库中查出)

    在高并发情况下,会遇到一种问题:

    假设数据表中有一条记录为 id=123456; useCount=999

    a与b两个连接并发查询这个id 123456 都执行下列sql:

    select * from table where id=123456 and useCount < 1000

    a先执行 得到id 123456的useCount是999 之后在程序里做了一些逻辑判断或业务操作后执行sql: update useCount + 1

    在a做判断且没有update之前 b也执行了查询sql 发现useCount是999 之后它也会执行sql: update useCount +1

    但是 事实上b不应该取得这个id 因为a已经是第1000个使用者

    所以请教一下 在高并发情况下 仅使用数据库 如何完成这一需求?

    回复内容:

    一张表 两个字段 一个id 一个useCount

    表里存了100个id 每个id对应自己的useCount

    业务场景是:当id每使用一次 useCount要加1。 当useCount大于1000时 这个id就不能在被使用了(换句话说 无法从数据库中查出)

    在高并发情况下,会遇到一种问题:

    假设数据表中有一条记录为 id=123456; useCount=999

    a与b两个连接并发查询这个id 123456 都执行下列sql:

    select * from table where id=123456 and useCount < 1000

    a先执行 得到id 123456的useCount是999 之后在程序里做了一些逻辑判断或业务操作后执行sql: update useCount + 1

    在a做判断且没有update之前 b也执行了查询sql 发现useCount是999 之后它也会执行sql: update useCount +1

    但是 事实上b不应该取得这个id 因为a已经是第1000个使用者

    所以请教一下 在高并发情况下 仅使用数据库 如何完成这一需求?

    典型的并发问题。建议用乐观锁模式处理,同时兼顾性能。具体步骤如下:

    1、添加第3个字段version, int类型,default值为0。version值每次update时作加1处理。

    ALTER TABLE test_tb ADD COLUMN version INT DEFAULT '0' NOT NULL AFTER useCount;

    2、select时同时获取version值(例如为3)

    SELECT useCount, VERSION FROM test_tb WHERE id=123456 AND useCount < 1000

    3、update时检查version值是否为第2步获取到的值

    UPDATE test_tb SET VERSION=4, useCount=useCount+1 WHERE id=123456 AND VERSION=3

    如果update的记录数为1,则表示成功;

    如果update的记录数为0,则表示已经被其他应用(线程)update过了,需作异常处理

    注:以上思路参考自JavaEE的JPA乐观锁@version处理机制。

    这里有一个参考http://www.blogjava.net/sway/archive/2008/10/10/233569.html

    对于你现在的使用方式,userCount就类似于version,有些类似乐观锁的方式。

    只是你要严格控制userCount的更新,那就加行锁呗!

    select * from table where id=123456 and useCount < 1000 for update;

    update table set userCount = userCount + 1 where userCount = userCount and userCount < 1000;

    InnoDB环境下为了不锁表,userCount还需要建索引。

    f68f2add0b68e4f9810432fce46917b7.png

    本文原创发布php中文网,转载请注明出处,感谢您的尊重!

    展开全文
  • 如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在WEB应用中很常见。可以用这种表缓存一个用户的朋友书、文件下载次数等。创建一张独立的表存储计数器通常是一个好主意,这样可使计数器表小...

    如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在WEB应用中很常见。可以用这种表缓存一个用户的朋友书、文件下载次数等。创建一张独立的表存储计数器通常是一个好主意,这样可使计数器表小且快。使用独立的表可以帮助避免查询缓存失效。

    假设只有一个计数器表,只有一行数据,记录网站的点击次数:

    mysql>CREATE TABLE hit_counter(

    -> cnt int unsigned not null

    ->) ENGINE=InnoDB;

    mysql>CREATE TABLE hit_counter(

    -> cnt int unsigned not null

    ->) ENGINE=InnoDB;

    网站的每次点击都会导致对计数器进行更新:

    mysql>UPDATE hit_counter SET cnt = cnt + 1;

    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;

    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;

    mysql>UPDATE hit_counter SET cnt = cnt + 1 WHERE slot = RAND()*100;

    要获得统计结果,需要使用下面的聚合查询:

    mysql> SELECT SUM(cnt) FROM hit_counter;

    mysql> SELECT SUM(cnt) FROM hit_counter;

    展开全文
  • 计数器如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数、文件下载次数等。创建一张独立的表存储计数器通常是个好主意,这样可使计数器...

    计数器

    如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数、文件下载次数等。创建一张独立的表存储计数器通常是个好主意,这样可使计数器表小且快。使用独立的表可以帮助避免查询缓存失效,并且可以使用本节展示的一些更高级的技巧。

    应该让事情变得尽可能简单,假设有一个计数器表,只有行数据,记录网站的点击次数:

    CREATE TABLE hit_counter (

    cnt INT UNSIGNED NOT NULL

    ) ENGINE = INNODB;

    网站的每次点击都会导致对计数器进行更新:

    UPDATE hit_counter SET cnt = cnt+ 1;

    问题在于,对于任何想要更新这一行的事务来说,这条记录上都有一个全局的互斥锁(mutex)。这会使得这些事务只能串行执行。要获得更高的并发更新性能,也可以将计数器保存在多行中,每次随机选择一行进行更新。这样做需要对计数器表进行如下修改:

    CREATE TABLE hit_counter (

    slot TINYINT UNSIGNED NOT NULL PRIMARY KEY,

    cnt INT UNSIGNED NOT NULL

    ) ENGINE = INNODB;

    然后预先在这张表增加100行数据。现在选择一个随机的槽 (slot) 进行更新:

    UPDATE hit_counter SET cnt = cnt + 1 WHERE slot = RAND() * 100;

    要获得统计结果,需要使用下面这样的聚合查询:

    SELECT SUR(cnt) FROM hit_counter;

    每日计数器

    另外一个常见的需求是每隔一段时间开始一个新的计数器(例如,每天一个)。如果需要这么做,则可以再简单地修改一下表设计:

    CREATE TABLE dally_hit_counter (

    day DATE not null,

    slot TINYINT UNSIGNED NOT NULL,

    cnt INT UNSIGNED NOT NULL,

    primary key(day, slot)

    )ENGINE = INNODB;

    在这个场景中会,可以不用像前面的例子那样预先生成行,而用ON DUPLICATE KEY UPDATE进行代替

    INSERT INTO `dally_hit_counter` ( DAY, slot, cnt )

    VALUES

    ( CURRENT_DATE, RAND( ) * 100, 1 )

    ON DUPLICATE KEY UPDATE cnt = cnt + 1;

    如果希望减少表的行数,以避免表变得太大,可以写一个周期执行的任务,合并所有结果到0号槽,并且删除所有的槽。

    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》 P135

    展开全文
  • 假如我们的mysql有一个计数器,而这个计数器需要我们重新统计,怎么办呢?应用场景,比如说有一个商场,每卖一个产品都产生一个流水,然后我们需要知道每笔流水是该产品第几次出售的,这样说可能不明白,我拿一个...
  • MySQL——计数器

    2019-05-03 16:51:16
    如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数、文件下载次数等。创建一张独立的表存储计数器通常是个好主意,这样可以使计数器表小...
  • 如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在web应用中非常常见。可以用这个表缓存一个用户的朋友书、文件下载次数等。创建一张独立的表存储计数器是一种非常好的做法,这样可以使...
  • MySQL计数器

    2017-12-17 17:41:38
    如果应用在表中保存计数器,则在更新计数器是可能碰到并发问题。计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数、文件下载次数等。创建一张独立的表存储计数器通常是个好主意,这样可使计数器表小且...
  • mysql计数器需要注意的问题 一般写计数器就是 update jishuqi set count=count+1 where id=1; 但是并发的时候就会出问题 比方说1000个人并发 更新 都是同一行数据 mysql写入的肯定锁表 导致其他用户...
  • 网站访问量统计,自己实现思路:每当用户访问页面,前端初始化方法自动调用后端接口,进行访问量统计,可以单独创建一个计数器表,使用独立的表可以帮助避免查询缓存失效。udpate hit_counter set cnt=cnt+1 ;但是当...
  • 简单易用的计数器(数据库)更新时间:2006年10月09日 00:00:00 作者:用法include("counter.php");Counter(__FILE__);//为文件增加一个计数if($PHP_SELF=="/index.php"){$count=Counter("INDEX_COUNT");//为首页增加...
  • 假如我们的mysql有一个计数器,而这个计数器需要我们重新统计,怎么办呢? 应用场景,比如说有一个商场,每卖一个产品都产生一个流水,然后我们需要知道每笔流水是该产品第几次出售的,这样说可能不明白,我拿一个...
  • 如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数、文件下载次数等。创建一张独立的表存储计数器通常是个好主意,这样可使计数器表小且...
  • 怪我咯2017-04-10 14:30:033楼典型的并发问题。建议用乐观锁模式处理,同时兼顾性能。具体步骤如下:1、添加第3个字段version, int类型,default值为0。version值每次update时作加1处理。ALTER TABLE test_tb ADD ...
  • mysql计数器的优化

    2019-03-15 15:37:05
    mysql计数的一些优化 ...**每次点击之后都会更新计数器** UPDATE hit_counter SET cnt = cnt+1; 问题:任何想要更新这一事务来说,都会产生全局互斥锁。 解决:使用多行 CREATE TABLE hit_counter( ...
  • mysql计数器

    2017-07-28 22:03:13
    在web应用中,计数器是非常常见的,如访问量计数,文件下载计数等。那么我们可以创建一张表来进行计数:create table counter ( cnt int unsigned not null ) 我们更新的时候只需要对这一行更新就行了,但是这样的...
  • mysql计数器表设计

    2019-12-18 10:57:19
    可以创建一个独立的表来存储计数器次数,当然,为了避免对这个表的某一行的更新造成全局锁的问题,可以使用多种方法来生成多行,然后根据实时或者某个时间来合并这个多行数据,下面仅仅是一个从《mysql高性能》书...
  • 如果相关应用在Mysql数据库的表中保存计数器,在更新计数器的时候可能会碰到并发问题。例如在web应用中,记录网站的点击次数。网站的每次点击都会导致对计数器进行更新。问题来了,对于Mysql数据表的更新操作,都会...
  • 现在有很多的项目,对计数器的实现甚是随意,比如在实现网站文章点击数的时候,是这么设计数据表的,如:”article_id, menu_id, article_name, article_content, article_author, article_view......在article_view...
  • MySQL计数器表的设计

    2015-07-21 22:41:00
    如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在web应用中非常常见。可以用这个表缓存一个用户的朋友书、文件下载次数等。创建一张独立的表存储计数器是一种非常好的做法,这样可以使...
  • SQLServer MySql 计数器

    千次阅读 2015-10-12 21:11:33
    例子参考《高性能MySql》第三版4.4.2 计数器表(page 135) 由于mysql 没有执行成功,现在用sqlserver 模拟样本。计数器表可用于缓存一个用户的朋友数,文件下载次数等。 创建表 hit_counter 用于计数,先插入...
  • 例子参考《高性能MySql》第三版4.4.2 计数器表(page 135) 由于mysql 没有执行成功,现在用sqlserver 模拟样本。计数器表可用于缓存一个用户的朋友数,文件下载次数等。 创建表hit_counter 用于计数,先插入一行...
  • 如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在WEB应用中很常见。可以用这种表缓存一个用户的朋友书、文件下载次数等。创建一张独立的表存储计数器通常是一个好主意,这样可使计数器表小...
  • 转自:http://www.lanecn.com/article/main/aid-12现在有很多的项目,对计数器的实现甚是随意,比如在实现网站文章点击数的时候,是这么设计数据表的,如:”article_id, menu_id, article_name, article_content, ...
  • 如果应用在表中保存计数器,则在更新计数器时可能碰到并发问题。计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数,文件下载次数等。创建一张独立的表存储计数器通常是个好主意,这样可使计数器表小且...
  • 现在有很多的项目,对计数器的实现甚是随意,比如在实现网站文章点击数的时候,是这么设计数据表的,如:”article_id, article_name, article_content, article_author, article_view……在article_view中记录该...
  • 另一种比较好的办法是对每一个文章的计数器不是一行,而是多行,比如吧,一百行。每次随机更新其中一行,该文章的浏览数就是所有行的和。CREATE TABLE `article_view`( `article_id` int(11) NOT NULL, `pond` ...
  • [导读]什么是竞态问题?假设有一个计数器,首先当前值自增长,然后获取到自增长之后的当前值。自增长后的值有可能被有些操作用来当做唯一性标识,因此并发的...为什么不能使用使用UPDATE语句更新计数器,然后SELEC...
  • 什么是竞态问题?...为什么不能使用使用UPDATE语句更新计数器,然后SELECT语句获取自增长后的当前值?问题在于并发的操作有可能获取到相同的计数器值。CREATE TABLEcounters(idINT NOT NULL UNIQUE, --计数...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 127
精华内容 50
关键字:

Mysql更新计数器