MySQL-性能优化_大表和大事务的常用处理方案

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL-性能优化_大表和大事务的常用处理方案

20200129003012618.png

生猛干货

带你搞定MySQL实战,轻松对应海量业务处理及高并发需求,从容应对大场面试


官方文档

https://dev.mysql.com/doc/


20200131202811239.png


如果英文不好的话,可以参考 searchdoc 翻译的中文版本

http://www.searchdoc.cn/rdbms/mysql/dev.mysql.com/doc/refman/5.7/en/index.com.coder114.cn.html


20200131203226295.png


影响MySQL性能的几大因素


通常来说 ,有以下几点

慢SQL(重点) 、 主机的硬件资源(CPU、内存、磁盘I/O等)、网卡流量等等


超高的QPS和 TPS


QPS(Queries Per Second 每秒处理的查询量) : 假设处理一个SQL 需要 10ms , 1s 最多也就处理100个,那么QPS < = 100 ,如果 100ms处理一个呢? 那 QPS <=10 ,可以推断出SQL的执行效率队QPS的影响很重要。 一般来说,80%的数据库问题都可以通过SQL优化来解决。


TPS(Transactions Per Second,事务数/秒,这个完整的事务包括了用户请求服务器,服务器内部处理,服务器返回信息给用户三个过程)


QPS和TPS高,说明应用的负载较高.


MySQL数据库中的QPS和TPS的计算方法

Questions = SHOW GLOBAL STATUS LIKE 'Questions';
Uptime = SHOW GLOBAL STATUS LIKE 'Uptime';
QPS=Questions/Uptime
-----------------------
Com_commit = SHOW GLOBAL STATUS LIKE 'Com_commit';
Com_rollback = SHOW GLOBAL STATUS LIKE 'Com_rollback';
Uptime = SHOW GLOBAL STATUS LIKE 'Uptime';
TPS=(Com_commit + Com_rollback)/Uptime


高并发和高CPU使用率


高并发–>数据库连接池被用光的几率大增 (max_connections默认100),超过的话,就会看到500子类的错误了


高CPU使用率—>响应慢,甚至导致宕机


磁盘I/O


磁盘I/O的性能突然下降—>使用更快的磁盘设备


其他大量消耗磁盘性能的计划任务等 —> 可预期的高峰期,调整计划任务的执行时间


网卡流量


比如我们常说的千兆网卡, 这里的千兆 其实是 小b , 1Byte = 8 bit . bit 小b Byte 大B


1000Mb / 8 约等于 100MB (我们熟悉的带宽)


网卡被占满的风险增加 ,被占满的话,肯定访问不到数据库了 ,如何避免呢?


通常来说,


1. 减少slave节点的数量,避免大量的复制,占用带宽

2. 合理的使用多级缓存,避免大量缓存失效,请求到DB

3. 避免使用 select * 查询,占用带宽传输

3. 分离业务网络和服务器网络等等


大表带来的风险


大表的定义


啥叫大表? 粗略的定义 ,可以从两个维度去考虑,仅供参考

  1. 记录超过1千万
  2. 表数据文件巨大,超过10G


大表带来的风险


  • 对查询的影响
    举个例子: 从超巨数据中,查找区分度不高的数据,将导致大量的磁盘I/O,有可能导致数据库hang死 ,从而产生大量的慢查询,需要特别关注解决。
  • 对DDL的影响
  • 建立索引 耗时特别长, 风险: MySQL 5.5 以前的版本,建立索引会锁表 。 5.5以后的版本虽然不会引起锁表,但会引起主从延迟。
  • 修改表结构的话,需要长时间锁表 ,风险:1. 主从延迟 2. 影响正常的数据操作


如何应对大表?


  • 1. 分库分表 (分表主键如何选择,分表后跨分区的查询和统计如何解决) 慎重!!!
  • 2. 对历史数据进行归档 (归档时间点的选择 、如何高效的归档)


大事务带来的风险


基本特性:ACID


事务的4个特性: ACID

原子性 atomicity | 一致性 consistency | 隔离性 isolation | 持久性 durability


原子性(atomicity)

一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。


举个例子: 转账 A 转给B , A账户 扣减 2千, B账户 增加两千 。 这两个必须在一个事务中,有任何一步出现问题,都不会提交,需要回滚, 否则的话,A扣了2000成功,B增加2000没成功,钱就莫名其妙的少了,谁能受得了?


一致性 consistency


