1 事务
数据库事务是指一个逻辑工作单元中执行的一系列操作,要么完全地执行,要么完全地不执行.
它具有如下特征: (原子性、一致性、隔离性、持久性),或称(ACID),由 Andreas Reuter 于 1983 年提出。
它是数据库管理系统(DBMS)中的一个概念,它标识了一组用于保证数据库可靠性的标准属性。
单个事务的属性:
原子性 事务所有步骤必须全部成功,否则 任何步骤都不会被提交
一致性 事务所有步骤必须全部成功,否则,所有数据恢复到事务开始之前
隔离性 事务完成之前,所有已执行步骤必须与系统保持隔离
持久性 所有提交的数据,系统必须加以恰当保存,并保证万一系统发生故障时仍然能恢复数据到有效
ACID 属性可确保所有数据库事务保持准确且一致,并支持从处理操作期间可能发生的故障中恢复。
因此,几乎所有关系数据库都实现了它。而Mysql的InnoDB的支持相对最严谨。
事实证明,为事务提供支持的 DBMS 会自动强制实施四个 ACID 属性。
我们将查看如何在存储过程中使用事务来防止数据不一致。
举个例子: 我们将钱从支票帐户转移到储蓄帐户。这个动作实际上由两部分组成:
1 从银行帐户中取资金。
2 将资金存入储蓄银行。
现在,想象一下如果第一步之后停电了会发生什么。
如果从支票帐户中扣除了资金但未将其添加到储蓄帐户中,我认为我们都同意那是一个问题!
正如你不希望在财务交易中发生这种情况一样,我们也不希望更新一个数据库表而没有更新引用它的表。通过使用事务,可以保证两个操作一起成功或一起失败。
这样,所有涉及的实体将保持一致状态。
2 事务控制语句
BEGIN 或 START TRANSACTION 显式地开启一个事务
COMMIT 也可以使用COMMIT WORK,不过二者是等价的,COMMIT 提交事务,并使得对数据库进行的所有修改成为永久
ROLLBACK 也可以使用 ROLLBACK WORK,二者等价,回滚将结束用户事务,并撤销正在进行的所有未提交的事务修改
SAVEPOINT pointname, SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT
RELEASE SAVEPOINT pointname 删除一个事务的保存点,当没有指定保存点时,执行该语句抛出一个异常
ROLLBACK TO pointname 把事务回滚到标记点
RELEASE SAVEPOINT savepoint_name; // 删除指定保留点
脏读:读到了还未提交事务的数据。
幻读:两次事务读到的数据不一致。中间有新事务提交。
不可重复读:一次事务中不允许多次读,会发生数据不一致。中间有新事务提交。
SET TRANSACTION 用来设置事务的隔离级别,InnoDB 存储引起提供事务隔离级别如下
脏读 不可重复读 幻读 序列化事务
READ UNCOMMITTED 可能 可能 可能 可能
当前连接 (此时其他连接修改将被卡住)
表数据为 最后由提交事务确定。
特征:读取未提交数据,即临时数据。 A可以读取到B还未提交的事务。
优点: redo日志,可以看到其他事务的数据。 比如买票。
缺点:安全性较差,隔离级别低。
READ COMMITTED 不可能 不可能 不可能 可能 (此时其他事务的写将被卡住)
表数据为 最后由提交事务确定。
特征: 读取已提交数据。 A只能读取到B已经提交的事务。A事务中两次读取相同数据,内容可以不一致,因为包括B事务的提交数据 。
当前事务只能读取其他事务已经提交的数据,未提交的临时数据是读取不到的;
优点:性能适中,适用范围广,比如银行转账
缺点: 仍然可以读取其他事务的数据,可能导致严格业务的错误。
REPEATABLE READ 不可能 不可能 不可能 可能
(此时其他事务的写将被卡住)
表数据为 最后由提交事务确定。
特征: 重复读取 数据一致。 A不读取到B已经提交的事务。 并且A事务中两次读到的内容一致,A事务结束后再读取会读取到B提交事务。
优点:业务隔离更严格,适用于电商业务;
当前的事务能读到的数据是事务开始之前的数据,事务开启之后,其他事务提交的数据是读不到的;
缺点:
将增加 间隙锁冲突的 可能。 性能可能下降
有索引时,为间隙锁,没有索引 则锁全表。
频繁的插入、更新过程中更容易产生锁等待。甚至是死锁。
RR级别使用MVCC(多版本并发控制) + 间隙锁来解决幻读的情况
SERIALIZABLE 不可能 不可能 不可能 不可能
特征:序列化。 A事务未提交,B事务就等待。 直到失败
优点:避免一起业务问题,
缺点:数据库的并发性能急剧下降。
"READ-UNCOMMITTED", A 可以 读取 B 未提交的更改
"READ-COMMITTED", A 只能读取 B 已提交的更改
"REPEATABLE-READ", 事务只能读取事务内的数据
"SERIALIZABLE", 事务 按顺序执行,不能相互读取任何内容,A 执行时,B 不能进行操作。
3 事务的示例:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN
...
COMMIT;
深入问题常用操作
1.数据库默认隔离级别: mysql ---repeatable, oracle,sql server ---read commited postgresql --- read commited 2.mysql binlog的格式三种:statement,row,mixed 3.为什么mysql用的是repeatable而不是read committed: 在 5.0之前只有statement一种格式,而主从复制存在了大量的不一致,故选用repeatable 4.为什么默认的隔离级别都会选用read commited 原因有二: repeatable存在间隙锁会使死锁的概率增大,在RR隔离级别下,条件列未命中索引会锁表! 而在RC隔离级别下,只锁行**** 2.在RC级用别下,主从复制用什么binlog格式:row格式,是基于行的复制!
MYSQL 事务处理主要两种方法
1, BEGIN 开始事务
ROLLBACK 事务回滚 COMMIT 事务确认
2, 直接用SET 改变MySQL自动提交模式
SET AUTOCOMMIT=0 禁止自动提交 SET AUTOCOMMIT=1 开启自动提交
MySql的默认事务隔离级别是RR(可重复读),设置 为 RC 读提交
1、使用RR事务隔离级别,能避免幻读, 但是由于引入间隙锁导致加锁的范围可能扩大,从而会影响并发,还容易造成死锁, 因为间隙锁和间隙锁是不冲突的; 2、在大多数业务场景下,事务隔离级别RC基本上能满足业务需求, 幻读出现的机率较少;
从够用的角度来看,选择默认RC隔离级别是可以的.