mysql事务

如下摘自 《高性能mysql》--鸟哥

1.1事务概念

事务数据库系统一组sql操作,作为不可再分的独立工作单元,此单元中任何一条sql操作失败,则所有sql操作都将回滚,只有所有操作都ok则此事务才算成功。所以事务内所有的操作要么全部成功,要么全部失败。

 

1.2事务的四个特性:ACID 原子性、一致性、隔离性、持久性。

原子性:一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。

一致性:数据库总是从一个一致性的状态转换到另一个一致性状态。 比如:A账户有100元,B账户有100元,A转给B 50元,那么就需要两步操作,A数据减去50,B数据加上50. 事务成功要达到的一致性就是 A账户有50元,B账户有150元。 

隔离性:一个事务内部的所有操作的执行,都不会受到另外一个事务任何操作的影响。事务与事务之间是互相不影响的。

持久性:数据库操作时,要操作的数据都是先提取到内存中的,当事一系列操作完成后,最终的数据需要刷回到硬盘中才算完成了事务。持久性,就是说事务完成的最终数据要存储到硬盘中,能永久存储。数据在内存中一旦断电或者异常,数据就会丢失,但是刷回到硬盘,那么数据就能永久存储。

 

1.3隔离级别,四种隔离级别:读未提交、读已提交、可重复读、可串行化

读未提交:事务中可读取其他事物还未提交的数据,也就是读取了脏数据。读取的是数据不是最终确定的数据,数据安全性极低,会导致很多问题。所以此隔离级别在实际应用中很少使用。

读已提交:(此隔离级别是oracle默认隔离级别),事物开始时只能读取到其他事物已经提交了的数据,也就是说,一个事务从开始直到提交之前,所做的任何修改,对外是不可见的(其他事物读取不到还未最终提交的数据)。此级别也叫不可重复读,就是说这个隔离级别的事物里两次执行同样的查询,可能会读取到不同的数据,因为,其他事物有可能在第二次读取数据之前已经成功修改了数据。

可重复读:(此隔离级别是mysql默认隔离级别),该级别保证了,在同一个事物中多次读取同样的数据记录结果是一致的。但是此级别还是解决另外一个问题,就是幻读。所谓幻读,即在一个事务读取了某一个范围内的数据进行处理时,另外一个事务在此范围内成功插入了一条数据,当前事物再次读取范围内的数据时,就出现前后条数不一致的问题。

可串行化:此隔离级别,就是将强制将各个事物放入队列逐个排序执行,即时间段内只能有一个事务执行,其他等候执行。串行化,虽然解决了事务以上的所有问题,最大限度的保证了数据的安全性,但是它会在读取的每一行数据都加上锁,导致大量的超时和争锁问题。降低了数据库系统的运行效率。此级别除非非常需要确保数据的一致性而且可以接受没有并发的情况下,才可以考虑采用。

 

1.4 事务日志

事务日志可以帮助提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不是每次都将修改的数据本身持久到硬盘。事务日志持久以后,内存中被修改的数据在后台可以慢慢地刷回到磁盘。目前大部分引擎都是这样实现的,我们常称之为预写式日志,修改数据需要写两次磁盘。

如果数据的修改已经记录到事物日志并持久化,但是数据还没有刷回到硬盘,此时系统崩溃了,存储引擎在重启的时候能够自动恢复这部分修改的数据,具体的恢复方式则视存储引擎而定。

 

1.5 mysql中的事物

mysql默认采用自动提交模式,也就是不是显式的开始一个事务,即把每一个sql查询当做一个事务执行提交操作。需要在多个操作上开启事务,则需要显式的开启。

SET AUTOCOMMIT = 1   启用自动提交  1或者ON

SET AUTOCOMMIT = 0   禁用自动提交 0或者OFF   要注意的是 :禁用了自动提交,所有的查询、修改、新增都是在一个事务中,直到显式地执行COMMIT进行提交或者ROLLBACK进行回滚,该事务才结束。同时又开始了另一个事务。

 

1.6 事务对非事务引擎的表没有作用

当一个事务中,执行的一系列操作,有对事务型表和非事务型表进行操作时,事务操作失败,事务型表的数据会回滚,非事务型的表数据不会回滚。这种情况就会导致数据库数据不一致的情况,所以每张表选择合适的引擎非常重要。

在非事务型的表上执行事务相关操作的时候,mysql通常不会发出提醒,也不会报错。有时候也只有回滚的时候发出一个警告。大多数情况下,对非事务型表的操作都不会有提示。

 

1.7多版本并发控制mvcc

mvcc是基于行级锁,为了提升并发控制而进行的优化策略。各种数据库系统实现的mvcc机制也各有不同,因为mvcc没有一个统一的标准。

mvcc就是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然个实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。

mvcc的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事物看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

mvcc实现不同,典型的有乐观并发控制和悲观并发控制。

InnoDB的mvcc,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,一个保存了行的“创建时间”,一个保存了行的“过期时间“(或删除时间)。当然存储的并不是实际的时间值,而是系统的版本号。每开启一个新的事物,系统的版本号就会自动递增。事物开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。如下看看可重复读隔离级别下,mvcc是如何操作的。

select 查询 :InnoDB会根据以下两个条件检查每行记录:

        a. InnDB只查找版本早于当前事物版本的数据行(也就是,行的记录版本号小于或等于事物的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。

        b. 行的删除版本要么未定义,要么大于当前事物的版本号。这可以确保事务读取到的行,在事务开始之前未被删除。

insert 新增数据: InnoDB为新插入的每一行保存当前系统版本号作为行版本号。

delete 删除数据:InnoDB为删除的每一行保存当前系统版本号作为行删除标识。

update 修改数据:InnoDB插入一行新的行记录(即修改后的行数据记录),并保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为删除标识。

保存这两个额外系统版本号,使大多数读操作都可以不用加锁。这样读操作简单、性能也很好、并且也能保证读取到符合标准的行数据。不足之处就是需要额外的存储空间,需要做行的检查工作以及一些额外的维护工作。

注意:mvcc只在  读已提交和可重复读 两个隔离级别下工作。 读未提交和串行化级别下都不兼容mvcc,因为读未提交总是会读取最新的数据行,而不是符合当前版本的数行。而可串行化隔离级别会对所有读取的行都加锁。

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值