第六章 事务与并发控制


参考见:https://zhidao.baidu.com/question/329349963.html

参考见:http://www.voidcn.com/article/p-cyrpkvrk-tx.html

参考见:https://blog.csdn.net/nanaranran/article/details/77716377

参考见:https://www.cnblogs.com/diegodu/p/8818776.html

6.1 事务

1.事务:是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。

2.事务的划分:1)显式划分事务;2)隐式划分事务

3.事务的ACID特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持续性(Durability)

1)原子性:事务是 数据库的逻辑工作单位,是不可分割的工作单元。事务中包括的诸操作要么都做,要么都不做。

2)一致性:事务执行的结果必须是使数据库从一个一致性状态转向为另一个一致性状态。一致性状态是指数据库中只包含成功事务提交的结果;不一致状态是指数据库中包含事务提交的部分结果。

3)隔离性:一个事务的执行不能被其他事务干扰,即一个事务内部的操作以及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

4)持续性:持续性也称为永久性,是指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的操作或故障不应该对其执行结果有任何的影响

4.Mysql中的事务控制:

1)mysql中的InnoDB

存储引擎是innodb。nnodb是Mysql上第一个提供外键约束的数据引擎,除了提供事务处理外,InnoDB还支持行锁,提供和Oracle一样的一致性的不加锁读取,能增加并发读的用户数量并提高性能,不会增加锁的数量。InnoDB的设计目标是处理大容量数据时最大化性能,它的CPU利用率是其他所有基于磁盘的关系数据库引擎中最有效的

InnoDB是一套放在Mysql后台的完整的数据库系统,InnoDB有自己的缓冲池能缓冲数据和索引,InnoDB还把数据和索引存放在表空间中,可能包含好几个文件,这和MyISAM表完全不同,在MyISAM中,表被存放在单独的文件中,InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。

2)参数之autocommit

A:autocommit是mysql中InnoDB数据表中特有的语句。(只有在表引擎=InnoDB时,autocommit才会生效)并且,在InnoDB表中,所有的数据都是需要commit之后,才会在真实数据库中生效

A:在没有开启事务(begin;)的InnoDB表中,autocommit才会生效。对已经开启了事务的SQL语句,autocommit参数不会生效

eg:

InnoDB数据库引擎:

update  tablenam  set  id=999  where  id=1;(缓存生效)

commit;(真实生效)

其他数据库引擎:

update  tablenam  set   id=999  where  id=1;(真实生效)

A:查看autocommit:select  @@autocommit

      修改autocommit:set  autocommit=0;(默认是1)

3)参数之completion_type

commit和commit work的级别一致,都用来提交事务(rollback和rollback work跟commit和commit work的关系一样)不同之处在于commit work用来控制事务结束后的行为是chain还是release的。如果是chain,那么就变成了链事务。

用户可以通过参数completion_type来控制。默认为0,表示没有任何操作,此时commit=commit work

当参数completion_type的值为1时,commit work等同于commit and chain,表示马上自动开启一个相同隔离级别的事务。

当参数completion_type的值为2时,commit work等同于commit and release,表示当事务提交后自动断开与服务器的连接。

4)样例1:

    mysql> set names utf8;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> create table t(a int, primary key (a))engine=innodb;  
    Query OK, 0 rows affected (0.29 sec)  
      
    mysql> select @@autocommit;  
    +--------------+  
    | @@autocommit |  
    +--------------+  
    |            1 |  
    +--------------+  
    1 row in set (0.00 sec)  
      
    mysql> set @@completion_type=1;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> begin;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> insert into t select 1;  
    Query OK, 1 row affected (0.00 sec)  
    Records: 1  Duplicates: 0  Warnings: 0  
      
    mysql> commit work;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> insert into t select 2;  
    Query OK, 1 row affected (0.00 sec)  
    Records: 1  Duplicates: 0  Warnings: 0  
      
    mysql> insert into t select 2;  
    ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'  
    mysql> rollback;  
    Query OK, 0 rows affected (0.00 sec)  
      
    # 回滚之后只有1这个记录,而没有2这个记录  
    mysql> select * from t;  
    +---+  
    | a |  
    +---+  
    | 1 |  
    +---+  
    1 row in set (0.00 sec)  

说明:在此样例中,将completion_type设置成1,第一次通过commit work来insert这条记录。之后insert 2的时候并没有启用begin(start transaction)来开启一个事务,之后再插入一条重复的记录2,这时会抛出异常rollback后,最后发现只有1这样的一条记录。2并没有被insert进去。因为completion_type为1的时候,commit work会开启另外一个事务,因此2个insert语句是在同一个事务里面的所以回滚以后没有insert进去

