我是靠谱客的博主 无辜黑夜,最近开发中收集的这篇文章主要介绍[MySQL] 并发更新性能测试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

MySQL 版本:5.7.9
表结构:

CREATE TABLE `award` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `award` varchar(255) DEFAULT NULL,
  `count` int(11) NOT NULL COMMENT '数量',
  `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

一、测试代码

原理可参看:CountDownLatch 模拟高并发

package com.wlm.test.concurrent;

import java.util.concurrent.CountDownLatch;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wlm.test.award.AwardDao;

/**
 * @author wengliemiao
 */
@Service
public class ConcurrentTest {
    @Autowired
    private AwardDao awardDao;

    /**
     * 线程数量
     */
    public static final int THREAD_NUM = 50;

    /**
     * 开始时间
     */
    private static long startTime = 0L;

    @PostConstruct
    public void init() {
        try {
            startTime = System.currentTimeMillis();
            System.out.println("CountDownLatch started at: " + startTime);

            // 初始化计数器为1
            CountDownLatch countDownLatch = new CountDownLatch(1);

            for (int i = 0; i < THREAD_NUM; i ++) {
                new Thread(new Run(countDownLatch)).start();
            }

            // 启动多个线程
            countDownLatch.countDown();

        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }
    }

    /**
     * 线程类
     */
    private class Run implements Runnable {
        private CountDownLatch startLatch;

        public Run(CountDownLatch startLatch) {
            this.startLatch = startLatch;
        }

        @Override
        public void run() {
            try {
                // 线程等待
                startLatch.await();

                // 执行操作
                awardDao.update(4);

                long endTime = System.currentTimeMillis();
                System.out.println(Thread.currentThread().getName() + " ended at: " + endTime + ", cost: " + (endTime - startTime) + " ms.");
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

二、测试结果

并发50: 约381ms
这里写图片描述

并发100: 约387ms
这里写图片描述

并发200:约445ms
这里写图片描述

并发500:约1173ms
这里写图片描述

并发1000: 约1324ms
这里写图片描述

注:线程并发执行的时间取决于当时执行时的系统状态。

三、总结

此处可以看出,并发对同一条数据进行update操作时,随着并发数的增高,执行时间增长。这是由于 MySQL 的 InnoDB 存储引擎对 CUD 操作默认加排他锁,因此一次只能有一条数据执行update操作。

可参看:MySQL行级锁

四、有无索引情况下并发更新性能的测试

对以下几种情况进行测试:

  • 数据量少时,并发更新同一行数据;
  • 数据量少时,并发更新不同行数据;
  • 数据量大时,并发更新同一行数据;
  • 数据量大时,并发更新不同行数据;

1、数据量少时,执行5次,并发2000更新同一行数据性能测试结果为:

执行语句:

update `award` set `count` = `count` + 1 where `award` = '4' 

数据量为:
这里写图片描述

有索引数据表结构为:

CREATE TABLE `award` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `award` varchar(255) DEFAULT NULL,
  `count` int(11) NOT NULL COMMENT '数量',
  `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `Index` (`award`,`count`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
执行次数未加索引加索引
12830ms3414ms
23439ms2870ms
32950ms2689ms
42673ms3325ms
53245ms2916ms


从以上结果可以看出,数据量少时,有无索引情况下,并发更新同一行数据的性能大致相同。

2、数据量少时,执行5次,各并发1000更新不同行数据性能测试结果为:

执行次数未加索引加索引
12884ms3002ms
22988ms3007ms
32827ms3184ms
43147ms3763ms
52941ms2675ms


从以上结果可以看出,数据量少时,有无索引情况下,并发更新不同行数据的性能大致相同。

3、数据量大时,执行5次,并发10更新同一行数据性能测试结果为:

执行语句:

update `category2` set `updated_time` = CURRENT_TIMESTAMP() where `name` = 'cate_1000'

加索引数据表结构为:

CREATE TABLE `category2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(220) NOT NULL,
  `created_time` datetime NOT NULL,
  `updated_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `Index` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10277277 DEFAULT CHARSET=utf8

数据量为:
这里写图片描述

执行次数未加索引加索引
155773ms427ms
261479ms311ms
355599ms355ms
455280ms357ms
553652ms350ms


从以上数据可以看出,数据量大时,有索引并发更新同一行数据性能远远超过无索引。

4、数据量大时,执行5次,各并发5更新不同行数据性能测试结果为:

执行次数未加索引加索引
157077ms318ms
256290ms352ms
355726ms361ms
455465ms324ms
555483ms365ms


从以上数据可以看出,数据量大时,有索引并发更新不同行数据性能远远超过无索引。

结论:
1、数据量少时,有无索引对并发更新性能影响不大;
2、数据量大时,有索引并发更新性能远远超过无索引;
3、从以上数据看出,单纯执行update操作时,有无索引情况下并发更新不同行性能大致相同(可能是由于无索引情况下 update 占据的表锁在执行完当前 update 操作之后,自动释放,参看MySQL行级锁)。

最后

以上就是无辜黑夜为你收集整理的[MySQL] 并发更新性能测试的全部内容,希望文章能够帮你解决[MySQL] 并发更新性能测试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部