【MySQL】之性能优化-事务+锁+MVCC

事务

1、概念

**数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作; 事务是一组不可再分割的操作集合(工作逻辑单元);**是什么
**update user_account set balance = balance - 1000 where userID = 3;
update user_account set balance = balance +1000 where userID = 1;–****场景(转账)


mysql中如何开启事务:
begin / start transaction –
**手工
**commit / rollback – **事务提交或回滚
set session autocommit = on/off; – **设定事务是否自动开启

**JDBC 编程:
connection.setAutoCommit(boolean);–根据参数开启事务


**Spring 事务AOP编程: **
**expression=execution(com.gpedu.dao.
.
(…))–**先开启再进行提交


2、事务特性ACID

原子性(Atomicity)
最小的工作单元,整个工作单元要么一起提交成功,要么全部失败回滚
一致性(Consistency)
事务中操作的数据及状态改变是一致的,即写入资料的结果必须完全符合预设的规则,
不会因为出现系统意外等原因导致状态的不一致
隔离性(Isolation)
一个事务所操作的数据在提交之前,对其他事务的可见性设定(一般设定为不可见)
持久性(Durability)
事务所做的修改就会永久保存,不会因为系统意外导致数据的丢失

3、事务并发的问题

脏读,不可重复读,幻读。

4、事务隔离级别四种

**Read Uncommitted(未提交读) --**未解决并发问题
****Read Committed(提交读) --**解决脏读问题
****Repeatable Read (可重复读) --**解决不可重复读问题
****Serializable(串行化) --**解决所有问题




屏幕快照 2019-05-25 上午9.36.48.png

1、是什么

锁是用于管理不同事务对共享资源的并发访问。

2、有什么

行锁和表锁–InnoDB支持,表锁是将所有的行锁住。

行锁锁住的是索引

InnoDB的行锁是通过给索引加锁来实现的。
只有通过索引条件进行数据检索,InnoDB才使用行级锁,否则,InnoDB 将使用表锁(锁住索引的所有记录)
表锁:lock tables xx read/write;

3、行锁和表锁的区别

锁定粒度:表锁 > 行锁
加锁效率:表锁 > 行锁
冲突概率:表锁 > 行锁
并发性能:表锁 < 行锁

4、锁类型

4.1共享锁(S)

共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改;
select * from users WHERE id=1 LOCK IN SHARE MODE; commit/rollback

4.2排他锁(X)

只有该获取了排他锁的事务是可以对数据行进行读取和修改,(其他事务要读取数据可来自于快照)Undo日志。
delete / update / insert 默认加上X锁
SELECT * FROM table_name WHERE … FOR UPDATE commit/rollback

4.3意向共享锁(IS)

4.4意向排他锁(IX)

意向锁**(IS****、IX)InnoDB数据操作之前自动加的,不需要用户干预
意义:
当事务想去进行锁表时,可以先判断意向锁是否存在,存在时则可快速返回该表不能 启用表锁

4.5自增锁(AUTO-INC)

针对自增列自增长的一个特殊的表级别锁
show variables like ‘innodb_autoinc_lock_mode’;
默认取值1,代表连续,事务未提交ID永久丢失

5、行锁的算法

5.1临建锁(Next-key)–是InnoDB默认的行锁算法–解决幻读

当sql执行按照索引进行数据的检索时,查询条件为范围查找(between and、<、>等)并有数 据命中则此时SQL语句加上的锁为Next-key locks,锁住索引的记录+区间(左开右闭)。

5.2间隙锁(Gap)–只在**RR(可重复读)**事务隔离级别存在

当sql执行按照索引进行数据的检索时,查询条件的数据不存在,这时SQL语句加上的锁即为Gap locks,锁住索引不存在的区间(左开右开)。

5.3记录锁(Record)

当sql执行按照唯一性(Primary key、Unique key)索引进行数据的检索时,查询条件等值匹 配且查询的数据是存在,这时SQL语句加上的锁即为记录锁Record locks,锁住具体的索引项。

6、利用锁解决事务并发问题

6.1脏读

屏幕快照 2019-05-25 上午11.01.44.png

6.2不可重复读

屏幕快照 2019-05-25 上午11.03.36.png

6.3幻读

屏幕快照 2019-05-25 上午11.04.26.png

7、死锁

