06-MySQL-数据库事务

1 什么是数据库事务

可以先查询下本地安装的数据库版本以及存储引擎、事务的隔离级别

-- 查看数据库版本
SELECT VERSION();
-- 存储引擎
SHOW VARIABLES LIKE '%engine%';
-- 事务隔离级别(RR)
SHOW GLOBAL VARIABLES LIKE '%transaction_isolation%';

1.1 事务的典型场景

在项目中一般涉及到多张表的同时更新操作需要增加事务来保证一致性;在业务代码中增加@Transactional注解,还是在xml文件里面配置切面,还是直接通过JDBC的方法。

<tx:advice id="txAdvice" transaction-manager-"transactionManager">
    <tx:attributes>
    <tx:method name="save*" rollback-for="Throwable"/>
    <tx:method name="add*" rollback-for="Throwable"/>
    <tx:method name="send*" rollback-for="Throwable" />
    <tx:method name="insert*" rollback-for="Throwable"/>
    </tx:attributes>
</tx:advice>

        很多时候我们需要事务是因为我们涉及数据库的多个操作都能同时成功,比如客户下单操作,会操作订单表、订单明细表、订单关联订单收货地址表等等,这个时候就需要放在一个事务里面执行。来保证操作可以同时成功。
          一个很典型的案例,比如银行转账,我们的A账户需要转账100元到B账户,就要保证一个账户的余额减少,另一个账户的余额增加,那么这两个动作一定是同时成功或者同时失败的,否则就会造成银行的会计科目不平衡。

        另外一个例子:12306换乘中转的问题,要保两张票能同时购买成功,只买到前半场或者后半场都是没有任何意义的。

1.2 事务的定义

        维基百科的定义:事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
        这里面有两个关键点,第一个,所谓的逻辑单位,意味着它是数据库最小的工作单元,是不可以再分的。第二个,它可能包含了一个或者一系列的 DML语句,包括insertdelete update。
(单条 DDL(create drop)和DCL(grant revoke)也会有事务)

1.3 哪些存储引擎支持事务

        MySQL中并不是所有的存储引擎都支持事务,它是作为一种特性出现的在MySQL所支持的这些存储引擎里面,除了做集群的NDB之外,只有InnoDB支持事务,这个也是它成为默认的存储引擎的一个重要原因。

1.4 事务的四大特性

        原子性:Atomicity,也就是我们刚才说的不可再分,因为原子是化学上最小的单位,也就意味着我们对数据库的一系列操作,要么都是成功,要么都是失败,存在部分成功,部分失败的情况,以刚才的转账场景为例,一个账户的余额减少,必然对应着另一个账户余额的增加。
       全部成功的场景比较简单,问题是如果前面一个操作已经成功了,后面的操作失败了,怎么让它全部失败呢,这个时候我们必须回滚。
        原子性,在InnoDB里面是通过undo log来实现的,他记录了数据修改之前的值(逻辑日志)。一旦发生异常,就可以用undo log来实现回滚操作。
        隔离性:Isolation,我们有了事务的定义以后,在数据库里面会有很多的事务同时操作我们的同一张表或者同一行数据,必然会产生一些并发或者干扰的操作。隔离性就是说在多个事务并发执行的时候,对表或者行的并发操作,应该是透明的,互相不干扰的,比如两个人给张三转账100,开启两个事务,都拿到了张三账户的余额1000,然后各自加上100,最后的结果是1100,就出现了数据混乱的问题。
        持久性:事务的持久性是什么意思呢?我们对数据库的任意的操作,增删改,要事务提交成功,那么结果就是永久性的,不可能因为数据库掉电宕机、意外重启,又变成原来的状态。这个就是事务的持久性。
持久性怎么实现呢?回想一下,InnoDB 崩溃恢复(crash-safe)是通过什么实现的?
        持久性是通过 redo log和 double write buffer(双写缓冲)来实现的,我们操作数据的时候,会先写到内存的 buffer pool里面,同时记录redo log,如果在刷盘之前出现异常,在重启后就可以读取redo log的内容,写入到磁盘,保证数据的持久性当然,恢复成功的前提是数据页本身没有被破坏,是完整的,这个通过双写缓冲保证
        需要注意的是,原子性,隔离性,持久性,最后都是为了实现一致性,
