您现在的位置是:首页 >其他 >MySQL数据库:事务网站首页其他
MySQL数据库:事务
一、事务简介
1.概念
事务就是一组DML(sql)语句组成的集合,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。
2.ACID特性
2.1 原子性A
一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在某个中间环境。事务在执行过程中若发生错误,会被回滚到事务开始前的状态,就像这个事务完全没被执行过一样。
2.2 一致性C
在事务开始之前,和事务结束之后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
2.3 隔离性I
数据库允许多个并发事务同时对其数据进行读写和修改,隔离性可以防止多个事务并发执行时 由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交 ( read committed )、可重复读( repeatable read )和串行化( Serializable )。
2.4 持久性D
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
二、事务并发操作带来的问题
1.脏读
比如事务A进行了数据修改,但还未提交,此时事务B对该数据进行了查询,之后事务B发现问题对事务进行了回滚。
此时事务B就是脏读,读取到来其他事务还未提交之后的修改结果。
2.不可重复读
一个事务在不同的时间段,读取同一个数据得到了不同的结果(中途其他事务对数据进行了修改提交)。
3.幻读
同一个事务在不同的时间段,读取到的结果条数不同(中途其他事务对数据进行了修改提交,导致某些数据满足或不满足了该事务读取条件,导致该事务两次读取结果条数不同)。
4. 解决方法
MySQL数据库针对并发操作存在的问题,提供了四种隔离级别,如下。
三、事务隔离级别
1. 读未提交
在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别),但是相当于没有任何隔离性,仍有很多并发问题,如脏读,幻读,不可重复读等。
不加锁,什么问题都没有解决。
2.读已提交
该隔离级别是大多数数据库的默认的隔离级别( MySQL 不是)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读, 即一个事务执行时,如果多次 select, 可能得到不同的结果。
解决了脏读,仍然存在不可重复读和幻读问题。
3.可重复读
MySQL默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。
解决了脏读、不可重复读、幻读问题。
4.串行化
事务的最高隔离级别,它通过加锁强制事务按序、串行化执行,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁。但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)。
解决了所有问题。
隔离级别如何实现?
隔离,基本都是通过锁实现的,不同的隔离级别,锁的使用是不同的。常见有,表锁,行锁,读 锁,写锁,间隙锁(GAP),Next-Key锁(GAP+行锁)等。
四、可重复读解决并发问题思想
1.基于MVCC多版本并发控制
MySQL数据库的可重复读隔离级别中,基于MVCC多版本并发控制,解决不可重复读和幻读的问题。
2.MVCC实现思想
(1)每张表中都有三个隐藏字段
①DB_TRX_ID:最近修改事务ID,记录创建/最后一次修改该记录的事务ID。
②DB_ROW_ID:隐含的自增ID(隐藏主键),如果数据表没有主键, InnoDB会自动以DB_ROW_ID 产生一 个聚簇索引。
③DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本。
(2)MySQL为每个事务生成一个事务ID
事务ID是持续增长的,即越往后的事务,事务ID越大。
3.解决原理
(1)修改操作的事务,会先将原始数据向undo日志中保存一份,并且给当前数据操作事务ID为自己的事务ID。
(2)查询操作的事务,在查询数据的时候,只能从数据库的undo日志中获取比自己小的事务ID,且已经提交了的数据。
五、事务操作
1.开始事务
begin;
开始事务。
2.保存事务回滚点
savepoint pos_name;
保存事务回滚点,并命名为pos_name。
3.提交事务
commit;
提交事务
4.回滚事务
(1)rollback
事务全部回滚,即回滚到事务开始前。
(2)rollback to 回滚点
回滚到指定位置。
注意:
①事务未提交时:随时可以回滚,并且出现异常未完成事务时,数据库重启后也会自动回滚。
②事务提交后:根据事务的持久性,数据将被持久化存储,无法再回滚。