【数据库】事务、ACID、数据库的隔离级别、脏读、不可重复、幻读

事务的思想:

很多复杂的事物要分步进行(复杂的东西经常要拆分),但它们组成一个整体,要么整体生效,要么整体失效。这种思想反映到数据库上,就是多个SQL语句,要么所有执行成功,要么所有执行失败。
数据库事务:

数据库事务(Database Transaction)是指将一系列数据库操作当作一个逻辑处理单元的操作,**这个单元中的数据库操作要么完全执行,要么完全不执行。**通过将一组相关操作组合为一个逻辑处理单元,可以简化 错误恢复,并使应用程序更加可靠。
一个逻辑处理单元要成为事务,必须满足ACID属性。(原子性Atomic、一致性Consistency、隔离性Isolation和持久性Durabiliy),所谓的ACID含义如下。

原子性(Atomicity):表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的操作执行成功,整个事务才提交,事务中任何一个数据库操作失败,已经执行的任何操作都必须撤销,让数据库返回到初始状态。也就是一个事务内的操作,要么全部执行成功,要么全部执行不成功。
一致性(Consistency):事务执行后,数据库所处的状态和它的业务规则是一致的,即数据不会被破坏。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的(两人的钱总额是不变的。)。
隔离性(Isolation):在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。准确地说,并非要求做到完全无干扰,数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,**隔离级别越高,数据一致性越好,但并发性越弱。**每个事务独立运行。在并发环境中,并发的事务是互相隔离的,互不影响。
持久性(Durability):一旦事务提交成功后,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须保证能够通过某种机制恢复数据。也就是事务一旦提交后,数据库中的数据必须被永久地保存下来。

1、事务:
事务是表示一组操作要么同时成功,要么同时失败,而且事务与事务之间是独立。
事务有ACID的特性。
(1)原子性(2)一致性(3)隔离性(4)持久性

银行转账

张三-》李四转账500元
张三原来的余额是1000元,
李四原来的余额是0元。

(1)张三账户-500
(2)李四账户+500

一致性:要么张三还是1000,李四是0
	    要么张三现在是500,李四是500
		
张三-500成功了,要给李四+500时,发现李四的账号异常,那么要回滚,还原刚刚张三-500的操作。
如果都成功了,就提交。

事务:
网购,下订单

(1)创建订单--》订单表中要添加记录
(2)记录订单明细--》订单明细表中要添加订单都买了什么
(3)商品表修改-->库存量修改,销量增量	

2、
mysql默认是自动提交事务,一句SQL是一个事务,执行成功一句就提交一句。

手动开始事务,取消自动提交。
方式一:
set autocommit = false;
这次客户端连接,在你恢复自动提交之前,
接下来所有的SQL执行都必须手动提交了,否则就不生效。

这个设置只管一个连接,和其他的连接(登录)无关。
set autocommit = false;
… 都是需要手动提交的。
set autocommit = true;

当只是部分的SQL需要构成事务,手动提交,而其他SQL还是想要自动提交的。
那么我们选择方式二。

方式二:
start transaction;
… 一个事务
commit;或rollback;

start transaction;
… 另一个事务
commit;或rollback;

… 自动提交

3、事务的隔离级别
同一个库的同一个表同一个记录,对于多个事务来说,就是共享数据。
多个事务被多个线程同时执行时,那么共享数据就会线程安全问题。

隔离级别低 实时性、速度
针对不同安全级别的要求,设置了不同的隔离级别:
(1)read uncommitted:可以读取未提交的
事务1,可以读取到事务2已经修改,但是还没正式提交的数据
会出现脏读、不可重复读、幻读
(2)read committed:读取已提交的数据
事务1,只能读取到事务2已提交的数据
会出现不可重复读、幻读
(3)repeatable READ:
原来:会出现幻读
现在:幻读也可以避免
行锁
(4)Serializable
所有问题都可以避免。
表锁
锁的级别不一样 性能低
几种问题:
(1)脏读现象
事务1对某个记录进行修改,还未提交。事务2就看到了。
那么这个被事务1修改还未提交的数据就是脏数据。

如何避免脏读,把事务隔离级别设置为(2)(3)(3)都可以避免。

(2)不可重复的
事务1对某个表进行修改,已经提交。
但是事务2,在事务1提交之前,查询了一下这个记录,
在事务1提交之后,又查询了一下这个记录,
对于事务2来说,出现了不可重复读的现象。
在同一个事务中,前后两次对同一个记录的读取发现不一样。
如果想要避免不可重复读,那么需要设置隔离级别为(3)(4)

(3)幻读
事务1给某个表增加了新的记录,或者删除了某个表的记录。(记录数有变化)
并且提交了。
事务2,在事务1提交之前,查询了这个表
在事务1提交之后,查询了这个表
对于事务2来说,前后两次的记录数不一样。好比出现幻觉一样。多出或少了记录。多了少了数据

如果想要避免幻读,那么需要设置隔离级别为(4)。
但是mysql在5.0之后,升级了。在隔离级别(3)的时候,就可以避免幻读了。

对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:

  • 脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。 之后, 若 T2 回滚, T1读取的内容就是临时且无效的。

  • 不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。 之后, T1再次读取同一个字段, 值就不同了。

  • 幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。 之后, 如果 T1 再次读取同一个表, 就会多出几行。

  • 数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题。

  • **一个事务与其他事务隔离的程度称为隔离级别。**数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。

  • Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE。 Oracle 默认的事务隔离级别为: READ COMMITED 。

  • Mysql 支持 4 种事务隔离级别。 Mysql 默认的事务隔离级别为: REPEATABLE READ。在mysql中REPEATABLE READ的隔离级别也可以避免幻读了。

4、如何查询当前连接是什么隔离级别
mysql默认的隔离级别是:
±----------------+
| @@tx_isolation |
±----------------+
| REPEATABLE-READ |
±----------------+

用户要查看的话:select @@tx_isolation;

5、如何修改当前连接的隔离级别
set tx_isolation = ‘read-uncommitted’;
set tx_isolation = ‘read-committed’;
set tx_isolation = ‘REPEATABLE-READ’;
set tx_isolation = ‘serializable’;

在MySql中设置隔离级别

  • 每启动一个 mysql 程序, 就会获得一个单独的数据库连接。每个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别.
  • 查看当前的隔离级别: SELECT @@tx_isolation;
  • 查看全局的隔离级别: SELECT @@global.tx_isolation;
  • 设置当前 mySQL 连接的隔离级别:
set tx_isolation ='repeatable-read';
  • 设置数据库系统的全局的隔离级别:
set global tx_isolation ='read-committed';

注意:这里的隔离级别中间是减号,不是下划线。

SQL:
1、DDL
2、DML
3、DCL
事务的commit等是属于DCL

事务回滚和提交只对insert, update,delete有效。
对create,drop等DDL语句是无效的。





delete from 【数据库名.]表名称 【where 条件】;


如果没有where条件,表示删除整张表的数据;


truncate 【数据库名.]表名称;#删除整张表的数据,还可以使用这个语句,效率更高,但是它不能回滚
删除了不能回滚

用delete删除整张表和用truncate删除整张表的数据的区别?

(1)truncate速度快

(2)truncate无法回滚

truncate因为底层是把表drop掉,然后新建了一张空表。

delete因为底层是一行一行删数据。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值