性能调优专题-mysql事务原理与优化最佳实践

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

事务四大特性:

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

undo log:就是比如你是插入操作,日志里面就是删除此条数据,就是回滚时方便,保证原子性。

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

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

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

Innodb引擎中,定义了四种隔离级别供我们使用,级别越高事务隔离性越好,但性能就越低,而隔离性是由mysql的各种锁以及MVCC机制来实现的。

- read uncommit(读未提交):脏读:事务A读到了事务B已经修改但未提交的数据。

设置当前session的隔离级别:

begin;开启事务

rollback; #回滚

commit;提交事务

- read commit(读已提交):不可重复读

不可重复读:事务A内部的相同查询语句在不同时刻读出的结果不一致,受到了其他事务的影响。

底层实现原理:

- repeatable read(可重复读): 幻读。

别的事务的提交不会影响我自己事务的查询结果。

只要事务开启之后,有一条查询语句,就可认为数据库中所有的记录,包括所有表,都有一个状态,之后的查询语句查到都是第一次查询语句的记录(相当于一次快照数据)。但是如果对一条数据进行了修改,那之后查询这条数据就是最新的数据,而其他没修改的还是读的第一次快照数据。

新开启一个事务肯定查的是数据库中的最新数据。

底层实现原理:

rc:读已提交,rr:可重复读,两边在读,中间在写入,实现了读写并行执行,就是mvcc起作用。

其中trx_id是事务id,roll_pointer是回滚指针,指向undo log记录,比如你插入一条数据,指针指向的就是删除这条记录的undo log。

roll_pointer后来指的是上一版本的数据,每一条记录当有修改时都会有这样数据版本链。

幻读: 事务A读取到了事务B提交的新增数据。(注意是新增数据)

可重复读+间隙锁可以有效解决幻读现象。

oracle默认隔离级别是read commit, mysql默认隔离级别是repeatable read可重复读。

更新丢失或脏写?

上面三种读的是其他事务的数据或者本事务的快照版本数据,不是数据库的真实数据,然后java将这些数据重新计算后写入数据库就导致有bug。

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

怎么解决脏写问题?

1. 悲观锁:

2. 乐观锁:

增加一个字段version,每次修改数据这个版本号加1:

- serializable(串行):解决上面所有问题,包括脏写。幻读,脏读。

同一条数据读和写只能串行执行,a事务在执行读时,b事务对同一事务就不能执行更改操作

串行化的实现原理:

在select语句mysql底层会在后面加上lock in share mode; 读锁与写锁是互斥的,写锁与写锁之间也是互斥的。

读锁(共享锁,S锁):select... lock in share mode;

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

写锁(排它锁,X锁):select ... for update;

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

MVCC(multi-version concurrency control)多版本并发控制,就可以做到读写不阻塞,且避免了类似脏读这样的问题,主要通过undo日志链来实现

select操作是快照读(历史版本)

insert, update和delete是当前读(当前版本)

read commit(读已提交),语句级快照

repeatable read(可重复读),事务级快照

面试题:只有查询操作方法,没有修改方法需要使用事务吗?

如果只有一个select语句,那就不需要加事务

如果有多个select语句,需要加读锁readonly=true, (写锁是readonly=false)

当隔离级别是rr时,需要注意在同一时间维度内,可重复读处理是同一时期的数据,(比如报表处理数据)

传统公司用的大部分是rr,同一时间维度,oa系统,erp系统,这种查询同一时间的数据,如果不对重新查询

互联网公司用的是rc,这种性能更高,

持久性:

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

磁盘顺序写(性能很高):写磁盘文件(ibd)是无法支持磁盘顺序写的,写redo日志文件是可以支持磁盘顺序写的。就是对应redo日志文件,比如十个sql,操作不同的数据表,这些表在磁盘文件中是不同的十个文件,而在redo日志文件是一个就可以追加日志文件编写。实现了磁盘顺序写。

疑问:redo日志文件中有很多记录,关联多张表,在写入磁盘文件时是怎么关联的?

事务的优化:

针对倒数第三条:更新放在事务靠后的位置:

分析:insert和update:两种update放在后面因为update操作是已经存在的数据,可能有别的事务也在操作这条数据,就会等待他提交完才能操作,insert操作的新数据,其他事务没有这条数据就无法操作。

针对最后一条:利用代码来实现回滚,对性能要求很高。适用于业务比较简单的

疑问:

mysql什么时候会用到事务?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值