目录
事务
概念
InnoDB默认的事务隔离级别是read repeatable,其完全符合ACID特定,而有些公司的产品多少在某些方面没有严格满足事务的ACID标准,下面分别是ACID详解:
①atomicity原子性:指整个数据库事务是不可分割的工作单位,只有使事务中所有的数据库操作要么都执行成功,要么数据库回退到执行事务前的状态;
②consistency一致性:指事务将数据库从一种状态转变为下一种一致的状态,比如事务开始之前与结束之后,数据库的完整性约束没有被破坏;
③isolcation隔离性:要求每个读写事务的对象,对其他事务的操作对象能互相分离,即该事务提交前对其他事务都不可见,通常使用各种锁来实现,隔离性主要是描述并发事务场景;
④durability持久性:事务一旦提交,其结果就是永久性的,即便发生宕机等故障,数据库也能将数据恢复;这是从事务角度来保证结果的永久性,持久性保证事务系统的高可靠性,而不是数据库系统的高可用性,对于数据库系统的高可用性,事务本身并不能保证,需要额外的系统来共同配合完成;
分类
从事务理论的角度来看,可以把事务分为以下几种类型:
①扁平事务:事务类型中最简单的一种,也是使用最频繁的事务,在扁平事务中,所有操作都处于同一层次,由begin work开始,由commit work/rollback work结束,中间操作都是原子的;
缺点是:不能提交/回滚事务的某一部分,或分几个步骤提交,例如:一个事务有3个业务模块SQL组成,且这3个SQL没有任何业务关联,由于扁平事务要求要么这3个都成功,要么这3个都回滚,显然代价就有点高了;
②带有保存点的扁平事务:除了支持扁平事务支持的操作外,允许在事务执行过程中回滚到同一事务中较早的一个状态;因为某些事务可能在执行过程中出现的错误并不会导致所有的操作都无效,放弃整个事务不合理且开销大,所以保存点用来通知系统应该记住事务当前的状态,以便之后发生错误时,事务能回到保存点当时的状态;
③链事务:可以看做是保存点模式的一个变种,带有保存点的扁平事务在发生系统崩溃后,所以的保存点都将消失,因此当进行恢复时,事务需要重新执行,而不能从最近的一个保存点继续执行;
链事务则是:提交一个事务时,释放不需要的数据对象,将必要的处理上下文隐式传给下一个要开始的事务,这里提交事务操作和开始下一个事务操作合并为一个原子操作,从而把上一个事务与下一个事务形成一个链;
链事务与带有保存点的扁平事务不同的是:带有保存点的扁平事务能回滚到任意正确的保存点,而链事务中的回滚仅限于当前事务,即只能恢复到最近一个的保存点,至于锁,链事务在commit后立即释放当前事务所持有的锁,而带有保存点的扁平事务不影响迄今为止所持有的锁;
④嵌套事务:是一个层次结构框架,由一个顶层事务控制着各个层次的事务。顶层事务之下嵌套的事务被称为子事务,其控制每一个局部的变换,任何子事务都在顶层事务提交后才真正的提交,事务树中的任意一个事务回滚会引起它的所有子事务一同回滚,所以子事务只有ACI特性,不具有D特性;
⑤分布式事务:是指一个在分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点;
事务的实现
概念
原子性、持久性是通过redo log重做日志来保证的;redo可以用来恢复提交事务修改的页操作;redo通常是物理日志,记录的是页的物理修改操作;
一致性则是通过undo log来保证的;可以用来回滚行记录到某个特定版本;undo是逻辑日志,根据每行记录进行记录;
redo
概念
重做日志用来实现事务的持久性,日志由2部分组成:内存中的重做日志缓冲redo log buffer(容易丢失)、磁盘上的重做日志文件redo log file(持久存储)
InnoDB事务通过force log at commit机制来实现事务的持久性,即当事务提交commit时,必须先将该事务的所有重做日志写入到重做日志文件来进行持久化,等事务commit操作完成才算彻底结束;
在InnoDB中由redo log和undo log来组成,其中redo log用来保证事务的持久性,undo log用来帮助事务回滚以及MVCC功能;redo log基本是循序写的,在数据库运行时不需要对redo log文件进行读取操作,而undo log是需要进行随机读写的;
为了确保每次日志都能写入重做日志文件,在每次将重做日志缓冲写入重做日志文件后,InnoDB都需要调用一次fsync操作;由于重做日志文件没有使用o_direct选项,因此重做日志缓冲先写入文件系统缓存,然后为了确保重做日志写入磁盘,必须进行一次fsync操作,但由于fsync效率取决于磁盘性能,因此,磁盘性能决定了事务提交的性能,也就是数据库的性能;
InnoDB允许用户手工设置非持久性的情况发生,来提高数据库的性能,当事务提交commit时,日志不写入重做日志文件,而是等待一个时间周期后再去执行fsync操作,虽然在事务提交时没有强制进行一次fsync操作,来提高数据库的性能,但当数据库宕机时,由于部分日志未刷新到磁盘,因此会丢失最后一段时间的事务;
innodb_flush_log_at_trx_commit参数控制重做日志刷新到磁盘的策略,默认值为1即事务提交时必须调用一次fsync操作,还可以设置为0和2,其中0表示事务提交时不进行写入重做日志操作,写入操作仅在master thread中完成,而在master thread中每隔1秒回进行一次重做日志文件的fsync操作;2表示事务提交时将重做日志写入重做日志文件,但仅仅写入文件系统的缓存中,不进行fsync操作,虽然数据库宕机且操作系统不宕机的前提下,并不会导致事务的丢失,但当操作系统宕机时,重启数据库后会丢失未从文件系统缓存刷新到重做日志文件那部分事务;
MySQL还有一种二进制日志binlog,用来进行point-time恢复以及主从复制replication环境的建立,binlog 与 redo log区别在于:
①redo log是InnoDB产生的,bin log则是MySQL产生的,MySQL下所有的存储引擎对数据库的修改都会产生bin log;
②bin log是一种逻辑日志,记录的是对应的SQL语句(毕竟,各个存储引擎的底层都不了解,取最大公约数就是SQL语句呗,这总的支持吧),redo log是InnoDB的物理格式日志,记录的是对于每个页的修改(毕竟只有自己来用);
③bin log只有在事务提交完成后进行一次写入;redo log在是事务进行中就不断地被写入;
redo log block
InnoDB中重做日志都是以512B进行存储的,意味着重做日志缓存、重做日志文件都是以块block的方式进行保存的,叫做重做日志块redo log block,每个块的大小为512字节;
若一个页中产生的重做日志大于512字节,则需要分割为多个重做日志块进行存储,由于重做日志块与磁盘扇区都是512字节,因此重做日志写入时可以保证原子性,不需要doublewrite技术;
重做日志块除了日志本身之外,还由日志块头log block header以及日志块尾log block tailer组成,其中重做日志头占12字节,重做日志尾占8字节,因此每个重做日志块实际占492字节;
redo log group
log group为重做日志组,包含多个重做日志文件,InnoDB中只有1个log group;
log group是一个逻辑上的概念,并没有一个实际存储的物理文件来表示log group信息;log group由多个重做日志文件组成,每个log group中日志文件大小是相同的,在InnoDB 1.2之前重做日志文件总大小要小于4GB,InnoDB 1.2之后把总大小限制提高为512GB;
重做日志文件中存储的就是之前在log buffer中保存的log block,因此其也是根据块的方式进行物理存储的管理,每个块大小与log block一样都是512字节;
undo
回滚操作就需要undo,在对数据库进行修改时,InnoDB既要产生redo log,还要产生一定量的undo,这样当用户事务失败或者rollback命令回滚时,就可以利用这些undo信息将数据回滚到修改之前的样子;
redo存放在重做日志文件中,undo存放在数据库内部的一个特殊字段中,这个字段叫做undo段undo segment,undo段位于共享表空间内;
事务控制语句
MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后会马上执行commit操作;
想显式开启事务需要使用begin、start transaction或者set autocommit=0,这样就会禁止自动提交事务;
常用的事务控制命令如下:
①start transaction|begin:显式开启一个事务;由于在存储过程中会把begin识别为begin-end,因此在存储过程中只能使用start transaction语句来开启事务;
②commit:提交事务,让已对数据库做的所有修改成为永久性;这里注意的是:
commot和commit work功能基本一致,都是用来提交事务,不同之处在于commit word用来控制事务结束后的行为是chain还是release,如果是chain方式则事务就变成链事务
当completion_type=0时,commit与commit work功能相同;
当completion_type=1时,commit work等同于commit and chain,表示马上自动开启一个相同隔离级别的事务;
当completion_type=2时,commit work等同于commit and release,即在事务提交后自动断开与服务器的连接;
③rollback:回滚结束事务,并撤销正在进行的所有未提交的修改;rollback和rollback work与commit和commit work工作一样;
④savepoint identifier:savepoint在事务中创建一个保存点,一个事务可以有多个保存点;
⑤release savepoint identifier:删除事务的一个保存点,当没有一个保存点执行该命令时则抛出一个异常;
⑥rollback to [savepoint] identifier:与savepoint一起使用,把事务回滚到标记点,而不回滚在此标记点之前的任何工作;
⑦set transaction:用来设置事务的隔离级别,InnoDB提供的事务隔离级别有:read uncommitted/read committed/repeatable read/serializable;
一条语句失败并抛出异常时,并不会导致先前已经执行的语句自动回滚,所有的执行都会得到保留,必须由用户自己来决定是否对其进行提交/回滚操作,另外就是rollback to savepoint,虽然有rollback,但其并不是真正结束一个事务,因此即便执行rollback to savepoint,仍然需要显式运行commit或rollback命令;
隐式提交的SQL语句
下面这些SQL语句会产生一个隐式的提交操作,即执行完这些语句后,会有一个隐式的commit操作:
①DDL语句:alter命令、create命令、drop命令、rename table、truncate table;
②修改MySQL架构:create user/drop user/grant/rename user/revoke/set passowrd;
③管理语句:analyze table/cache index/check table/load index into cache/optimize table/repaire table;
事务的隔离级别
数据库需要在正确性与性能之间做出妥协,SQL标准定义了4个隔离级别:
read uncommitted、read committed、repeatable read、serizlizable;
InnoDB在默认的repeatable read的事务隔离级别下已经能完全保证事务的隔离性要求,即达到SQL标准的serializable隔离级别;隔离级别越低,事务请求的锁越少,保持锁的时间就越短
MySQL数据库分布式事务
InnoDB提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现;在使用分布式事务时,InnoDB的事务隔离级别必须设置为serializable;
MySQL数据库XA事务的SQL语法如下:
XA {START|BEGIN} xid [JOIN|RESUME]
XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
XA RECOVER

被折叠的 条评论
为什么被折叠?



