事务性质和隔离级别

事务的性质和隔离级别

事务的三个基本要素:ACID

事务:是一系列的数据库操作,是数据库应用的基本逻辑单位

  • 原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。
  • 一致性或可串性:事务的执行使得数据库从一种正确状态转换成另一种正确状态。
  • 隔离性:在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务。
  • 持久性:事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。

事务并发问题

事务并发时出现的场景:

  1. 更新丢失:事务A将数值5改为1并提交; 事务B将数值5改为2并提交。 这时数据的值为2,事务A所做的更新将会丢失。或者事务B中途失败退出,导致对数据的两个修改都失效了。数值还是原来的5
  2. 脏读:一个事务读到另一个事务,尚未提交的修改,就是脏读。这里所谓的修改,除了Update操作,还包括Insert和Delete操作。脏读的后果:如果后一个事务回滚,那么它所做的修改,统统都会被撤销。前一个事务读到的数据,就是垃圾数据。
    事务1:在Reservation表中插入一条记录,用于预订99号房间。
    事务2:查询,尚未预定的房间列表,因为99号房间,已经被事务1预订。所以不在列表中。
    事务1:信用卡付款。由于付款失败,导致整个事务回滚。所以插入到Reservation 表中的记录并不置为持久(即它将被删除)。现在99号房间则为可用。所以,事务2所用的是一个无效的房间列表,因为99号房间,已经可用。
  3. 不可重复读:在同一个事务中,再次读取数据时【就是你的select操作】,所读取的数据,和第1次读取的数据,不一样了。就是不可重复读。
    事务1:查询所有的年龄小于15的学生。
    事务2:修改一条年龄小于15的学生为年龄大于15。
    事务1再次执行,得到俩次不一样的查询结果。在不可重复读里面,可以看到其他事务所做的修改,而导致2次的查询结果不再一样了。这里的修改,是提交过的。也可以是没有提交的,这种情况同时也是脏读。

  4. 幻读:事务1读取指定的where子句所返回的一些行。然后,事务2插入一个新行,这个新行也满足事务1使用的查询where子句。然后事务1再次使用相同的查询读取行,但是现在它看到了事务2刚插入的行。这个行被称为幻象,因为对事务1来说,这一行的出现是不可思议的。

    不可重复读的重点是修改
    同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了
    幻读的重点在于新增或者删除
    同样的条件 , 第 1 次和第 2 次读出来的记录数不一样

SQL定义的四个事务隔离级别

  1. 未授权读取(Read Uncommitted)(读未提交):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。
  2. 授权读取(Read Committed)(读已提交):允许不可重复读取和幻读,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。当前事务只能读取到其他事务已经提交后的数据。最为常用。
  3. 可重复读取(Repeatable Read):保证当前事务多次读取特定记录的结果相同,可以防止脏读、不可重复读,但可能会幻读。
  4. 序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能放在队列里一个接着一个地执行,但不能并发执行。一个时刻只能一个事务操作数据库。降低了系统的并发能力。

大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle

少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎

MyISAM引擎使用的是表锁。对于MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但是会阻塞对同一表的写请求;对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作。MyISAM的读和写之间,以及写操作之间都是串行的
InnoDB引擎与MyISAM的最大不同点有两处:一是支持事务,二是采用行级锁(也可以用表锁,默认行级锁),
共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁;
排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
默认 对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任意锁。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任意锁。

在InnoDB中,锁是逐步获得的,因此发生死锁是可能的。发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并回退,另外一个事务获得锁,并继续完成事务。但在涉及外部锁,或涉及表锁的情况下,InnoDB并不能完全自动检测到死锁,这需要通过设置锁等待超时参数innodb_lock_wait_timeout来解决。

关于锁机制,未完待续

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值