程子 orange of backroom 1月11日
-
什么是事务
-
事务的四大特征
-
事务的执行流程
-
事务的隔离性
-
伪事务(锁定)
一,什么是事务:(transaction)
1.事务的一个机制,一个操作系列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即要么执行全部,要么全部不执行。
事务简单的说就是确保数据的准确性
2.那些方面适合使用事务:1.银行 2.保险公司 3.订票系统等等。
二,事务有四大特性:
原子性:事务是一个完整的操作。事务的各元素是不可分的。事务中的所有元素必须为一个整体提交和回滚。如果事务中的任何元素失败,则整个事务将失败
一致性:当事务完成时,数据必须处于一致状态。也就是说,但事务开始后,部分数据可能会进行修改或其他,当事务结束时,数据必须回到已知的一致状态,
通过事务对数据进行修改不能损坏数据,或者说不能使数据处于一个不稳定状态
隔离性:对数据进行修改的所有并发事务是彼此隔离的,也就是说事务必须是独立的,它不应以任何方式依赖或影响其他事务。另外,当事务修改数据时,如果任何其他进程正在同时使用相同的数据,则直到该事务成功提交之后,对数据的修改才能生效。比如,张三和李四两人之间的转账,永远是相互独立的。
持久性:就是说一个事务成功提交之后,它对数据库的改变的永久性的,即使系统出现故障也如此,除非你电脑被外星人吃了。也就是一旦事务被提交,事务的效果会被永久保留在数据库中
UNDO日志:复制事务执行前的数据,用于在事务发生异常时回滚数据
REDO日志:记录在事务执行中,对数据进行的每条跟新操作,当事务提交时,该内容被刷新到磁盘中
三,事务的执行流程:
默认下每条sql语句就是一个事务,即执行sql语句后自动提交。
我们可以通过设置set autocommit=0 来禁止当前对话的自动提交 0|1 (0表示禁止,1表示开启)
下面开始管理事务
1.开始事务
BEGIN 或 START TRANSACTION , beginwork 都表示开启一个事务
insert into stu1 values('', ); //进行相关的操作
insert into stu2 values('', ); //进行相关的操作
2.提交事务 //如果成功事务提交
COMMIT
3.回滚事务 //如果失败则回滚
ROLLBACK
四,事务的隔离级别
现在重点来说明下事务的隔离性,当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,下面看看四种隔离界别
1、READ UNCOMMITTED(未提交读/脏读)
该隔离级别的事务,在数据修改过程中,即使没有提交,其他事务对于这些数据也是可读的。事务可读到未提交的数据也叫脏读(Dirty Read),由于脏读在实际应用中会导致很多问题,一般这类隔离级别应用很少,看示例:
(1)A 从数据库中读取整数 N,当前数据库中 N=0;
(2)N 加上 10,并将其更新到数据库中,当前数据库中 N=10。然而由于 A 的事务还没有提交,所以数据库更新还没有称为持久性的;
(3)B 从数据库中读取整数 N,当前数据库中 N=10;
(4)A 回滚了事务,所以 N 恢复到了 N=0;
(5)B 将 N 加上 10,并将其更新到数据库中,当前数据库中 N=20;
这里出现了 B 在 A 提交之前读取了 A 所更新的数据,由于 A 回滚了事务,所以数据库中出现了错误的数据 20。尽管 A 回滚了事务,但是 A 更新的数据还是间接的通过 B 被更新到了数据库中。这种读取了未提交的数据的方法就叫脏(dirty)读问题。
2、READ COMMITTED(不可重复读/提交后读)
(1)、不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
(2)、(一般数据库默认事务级别)只有当前事务执行完,把数据提交之后,其他事务才可对这些数据进行读取。也叫不可重复读,因为其他事务执行2次查询可能前后会得到2个不同结果(事务执行前读一次,执行后读一次)。
3、REPEATABLE READ(可重读/幻读)
(1)、幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
(2)、(Mysql的默认隔离级别)解决了脏读的问题,该级别保证了在同一事务中,多次读取的结果是一致的。但仍旧无法解决幻读问题。幻读:事务A在读取一定范围内数据时,事务B有对该范围数据进行插入等更新操作,事务A再次读取该范围记录时,会产生幻读。
4、SERIALIZABLE(序列化/串行化)
(1)、在读取每一行数据的时候都对该行数据加锁,强制事务串行执行,在事务提交的时候会释放锁,这时其他事务才能获取相关数据的锁进行处理这样避免了幻读问题,隔离性达到了最高但是这种执行方式效率 低,锁竞争激烈容易出现超时问题。
只有在对数据一致性要求很强的时候和没有并发或并发量很小的时候使用!
5、事务隔离级别的查看和修改
查看:select @@tx_isolation;
修改:set global transaction isolation level 设置的隔离级别;
6、mysql中支持的四种隔离级别
(1)、Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
(2)、Repeatable read (可重复读):可避免脏读、不可重复读的发生。
(3)、Read committed (读已提交):可避免脏读的发生。
(4)、Read uncommitted (读未提交):最低级别,任何情况都无法保证。
五、伪事务(锁定)
1、在MySQL中根据不同的需求,提供了很多存储引擎,但是有的存储引擎不支持事务,对于这种情况,可以使用表锁定来代替事务。
2、对于不支持事务的存储引擎MYISAM类型数据表,当用户插入,修改,删除时,这些操作都会立即保存到磁盘中,当多用户同时操作某个表时,可以使用表锁定来避免同一时间有多个用户对数据库中指定表进行操作,这样可以避免在用户操作数据表过程中受到干扰。只有在用户释放表的操作锁定后,其他用户才可以访问这些修改的数据表。
这里的锁和java多线程中锁的作用一样,个人觉的可以这样理解。
3、对指定表进行锁操作的过程:
(1)lock table table-name lock type ; //locktype 有read 和write 两种
对多个表进行加锁:
lock table table-name1 lock type, table -name2 lock type ,table -name3 lock type;
(2)在指定的表中进行相应的操作
(3)当用户完成对锁定数据表的操作后,进行解锁。
unlock tables ; //释放了所有加锁表的锁。