5)样例2:

    mysql> set @@completion_type=2;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> begin  
        -> ;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> insert into t select 3;  
    Query OK, 1 row affected (0.00 sec)  
    Records: 1  Duplicates: 0  Warnings: 0  
      
    mysql> commit work;  
    Query OK, 0 rows affected (0.00 sec)  
      
    mysql> select @@versison;  
    ERROR 2006 (HY000): MySQL server has gone away  
    No connection. Trying to reconnect...  
    Connection id:    205656  
    Current database: test  
      
    ERROR 1193 (HY000): Unknown system variable 'versison'  
    mysql>   

说明:参数completion_type为2时,commit work等同于commit and release,当事务提交的时候会自动断开与db的连接

6)rollback(rollback work)

savepoint identifier:在事务中创建一个保存点,一个事务允许有多个保护点

release savepoint identifier:删除事务中的保存点,当时一个保存点也没有执行这个命令,会报错抛出一个异常

说明:构成事务的每条语句都会commit,否则事务的每条语句都会rollback,这种保护还会涉及到单调的语句,一条语句要么完成成功要么完全回滚。但是一条语句失败并不会导致前一条执行的语句西东回滚,他们的工作会保留,需要你手动commit或者rollback

5.事务的执行方式

两种方式:串行/交叉并发执行

6.2  并发控制

1.丢失修改:两个事务读取统一数据并分别进行修改,T1先提交了修改结果,T2后提交的修改结果覆盖了T1提交的结果,导致T1的修改结果丢失。

2.读“脏”数据:T1修改某一数据,并将其写回磁盘。事务T2读取同一数据后,事务T1由于某种原因被撤销,这时事务T1修改过的数据恢复原值,而事务T2读取到的是一个过渡性的不再需要的“脏”数据,与数据库中的数据不同

3.不可重复读:事务T1读取某一数据之后,事务T2对其进行了更改,当事务T1再次读取该数据时,无法再现前一次读取的结果。

4.主要原因:并发执行的事务破坏了事务的隔离性

6.3  封锁

1.基本锁:排它锁(X锁)/共享锁(S锁)

2.封锁粒度:封锁对象的大小称为封锁粒度

3.封锁协议:

1)一级封锁协议:事务T在修改数据对象之前必须对其加X锁,直到事务结束才能释放X锁。

2)二级封锁协议:在一级封锁协议的基础上,再进一步的规定:事务T再读取数据对象之前必须对其加S锁,读完后立即释放S锁

3)三级封锁协议:是在一级封锁协议上,再进一步的规定:事务T在读取数据对象之前必须对其加S锁,读完后并不立即释放S锁,直到事务T结束后才释放。

4.活锁与死锁:

1)活锁:是指系统中某个事务始终处于等待状态,得不到封锁的机会(永远等待)

2)死锁:如果两个系统中有两个或两个以上的事务都处于等待状态,并且每个事务都在等待其中另一个事务解除封锁,它才能继续执行下去,结果造成任何一个事务都无法继续执行,这种现象称为“死锁”(两个互锁,相互等待)

    (1)死锁的预防:一次封锁法(每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行)/顺序封锁法(预先对数据对象规定一个封锁顺序,所有的事务都必须按照这个顺序实行封锁)

    (2)死锁的诊断:超时法/事务等待图法

    (3)死锁的解除:选择一个处理死锁代价最小的事务,将其撤销,释放该事务持有的所有锁,使其他事务得以继续运行下去

6.4  并发调度的可串行性

1.可串行化调度:多个事务的并发执行是正确的,当且仅当其结果与按照某一次串行的执行他们时的结果相同,这种并行调度策略称为可串行化的调度

2.冲突可串行化调度:对于时间上相邻的两个操作,能交换的是不冲突的操作(对同一数据,只要带写就冲突)

3.冲突可串行化调度:一个调度SC在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度SC’。如果SC’是串行的,那么就称SC是冲突可串行化的调度

6.5  两段锁协议

1.两条规则:

1)在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁

2)在释放一个封锁之后,事务不再申请和获得任何其他封锁

说明:1)所谓两段锁协议实际上是将事务分为两个阶段,第一阶段是获得封锁,也称为扩展阶段。在这个阶段,事务可以申请任何数据项上的任何类型的锁,但是不能释放任何锁。第二阶段是释放封锁,也称为收缩阶段。在这个阶段,事务可以释放任何数据项上的任何类型的锁,但是不能在申请任何锁。

2)事务遵守两段锁协议是可串行化调度的充分不必要条件。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM