Mysql进阶(事务)

一、数据库事务

数据库事务是访问并可能操作数据项的一个数据库操作序列,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作完成·。

通俗的来讲,就是一次对数据库操作过程,这个过程由多条sql执行,这么多条sql在一次执行过程中要么都成功执行么都不执行,保证数据完整性。mysql中只有innodb引擎支持事务。

二、事务的特性

原子性(Atomicity ,或称不可分割性)、一致性(Consistency)、隔离性(Isolation ,又称独立性)、持久性(Durability)。

1.原子性:

一个事务中的多条sql要么都成功执行,要么都不执行,回滚到事务执行前的状态。

2.隔离性:

数据库事务是可以有多个同时执行的(类似线程),需要对多个事务进行隔离。

3.持久性:

事务正常提交后可以保证数据持久保存,即使宕机。

4.一致性:

前面的原子性,隔离性,持久性都是为了保证一致性。保证数据是完整可靠的。例如转账,保证操作后的结果与我们预期的一致。

三、事务设置

默认情况下、Mysql启用自动提交模式(变量autocommit为ON)。这意味着,只要你执行DML操作的语句,Mysql会立即隐式提交事务。

由于变量autocommit分会话系统变量和全局系统变量,所以查询的时候,最好区别是会话系统变量还是全局系统变量。

Mysql事务处理的两种办法:

1.用BEGIN,ROLLBACK,COMMIT来实现

BEGIN:开始一个事务

ROLLBACK:事务回滚

COMMIT:事务提交

2.直接SET来改变Mysql的自动提交模式

SET GLOBAL / SESSION autocommit=0; -- 禁止自动提交
SET GLOBAL / SESSION autocommit=1;-- 开启自动提交

查看autocommit模式

SHOW GLOBAL / SESSION VARIABLES LIKE 'autocommit';

四、事务隔离级别

为什么要有隔离级别?

因为Mysql是一个服务器和客户端之间架构的软件,对于同一个服务器来说,可以有若干个客户端与之连接,每个客户端与服务器连接之上后,就可以称之为一个会话。我们可以同时在不同的会话里输入语句,这些语句可以作为事务的一部分进行处理。

不同的会话可以同时发送请求,即服务器可能同时在处理多个事务,这样子就会导致不同的事务可能同时访问到相同的记录。

虽然事务具备隔离性的特点,理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交后,其他事务才可以继续访问这个数据。但是这样子对性能影响太大,所以提出了各种隔离级别,来最大限度的提升系统并发处理事务的能力。

但是只有lnnoDB支持事务,所以这里所说的事务隔离级别是指InnoDB下的事务隔离级别。

1.查看隔离级别

SELECT @@session.transaction_isolation,@@transaction_isolation;

2.设置隔离级别

1)读未提交

(read uncommitted):一个事务可以读取到另一个事务未提交的修改。

问题:会带来脏读(垃圾数据,别的事务可能会回滚),不可重复读,幻读的问题。

即当另一个事物正在修改数据,但是还没有提交,可能会发生回滚,若此时事物正在执行某些操作,还会读到另一个未回滚前的数据。用select测试比较好。

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

2)读已提交

(read committed):一个事务只能读取到另一个事务提交后的数据。

解决了脏读问题,但是没有解决可重复读和幻读问题。

不可重复读:一个事务在同一次的读操作中,先后读取了两次数据,结果两次数据不一致,称为不可重复读。

造成这种现象的原因可能是另一个事务的修改操作还没有提交,所以读操作可能会读到两次数据不一致。

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED

3)可重复读

(repeatable read Mysql中默认的隔离级别):一个事务在同一次事务中,多次读取同一个数据是是一致的。即使别的事物修改并提交了数据,也是一致的。(第二次与第一次读取结果一致)

解决了不可重复读问题,但是没有完全解决幻读问题

幻读:同一个事务中,读取了两次,结果读到的数据数量不同,称为幻读。

可重复读:可以解决正常的查询语句中出现的幻读问题,但是在查询语句的后面,如果添加了for update,就会出现幻读问题。

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

例如:事务1不加for update执行时,事务2添加一行记录后并且提交,事务1不会出现幻读,但是当事务1加了for update后执行,事务2添加一行记录后并且提交,事务1会出现幻读。

4)串行化

(serializable):事务串行执行,即事务只能一个一个地执行,即使一个事务写,另一个事务读也不可以。

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE

五、事务实现原理

1.原子性实现

实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。mysql使用的是undo log日志文件,用来记录增删改的反向操作。如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

undo log属于逻辑日志,它记录的是sql执行相关信息。当发生回滚时,执行对应操纵的反向操作即可还原。

insert--->delete

delete--->insert

update--->update

2.持久性实现

(mysql保证数据不丢失)

当数据库事务提交后,保证数据时不可撤销。当sql发送到mysql后,事务还未提交之前,如果发生断电/宕机,会将sql保存到redo log日志文件中,在mysql重新启动时,执行redo log中的sql

redo log叫做重做日志,是保证事务持久的重要机制。

3.隔离性实现原理(MVCC)

mvcc:

多版本并发机制,为了提高并发访问,读写可以同时进行。每次事务对某条记录操作时,会生成一个操作的版本链。

如果隔离级别是读已提交:

在同一个事务中,每次读取时,都会从版本链上生成一个快照(readView),每次读到的是查询时最新数据,也称为当前读。

如果隔离级别是可重复读:

在事务第一次读取数据时,会从版本链上生成一个快照(readView),之后再次读取时,仍然从上次的版本快照中读取,所以可实现重复读。也称为快照读。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值