MySQL事务(ACID)
事务就是要保证一组数据库操作,要么全部成功,要么全部失败。
Atomicity(原子性):
一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
Consistency(一致性):
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
Isolation(隔离性):
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatableread)和串行化(Serializable)。
Durability(持久性):
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
Mysql事务隔离级别
隔离级别主要是指,当我们多个事务在进行的时候,就可能出现脏读、不可重复读、幻读的问题。
读未提交(read uncommitted)别人改数据的事务尚未提交,我在我的事务中也能读到。
一个事务还没提交时,它做的变更就能被别的事务看到。
读已提交(read committed)别人改数据的事务已经提交,我在我的事务中才能读到。
一个事务提交之后,它做的变更才会被其他事务看到。
可重复读(repeatable read)别人改数据的事务已经提交,我在我的事务中也不去读。
一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
串行化(serializable )我的事务尚未提交,别人就别想改数据。
顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
事务隔离的实现
每条记录在更新的时候都会同时记录一条回滚操作。同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)。在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。
1.在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。
2. 在“读提交”隔离级别下,这个视图是在每个 SQL语句开始执行的时候创建的。
3.“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;
4. “串行化”隔离级别下直接用加锁的方式来避免并行访问。
长事务
长事务(Long-Lived Transactions),顾名思义,就是执行时间较长的事务。而我们在开发中是要尽量避免使用长事务。
1.长事务意味着系统里面会存在很老的事务视图,在这个事务提交之前,回滚记录都要保留,这会导致大量占用存储空间
2.在访问表时,innodb会自动给加上元数据锁(meta data lock,MDL),MDL是表级锁。如果是读,就是共享锁,写就是排它锁。当执行长事务时,后续的事务如果要获取排它锁就会被阻塞。可能引发系统崩溃严重事故。