MySQL的事务基础概念:
目录
事务的ACID特性:
原子性:
一致性:
隔离性:
持久性:
事务的状态:
活动状态:
部分提交状态:
失败状态:
争执状态:
提交状态:
事务的使用:
查看事务:
显示事务:
1.开启事务:
2.事务的DML操作。
3.结束的状态:
隐式事务:
事务的隔离级别:
SQL中的四种隔离级别:
设置事务的隔离级别:
事务是数据库区别于文件系统的重要特性之一,事务会让数据库始终保持一致性,还能通过事务恢复到某一个时间点,可以保证已提交的数据库的修改不会因为系统崩溃而丢失。
事务是数据库中的核心概念,指一组逻辑单元,使数据从一种合法状态转换到另一种合法状态。
当一个事务中执行多个操作时,要么所有事务都提交,对应的修改永久保存,要么数据库管理系统放弃所做的修改,整个事务回滚到最初状态。
事务的ACID特性:
原子性:
指事务是一个不可分割的工作单位,要么全部提交成功,要么全部失败回滚。通过日志系统记录操作步骤,支持回滚。
一致性:
指事务执行前后,数据从一个合法状态转换到另一个合法状态。如果事务中某个操作失败,系统自动撤销当前正在执行的事务。
隔离性:
指事务的执行不能被其他事务所干扰,也就是一个事务的内部操作对并发的其他事务是隔离的,并发执行的各个事务之间不能相互干扰。可以通过锁机制、多版本并发控制等实现。
持久性:
一个事务一旦被提交,对数据库中数据的改变就是永久性的,之后的操作不应该对其有影响。
当通过事务对数据进行修改时,首先会将数据库中变化的信息记录到重做日志中,然后再对数据中对应的行进行修改,这样能够保证数据库即使崩溃,重启之后也能找到没有更新到数据库系统中的重做日志,重新执行。
事务的状态:
事务状态描述了事务从开始到结束的生命周期阶段。
活动状态:
事务的初始状态,事务执行期间出于此状态,所有操作都在进行中但是未提交。
部分提交状态:
事务的所有操作执行完之后进入此状态,由于操作是在内存中执行,所造成的影响并没有刷新到磁盘。
失败状态:
当事务处在活动状态或者部分提交状态,因为硬件或者逻辑错误导致事务无法继续正常执行,必须进行回滚恢复数据。
争执状态:
事务回滚后的状态,所有修改被撤销,数据库恢复到事务开始前的状态,标志着事务的中止。
提交状态:
当一个处在部分提交状态的事务将修改后的数据同步到磁盘上之后,那么事务就处在提交状态。
当事务处在提交状态或者中止状态(争执状态),一个事务的生命周期就算是结束了。对于已提交的,该事务对数据库所做的修改将永久生效,对于处于中止状态的事务,该事务对数据库所做的修改都会回滚到执行事务之前的状态。
事务的使用:
查看事务:
show engines;
显示事务:
1.开启事务:
使用start transaction或者begin,作用是显示开启一个事务。
BEGIN
或者
START TRANSACTION [read only | read write(默认) | with consistent snapshot];
read only:标识当前事务是一个只读事务。是针对于其他事务也能访问到的表,而对于临时表,由于只能在当前会话可见,所以只读事务也可以对临时表进行写操作。
read write:标识当前事务是一个读写事务。
with consistent:启动一致性读。
2.事务的DML操作。
3.结束的状态:
提交:
commit;
中止事务:
rollback;
注意:
回滚到事务中设置的保存点是不属于中止状态,而是活动状态,需要继续执行事务。
关于保存点的创建、删除和回滚语句:
回滚到保存点不属于中止状态:
rollback to [savepoint];//将事务回滚到某个保存点
savepoint:
在事务中创建保存点,方便针对保存点进行回滚,一个事务中可以存在多个保存点
savepoint 保存点名称;
删除保存点:
release savepoint 保存点名称;
隐式事务:
默认情况下,如果不显示使用start transaction或者bgein语句开启一个事务,那么每一条语句都算一个独立的事务,这种特性为事务的自动提交。
如果想关闭自动提交,可以显示开启一个事务,那么本次事务提交或者回滚之前会暂时关闭自动提交,此时DML操作就不会自动提交。
也可以把系统变量autocmommit的值设置为off。
查看autocommit的值:
show variables like 'autocommit';
关闭自动提交:
set autocommit = off;是针对于DML操作是有效的,对DDL是无效的
当关闭自动提交之后,无论是否使用显示开启事务,都需要使用commit来提交事务。
未关闭时,如果是显式开启的事务,只有使用commit提交。
事务的隔离级别:
因为一个事务对某个数据进行访问时,其他事务不能进行访问该数据,性能很低。但是并发事务又会带来以下问题:
脏写:对于两个事务A、B,如果事务A修改了另一个未提交事务B修改过的数据,就意味着发生了脏写。
脏读:对于两个事务A、B,事务A读取了已经被B修改但是还没有提交的数据,之后如果B回滚,那么事务A读取到的数据就是临时且无效的。
不可重复读:对于两个事务A、B,事务A读取了一个字段,之后事务B更新了该字段,然后事务A再次读取了同一个字段,但是值不相同,就意味着发生了不可重复读。在事务B中提交了几个隐式事务,都修改了某个字段的值,而事务A都能看到最新的值,这种也是不可重复读。
幻读:对于两个事务A、B,事务A从一个表中读取了一个字段,然后事务B在该表中插入了一些新的行,之后,事务A再次读取同一个表,就会多出几行,就意味着发生了幻读。事务B隐式提交了一个事务,进行了插入数据记录,之后事务A读取该表得到的数据行包含了事务B插入的数据,这种现象也称为幻读。新插入的数据记录称为幻影记录。
如果是事务B删除了数据记录进行提交之后,事务A进行读取之后的数据记录变少了,这种现象不属于幻读。对于这种现象相当于每一条记录都发生了不可重复读的现象。
幻读是一个事务按照同一个条件进行多次读取,结果集中出现了之前没有出现的数据记录。
脏写>脏读>不可重复读>幻读。
SQL中的四种隔离级别:
未提交读:
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果,不能避免脏读、不可重复读、幻读。
提交读:
一个事务只能看见已经提交的事务所走的改变,是大多数数据库系统默认的隔离级别。可以避免脏读,不能避免不可重复读、幻读。
可重复读:
事务A在读取到一条数据后,此时事务B对数据进行了修改并提交,那么事务A再读取该数据,读取的内容还是之前的内容。可以避免脏读、不可重复读,不能避免幻读。这是MySQL默认的隔离级别。
可串行化:
确保事务可以从一个表中读取到相同的行,这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。可避免脏读、可重复读、幻读。但是性能很低。
四种隔离级别都能避免脏写。
随着隔离级别的增高,并发性性能越低。
设置事务的隔离级别:
在MySQL中是支持未提交读、提交读、可重复读和可串行化隔离级别。
set [global | session] transaction isolation level 隔离级别;
READ UNCOMMITTED未提交读
READ COMMITTED提交读
REPEATABLE READ可重复读
SERIALIZABLE可串行化
或者
set [global | session] transaction_isolation = '隔离级别';
READ-UNCOMMITTED未提交读
READ-COMMITTED提交读
REPEATABLE-READ可重复读
SERIALIZABLE可串行化
global:
在全局范围影响,当前已经存在会话无效,只对执行完该语句之后产生的会话起作用。
session:
在会话范围影响,当前会话的所有后续的事务有效,如果在事务之间执行,则对后续的事务有效,该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务。