DTL,数据事务语言
示例:
一个转账操作,有多条sql 组成 要么全部都执行成功,要么全部都不执行
begin transaction -- 开始事务 (1) update account set banlance = balance -100 where accountId = 1001; (2) sql... (3) sql... (4) sql (5) update account set banlance = balance +100 where accountId = 1002; commit;--提交
if exception rollback ---回滚 (到上一次提交的时候)
注意:设置mysql的自动提交方式, 关闭自动提交
show session variables like 'autocommit'; -- 查看当前会话的自动提交方式 set session autocommit =0; -- 不自动提交 | Variable_name | Value | +---------------+-------+ | autocommit | OFF
事务的定义:
就是指一个任务中有一组sql语句组成,这些sql语句要么全部执行成功,要么全部不执行
注意:
- 在数据库中,执行业务的基本单位是事务,不是以某一条SQL
- 数据库在默认情况下,事务都是打开的,也就是说它是一直处在事务中的,一个事务的结束,代表着下一个事务的开启
- 执行commit或者rollback指令时,会结束当前事务
作用:用来保证数据的平稳性和可预测性.
事务的四大属性(ACID):【面试必问】
1. atomic,原子性,事务是业务逻辑单元中不可再分割的,一个任务中的多个sql语句,要么同时成功,要么不执行 2. consistency,一致性,事务一旦结束,内存中的数据和数据库中的数据是保持一致的 或者:几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致 或者:事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态 这种特性称为事务的一致性。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的 3. isolation,隔离性,事务之间互不干扰,一个事务的结束意味着下一个事务的开启 4. duration,持久性,事务一旦提交,则数据持久化到数据库中,永久保存
事务控制语句
- BEGIN或START TRANSACTION;显式地开启一个事务;
- COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的;
- ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
- SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;
- RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
- ROLLBACK TO identifier;把事务回滚到标记点;
- SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。
MYSQL 事务处理主要有两种方法
- 用 BEGIN, ROLLBACK, COMMIT来实现
1-1. BEGIN 开始一个事务
1-2. ROLLBACK 事务回滚
1-3. COMMIT 事务确认 - 直接用 SET 来改变 MySQL 的自动提交模式:
2-1. SET AUTOCOMMIT=0 禁止自动提交
2-2. SET AUTOCOMMIT=1 开启自动提交
多事务的并发处理机制
原因:多个事务同时操作一个表中的同一行数据,如果这些操作是.修改操作的话,就会产生并发问题,如果不处理,则会造成数据不一致的情况.
数据库可能产生的并发问题包括:
脏读
是指一个事务正在访问数据,并且对这个数据进行修改,而这种修改
还没有提交到数据库中,而另一个事务也访问了这个数据,并且使用了这个数据.
解决方法:一个事务在修改数据时,该数据不能被其他事务访问
不可重复读
是指一个事务多次读取同一条记录,如果此时另一个事务也访问并且
修改了该数据,则就会出现多次读取出现数据不一致的情况,原来的
数据变成了不可重复读取的数据
解决方法:只有在修改事务完全提交过后才可以读取到数据
幻读
是指一个事务修改表中的多行记录,但是此时另一个事务对该表格进行
了插入数据的操作,则第一个事务会发现表格中会出现没有被修改的行,
就像发生了幻觉一样.
解决方法:在一个事务提交数据之前,其他事务不能添加数据
不可重复读的重点是修改,同样的条件,你读取过的数据,再次读取出来发现值不一样了幻读的重点在于新增或者删除
事务隔离级别
- READ_UNCOMMITTED
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
解决第一类丢失更新的问题,但是会出现脏读、不可重复读.
- READ_COMMITTED
保证一个事务修改的数据提交后才能被另外一个事务读取,即另外一个事务不能读取该事务未提交的数据。
解决第一类丢失更新和脏读的问题,但会出现不可重复读.
- REPEATABLE_READ
保证一个事务相同条件下前后两次获取的数据是一致的
解决第一类丢失更新,脏读、不可重复读.
- SERIALIZABLE
事务被处理为顺序执行。解决所有问题
提醒:
Mysql默认的事务隔离级别为repeatable_read
InnoDB引擎的锁机制
之所以以InnoDB为主介绍锁,是因为InnoDB支持事务,支持行锁和表锁用的比较多,Myisam不支持事务,只支持表锁
- 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
共享锁就是我读的时候,你可以读,但是不能写 - 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
排他锁就是我写的时候,你不能读也不能写 - 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
- 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
说明:
- 共享锁和排他锁都是行锁,意向锁都是表锁,应用中我们只会使用到共享锁和排他锁,意向锁是mysql内部使用的,不需要用户干预。
- 对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁,事务可以通过以下语句显示给记录集加共享锁或排他锁。
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。 - InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!