一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。


说实话,这个定义太难懂了。。。。


[1]Transactions are not a law of nature; they were created with a purpose, namely to simplify the programming model for applications accessing a database. By using transactions, the application is free to ignore certain potential error scenarios and concurrency issues, because the database takes care of them instead (we call these safety guarantees).


上述说出了为什么会出现事务 : 事务的产生,其实是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题。 因此事务本质上是为了应用层服务的。


ACID里的AID都是数据库的特征,也就是依赖数据库的具体实现.而唯独这个C,实际上它依赖于应用层,也就是依赖于开发者.


一致性是指系统从一个正确的状态,迁移到另一个正确的状态.什么叫正确的状态呢?就是当前的状态满足预定的约束就叫做正确的状态.而事务具备ACID里C的特性是说通过事务的AID来保证我们的一致性.


CASE1: A要向B转2000元,而A的账户中只有1800元,并且我们给定账户余额这一列的约束是,不能小于0.那么很明显这条事务执行会失败,因为1800-2000=-200,小于我们给定的约束了. -----------------> 这个例子里,支付之前我们数据库里的数据都是符合约束的,但是如果事务执行成功了,我们的数据库数据就破坏约束了,因此事务不能成功,这里我们说事务提供了一致性的保证 .


CASE2: A要向B支付2000元,而A的账户中只有1800元,我们的账户余额列没有任何约束.但是我们业务上不允许账户余额小于0.因此支付完成后我们会检查A的账户余额,发现余额小于0了,于是我们进行了事务的回滚. -------------------> 这个例子里,如果事务执行成功,虽然没有破坏数据库的约束,但是破坏了我们应用层的约束.而事务的回滚保证了我们的约束,因此也可以说事务提供了一致性保证. (事实上,是我们应用层利用事务回滚保证了我们的约束不被破坏)


CASE3: A要向B支付2000元,而A的账户中只有1800元,我们的账户余额列没有任何约束.然后支付成功了.-------------------->这里,如果按照很多人的理解,事务不是保证一致性么?直观上账户余额为什么能为负呢.但这里事务执行前和执行后,我们的系统没有任何的约束被破坏.一直都是保持正确的状态.


所以,综上.我们可以理解一致性就是:应用系统从一个正确的状态到另一个正确的状态.而ACID就是说事务能够通过AID来保证这个C的过程.C是目的,AID都是手段.


隔离性 isolation


一个事务所做的修改在最终提交以前,对其他事务是不可见的。


还是转账的例子 ,A转账给B,A扣减,B增加。 假设在A扣减完成,B未增加时, 有另外一个事务,统计A账户的余额 ,这个时候看到的应该是A扣减前的金额。


持久性 durability

事务的操作,一旦提交,对于数据库中数据的改变是永久性的,即使数据库发生故障也不能丢失已提交事务所完成的改变。


SQL标准中的4个隔离级别


Read UnCommitted 读取未提交内容


在这个隔离级别,所有事务都可以“看到”未提交事务的执行结果。在这种级别上,可能会产生很多问题,除非用户真的知道自己在做什么,并有很好的理由选择这样做。本隔离级别很少用于实际应用,因为它的性能也不必其他性能好多少,而别的级别还有其他更多的优点。读取未提交数据,也被称为“脏读”


Read Committed 读取提交内容 (oracle等大部分数据库的隔离级别)


大多数数据库系统的默认隔离级别(但是不是MySQL的默认隔离级别),满足了隔离的早先简单定义:一个事务开始时,只能“看见”已经提交事务所做的改变,一个事务从开始到提交前,所做的任何数据改变都是不可见的,除非已经提交。


这种隔离级别被称为“不可重复读”。这意味着用户运行同一个语句两次,看到的结果是不同的。


Repeatable Read 可重复读 (MySQL默认的隔离级别)


MySQL数据库默认的隔离级别。该级别解决了READ UNCOMMITTED隔离级别导致的问题。它保证同一事务的多个实例在并发读取事务时,会“看到同样的”数据行。不过,这会导致另外一个棘手问题“幻读”。InnoDB和Falcon存储引擎通过多版本并发控制机制解决了幻读问题。


Serializable 可串行化


该级别是最高级别的隔离级。它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简而言之,SERIALIZABLE是在每个读的数据行上加锁。在这个级别,可能导致大量的超时Timeout和锁竞争Lock Contention现象,实际应用中很少使用到这个级别,但如果用户的应用为了数据的稳定性,需要强制减少并发的话,也可以选择这种隔离级


