如果是为了考试的话,只需要记住事务的定义,特性及定义,四种隔离级别和产生的问题
算了都背吧!理解性记忆
事务的定义:
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
比如:银行账户转账,从A账户向B账户转账1000
需要两条updata语句
这两条语句需要同时成功或失败
如何保证同时成功或失败呢,依靠事务机制就可以
事务的存在是为了保证数据的安全性,完整性
如果所有的SQL语句一条就能搞定的话,那么事务就没有必要存在了
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
事务流程
假设一个事务,需要一个insert与一条updata,一条delete
执行insert(这个执行成功后,会记录到数据库操作历史中,并不会修改数据库
执行updata(也是记录不修改
执行delete(记录不修改
提交事务commit(把历史操作同步至数据库,然后清空历史操作)
或者回滚事务rollback(清空历史操作)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
事务的四个特性:(ACID)
1 、原子性。事务是数据库的最小的工作单位,不可再分,事务中包含的各操作要么都做,要么都不做
2 、一致性。事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一个事务重的多条语句要么同时成功要么同时失败
3 、隔离性。一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性。也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
四种隔离级别,以及可能产生的问题
SQL标准定义了4类隔离级别
Read Uncommitted(读取未提交内容)
可以读取对方事务未提交的数据
会产生脏读(读取脏数据)
Read Committed(读取提交内容)
对方事务的数据提交后我方立即可以读到
自己事务运行时执行了好几个别的事务,自己事务如果要用到的数据在这期间被别的事务修改了,就会在自己事务运行期间读到不同的数据
会产生不可重复读
Repeatable Read(可重读,解决了不可重读问题)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。不同时间读取的数据会出现不同的情况,如果你选择插入新的行的话
举个例子
事务A查id=5的
事务B插入一条id=5的
事务A查id=5的
结果会不同
这就是幻读
如何解决幻读?
目前InnoDB引擎使用的方法 间隙锁
https://blog.youkuaiyun.com/new_buff_007/article/details/104249866
这个博主整理的mysql45讲里面的一节,讲的挺清楚的,用心去读
简单来说就是把每个值之间的间隙也加锁,这个锁只不允许插入,
但是会造成死锁,两个事务同时对一个间隙加锁,(同时对间隙加锁不会等待),然后对该间隙插入,就是由于对方的间隙锁而互相等待
Serializable(可序列化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
实操
mysql默认DML语句是自动提交的(就是提交一句语句后立马执行)
关闭自动提交:start transaction
rollback:回滚
commit:提交
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果不支持乐观锁的话,可以使用
MVCC
多版本并发控制技术。原理是,通过数据行的多个版本管理来实现数据库的并发控制,简单来说就是保存数据的历史版本。可以通过比较版本号决定数据是否显示出来。读取数据的时候不需要加锁可以保证事务的隔离效果。