一、理解事务
1、本质
事务由一组DML语句组成,这一组语句要么全部成功,要么全部失败。在逻辑上,事务就是一组sql语句,但在实际中,公共的数据库一定会高并发地接受各种事务的请求,所以一个事务要有4个属性来保护数据库中的数据。
2、属性
原子性(Atomicity):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环 节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过 一样。
一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有 的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时 由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交 ( read committed )、可重复读( repeatable read )和串行化( Serializable )
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
3、进一步理解事务
事务不是数据库天生就有的,而是我们在操作数据时,数据库自己来考虑潜在的问题并解决,本质就是为了服务于应用层,简化我们编程模型。
4、事务的提交方式
(1)显示提交方式
show variables like 'autocommit';
(2)修改提交方式
set autocommit=0; OFF
set autocommit=1; ON
二、事务的正常操作
1、启动事务
start transaction; / begin;
2、创建保存点
savepoint save_name;
3、定向回滚
rollback save_name;
4、结束事务(提交)
commit;
5、丢弃全部事务操作
rollback;
三、事务的非正常操作
1、commit 之前发生异常,自动回滚,保证原子性。
2、commit 之后,数据被插入,保证持久性。
3、若是手动 begin 开启事务,一定是手动 commit 提交事务,数据才会持久化,和 sutocommit 是否开启无关。
4、我们之前没有 begin 进入事务的 CURD 操作在数据库看来是一次次单sql语句事务,autocommit 影响的是未进入 begin 进行的单sql语句事务。即 autocommit打开遇到异常上一次操作自动提交,autocommit关闭就自动回滚。
四、事务的隔离级别
在用户层面看,事务就是原子的,只有执行前和执行后,但其实任何事物都会有执行中,多个事务也相互影响。所以为了在执行中不受干扰就会有隔离性。
1、隔离级别
(1)读未提交(Read Uncommitted): 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。 (实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻 读,不可重复读等。
(2)读提交(Read Committed) :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满 足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读, 即一个事务执行时,如果多次 select, 可能得到不同的结果。
(3)可重复读(Repeatable Read): 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操 作数据时,会看到同样的数据行。但是会有幻读问题。
(4)串行化(Serializable): 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了 幻读的问题。它在每个读的数据行上面加上共享锁。但是可能会导致超时和锁竞争(这种隔离级别太极端, 实际生产基本不使用)。增删改操作会放入等待队列中,只有查看的锁解开提交才会进行操作。
2、查看与设置隔离性
(1)查看
查看全局隔离级别:select @@global.tx_isolation
查看当前会话隔离级别:select @@session.tx_isolation
同上简写:select @@tx_isolation
(2)设置
set [session, global] transaction isolation level [read uncommitted, read committed, repeatable read, serializable];
会话的隔离级别只会影响当前会话。全局隔离级别在设置后,新起一次会话就会影响之后会话的隔离级别。
3、隔离级别的问题
(1)脏读
在一个事务中读到另一个事务修改但是未提交的内容。
(2)不可重复读
一个事务读到另一个事务提交之后的数据,就会导致多次读到不同的数据。
(3)幻读
两个事务并发运行,是不可以读到对方的任何操作的,但是一般数据库在RR级别依然无法对 insert 进行隔离(隔离性的实现是对数据上锁,但是insert的数据是不存在的,所以一般无法屏蔽此问题)就会导致读到越来越多的数据。
五、一致性
1、事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的 结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务 对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原 子性来保证的。
2、其实一致性和用户的业务逻辑强相关,一般MySQL提供技术支持,但是一致性还是要用户业务逻辑做支撑,也 就是一致性是由用户决定的。
3、而技术上,通过AID保证C