Read Committed (不可重复读) VS Repeatable Read (可重复读) VS Read UnCommitted(脏读)


我们以MySQL数据库为例子,对比下这两种事务隔离级别对查询数据的影响


打开两个会话

会话一 :

# 连接mysql
[root@artisan ~]# mysql -u root -p
Enter password:
 ....
 ....
 ....
 ....
# 切到artisan数据库
mysql> use artisan;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> desc t_test;  # 查看t_test表结构
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> select * from t_test; # 查询数据
+----+
| id |
+----+
|  1 |
|  3 |
|  5 |
|  7 |
|  9 |
+----+
5 rows in set (0.00 sec)
mysql> show variables like '%iso%'  # 查看隔离级别 
    -> ;
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation          | REPEATABLE-READ |
+-----------------------+-----------------+
2 rows in set (0.00 sec)
mysql> begin;   # 开启事务 
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t_test where id < 7;
+----+
| id |
+----+
|  1 |
|  3 |
|  5 |
+----+
3 rows in set (0.00 sec)
mysql> 


然后 切到会话二 ,插入几条数据

[root@artisan ~]# mysql -u root -p
Enter password: 
.....
.....
.....
mysql> use artisan;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from t_test;
+----+
| id |
+----+
|  1 |
|  3 |
|  5 |
|  7 |
|  9 |
+----+
5 rows in set (0.00 sec)
mysql> begin ;  # 开启事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t_test values(2);  #插入数据 
Query OK, 1 row affected (0.00 sec)
mysql> commit;   #提交事务
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t_test; 
+----+
| id |
+----+
|  1 |
|  3 |
|  5 |
|  7 |
|  9 |
|  2 |
+----+
6 rows in set (0.00 sec)
mysql> 


重新切回到 会话一,重复执行刚才的SQL (此时,会话一这个事务还未提交,还在事务中)


20200129131906649.png


可以看到,在 **REPEATABLE-READ (可重复读)**这种隔离级别下, 事务一 在事务内,每次查询到的数据都是一样的,而且也无法读取到事务二已经提交的数据。


这也就理解了为啥叫 “可重复读” : 因为 它保证同一事务的多个实例在并发读取事务时,会“看到同样的”数据行 。


那 这种事务级别潜在的问题是啥呢 ? --------> 会导致另外一个棘手问题“幻读”。InnoDB和Falcon存储引擎通过多版本并发控制机制解决了幻读问题。


幻读是事务非独立执行时发生的一种现象,例如事务T1批量对一个表中某一列列值为1的数据修改为2的变更,但是在这时,事务T2对这张表插入了一条列值为1的数据,并完成提交。此时,如果事务T1查看刚刚完成操作的数据,发现还有一条列值为1的数据没有进行修改,而这条数据其实是T2刚刚提交插入的,这就是幻读


我们修改下 MySQL的隔离级别为 read-committed

我们把会话一的事务先提交了,然后修改下隔离级别

mysql> commit ;
Query OK, 0 rows affected (0.00 sec)
mysql> set session tx_isolation='read-committed';   # 设置隔离级别
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show variables like '%iso%'   
    -> ;   #查看隔离级别
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
| tx_isolation          | READ-COMMITTED |
+-----------------------+----------------+
2 rows in set (0.01 sec)
mysql> 


然后切到会话二


20200129135932408.png

回切到会话一,重新查询

20200129140033352.png


所以 READ-COMMITTED 又被称为不可重复读 ,因为对于数据库中的某个数据,一个事务执行过程中多次查询返回不同查询结果,这就是在事务执行过程中,数据被其他事务提交修改了。 每次查询都有可能查询到其他事务修改过的数据,所以称为 不可重复读。


不可重复读 VS 脏读 VS 可重复读


不可重复读同脏读的区别在于,脏读是一个事务读取了另一未完成的事务执行过程中的数据,而不可重复读是一个事务执行过程中,另一事务提交并修改了当前事务正在读取的数据。