![屏幕快照 2019-05-25 上午11.05.58.png](https://cdn.nlark.com/yuque/0/2019/png/143030/1558753563144-c022a233-363e-431b-a2b2-6e27a645633e.png#align=left&display=inline&height=200&name=%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202019-05-25%20%E4%B8%8A%E5%8D%8811.05.58.png&originHeight=569&originWidth=951&size=130399&status=done&width=335)

避免死锁
屏幕快照 2019-05-25 上午11.07.44.png
**
屏幕快照 2019-05-25 上午11.09.06.png

MVCC

1、是什么

Multiversion concurrency control (多版本并发控制)
并发访问(读或写)数据库时,对正在事务内处理的数据做多版本的管理。以达到用来避免写操作的堵塞,从而引发读操作的并发问题。

2、MVCC流程

2.1删除

        ![屏幕快照 2019-05-25 上午11.15.59.png](https://cdn.nlark.com/yuque/0/2019/png/143030/1558754165455-4237a1c1-2ec7-4984-8bbb-4df4596970cd.png#align=left&display=inline&height=272&name=%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202019-05-25%20%E4%B8%8A%E5%8D%8811.15.59.png&originHeight=851&originWidth=1401&size=317984&status=done&width=448)<br />            表中有隐藏列数据行的版本号、删除版本号等等。<br />**开启一个事务将拿到系统的事务ID,删除数据行时将此行的删除版本号填入事务ID。**<br />**

2.2修改

屏幕快照 2019-05-25 上午11.21.22.png
当前事务ID为33
当修改数据行时,先将此行数据复制一行,数据行的版本号为33,元数据行删除版本号为33。
**

2.3查询

屏幕快照 2019-05-25 上午11.27.57.png
查数据规则【1&&2–并且关系】
1、数据行的版本号<=当前事务ID
–确保查询出事务之前的数据和自己插入或修改过的数据
2、删除版本号要么为NULL,要么大于当前事务ID
–确保查询****比当前事务ID大的事务正在修改或删除数据的之前数据
注意:【1&&2–并且关系】
**
解决【先事务读后事务写再读】的并发引起的脏读
但【先事务写后事务读】然并卵–脏读问题并没有解决——>用一下Undo日志解决的。


3、Undo log

是什么

事务开始之前,在操作任何数据之前**,**首先将需操作的数据备份到一个地方。

干了什么

UndoLog是为了实现事务的原子性而出现的产物
在事务处理过程中出现了错误或ROLLBACDK语句,mysql利用Undo Log中的备份将数据恢复到事务开始之前的状态。
UndoLogMysql innodb存储引擎中用来实现多版本并发控制
事务未提交之前,Undo保存了未提交之前的版本数据,作为数据旧版本快照供
其他并发事务进行快照读-----哈哈哈!解决的【先事务写后事务读】产生脏读问题。

屏幕快照 2019-05-25 下午3.07.14.png

当前读:
读取的最新版本的数据,所有通过锁机制来读取的数据都是当前读。
快照读:不带锁的select是快照读。innodb快照读,数据的读取将由 **cache(原本数据) + undo(事务修改过的数据) **两部分组成。

4、Redo log

是什么

事务中操作的数据**,将最新的数据备份到Redo log。
不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入
redo **中。具体的落盘策略可以进行配置

干了什么

RedoLog是为了实现事务的持久性而出现的产物
防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。

屏幕快照 2019-05-25 下午3.15.20.png

指定Redolog记录在{datadir}/ib_logfile1&ib_logfile2 可通过innodb_log_group_home_dir配置指定 目录存储。

一旦事务成功提交且数据持久化落盘之后,此时Redo log中的对应事务数据记录就失去了意义,所 以Redo log的写入是日志文件循环写入的**----这个地方不懂?
指定Redo log日志文件组中的数量 innodb_log_files_in_group 默认为2
指定Redo log每一个日志文件最大存储量innodb_log_file_size 默认48M
指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默认16M


Redo buffer持久化Redo log的策略,Innodb_flush_log_at_trx_commit:
----到Redo buffer到Redo Log持久化**
取值 0 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丢失一秒内
的事务数据]
取值 1 默认值,每次事务提交执行Redo buffer --> Redo log OS cache -->flush cache to disk
[最安全,性能最差的方式]
取值 2 每次事务提交执行Redo buffer --> Redo log OS cache 再每一秒执行 ->flush cache to disk操作

配置优化

https://www.cnblogs.com/wyy123/p/6092976.html 常见配置的帖子

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值