Mysql:事务

一、概念和特性

1、何为事务

  • 事务是指逻辑上的一组操作,组成这组操作的各个单元要么全部成功,要么全都失败

2、事务的四大特性(ACID)

  • 原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
  • 一致性(Consistency):事务执行的结果必须使数据库从一个一致性状态到另一个一致性状态
  • 隔离性(Isolation):多个并发用户访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离,隔离性由隔离级别保障
  • 持久性(Durability):一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

3、事务并发问题

  • 脏读:一个事务读到了另一个事务未提交的数据
  • 不可重复读:一个事务读到了另一个事务已经提交的数据。引发事务中的多次查询结果不一致
  • 幻读:一个事务读到了另一个事务已经插入的数据。导致事务中多次查询的结果不一致

4、事务隔离级别

  • read uncommitted 读未提交:一个事务读到另一个事务没有提交的数据。产生问题:脏读、不可重复读、幻读
  • read committed 读已提交:一个事务读到另一个事务已经提交的数据。产生问题:不可重复度、幻读
  • repeatable read 可重复读:在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。
  • serializable 串行化:同时只能执行一个事务。

二、事务是如何实现的?

<一>、原子性(undo log)

  • 原子性的实现主要是靠数据库中的回滚机制,回滚则是通过undo log实现的,所以undo log也称为回滚日志
  • undo log能够保证事务在回滚时,能够撤销所有执行成功的Sql
  • undo log是逻辑日志,记录的是sql相关的信息,比如在执行insert时,undo log记录的是delete语句;反之执行delete语句的时候,undo log保留的是insert

<二>、持久性(redo log)

1、redo log

  • Mysql最终的数据都是存在磁盘中的,但对mysql的操作如果都是读写磁盘的话,就太慢了,所以mysql提供了buffer pool,buffer pool包含了磁盘中部分数据页的映射
  • 从mysql读取数据时,会先从buffer pool读取数据,如果没有,则从磁盘中读到buffer pool中
  • 当向mysql写入数据时,会先写到buffer pool中,buffer pool更新的数据会定期刷新到磁盘中(此过程称为刷脏),如果在刷脏的过程中,mysql突然出现宕机,就会导致出现数据丢失
  • redo log就是解决这个问题,采用预写的方式记录日志,先记录日志,再刷数据到buffer pool,这样在mysql出现宕机时,可以从磁盘中读取redo log进行数据的恢复,从而保证了数据的持久性
  • redo log最主要的作用就是用于数据库异常宕机的恢复工作,假如数据库永远不会发生异常宕机,那么根本不需要redo log,因为InnoDB有线程不断的把做把脏页刷新到磁盘的工作,数据库如果一直不宕机,就不会有问题

2、binlog
与redo log常用来比较的是binlog,binlog主要是用来做备份的,下面是它们的一些区别

  • redo log是innoDB存储引擎特有的;binlog是server层,属于共有的
  • redo log是物理日志,记录某个数据页的修改;binlog是逻辑日志(记录DML语句)
  • redo log是一个环,循环写;binlog是追加写,不会覆盖以前的日志
  • redo log用于异常重启;binlog用于备份
  • binlog以事件的形式记录了所有的DML和DDL语句(因为它记录的是操作而不是数据值,属于逻辑日志),可以用来做主从复制和数据恢复

<三>、隔离性(mvcc + lock)

  • 原子性和持久性都是基于单个事务内部的措施,而隔离性是多个事务相互隔离、互不影响的特性
  • 事务间的写操作主要是通过锁来实现的,但如果读也加锁的话就会极大地降低并发所以产生了MVCC机制

1、MVCC

  • 全称:MutilVersion concurrency control,多版本并发控制,核心思想是读不加锁,读写不冲突
  • MVCC实现原理是数据快照,不同事务访问不同版本的数据快照。

首先不同版本的数据快照是由undo log实现的

  • Innodb下的表有默认字段和可见字段,默认字段有隐藏的列,默认字段最关键的两个列,一个保存了行的事务id,一个保存了行的回滚指针,如下所示