幻读和不可重复读都是读取了另一条已经提交的事务(这点同脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。


总结下不同隔离级别的缺点


20200129134359914.png


隔离行由低到高 : Read UnCommitted —> Read Committed —> Repeatable Read -----> Serializable


并发性由高到低 : Read UnCommitted —> Read Committed —> Repeatable Read -----> Serializable


MySQL修改隔离级别的方法

全局修改需要修改MySql的全局文件my.cnf (linux操作系统)

#可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.
[mysqld]
transaction-isolation = REPEATABLE-READ

修改当前会话Session的隔离级

mysql> set session tx_isolation = 'REPEATABLE-READ';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show variables like '%iso%'
    -> ;
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation          | REPEATABLE-READ |
+-----------------------+-----------------+
2 rows in set (0.00 sec)
mysql> 


MySql 的autoCommit设置

另外MySql中有autoCommit参数,默认为on,也就是开启状态

mysql>  show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)
mysql> 


如果需要关闭autocommit,我们可以使用下面语句设置

mysql> set autocommit=0;


0就是OFF,1就是ON。设置为OFF之后,则用户执行语句之后,将一直处于一个事务中,直到执行commit或者rollback,才会结束当前事务,重新开始新的事务。


大事务的定义


定义: 运行时间比较长,操作数据比较多的事务


大事务的潜在风险

  • 锁定太多的数据,容易造成阻塞和超时 。
  • 回滚时间耗时较长,回滚过程中也容易阻塞
  • 容易造成主从延迟

如何处理大事务

  • 避免一次处理太多数据
  • 移除事务中不必要的 select操作

搞定MySQL


https://artisan.blog.csdn.net/article/details/104103852?spm=1001.2014.3001.5502


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
存储 SQL 关系型数据库
Mysql高可用架构方案
本文阐述了Mysql高可用架构方案,介绍了 主从模式,MHA模式,MMM模式,MGR模式 方案的实现方式,没有哪个方案是完美的,开发人员在选择何种方案应用到项目中也没有标准答案,合适的才是最好的。
270 3
Mysql高可用架构方案
|
1天前
|
监控 关系型数据库 MySQL
Aurora MySQL负载突增应对策略与优化方案
通过以上策略,企业可以有效应对 Aurora MySQL 的负载突增,确保数据库在高负载情况下依然保持高性能和稳定性。这些优化方案涵盖了从架构设计到具体配置和监控的各个方面,能够全面提升数据库的响应速度和处理能力。在实际应用中,应根据具体的业务需求和负载特征,灵活调整和应用这些优化策略。
36 22
|
2天前
|
Java 关系型数据库 MySQL
MySQL 分库分表方案
本文总结了数据库分库分表的相关概念和实践,针对单张表数据量过大及增长迅速的问题,介绍了垂直和水平切分的方式及其适用场景。文章分析了分库分表后可能面临的事务支持、多库结果集合并、跨库join等问题,并列举了几种常见的开源分库分表中间件。最后强调了不建议水平分库分表的原因,帮助读者在规划时规避潜在问题。
36 19
|
22天前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
MySQL事务日志-Undo Log工作原理分析
|
1月前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
1月前
|
SQL 安全 关系型数据库
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
事务是MySQL中一组不可分割的操作集合,确保所有操作要么全部成功,要么全部失败。本文利用SQL演示并总结了事务操作、事务四大特性、并发事务问题、事务隔离级别。
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
|
1月前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
1月前
|
SQL 关系型数据库 MySQL
MySQL进阶突击系列(04)事务隔离级别、AICD、CAP、BASE原则一直搞不懂? | 看这篇就够了
本文详细介绍了数据库事务的四大特性(AICD原则),包括原子性、隔离性、一致性和持久性,并深入探讨了事务并发问题与隔离级别。同时,文章还讲解了分布式系统中的CAP理论及其不可能三角关系,以及BASE原则在分布式系统设计中的应用。通过具体案例和图解,帮助读者理解事务处理的核心概念和最佳实践,为应对相关技术面试提供了全面的知识准备。
|
2月前
|
关系型数据库 MySQL
mysql事务特性
原子性:一个事务内的操作统一成功或失败 一致性:事务前后的数据总量不变 隔离性:事务与事务之间相互不影响 持久性:事务一旦提交发生的改变不可逆
|
2月前
|
存储 缓存 负载均衡
mysql的性能优化
在数据库设计中,应选择合适的存储引擎(如MyISAM或InnoDB)、字段类型(如char、varchar、tinyint),并遵循范式(1NF、2NF、3NF)。功能上,可以通过索引优化、缓存和分库分表来提升性能。架构上,采用主从复制、读写分离和负载均衡可进一步提高系统稳定性和扩展性。
51 9

热门文章

最新文章

推荐镜像

更多