Mysql事务原理

事务:一组操作要么全部成功,要么全部失败,目的是为了保证数据一致性

事务的四大特性

原子性:当前事务的操作要么同时成功,要么同时失败。原子性由undo log日志来实现

一致性:使用事务的最终目的,由其他三个特性以及业务代码正确逻辑来实现

隔离性:在事务并发执行时,他们内部的操作不能互相干扰,隔离性由MySQL的各种锁以及MVCC机制来实现

持久性:一旦提交了事务,它对数据库的改变就应该是永久性的。持久性由redo log日志来实现

InnoDB引擎中,定义了四种隔离级别

读未提交:会出现脏读  即 事务A读到了事务B已经修改但尚未提交的数据

读已提交:会出现不可重复读  即 事务A内部的相同查询语句在不同时刻读出的结果不一致

可重复读:会出现幻读   即  事务A读取到了事务B提交的新增数据(不管其他线程怎么修改数据,在当前事务中查询到的数据都是最早之前的数据即快照且不会改变)

串行:解决上面所有问题,包括脏写

脏写: 当两个或多个事务选择同一行数据修改,有可能发生更新丢失问题,即最后的更新覆盖了由其他事务所做的更新

RR可重复读

Select操作是快照读(历史数据)

insert、update、delete是当前读(当前数据)

读已提交,语句级快照

可重复读,事务级快照

串行是怎么解决脏写问题的?

读锁:select …. lock in share mode

共享锁,读锁是共享的,多个事务可以同时读取同一个资源,但不允许其他事务修改

写锁:

排他锁,写锁是排他的,会阻塞其他的写锁和读锁,update、delete、insert都会加锁

隔离级别是串行的话,执行读操作会加上读锁,读锁和写锁是互斥的

那么如何让最低级别的隔离达到最高的隔离级别串行的效果呢?

在每个读操作上加上读锁

查询操作方法需要使用事务吗?

需要看事务隔离级别和业务需求

如果有多条select查询语句,在rr可重复读隔离级别下,与其他隔离级别查询到的数据可能是不相等的,需要在读操作上也加事务

rr可重复读的数据都是同一时间维度的,在其他隔离级别如RC读已提交是不需要使用事务的

如何选择隔离级别

是否同一时间维度  选择 rr  可重复读

对并发要求高的话  选择 rc 读已提交

顺序写

Redo日志在后台就一个,十个sql去执行,每个sql针对的表都不一样,redo日志事先在内存中开辟空间,写redo日志的时候是在文件当中按照顺序写

磁盘文件不能顺序写,因为不同的表有不同的ibd文件,这十张表可能落在磁盘的不同地方

事务优化实践原则

1、在RR隔离级别下,将查询等数据准备操作放到事务外

2、事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久

3、事务中避免一次性处理太多数据,可以拆分成多个事务分次处理

4、更新等涉及加锁的操作尽可能放在事务靠后的位置

5、能异步处理的尽量异步处理

6、应用侧(业务代码)保证数据一致性,非事务执行

你可能感兴趣的:(mysql,数据库)