mysql事务

事务的四大特性

ACID:原子性 一致性 隔离性 持久性 

假如A向B转账500元

原子性表示:A账户减少500元和B账户增加500元必须同时发生或同时失败

一致性表示:A的余额必须减少500 B的余额必须增加五百

隔离性表示:在A向B转账500的过程中 不能被其他事务所影响

持久性表示:在A向B转账500元这个事务提交之后 数据要持久化(落盘操作)

InnoDB引擎通过什么技术来保证事务的四大特性

原子性:通过undo log(回滚)来实现原子性

持久性:通过redo log来实现原子性

隔离性:通过MVVC(多版本并发控制)和锁机制来保证隔离性

一致性:通过原子性 持久性 隔离性来保证一致性

并发事务带来的问题

脏读:一个事务读到了另一个另一个未提交事务修改的数据。

假设还是上面的例子 A向B转账500元 事务a在执行这个转账操作时还没有进行提交 此时事务b来读取B的余额时 会读到余额+500 但如果此时事务a进行回滚 然后再提交的话 B的余额是没有变化的 此时就发生了脏读现象

不可重复读:在一个事务中 对同一数据进行了两次读操作 这两次读到的数据不一致

还是上面的例子 A向B转账500元 此时事务a查了一下A余额 发现少了500元 这时候有另一个事务B 对A的余额进行了一次+600元操作 此时事务a在查A的余额 发现多了100元 此时就发生了不可重复读现象

幻读:在一个事务内 多次查询符合某一条件的记录数量 如果出现前后两次读到的记录数量不一样

假设余额大于100账户的数量是10个 事务a第一次查询时是10 此时事务b给某一个余额小于100的账户进行了汇款101元的操作 此时事务a再次查询就变成了11个

怎么解决并发事务带来的问题

给事务设置隔离级别

事务的隔离级别

读未提交:在事务还没提交时 该事务的操作就可以被其他事务看见(解决不了任何问题)

读已提交:只有事务提交之后 该事务的操作才可以被其他事务看见(解决脏读)

在读已提交这个隔离级别中 每一次语句执行前都会进行一次ReadView ReadView是一个数据的快照 读已提交可以不加事务

可重复读:一个事务执行过程中看到的数据 和他刚开始执行时看见的数据是一致的(解决不了幻读 mysql默认的隔离级别)

在可重复读这个隔离级别中 事务在刚开始执行时会进行一个ReadView 在事务的执行过程中都会使用刚开始的这个数据快照中的数据 正因如此 可能会导致数据是旧数据的情况 解决方案是乐观锁或悲观锁 乐观锁就是新增一个版本号字段 当对旧数据进行操作时会加上版本 而悲观锁则是 只有前一个事务提交了之后才能执行该事务 可重复读隔离级别如果只有一条语句可以不加事务 两条或两条以上必须加事务

串行化:加上读写锁 当发生读写冲突时 后访问的事务必须等前面的事务提交后才能执行(解决所有问题 但性能较差)

redo log和undo log的区别

redo log 记录的是物理页的变化 当服务宕机时可以快速恢复数据

undo log记录的是操作的反操作 是逻辑日志 当事务回滚时 会调用undo log的逆操作

redo log保证了持久性 undo log保证了原子性

事务的隔离性是如何保证的(MVVC)

mvvc是多版本并发控制 可以保证读写分离 类似从copy on write 当进行写操作是 会有一个副本也就是版本 写操作会在这个副本里进行 读操作还是读旧的版本 mvvc由三个部分 第一部分是隐藏字段 在mysql中每张表都会有隐藏字段 一个是事务id 记录每一次事务的id 是自增的 还有一个是回滚指针 指向上一个版本 第二部分是undo log记录的是回滚日志 存储老版本数据 内部会形成一条版本链 roll_point指针 指向上一个版本 形成一个链条 第三部分是ReadView 是一个数据快照 会根据隔离级别的不同 产生不同的快照数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值