insert into user (id,name,age,sex)  values (1,'李世民','2000','男');
trx_idroll_pointeridnameagesex
rowid1NULL1李世民2000
执行update语句
update user set name = '武则天',sex = '女' where id = 1;
  • –最新版本
trx_idroll_pointeridnameagesex
rowid2aaaa1武则天2000
  • –上个版本,上面那个版本的回滚指针就是指的下面这条的地址
trx_idroll_pointeridnameagesex
rowid1NULL1李世民2000

其次,当前事务能看到哪个版本的数据快照是由readview实现的

  • 对于读未提交隔离级别来说,直接读取最新版本记录就好了,不需要读取快照版本
  • 对于串行化隔离级别来说,读写都加锁,也不需要快照版本
  • 对于读已提交和可重复读隔离级别来说,就需要undo log中的版本链

2、MVCC中的读操作

  • MVCC中的读不加锁是相对的,快照读不会加锁,同时还会根据隔离级别来判断会不会加锁,串行化读写都会加锁

快照读:普通的select操作

select * from table where ?

快照读就是通过MVCC实现的,访问可见版本的数据

当前读:特殊的读操作,插入/更新/删除操作,需要加锁

update table set ? where ?;
insert into table values ();
delete table where ?;
select * from table where ? lock in share mode;
select * from table where ? for update;

为什么当前读需要加锁?
数据库中的insert/update/delete操作都是伴随着读取数据的,且必须是当前最新数据,所以称为当前读
当一条update语句发送给Mysql后,Mysql server会根据where条件,读取第一条满足条件的记录,然后innodb引擎调用读取数据接口,返回这条记录,并加锁,会再发起一条update请求,更新这条记录,因此update操作内部包含了一个当前读,同理,delete操作也是如此,insert稍微有些不同,简单来说,insert的时候会触发unique key的冲突检查,也会进行一个当前读

<四>、一致性(constraint)

  • 一致性主要是指事务前后数据的完整性没有被破坏
  • 可以通过主键、外键、唯一约束、非空约束等来完成,如果有事务破坏这些约束,就不可以进行提交
  • 此外原子性、持久性、一致性都是为了保证最终的一致性
  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
MySQL数据库事务是一组数据库操作命令的集合,这些命令要么全部执行成功,要么全部回滚。事务具有以下特性: 1. 原子性(Atomicity):事务中的所有操作要么全部成功执行,要么全部回滚,不会出现部分执行的情况。 2. 一致性(Consistency):事务执行前后,数据库的状态保持一致,即满足预设的约束条件。 3. 隔离性(Isolation):并发执行的事务之间相互隔离,每个事务都感觉不到其他事务的存在。 4. 持久性(Durability):事务一旦提交,其结果将永久保存在数据库中,即使系统发生故障也不会丢失。 在MySQL中,可以使用以下语句来控制事务的开始、提交和回滚: 1. 开始事务:`START TRANSACTION;` 或 `BEGIN;` 2. 提交事务:`COMMIT;` 3. 回滚事务:`ROLLBACK;` 以下是一个示例,演示了如何在MySQL中使用事务: ```sql -- 开始事务 START TRANSACTION; -- 执行一系列数据库操作命令 INSERT INTO table1 (column1, column2) VALUES ('value1', 'value2'); UPDATE table2 SET column1 = 'new_value' WHERE condition; DELETE FROM table3 WHERE condition; -- 提交事务 COMMIT; ``` 如果在事务执行过程中发生了错误,可以使用回滚操作将事务恢复到开始之前的状态: ```sql -- 开始事务 START TRANSACTION; -- 执行一系列数据库操作命令 INSERT INTO table1 (column1, column2) VALUES ('value1', 'value2'); UPDATE table2 SET column1 = 'new_value' WHERE condition; DELETE FROM table3 WHERE condition; -- 发生错误,回滚事务 ROLLBACK; ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱夜来香A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值