一致性:consistent,指的是数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。

1.5 数据库什么时候会出现事务

update user set username="bonnie" where id=1;

        当我们执行上面的更新语句的时候,它不仅自动开启了一个事务,而且自动提交了,所以最终写入了磁盘。
        这个是开启事务的第一种方式,增删改的语句会自动开启事务,当然是一条 SQL一个事务。注意每个事务都是有编号的,这个编号是一个整数,有递增的特性。
如果要把多条 SQL放在一个事务里面,就要手动开启事务。手动开启事务有两种方式:一种是用 begin;-种是用 start transaction
        结束事务:两种方式,第一种是回滚事务rollback,事务结束。第二种就是提交事务commit,事务结束。
        InnoDB里面有一个autocommit的参数(分为两个级别,session级别和global级别)

SHOW VARIABLES LIKE 'autocommit';

        它的默认值是 ON。autocommit 这个参数是什么意思呢?是否自动提交。如果它的值是 true/on 的话,我们在操作数据的时候,会自动提交事务,
否则的话,如果我们把 autocommit 设置成 false/off,那么数据库的事务就需要我们手动地结束,用 rollback 或者 commit。
还有一种情况,客户端的连接断开的时候,事务也会结束。、

1.6 事务并发带来的问题?

1.6.1 脏读(读取到了未提交的数据)

        我们有以下两个事务,一个事务编号是3306, 一个是3307。在第一个事务里面,它首先通过一个where id=1的条件查询一条数据,返回age=16, 然后第二个事务将age更新成了18,第一个事务再次读取的时候age=18;但是此时事务3307还未提交。这种并发问题我们称之为脏读。

1.6.2 不可重复读(读到了其他事务更新的数据) 

          我们有以下两个事务,一个事务编号是3306, 一个是3307。在第一个事务里面,它首先通过一个where id=1的条件查询一条数据,返回age=16, 然后第二个事务将age更新成了18,第一个事务再次读取的时候age=18;这种一个事务读取到了其他事务已提交的数据导致前后两次读取数据不一致的情况。这种并发问题我们称之为不可重复读。

1.6.3 不可重复读(读到了其他事务插入的数据)

        在第一个事务里面我们执行了一恶搞范围查询,这个时候就有一条数据满足了条件,在第二个事务里面,它插入了一行数据,并且提交了。重点:插入了一行数据。在第一个事务了里面再去查询的时候,会发现多了一行数据。这种情况就好像突然冒出来的一个幻影一样;这种一个事务前后两次读取数据不一致,是由于其他事务插入数据造成的,这种情况我们把他叫做幻读。

        不可重复读和幻读最大的区别在那里呢?修改或者删除造成的读不一致叫做不可重复读,插入造成的读不一致叫做幻读这里有两个点务必要跟大家说明一下,避免有些同学想多了:
        1、一个事务读取到其他事务最新提交的数据,这不是正常的吗?当然是正常的,所以我们这里讨论的是读一致性。读一致性的意义就是一个事务的 select 操作跟其他事务没有瓜葛,你不需要修改数据,所以不需要获取最新的数据,这样能够提高并发性能。
        2、如果在第一个事务里面,select 以后,再执行一个update,就能获取到第二个事务的最新数据,这个怎么解释?同样的,这个也脱离了读一致性的讨论范畴。如果要修改数据,必然会读取到最新的数据,也会影响其他的事务,
        所以这里要不要修改,要不要读取到最新的数据,是一个区别点。目前我们讨论的都是在一个事务里面多次重复读取。

小结:我们刚才讲了事务并发带来的三大问题,现在来给大家总结一下。无论是脏读,还是不可重复读,还是幻读,它们都是数据库的读一致性的问题,都是在一个事务里面前后两次读取出现了不一致的情况。
        读一致性的问题,必须要由数据库提供一定的事务隔离机制来解决。就像我们去饭店吃饭,基本的设施和卫生保证都是饭店提供的。那么我们使用数据库,隔离性的问题也必须由数据库帮助我们来解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值