什么是事务?
事务是一组操作的集合,是一组不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或者撤销操作,就是说这些操作要么完成,要么失败。
数据库中事务的特性是什么?
简单来说就是ACID:
- 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性(Consistency):事务完成时所有的数据必须保证一直状态。
- 隔离性(Isolation):数据库提供的隔离环境,保证事务不受外部并发操作影响的独立环境下运行。(一个事务的运行不影响另一事务)
- 持久性(Durability):事务一旦提交或者回滚,他对数据库的改变就是永久的。
并发事务有哪些问题?
因为MySQL的服务端允许多个客户端连接,这就意味着MySQL可能会出现并发问题,常见的并发问题有:脏读、不可重复读、幻读。
详细解释可以参考小林coding
不可重复读和幻读在我看来的主要差别是,不可重复读偏向于更新操作update即原来的数据是存在的,而幻读是插入操作,原来数据不存在,在读取后插入了一条是insert操作。
如何解决并发事务出现的问题呢?
解决方案就是对事务进行隔离:
MySQL支持四种隔离级别来处理对应的问题:
- 读未提交(read uncommitted):它解决不了刚才提出的所有问题。
- 读已提交(read committed):读写已经提交的事务,他可以解决脏读,但是不能解决不可重复读和幻读。
- 可重复读(repeatable read):指的是一个事务执行中看到的数据一直和这个事务启动时看到的事务是一样的,他可以解决脏读和不可重复读,但是不能解决幻读。MySQL InnoDB 引擎的默认隔离级别
- 串行化(serializable):会对事务加上锁,在多个事务对这条数据进行操作的时候,如果发生了读写冲突,后边的时候会等待前一个事务执行完成,才能继续。可以解决所有问题但是效率过低不推荐使用。
事务中的隔离性是如何保证的呢?
事务的隔离性是由锁和mvcc实现的。
其中mvcc的意思是多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,它的底层实现主要是分为了三个部分,第一个是隐藏字段,第二个是undo log日志,第三个是readView读视图
- 隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事务id),记录每一次操作的事务id,是自增的;另一个字段是roll_pointer(回滚指针),指向上一个版本的事务版本记录地址。
- undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表。
- readView解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读是不一样的,最终的访问的结果不一样。如果是rc隔离级别,每一次执行快照读时生成ReadView,如果是rr隔离级别仅在事务中第一次执行快照读时生成ReadView,后续复用。