InnoDB 事务

来源:互联网 发布:js获取页面所有内容 编辑:程序博客网 时间:2024/05/16 09:21

事务是数据库的一大特征,也是InnoDB不同于Mysql其他存储引擎的重要特点。InnoDB可以实现ISO定义的标准事务4个事务隔离级别。

ACID特性

事务具备ACID特性,ACID特性可以很好的保障数据的一致性、完整性。ACID特性放映到事务上就是:事务中的Sql要么全做,要么全不做,不能出现部分生效的情况。

  • 原子性:一系列操作要么都生效,要么都不生效;
  • 一致性:数据是最终一致的,满足约束要求的;
  • 隔离性:事务之间在没有提交前互相是不可见的;
  • 持久性:事务生效后,修改是永久的,持久性不等于高HA;

事务的分类

根据事务的特点可以将事务分为如下几类:

  • 扁平事务:使用最多的事务,使用:begin transraction … commit (rollback)开始;
  • 带保存点的扁平事务:使用保存点,保存状态,可以将事务回滚到保存点;
  • 链事务:将上一个事务的结果传递给下一个事务,类似在事务中开始事务,但是两个事务的操作是一个原子操作;
  • 嵌套事务:在事务中进行子事务;
  • 分布式事务:分布式环境下的事务要求;

InnoDB支持扁平事务、带保存点事务、链事务、分布式事务,不支持嵌套事务。

事务的ACID实现

事务的I(隔离性)由锁实现,原子性、持久性通过redo log实现,一致性通过undo log实现。

注意:redo和undo并不是互逆向的操作;

  • redo:恢复事务结果,通常是物理日志,redo恢复的是事务修改的页操作结果,记录物理页修改结果;
  • undo:回滚行记录到某个特定结果,这个时候物理页操作已经发生,所以undo更多的是逻辑日志,逻辑操作,安行记录操作;

重做日志

Mysql重做日志是InnoDB引擎产生的,包括redo和undo日志。redo日志是对页的物理修改记录,undo是逻辑回滚操作。redo日志一般是顺序的不需要读,undo日志是随机的。

和binlog的区别

  • 产生方:重做日志是InnoDB产生,binlog是mysql标准和引擎无关;
  • 用途:重做日志是保证事务的ACID,binlog是mysql用来记录sql操作,进行主从同步pit恢复使用;
  • 记录内容:binlog是基于sql产生的,重做日志是基于事务产生的;
  • 写入时间点:binlog在事务commit后写入一次,重做日志在事务中不断写入。

重做日志的写入单位是512字节,是一个扇区,磁盘物理结构保证原子性,但是binlog、insert buffer需要通过double write技术来完保证数据的一致性;

事务相关Sql

开始事务:start transaction | begin提交:commit回滚:rollback创建保存点:savepoint id删除保存点:release [savepoint] id回滚到保存点:rollback to [savepoint] id 不能真正结束事务设置事务级别:set transcation 是否自动提交:set autocommit

隐式提交

某些DDL语句是隐式提交事务的,这意味着这些操作是不能被rollback的。

如truncate table清空表和delete效果一样,但是truncate不能回滚,因为truncate是隐式提交事务的。

事务统计

查询数据的QPS和TPS可以统计事务数量,sql如下:

select global status like 'com_commit' \G

事务隔离级别

ISO标准的事务隔离级别为4级:

  • Read Uncommitted:浏览访问,会产生脏读,也就是读取到可能rollback的数据;
  • Read Committed:游标稳定,解决脏读问题,会产生幻读,不可重复读问题;
  • Repeatable Read:无幻读保护,无法解决幻读问题,可以解决不可重复读问题;
  • Serializable:隔离,一般认为效率比较低,但是效率问题要看具体场景,不同实现方法和场景下,该级别效率不一定低,并发性低是肯定的,但是可以解决幻读。

PS:
低事务隔离级别锁少,但是不一定会带来大幅度的性能提升,要看数据库实现。

  1. Oracle不支持Read uncommited 和 repeatable read;

  2. InnoDB默认为Repeatable Read,使用Next-Key Lock,是可以解决幻读的。

  3. SQL和SQL2标准为Serializable但是并发性低;

  4. serializable 在InnoDB中一般用于分布式事务中。

  5. 纠正,网络上很多人把ISO和其他数据库尝试的事务隔离别产生的问题也按在了Mysql Innodb上,实际上MySql InnoDB在可重复读的隔离级别下,通过Next-Key Lock方案解决了“幻读”问题。

事务设置Sql:

设置事务级别Set [global|session] transaction isolation level read uncommitted;#查询事务级别select @@tx_isolation \G

分布式事务

分布式事务定义:允许多个独立的事务资源参与到全局事务中。全局事务要求,参与其中的事务要么都提交要么都不提交。

XA事务:允许跨数据库的分布式事务,要求每个数据库都支持XA事务,是分布式事务的一种实现和协议。

分布式事务实现需要如下组件:

  • 资源管理器:1或者N个,提供访问事务资源的访问,一般一个数据库就是一个资源管理器;
  • 事务管理器:协调参与全局事务的多个事务,需要和所有的资源管理器通信;
  • 应用程序:定义事务边界,制定全局事务中的操作;

两阶段式提交

InnoDB的事务实现和分布式事务都使用两阶段式提交:

  • 第一阶段:所有资源管理器都做prepare,告诉事务管理器,已经准备好提交;
  • 第二阶段:事务管理器告诉所有资源管理器,执行rollback或者commit;
  • 如果有某一个事务无法commit,则反馈事务管理器,然后周知其他资源管理器执行rollback;

InnoDB的分布式事务Sql

InnoDB的分布式事务在Client下无法模拟,在JPA下可以完美支持。

启动或加入事务:XA {start|begin} xid [join|resume]结束或终止事务:XA end xid [suspend [for migrate]]准备提交:XA Prepare xid执行回滚:XA rollback xidXA Recover

内部XA事务

主要用来控制主从同步时的数据一致性,binlog和重做日志的同步,保证主从一致。

由于事务的回滚操作,binlog可能带来主从不一致情况,使用Row格式的binlog,可以避免在主从复制的时候slave产生数据不一致的情况。

不好的事务习惯

  • 循环中提交事务:InnoDB默认是自动提交的,所以不显示commit不表示没在循环中提交事务,会产生大量的重做日志;
  • 使用自动提交事务:交给程序来控制,不要在存储过程中执行;
  • 使用自动回滚事务:同自动提交;
  • 不吞噬错误:发生错误要抛出来;

长事务的拆分

将长事务拆分为小批量事务,解决长事务时间过长,重做的代价太大,锁释放慢的问题;

原创粉丝点击