Mysql-事务(一)

1.事务概述

事务可以理解成一组sql语句的集合,mysql中,存储引擎一般使用innodb,因为innodb支持事务,而且事务完全符合ACID的特性,ACID是下面四大特性的首字母缩写:

    A:atomicity(原子性)

         整个事务中的所有操作要么全部执行成功,要么全部执行失败后回滚到最初状态。        

    C:consistency(一致性)

         数据库总是从一个一致性状态转为另一个一致性状态。

    I:isolation(隔离性)

         一个事务在提交之前所做出的操作是否能为其它事务可见,由于不同的场景需求不同,所以针对隔离性来说,有不同的隔离级别。

    D:durability(持久性)  

         事务一旦提交,事务所做出的修改将会永久保存,此时即使数据库崩溃,修改的数据也不会丢失。

mysql的事务是通过事务日志实现的,事务日志可以细分为redo log和undo log;

2.redo log概述

   mysql会将事务中的sql语句涉及到的所有数据操作先记录到redo log中,然后再将操作从redo log中同步到对应数据文件中(此处假设事务操作的数据量并非巨大),换句话说,在事务执行提交成功以前,在修改对应的数据文件中的记录之前,一定要保证对应的所有修改操作已经记录到了redo log中,假设事务中的sql语句涉及到60条记录的修改,那么在修改这60条记录之前,要先将这60条修改操作记录到redo log中,当这60条操作记录到redo log中以后,再从redo log中一条一条同步到数据文件的对应记录中。所以,即使数据文件中的数据被修改到一半时被打断(比如停电),那么也能依靠redo log中的日志将剩余的部分操作再次同步到对应的数据文件中。

 使用redo log能够实现ACID中的A,也就是原子性,即事务中的所有sql被当做一个执行单元。

redo log其实由两部分组成:redo log buffer(重做日志缓冲)和redo log file(重做日志文件)。

重做日志先被写入到redo log buffer中,虽然内存的速度极快,但是无法满足持久性的需求,因为内存中的数据时易失的。为了满足持久性,需要将redo log buffer中的日志写入到redo log file中,相当于从内存中同步到磁盘上,所以磁盘的性能会影响事务的性能。由于redo log file是磁盘上一段连续的空间,所以写速度还是比较快的,当操作记录被记录到redo log file中以后,再从redo log file中将操作同步到数据文件中。

虽然,我们应该实时将redo log buffer中的数据写入到redo log file中以保证数据的安全性,但是这样会极大的降低性能,我们可以通过设置innodb_flush_log_at_trx_commit参数来修改从redo log buffer同步到redo log file的策略,但是这样做,则会丧失持久性,有可能会丢失数据,具体使用怎样的刷写策略,还需要根据实际情况自己权衡。

redo log是物理日志,具有幂等性。

3.undo log概述

可以把undo log理解成数据被修改前的备份。如果事务进行了一半,有一条sql没有执行成功,那么数据库可以根据undo log进行撤销,将所有修改过得数据从逻辑上恢复到修改之前的样子,注意,是逻辑上还原成原来的样子,比如,之前insert了1000条数据,那么就delete它们,如果delete了2000条,就insert它们,如果update了500条数据,就再次根据undo log去update它们,所以,undo log是逻辑日志,与redo log记录的页操作物理日志不同。

 

4.log group概述

log group为redo log组,一个重做日志组(log group)中有多个重做日志文件(redo log file),当日志组中的第一个log file被写满,则会开始将redo log写入日志组中的下一个日志文件中,以此类推,当日志组中的所有redo log file都被写满了,则将redo log再写入第一个redo log file中,覆盖原来的redo log,以便新的redo log被写入。

如果重做日志所在的设备崩溃了,那么redo log将有可能丢失,这样就无法保证redo log在任何时候都是可用的了,所以,log group还支持日志组镜像,为了保险起见,我们应该将log group放在有冗余能力的设备上,比如raid1。

5. binlog

redo log存储于重做日志文件中,undo log则不同,undo存放在数据库内部的特殊段中,这个段被称为undo段(undo segment),undo段位于共享表空间中。

mysql中,innodb存储引擎是支持事务的,myisam存储引擎是不支持事务的,不管是redo log或者undo log都是innodb的产物,或者说是innodb存储引擎层面的产物,而在mysql中还有另一种重要的日志,二进制日志,也就是平常所说的binlog,它是建立mysql主从复制环境时所必须的日志,但是binlog并不是innodb存储引擎层面的产物,而是整个mysql数据层面的产物,换句话说,binlog不止针对于innodb,mysql数据库中的任何存储引擎对于数据库的更改都会产生二进制日志(binlog)。

innodb的redo log记录的时物理格式的日志,记录了对页的操作,而binlog记录的是逻辑日志,记录的是对应的SQL。

redo log与bin log写入磁盘的实际也不同,innodb的redo log在事务进行时会不断的写入redo log file,binlog只在事务提交完成后进行一次磁盘写入。

6. 事务控制语句

在mysql中,默认情况下,我们每执行一条sql语句,mysql都会把这条sql当作一个单语句事务进行提交,而且默认是自动提交的,我们可以使用如下语句查看mysql是否开启了自动提交功能,下面分别查看全局与当前会话是否开启了自动提交功能。

    > show global variables like 'autocommit%';

           

    > show session variables like 'autocommit%';

          

如上图所示,默认情况下,autocommit是开启的,表示事务都是自动提交,执行sql语句以后会立即自动执行commit操作。

如果想要手动的控制提交操作,则需要显性的开启一个事务,或者禁用自动提交功能(或),进行手动提交。

   > set session autocommit = 0;(session可省略)

   > set global autocommit = 0;

start transaction 或 begin: 表示显性的开始一个事务,虽然begin和start transaction都是开启一个事务,但在存储过程中,mysql会将begin识别为begin...end,所以在存储过程中,只能使用start transaction来开启一个事务。

commit 或者 commit work: 表示提交事务,也就是说从begin到commit之间所有sql语句对数据库所做出的修改将会被真正的执行,成为永久性的操作。

rollback 或者 rollback work: 表示回滚事务,回滚事务会撤销所有未提交的修改并结束当前事务,注意,使用rollback回滚事务以后,当前事务会结束,后面的操作不算在当前事务之内。

savepoint 标识符: 表示创建一个事务的保存点,以便我们回滚到当前保存点,而不是回滚整个事务,一个事务中可以创建多个保存点,例如:

   > savepoint p1;

rollback to savepoint 标识符: 表示根据标识符回滚到指定的保存点,使用rollback to savepoint只会撤销对应保存点之后的操作,而且不会结束当前事务,回滚到指定的保存点以后的操作仍然属于当前事务,与rollback不同,例如:

  > rollback to savepoint p1;

release savepoint 标识符: 表示删除一个保存点,例如:

  > release savepoint p1;

 

参考博文:

https://www.zsythink.net/archives/1204

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值