精华内容
下载资源
问答
  • 事务与并发控制

    千次阅读 2020-01-21 22:31:01
    事务与并发控制

    1 什么是事务 

    • 事务是数据库执行操作的最小逻辑单元
    • 事务可以由一个SQL组成也可以由多个SQL组成
    • 组成事务的SQL要么全执行成功要么全执行失败
    START TRANSACTION / BEGIN
    	SELECT ...
    	UPDATE ...
    	INSERT ...
    	DELETE ...
    COMMIT / ROLLBACK

    事务开启后只能执行DML操作(执行DDL会执行COMMIT操作会把这个事务结束掉)


    2 事务的特性

    事务的特性

    特征

    说明

    原子性(Atomicity

    一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

    一致性(Consistency

    在事务开始之前和事务结束以后,数据库的完整性没有被破坏。

    隔离性(Isolation

    事务的隔离性要求每个读写事务的对象与其它事务的操作对象能相互分离,即该事务提交前对其它事务都不可见。

    持久性(Durability

    事务一旦提交了,其结果就是永久性的,就算发生了宕机等事故,数据库也能将数据恢复。

    3 并发带来的问题

    3.1 脏读

    一个事务读取了另一个事务未提交的数据

     3.2 不可重复读

    一个事务前后两次读取的同一数据不一致。

    3.3 幻读

    指一个事务两次查询的结果集记录数不一致


    4 事务的隔离性

    INNODB的隔离级别:默认可重复读(SQL标准里面不能避免幻读,但是MySQL可以)

    隔离级别

    脏读不可重复读幻读隔离性并发性

    顺序读(SERIALIZABLE)

    NNN最高最低

    可重复读(REPEATABLE READ)

    NNN  

    读以提交(READ COMMITTED)

    NYY  
    读未提交(READ UNCOMMITTED)YYY最低最高

    4.1 设置事务的隔离级别

    SET [PERSIST|GLOBAL|SESSION]
         TRANSACTION ISOLATION LEVEL
         {
          | READ UNCOMMITTED
          | READ COMMITTED
          | REPEATABLE READ
          | SERIALIZABLE
         }

    4.2 查看当前SESSION的事务隔离级别

    SHOW VARIABLES LIKE '%iso%';

    4.3 数据

    DROP DATABASE IF EXISTS tx;
    CREATE DATABASE tx;
    USE tx;
    -- ----------------------------
    -- 账户表
    -- ----------------------------
    CREATE TABLE account (
      `id` INT (11) NOT NULL AUTO_INCREMENT COMMENT '账户表id',
      `username` VARCHAR (20) NOT NULL COMMENT '用户名',
      `deposit` DECIMAL (20, 2) DEFAULT NULL COMMENT '用户存款,单位是元,保留两位小数',
      PRIMARY KEY (`id`)
    ) ;
    INSERT INTO account(`username`, `deposit`) VALUES ('蔡徐坤','1000');
    INSERT INTO account(`username`, `deposit`) VALUES ('乔碧萝','2000');
    INSERT INTO account(`username`, `deposit`) VALUES ('卢本伟','3000');
    INSERT INTO account(`username`, `deposit`) VALUES ('张三','4000');
    INSERT INTO account(`username`, `deposit`) VALUES ('李四','5000');
    INSERT INTO account(`username`, `deposit`) VALUES ('王五','6000');
    SELECT * FROM account;
    mysql> SELECT * FROM account;
    +----+-----------+---------+
    | id | username  | deposit |
    +----+-----------+---------+
    |  1 | 蔡徐坤    | 1000.00 |
    |  2 | 乔碧萝    | 2000.00 |
    |  3 | 卢本伟    | 3000.00 |
    |  4 | 张三      | 4000.00 |
    |  5 | 李四      | 5000.00 |
    |  6 | 王五      | 6000.00 |
    +----+-----------+---------+
    UPDATE `account` SET `deposit` = 1000 WHERE `username` = '蔡徐坤' AND `id` = 1;
    UPDATE `account` SET `deposit` = 2000 WHERE `username` = '乔碧萝' AND `id` = 2;
    UPDATE `account` SET `deposit` = 3000 WHERE `username` = '卢本伟' AND `id` = 3;
    UPDATE `account` SET `deposit` = 4000 WHERE `username` = '张三' AND `id` = 4;
    UPDATE `account` SET `deposit` = 5000 WHERE `username` = '李四' AND `id` = 5;
    UPDATE `account` SET `deposit` = 6000 WHERE `username` = '王五'AND `id` = 6;
    mysql -u root -p123456 tx

    4.4 serializable 级别两个事务并发情况

    serializable 级别两个事务并发的情况
    事务1事务2
    SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE ; 
    BEGIN; 
    SELECT * FROM account; 
     # 修改前一个事务里面查询出来的数据
     BEGIN;
     

    UPDATE `account` SET `deposit` = `deposit` - 100 WHERE id = 1;

    # 阻塞

    ROLLBACK;

    # 事务1执行了rollback;或者commit;后 事务2才能继续执行

     
     ROLLBACK;

    4.5 repeatable read 级别两个事务并发情况

    repeatable read 级别两个事务并发的情况
    事务1事务2
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ; 
    BEGIN; 

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 两条记录

     
     # 修改一条记录 让其满足事务1执行的SQL的条件
     BEGIN;
     UPDATE `account` SET `deposit` = 100 WHERE `id` = 3;
     COMMIT ; 

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    #  无法读取到第事务2对数据的修改 还是两条记录

     

    ROLLBACK ;

    #  结束当前事务

     

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    #  能够查找到事务2修改的数据了 三条记录

     

    4.5 read committed 级别两个事务并发情况

    read committed 级别两个事务并发的情况
    事务1事务2
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; 
    BEGIN; 

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 两条记录

     
     # 修改一条记录 让其满足事务1执行的SQL的条件
     BEGIN;
     UPDATE `account` SET `deposit` = 100 WHERE `id` = 3;

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 两条记录

     
     COMMIT ; 

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 查询到了事务1修改的数据 三条记录

     
    ROLLBACK ; 

    4.6 read uncommitted 级别两个事务并发情况

    read uncommitted 级别两个事务并发的情况
    事务1事务2
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ; 
    BEGIN; 

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 两条记录 蔡徐坤 乔碧萝

     
     # 修改一条记录 让其满足事务1执行的SQL的条件
     BEGIN;
     UPDATE `account` SET `deposit` = 100 WHERE `id` = 3;

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 三条记录

     
     ROLLBACK;

    SELECT * FROM `account` WHERE  `deposit` <= 2000;

    # 二条记录

     
    ROLLBACK; 

    4.7 repeatable read 级别下的阻塞

    repeatable read 级别下的阻塞
    事务1事务2
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; 
    BEGIN; 
    UPDATE `account` SET `deposit` = `deposit` + 100 WHERE `id` <= 3; 
     BEGIN;
     

    UPDATE `account` SET `deposit` = `deposit` - 100 WHERE `id` <= 3;

    # 阻塞

    ROLLBACK; 
     ROLLBACK;

    INNODB中的锁(一个事务不能对另一个事务正在读取或修改的数据进行修改)

    • 查询需要对资源加共享锁(S)(被加锁的对象只能被持有锁的事务读取但不能修改,其他事务无法对该对象进行修改,但也可以对该对象加共享锁进行读取)
    • 数据修改需要对资源加排它锁(ⅹ)(被加了排他锁的对象只能被持有锁的事务读取和修改,其他事务无法读取修改被加了排他锁的对象)
     

    排它锁

    共享锁

    排它锁

    不兼容

    不兼容

    共享锁不兼容兼容

    5 阻塞和死锁

    5.1 演示阻塞现象

    什么是阻塞?

    • 由于不同锁之间的兼容关系,造成的一个事务需要等待另一个事务释放其所占用的资源后才能继续向下执行的现象

    事务1事务2
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;SET innodb_lock_wait_timeout = 3600 ;

    SELECT CONNECTION_ID();

    #当前连接的连接id 41

     
    BEGIN; 
    UPDATE `account` SET `deposit` = `deposit` + 100 WHERE `id` <= 3; 
     

    SELECT CONNECTION_ID();

    #当前连接的连接id 39

     BEGIN;
     

    UPDATE `account` SET `deposit` = `deposit` - 100 WHERE `id` <= 3;

    // 阻塞

    KILL 39;// ERROR 2013 (HY000): Lost connection to MySQL server during query
    ROLLBACK; 
     ROLLBACK;

     mysql -u root -p123456 tx

    -- 查询当前会话等待事务锁超时时间 默认50s
    SHOW VARIABLES LIKE 'innodb_lock_wait_timeout' ;
    -- 修改当前会话等待事务锁超时时间:
    SET innodb_lock_wait_timeout = 3600 ;

    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction  

    SELECT
      waiting_pid AS 'blocked pid',
      waiting_query AS 'blocked SQL',
      blocking_pid AS 'running pid',
      blocking_query AS 'running SQL',
      wait_age AS 'blocked time',
      sql_kill_blocking_query AS 'info'
    FROM
      sys.`innodb_lock_waits`
    WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(wait_started)) > 30 \G
    *************************** 1. row ***************************                 
     blocked pid: 39                                                               
     blocked SQL: UPDATE `account` SET `deposit` = `deposit` - 100 WHERE `id` <= 3 
     running pid: 41                                                               
     running SQL: NULL                                                             
    blocked time: 00:01:11                                                         
            info: KILL QUERY 41                                                    
    1 row in set (0.00 sec)                                                        

    如何处理阻塞?

    • 终止占用资源的事务 KILL;
    • 优化占用资源事务的SQL,使其尽快释放资源

    5.2 死锁

    5.2.1 什么是死锁

    并行执行的多个事务相互之间占有了对方所需要的资源

    5.2.2 演示死锁

    set global innodb_print_all_deadlocks = on ;

    演示死锁
    窗口1窗口2
    SET GLOBAL innodb_print_all_deadlocks = ON ; 
    # 退出在登陆,使设置生效 mysql -u root -p123456 tx 
    SHOW VARIABLES LIKE 'innodb_print_all_deadlocks'; 
    BEGIN; 
    UPDATE `account` SET `deposit` = 100000000 WHERE id = 1; 
     BEGIN;
     UPDATE `account` SET `deposit` = `deposit` + 10 WHERE id = 3;

    UPDATE `account` SET `deposit` = `deposit` + 10 WHERE id = 3;

    # 产生柱塞

     
     

    UPDATE `account` SET `deposit` = 10 WHERE id = 1;

    # ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    5.2.3 查看日志

    -- log_error就是错误日志的位置
    -- SHOW VARIABLES LIKE '%error%';
    SHOW VARIABLES LIKE 'log_error';

    5.2.4 如何处理死锁

    • 数据库自行回滚占用资源少的事务
    • 并发事务按相同顺序占有资源 (1->2->3->4 改为1->4->2->3)
    展开全文
  • 实验17事务与并发控制.pdf
  • 实验15事务与并发控制.pdf
  • 数据库教研室 第13章 事务与并发控制 软件学院 教学安排 事务概述 事务并发控制 封锁 1. 事务概述 事务(Transaction) 一组数据库操作的集合这些操作由一组相关的SQL语句组成事务是数据库系统中执行的一个独立工作...
  • 深入理解Mysql——锁、事务与并发控制

    万次阅读 多人点赞 2016-05-23 00:21:00
    深入理解Mysql——锁、事务与并发控制(辟谣) 深入理解Mysql——schema设计大表alter操作 mysql explain-output 译文 本文对锁、事务并发控制做一个总结,看了网上很多文章,描述非常不准确。如有您观点不...

    相关文章:
    深入理解Mysql——高性能索引与高性能SQL
    深入理解Mysql——锁、事务与并发控制
    深入理解Mysql——schema设计与大表alter操作
    mysql explain-output 译文

    本文对锁、事务、并发控制做一个总结,文章预计10分钟阅读完。本文内容均参考官方文档,尽可能严谨。读完本文将会对mysql锁\事务有一个较为深入的认识。

    1 mysql服务器逻辑架构

    这里写图片描述

    每个连接都会在mysql服务端产生一个线程(内部通过线程池管理线程),比如一个select语句进入,mysql首先会在查询缓存中查找是否缓存了这个select的结果集,如果没有则继续执行 解析、优化、执行的过程;否则会之间从缓存中获取结果集。


    2 mysql锁

    2.1 Shared and Exclusive Locks(共享锁与排他锁)

    它们都是标准的行级锁

    • 共享锁(S)
      共享锁也称为读锁,读锁允许多个连接可以同一时刻并发的读取同一资源,互不干扰;

    • 排他锁(X)
      排他锁也称为写锁,一个写锁会阻塞其他的写锁或读锁,保证同一时刻只有一个连接可以写入数据,同时防止其他用户对这个数据的读写。

    注意:所谓共享锁、排他锁其实均是锁机制本身的策略,通过这两种策略对锁做了区分。

    2.2 Intention Locks(意向锁)

    InnoDB支持多粒度锁(锁粒度可分为行锁和表锁),允许行锁和表锁共存。例如,一个语句,例如LOCK TABLES…WRITE接受指定表上的独占锁。为了实现多粒度级别的锁定,InnoDB使用了意图锁。

    意向锁:表级别的锁。先提前声明一个意向,并获取表级别的意向锁(IS或IX),如果获取成功,则稍后将要或正在(才被允许),对该表的某些行加锁(S或X)了。(除了 LOCK TABLES … WRITE,很少用,略)

    举例来说:

    SELECT … LOCK IN SHARE MODE,要获取IS锁;An intention shared lock (IS)

    SELECT … FOR UPDATE ,要获取IX锁;An intention exclusive lock (IX) i

    意向锁协议
    在事务能够获取表中的行上的共享锁之前,它必须首先获取表上的IS锁或更强的锁。
    在事务能够获取表中的行上的独占锁之前,它必须首先获取表上的IX锁。

    前文说了,意向锁实现的背景是多粒度锁的并存场景。如下兼容性的汇总:
    在这里插入图片描述

    意向锁仅表意向,是一种较弱的锁,意向锁之间兼容并行(IS、IX 之间关系兼容并行)。
    X与IS\IX互斥;S与IX互斥。

    可以体会到,意向锁是比X\S更弱的锁,存在一种预判的意义!先获取更弱的IX\IS锁,如果获取失败就不必要再花费跟大开销获取更强的X\S锁。

    2.3 Record Locks (索引行锁)

    record lock是一个在索引行记录的锁。

    比如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE,如果c1 上的索引被使用到。
    防止任何其他事务插入、更新或删除值为t的行。c1是10。

    record lock 总是会在索引行上加锁。即使一个表并没有设置索引,这种时候innoDB会创建一个隐式的聚集索引(primary Key),然后在这个聚集索引上加锁。

    在DML语句不走索引的语句中,比如这个DML update table set columnA=“A” where columnB=“B".

    如果columnB字段不存在索引(或者不是组合索引前缀),会锁住所有记录也就是锁表。如果语句的执行能够执行一个columnB字段的索引,那么会锁住满足where的行(RecordLock)。

    锁出现查看示例:
    (使用show engine innodb status命令查看):

    RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 
    trx id 10078 lock_mode X locks rec but not gap
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
     0: len 4; hex 8000000a; asc     ;;
     1: len 6; hex 00000000274f; asc     'O;;
     2: len 7; hex b60000019d0110; asc        ;;
    

    2.4 Gap locks(间隙锁)

    Gap Locks:
    锁定索引记录之间的间隙([2]),或者锁定一个索引记录之前的间隙([1]),或者锁定一个索引记录之后的间隙([3])。

    示例:如图[1]、[2]、[3]部分。一般作用于我们的范围查询> 、< 、between…
    在这里插入图片描述

    例如, SELECT userId FROM t1 WHERE userId BETWEEN 1 and 4 FOR UPDATE; 阻止其他事务将值3插入到列userId中。因为该范围内所有现有值之间的间隙都是锁定的。

    • 对于使用唯一索引来搜索唯一行的语句 select a from ,不产生间隙锁定。.
      (不包含组合唯一索引,也就是说gapLock不作用于单例唯一索引)

    例如,如果id列有唯一的索引,下面的语句只对id值为100的行使用索引记录锁,其他会话是否在前一个间隙中插入行并不重要:

    ```
    SELECT * FROM t1 WHERE id = 100;
    ```
    
    如果id**没有索引或具有非惟一索引,则语句将锁定前面的间隙**。
    
    • 间隙可以跨越单个索引值、多个索引值(如上图2,3),甚至是空的。

    • 间隙锁是性能和并发性之间权衡的一种折衷,用于某些特定的事务隔离级别,如RC级别(RC级别:REPEATABLE
      READ,我司为了减少死锁,关闭了gap锁,使用RR级别)。

    • 在重叠的间隙中(或者说重叠的行记录)中允许gap共存

      比如同一个gap中,允许一个事务持有 gap X-Lock(gap 写锁\排他锁),同时另一个事务在这个gap中持有(gap 写锁\排他锁)

    CREATE TABLE `new_table` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `a` int(11) DEFAULT NULL,
      `b` varchar(45) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_new_table_a` (`a`),
      KEY `idx_new_table_b` (`b`)
    ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8
    
    INSERT INTO `new_table` VALUES (1,1,'1'),(2,3,'2'),(3,5,'3'),(4,8,'4'),(5,11,'5'),(6,2,'6'),(7,2,'7'),(8,2,'8'),(9,4,'9'),(10,4,'10');
    
    
    
    ######## 事务一 ########
    START TRANSACTION;
    SELECT * FROM new_table WHERE a between 5 and 8 FOR UPDATE;
    ##暂不commit
    
    ######## 事务二 ########
    
    SELECT * FROM new_table WHERE a = 4 FOR UPDATE;
    
    ##顺利执行! 因为gap锁可以共存;
    
    
    ######## 事务三 ########
    
     SELECT * FROM new_table WHERE b = 3 FOR UPDATE;
     
    ##获取锁超时,失败。因为事务一的gap锁定了 b=3的数据。
     
    

    2.5 next-key lock

    next-key lock 是record lock 与 gap lock 的组合。

    比如 存在一个查询匹配b=3的行(b上有个非唯一索引),那么所谓NextLock就是:在b=3的行加了RecordLock 并且使用 GapLock锁定了b=3之前(“之前”:索引排序)的所有行记录。

    mysql查询时执行 行级锁策略,会对扫描过程中匹配的行进行加锁(X 或S),也就是加Record Lock,同时会对这个记录之前的所有行加GapLock锁。
    假设一个索引包含值10、11、13和20。该索引可能的NexKey Lock锁定以下区间:

    (negative infinity, 10]
    (10, 11]
    (11, 13]
    (13, 20]
    (20, positive infinity)
    

    另外,值得一提的是 : innodb中默认隔离级别(RR)下,next key Lock自动开启。
    (很好理解,因为gap作用于RR,如果是RC,gapLock不会生效,那么next key lock自然也不会)

    锁出现查看示例:
    (使用show engine innodb status命令查看):

    RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 
    trx id 10080 lock_mode X
    Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
     0: len 8; hex 73757072656d756d; asc supremum;;
    
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
     0: len 4; hex 8000000a; asc     ;;
     1: len 6; hex 00000000274f; asc     'O;;
     2: len 7; hex b60000019d0110; asc        ;;
    

    2.6 Insert Intention Locks(插入意向锁)

    一个insert intention lock 是一种发生在 insert 插入语句时的gap lock 间隙锁,锁定插入行之前的所有行。

    这个锁以这样一种方式表明插入的意图,如果插入到同一索引间隙中的多个事务没有插入到该间隙中的相同位置,则它们不需要等待对方。

    假设存在值为4和7的索引记录。尝试分别插入值为5和6的独立事务,在获得所插入行上的独占锁之前,每个事务使用insert intention lock 锁定4和7之间的间隙,但不会阻塞彼此,因为这些行不冲突。

    示例:

    mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
    mysql> INSERT INTO child (id) values (90),(102);
    
    ##事务一
    mysql> START TRANSACTION;
    mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;
    +-----+
    | id  |
    +-----+
    | 102 |
    +-----+
    
    ##事务二
    
    mysql> START TRANSACTION;
    mysql> INSERT INTO child (id) VALUES (101);
    ##失败,已被锁定
    
    mysql> SHOW ENGINE INNODB STATUS
     
    RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
    trx id 8731 lock_mode X locks gap before rec insert intention waiting
    Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
     0: len 4; hex 80000066; asc    f;;
     1: len 6; hex 000000002215; asc     " ;;
     2: len 7; hex 9000000172011c; asc     r  ;;...
    

    2.7 AUTO-INC Locks

    AUTO-INC锁是一种特殊的表级锁,产生于这样的场景:事务插入(inserting into )到具有AUTO_INCREMENT列的表中。

    在最简单的情况下,如果一个事务正在向表中插入值,那么其他任何事务必须等待向该表中插入它们自己的值,以便由第一个事务插入的行接收连续的主键值。

    2.8 Predicate Locks for Spatial Indexes 空间索引的谓词锁


    3 事务

    事务就是一组原子性的sql,或者说一个独立的工作单元。
    事务就是说,要么mysql引擎会全部执行这一组sql语句,要么全部都不执行(比如其中一条语句失败的话)。

    • 自动提交(AutoCommit,mysql默认)
    show variables like "autocommit";
    
    set autocommit=0; //0表示AutoCommit关闭
    set autocommit=1; //1表示AutoCommit开启
    

    mysql默认采用AutoCommit模式,也就是每个sql都是一个事务,并不需要显示的执行事务。

    如果autoCommit关闭,那么每个sql都默认开启一个事务,只有显式的执行“commit”后这个事务才会被提交。

    • 显示事务 (START TRANSACTION…COMMIT)

    比如,tim要给bill转账100块钱:
    1.检查tim的账户余额是否大于100块;
    2.tim的账户减少100块;
    3.bill的账户增加100块;

    这三个操作就是一个事务,必须打包执行,要么全部成功,
    要么全部不执行,其中任何一个操作的失败都会导致所有三个操作“不执行”——回滚。

    CREATE DATABASE IF NOT EXISTS employees;
    USE employees;
    
    CREATE TABLE `employees`.`account` (
      `id` BIGINT (11) NOT NULL AUTO_INCREMENT,
      `p_name` VARCHAR (4),
      `p_money` DECIMAL (10, 2) NOT NULL DEFAULT 0,
      PRIMARY KEY (`id`)
    ) ;
    INSERT INTO `employees`.`account` (`id`, `p_name`, `p_money`) VALUES ('1', 'tim', '200'); 
    INSERT INTO `employees`.`account` (`id`, `p_name`, `p_money`) VALUES ('2', 'bill', '200'); 
    
    START TRANSACTION;
    SELECT p_money FROM account WHERE p_name="tim";-- step1
    UPDATE account SET p_money=p_money-100 WHERE p_name="tim";-- step2
    UPDATE account SET p_money=p_money+100 WHERE p_name="bill";-- step3
    COMMIT;
    

    一个良好的事务系统,必须满足ACID特点:

    3.1 事务的ACID

    • A:atomiciy原子性
      一个事务必须保证其中的操作要么全部执行,要么全部回滚,不可能存在只执行了一部分这种情况出现。

    • C:consistency一致性
      数据必须保证从一种一致性的状态转换为另一种一致性状态
      比如上一个事务中执行了第二步时系统崩溃了,数据也不会出现bill的账户少了100块,但是tim的账户没变的情况。要么维持原装(全部回滚),要么bill少了100块同时tim多了100块,只有这两种一致性状态的

    • I:isolation隔离性
      在一个事务未执行完毕时,通常会保证其他Session 无法看到这个事务的执行结果

    • D:durability持久性
      事务一旦commit,则数据就会保存下来,即使提交完之后系统崩溃,数据也不会丢失。

    4 隔离级别

    这里写图片描述

    查看系统隔离级别:
    select @@global.tx_isolation;
    查看当前会话隔离级别
    select @@tx_isolation;
    设置当前会话隔离级别
    SET session TRANSACTION ISOLATION LEVEL serializable;
    设置全局系统隔离级别
    SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    

    4.1 READ UNCOMMITTED(未提交读,可脏读)

    事务中的修改,即使没有提交,对其他会话也是可见的。

    可以读取未提交的数据——脏读。脏读会导致很多问题,一般不适用这个隔离级别。
    实例:

    -- ------------------------- read-uncommitted实例 ------------------------------
    -- 设置全局系统隔离级别
    SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    -- Session A
    START TRANSACTION;
    SELECT * FROM USER;
    UPDATE USER SET NAME="READ UNCOMMITTED";
    -- commit;
    
    -- Session B
    SELECT * FROM USER;
    
    //SessionB Console 可以看到Session A未提交的事物处理,在另一个Session 中也看到了,这就是所谓的脏读
    id	name
    2	READ UNCOMMITTED
    34	READ UNCOMMITTED
    
    

    4.2 READ COMMITTED(提交读或不可重复读,幻读)

    一般数据库都默认使用这个隔离级别(mysql不是),
    这个隔离级别保证了一个事务如果没有完全成功(commit执行完),事务中的操作对其他会话是不可见的

    -- ------------------------- read-cmmitted实例 ------------------------------
    -- 设置全局系统隔离级别
    SET GLOBAL TRANSACTION ISOLATION LEVEL READ  COMMITTED;
    -- Session A
    START TRANSACTION;
    SELECT * FROM USER;
    UPDATE USER SET NAME="READ COMMITTED";
    -- COMMIT;
    
    -- Session B
    SELECT * FROM USER;
    
    //Console OUTPUT:
    id	name
    2	READ UNCOMMITTED
    34	READ UNCOMMITTED
    
    
    ---------------------------------------------------
    -- 当 Session  A执行了commit,Session B得到如下结果:
    id	name
    2	READ COMMITTED
    34	READ COMMITTED
    

    也就验证了read committed级别在事物未完成commit操作之前修改的数据对其他Session 不可见,执行了commit之后才会对其他Session 可见。
    我们可以看到Session B两次查询得到了不同的数据。

    read committed隔离级别解决了脏读的问题,但是会对其他Session 产生两次不一致的读取结果(因为另一个Session 执行了事务,一致性变化)。


    4.3 REPEATABLE READ(可重复读)

    一个事务中多次执行统一读SQL,返回结果一样。
    这个隔离级别解决了脏读的问题,幻读问题。

    这里指的是innodb的rr级别,innodb中使用next-key锁对"当前读"进行加锁,锁住行以及可能产生幻读的插入位置,阻止新的数据插入产生幻行。
    下文中详细分析。

    具体请参考mysql手册

    https://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html

    4.4 SERIALIZABLE(可串行化)

    最强的隔离级别,通过给事务中每次读取的行加锁,写加写锁,保证不产生幻读问题,但是会导致大量超时以及锁争用问题。


    5 并发控制 与 MVCC

    MVCC(multiple-version-concurrency-control)是个行级锁的变种,
    它在普通读情况下避免了加锁操作,因此开销更低

    虽然实现不同,但通常都是实现非阻塞读,对于写操作只锁定必要的行

    • 一致性读 (就是读取快照)
      select * from table …;

    • 当前读(就是读取实际的持久化的数据)
      特殊的读操作,插入/更新/删除操作,属于当前读,处理的都是当前的数据,需要加锁。
      select * from table where ? lock in share mode;
      select * from table where ? for update;
      insert;
      update ;
      delete;

    注意:select … from where… (没有额外加锁后缀)使用MVCC,保证了读快照(mysql称为consistent read),

    所谓一致性读或者读快照就是读取当前事务开始之前的数据快照,在这个事务开始之后的更新不会被读到。

    详细情况下文select的详述。

    对于加锁读SELECT with FOR UPDATE(排他锁) or LOCK IN SHARE MODE(共享锁)、
    update、delete语句,要考虑是否是唯一索引的等值查询。

    INNODB的MVCC通常是通过在每行数据后边保存两个隐藏的列来实现(其实是三列,第三列是用于事务回滚,此处略去),

    一个保存了行的创建版本号,另一个保存了行的更新版本号(上一次被更新数据的版本号)
    这个版本号是每个事务的版本号,递增的。

    这样保证了innodb对读操作不需要加锁也能保证正确读取数据。

    5.1 MVCC select无锁操作 与 维护版本号

    下边在mysql默认的Repeatable Read隔离级别下,具体看看MVCC操作:

    • Select(快照读,所谓读快照就是读取当前事务之前的数据。):
      a.InnoDB只select查找版本号早于当前版本号的数据行,这样保证了读取的数据要么是在这个事务开始之前就已经commit了的(早于当前版本号),要么是在这个事务自身中执行创建操作的数据(等于当前版本号)。

      b.查找行的更新版本号要么未定义,要么大于当前的版本号(为了保证事务可以读到老数据),这样保证了事务读取到在当前事务开始之后未被更新的数据。
      注意: 这里的select不能有for update、lock in share 语句。
      总之要只返回满足以下条件的行数据,达到了快照读的效果:

    (行创建版本号< =当前版本号 && (行更新版本号==null or 行更新版本号>当前版本号 ) )
    
    • Insert

      InnoDB为这个事务中新插入的行,保存当前事务版本号的行作为行的行创建版本号。

    • Delete
      InnoDB为每一个删除的行保存当前事务版本号,作为行的删除标记。

    • Update

      将存在两条数据,保持当前版本号作为更新后的数据的新增版本号,同时保存当前版本号作为老数据行的更新版本号。

    当前版本号—写—>新数据行创建版本号 && 当前版本号—写—>老数据更新版本号();
    

    5.2 脏读 vs 幻读 vs 不可重复读

    脏读一事务未提交的中间状态的更新数据 被其他会话读取到。

    当一个事务正在访问数据,并且对数据进行了修改,
    而这种修改还没有 提交到数据库中(commit未执行),
    这时,另外会话也访问这个数据,因为这个数据是还没有提交,
    那么另外一个会话读到的这个数据是脏数据,依据脏数据所做的操作也可能是不正确的。

    不可重复读简单来说就是在一个事务中读取的数据可能产生变化,ReadCommitted也称为不可重复读

    在同一事务中,多次读取同一数据返回的结果有所不同。
    换句话说就是,后续读取可以读到另一会话事务已提交的更新数据。
    相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,
    也就是,后续读取不能读到另一会话事务已提交的更新数据。

    幻读:会话T1事务中执行一次查询,然后会话T2新插入一行记录,这行记录恰好可以满足T1所使用的查询的条件。然后T1又使用相同 的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。

    这个新行就称为“幻像”,因为对T1来说这一行就像突然 出现的一样。

    innoDB的RR级别无法做到完全避免幻读,下文详细分析。

    在这里插入图片描述

    5.3 如何保证rr级别绝对不产生幻读?

    在使用的select …where语句中加入 for update(排他锁) 或者 lock in share mode(共享锁)语句来实现。其实就是锁住了可能造成幻读的数据,阻止数据的写入操作。

    其实是因为数据的写入操作(insert 、update)需要先获取写锁,由于可能产生幻读的部分,已经获取到了某种锁,所以要在另外一个会话中获取写锁的前提是当前会话中释放所有因加锁语句产生的锁。

    5.4 从另一个角度看锁:显式锁 隐式锁

    隐式锁:我们上文说的锁都属于不需要额外语句加锁的隐式锁。

    显示锁

    SELECT ... LOCK IN SHARE MODE(加共享锁);
    SELECT ... FOR UPDATE(加排他锁);
    

    详情上文已经说过。

    5.5查看锁情况

    通过如下sql可以查看等待锁的情况

    select * from information_schema.innodb_trx where trx_state="lock wait";
    或
    show engine innodb status;
    

    6 mysql死锁问题

    死锁,就是产生了循环等待链条,我等待你的资源,你却等待我的资源,我们都相互等待,谁也不释放自己占有的资源,导致无线等待下去。
    比如:

    //Session A
    START TRANSACTION;
    UPDATE account SET p_money=p_money-100 WHERE p_name="tim";
    UPDATE account SET p_money=p_money+100 WHERE p_name="bill";
    COMMIT;
    //Thread B
    START TRANSACTION;
    UPDATE account SET p_money=p_money+100 WHERE p_name="bill";
    UPDATE account SET p_money=p_money-100 WHERE p_name="tim";
    COMMIT;
    

    当线程A执行到第一条语句UPDATE account SET p_money=p_money-100 WHERE p_name=“tim”;锁定了p_name="tim"的行数据;并且试图获取p_name="bill"的数据;

    ,此时,恰好,线程B也执行到第一条语句:UPDATE account SET p_money=p_money+100 WHERE p_name=“bill”;

    锁定了 p_name="bill"的数据,同时试图获取p_name="tim"的数据;
    此时,两个线程就进入了死锁,谁也无法获取自己想要获取的资源,进入无线等待中,直到超时!

    innodb_lock_wait_timeout 等待锁超时回滚事务:
    直观方法是在两个事务相互等待时,当一个等待时间超过设置的某一阀值时,对其中一个事务进行回滚,另一个事务就能继续执行。这种方法简单有效,在innodb中,参数innodb_lock_wait_timeout用来设置超时时间。

    wait-for graph算法来主动进行死锁检测:
    innodb还提供了wait-for graph算法来主动进行死锁检测,每当加锁请求无法立即满足需要并进入等待时,wait-for graph算法都会被触发。

    6 .1 如何尽可能避免死锁

    1) 以固定的顺序访问表和行。比如两个更新数据的事务,事务A 更新数据的顺序 为1,2;事务B更新数据的顺序为2,1。这样更可能会造成死锁。

    2) 大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。

    3) 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。

    4) 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。(我司mysql规范做法)

    5) 为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。

    延伸阅读:
    https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html

    展开全文
  • 二、并发控制概述 2.1事务的并发执行 2.2并发执行导致的问题 2.2.1丢失修改 2.2.2读“脏”数据 2.2.3不可重复读 三、封锁 3.1基本锁类型 3.2封锁协议 3.2.1一级封锁协议 3.2.2二级封锁协议 3.2.3三级封锁...

    目录

    一、事务概述

    1.1定义

    1.2特性

    二、并发控制概述

    2.1事务的并发执行

    2.2并发执行导致的问题

    2.2.1丢失修改

    2.2.2读“脏”数据

    2.2.3不可重复读

    三、封锁

    3.1基本锁类型

    3.2封锁协议

    3.2.1一级封锁协议

    3.2.2二级封锁协议

    3.2.3三级封锁协议

    3.3活锁与死锁

    3.3.1活锁

    3.3.2死锁

    3.3.3死锁的检测与解除

    四、并发调度的可串行化

    4.1串行调度与并发调度

    4.1.1串行调度

    4.1.2并发调度

    4.2冲突可串行化

    五、两阶段锁协议

    六、多封锁粒度

    6.1粒度

    6.2意向锁


    一、事务概述

    1.1定义

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

    事务是并发控制的基本单位,是数据库恢复的基本单位,是数据库的逻辑基本逻辑单元

    数据库恢复机制和并发控制机制是数据库管理系统的重要组成部分

    在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序

    --显式定义事务
    begin transaction 
    SQL 语句1 
    ……  ……
    commit / rollback
    
    /*
    commit
        事务正常结束
        提交事务的所有操作(读+更新)
        事务中所有对数据库的更新写回到磁盘上的物理数据库中
    
    rollback
        事务异常终止
        事务运行的过程中发生了故障,不能继续执行
        系统将事务中对数据库的所有已完成的操作全部撤销
        事务滚回到开始时的状态
    */
    --将数学课程号由2修改为22
    /*
    解析:
    所涉及的关系:Course和SC,根据参照完整性约束,应将两表中的2都改为22。要将修改两个表的两个SQL语句定义成一个事务。因为DBMS对这两个语句要么都执行,要不都不执行
    */
    
    begin transaction
        update Course set CNO='22' where CNO='2'
        update SC set CNO='2' where CNO='22'
    commit

     

    1.2特性

    原子性 

    • 事务是数据库的逻辑工作单元
    • 事务的所有操作要么都全部成功地执行,要么都不执行
    • 若事务因故障而中止,则要设法消除该事务所产生的影响,使数据库恢复到该事务执行前的状态

    一致性

    • 事务执行的结果必须使数据库从一个一致性状态转变到另一个一致性状态

    隔离性 

    • 一个事务的执行不能被其他事务干扰。多个事务并发执行,任何事物的更新操作直到其成功提交,对其他事务都是不可见的

    持久性 

    • 一个事务完成后,它对数据库的改变必须是永久的,即使系统出现故障,它对数据库的更新也将永久有效

     

     

    二、并发控制概述

    事务的并发执行是数据库系统提高系统效率的有效方法,但可能破坏事务的 ACID性质,导致数据的不一致性

    2.1事务的并发执行

    1、并发执行的理由

    • 提高吞吐量和资源利用率
    • 减少等待时间

    2、并发执行方式

    • 交叉并发方式
    1. 单机系统中,事务的并行操作轮流交叉运行
    2. 优点:能够减少处理机的空闲时间,提高系统的效率
    3. 缺点:不是真正的并发操作,可能会产生数据不一致
    • 同时并发方式
    1. 多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现多个事务真正的并行运行
    2. 优点:最理想的并发方式
    3. 缺点:受制于硬件环境,同样可能会产生数据不一致

     

    2.2并发执行导致的问题

    2.2.1丢失修改

    2.2.2读“脏”数据

    2.2.3不可重复读

    产生原因

    • 事务T1读取某一数据后,事务T2对其做了修改,事务T1再次读取该数据时,发现与前次不同
    • 事务T1按一定条件读取了某些数据记录后,事务T2删除了其中的部分记录,事务T1再次按相同条件读取记录时,发现有些记录不存在
    • 事务T1按一定条件读取了某些数据记录后,事务T2插入了一些记录,事务T1再次按相同条件读取记录时,发现多了一些记录

     

    例:飞机订票系统中的一个活动序列

    ①甲售票点(事务T1)读出某航班的机票余额A,设A=16;

    ②乙售票点(事务T2)读出同一航班的机票余额A,也为16;

    ③甲售票点卖出一张机票,修改余额A←A-1,所以A为15,把A写回数据库;

    ④乙售票点也卖出一张机票,修改余额A←A-1,所以A为15,把A写回数据库

    结果明明卖出两张机票,数据库中机票余额只减少1

    这种情况称为数据库的不一致性,是由并发操作引起的

    在并发操作情况下,对T1、T2两个事务的操作序列的调度是随机的。若按上面的调度序列执行,T1事务的修改就被丢失。原因:第4步中T2事务修改A并写回后覆盖了T1事务的修改

    产生上述三类不一致性的主要原因就是并发操作破坏了事务的隔离性。并发控制就是要用正确的方式调度并发操作,使某个事务的执行不受其它事务的干扰

    并发控制的主要技术:封锁、时间戳、乐观控制法、多版本并发控制

     

     

    三、封锁

    封锁即事务在对某个数据对象操作之前,先向系统发出加锁请求,加锁后事务对该数据对象有了一定的控制权,在事务释放它的锁之前,其他事务不能更新该数据对象

    3.1基本锁类型

    排它锁,又称写锁或X,若事务 T对数据对象 A加上X锁,则只允许 T读取和修改 A,任何其它事务都不能再对 A读取和修改,直到 T释放A上的锁

    共享锁,又称读锁或S,若事务 T对数据对象 A加上 S锁,则事务 T可以读 A但不能修改 A,其它事务只能再对 A读取,而不能修改,直到 T释放 A上的锁2.2封锁协议

     

    3.2封锁协议

    3.2.1一级封锁协议

    事务T在修改数据对象R之前必须先对其加X锁,直到事务结束才释放

    作用:一级封锁协议可防止丢失修改,并保证事务T是可恢复的

    说明:在一级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和不读“脏”数据

    3.2.2二级封锁协议

    在一级封锁协议的基础上,事务T在读取数据对象R之前必须先对其加S锁,但是读完后即可释放S锁

    作用:二级封锁协议可以防止丢失修改和读“脏”数据

    说明:在二级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读

    3.2.3三级封锁协议

    在一级封锁协议的基础上,事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放

    作用:三级封锁协议可防止丢失修改、读脏数据和不可重复读

    三级协议的主要区别

    • 什么操作需要申请封锁以及何时释放锁(即持锁时间)
    • 封锁协议级别越高,一致性程度越高

     

     

    X

    S

    一致性保证

     

    操作结束释放

    事务结束释放

    操作结束释放

    事务结束释放

    不丢失

    修改

    不读“脏”数据

    可重复

    一级封锁协议

     

     

     

     

     

    二级封锁协议

     

     

     

    三级封锁协议

     

     

     

    3.3活锁与死锁

    3.3.1活锁

    又称饥饿,是某个事务因等待锁而处于无限期等待状态

    避免活锁:先来先服务,当多个事务请求封锁同一数据对象时,按请求封锁的先后次序对这些事务排队,该数据对象上的锁一旦释放,首先批准申请队列中第一个事务获得锁

    3.3.2死锁

    两个或两个以上的事务之间的循环等待现象

    死锁的预防

    1、一次性封锁法

    每个事务必须一次将所有要使用的数据对象全部加锁后,在实际执行实务操作,否则事务不进行任何实际行动也不封锁任何数据

    存在问题

    • 使数据的上锁时间增长,降低系统的并发度
    • 事先确定事务要封锁的数据对象很难

    2、顺序封锁法

    预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁

    存在的问题

    • 维护成本很高,数据库系统中封锁的数据对象极多,并且随数据的插入、删除等操作而不断地变化,要维护这样的资源的封锁顺序非常困难

    上述两种方法虽然都可以有效地预防死锁,但都存在一些问题,因此真正实施起来并不方便。所以预防死锁的策略不很适合数据库的特点,DBMS普遍采用诊断死锁并解除的方法

    3.3.3死锁的检测与解除

    1、死锁的检测

    数据库系统通常采用超时或事务等待图法发现死锁

    2、解除死锁

    选择一个或多个处于死锁状态的事务,将其撤消并释放这些事务持有的所有的锁,从而打破了循环等待条件,解除死锁,使其它事务能够继续运行

     

     

    四、并发调度的可串行化

    4.1串行调度与并发调度

    4.1.1串行调度

    一组事务的串行调度是指这些事务一个接一个地执行,其中每个事务都在上一个事务(如果有)完全结束之后才开始执行

    对于一组事务,串行调度总是正确的

    对于 n个事务,存在 n! 个不同的串行调度,可能导致不同的结果

    4.1.2并发调度

    一组事物的并发调度是指这些事务中至少有两个事务都开始了它们的执行,并且都尚未结束

    并发调度正确性规则:一组事物的并发调度是正确的,当且仅当调度的执行结果与某一个串行调度的执行结果相同,此时称并发调度是可串行化的

     

    4.2冲突可串行化

    冲突操作:是指不同的事务对同一数据的读写操作和写写操作

         Ri(x)与Wj(x)         /*事务Ti读x,Tj写x,其中i≠j*/

         Wi(x)与Wj(x)         /*事务Ti写x,Tj写x,其中i≠j*/

    不能交换的动作包括一事务的两个操作不同事务的冲突操作

    一个调度Sc在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度Sc',如果Sc'是串行的,称调度Sc是冲突可串行化的调度若一个调度是冲突可串行化,则一定是可串行化的调度

    冲突可串行化调度是可串行化调度的充分条件,不是必要条件

     

     

    五、两阶段锁协议

    “两阶段”锁的含义是事务分为两个阶段

    第一阶段是获得封锁,也称为扩展阶段

    • 事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁

    第二阶段是释放封锁,也称为收缩阶段

    • 事务可以释放任何数据项上的任何类型的锁,但是不能再申请任何锁

    两阶段锁协议的正确性

    • 若所有事务都遵守两段封锁协议,则对这些事务的任何并发调度策略都是可串行化的
    • 两阶段锁协议是并发控制正确性的充分条件,但不是必要条件。即若所有事务都遵守两阶段锁协议,则这些事务的任何并发调度都是可串行化的,反之,一个并发调度是可串行化的,不一定所有事务都遵守两阶段锁协议

    两段锁协议与防止死锁的一次封锁法

    • 一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行,因此一次封锁法遵守两段锁协议
    • 但是两段锁协议并不要求事务必须一次将所有要使用的数据全部加锁,因此遵守两段锁协议的事务可能发生死锁

     

     

    六、多封锁粒度

    6.1粒度

    封锁对象的大小称为粒度,可以是数据库、表、记录、字段等

    封锁粒度与系统的并发度和并发控制的开销密切相关。封锁的粒度越大,数据库所能够封锁的数据单元就越少,并发度就越小,系统开销也越小;封锁的粒度越小,并发度越高,但系统开销也就越大


    多粒度封锁是同时支持多种封锁粒度供不同事务选择的封锁方法

    • 依赖的数据结构——多粒度树
    1. 将数据库中的数据对象按相互关系和粒度大小组织成的树型结构,其中根结点表示最大数据粒度,通常为整个数据库,叶结点表示最小数据粒度

    多粒度封锁协议允许对多粒度树中的每个结点独立地加锁,并且对每一个结点加锁隐含着对其后裔结点也加以同样的锁

    • 在多粒度封锁中一个数据对象可能以两种方式封锁:显式封锁隐式封锁
    1. 由事务直接加到数据对象上的封锁称为显式封锁
    2. 因上级结点加锁而引起下级对象被封锁,称为隐式封锁
    3. 显式封锁和隐式封锁的效果是一样

    系统检查封锁冲突时要检查显式封锁还要检查隐式封锁

    多粒度封锁方法

    为对某数据对象加锁,系统要检查

    • 该对象有无显式封锁与之冲突
    • 该对象的上级结点有无显式封锁与之冲突
    • 该对象的下级结点有无显式封锁与之冲突

    当无任何冲突时方能加锁成功

     

    6.2意向锁

    对任一结点加锁时,必须先对其上级结点加意向锁

    目的:提高对某个数据对象加锁时系统的检查效率

    作用:减少加锁时的封锁冲突检查工作量。只需检查上级结点与本结点是否已加了不相容的锁,并通过本结点的意向锁了解下级结点是否有不相容的锁,从而不必再检查下级结点

    三种意向锁

    • 意向共享锁(IS锁):如果对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁
    • IX锁:如果对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁
    • SIX锁:如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX = S + IX

    锁的强度 指它对其他锁的排斥程度,一个事务在申请封锁时以强锁代替弱锁是安全的,反之则不然

    意向锁的封锁和释放顺序

    • 申请封锁时应该按自上而下的次序进行
    • 释放封锁时则应该按自下而上的次序进行
    展开全文
  • 事务与并发控制的认识

    千次阅读 2016-01-04 22:43:55
    一:事务的概念 事务的特性:ACID,即原子性,一致性,隔离性和持久性。 事务的状态:活跃状态,部分提交状态,提交状态,失败状态和中止状态。 SQL对事务的支持: SQL中的事务的开始是隐含的,结束有两种形式:...

    一:事务的概念

    事务的特性:ACID,即原子性,一致性,隔离性和持久性。

    事务的状态:活跃状态,部分提交状态,提交状态,失败状态和中止状态。

    SQL对事务的支持:

    SQL中的事务的开始是隐含的,结束有两种形式:

    COMMIT WORK

    ROLLBACK WORK

    SET TRANSACTION语句的格式:

    SET TRANSACTION 事务模式列表

    事务模式列表有存取列表和隔离级别,存取列表有READ ONLY和READ WRITE。隔离级别格式:

    ISOLATION LEVEL 级别

    级别可以是:READ UNCOMMITED,READ COMMITED,REAPTABLE READ,SERIALIZATION。

    二:并发控制概述

    方式:交叉并发方式和同时并发方式。

    并发执行可能导致的问题:覆盖修改,读脏数据,不可重复读,其中不可重复读有值改变,记录消失,多出记录。

    三:并发调度的可串行化

    四:基于锁的协议

    共享锁和排他锁:

    S锁和X锁。

    读锁和写锁。

    锁相容矩阵。

    申请和释放锁的语句格式:

    lock-S(Q)

    lock-X(Q)

    unlock(Q)

    封锁协议:

    一级封锁协议:事务T更新数据对象Q之前,要申请X锁,并且事务结束后才释放锁。

    二级封锁协议:在一级封锁协议的基础上,事务T读取数据对象Q之前,要申请S锁,读取完就立即释放锁。

    三级封锁协议:在一级封锁协议的基础上,事务T读取数据对象Q之前,要申请S锁,但是事务结束后才释放锁。

    READ UNCOMMITED,READ COMMITED和REPEATABLE READ分别对应一级封锁协议,二级封锁协议和三级封锁协议。

    活锁和死锁:

    活锁就是事务进入无限期等待状态,是由于不公平的锁调度导致的。

    死锁就是多个事务进入循环等待状态。处理方法有预防措施和允许措施。

    死锁的预防:一次封锁法和顺序封锁法。

    死锁的检测和解除:

    死锁的检测:超时法和等待图法。

    死锁的解除。

    事务与并发控制。



    展开全文
  • 本篇介绍 PostgreSQL 中的数据库事务概念和 ACID 属性,并发事务可能带来的问题以及 4 种隔离级别,演示了如何使用事务控制语句(TCL)对事务进行处理,包括 BEGIN、COMMIT、ROLLBACK 以及 SAVEPOINT 语句。
  • 3.在数据库中为什么要有并发控制? 答:为避免多个事务之间的相互干扰。 4.并发控制的措施是什么? 答:加锁。 5.设有三个事务:T1、T2和T3,其所包含的动作为: T1:A = A + 2;T2:A = A * 2;T3:A = A - 1 .....
  • Hibernate事务并发控制Hibernate事务并发控制Hibernate事务并发控制
  • 事务并发控制

    2018-12-01 12:41:01
    该PPT讲解,事务,嵌套事务,保存点,乐观并发控制及时间戳
  • 这是一节关于研究生研一分布式设计课程中的课件,里面的内容是关于分布式事务并发控制
  • Hibernate事务并发控制 实例,想深入理解Hiberante的朋友,可以去研究一下。
  • 数据库处理的经典资料: 叫你处理事务 如何并发处理 瞧瞧吧 机不可失哟
  • 事务并发控制

    2013-07-26 21:27:40
    并发控制指的是当多个用户同时更新运行时,用于保护数据库完整性的各种技术。并发机制不正确可能导致脏读、幻读和不可重复读等此类问题。并发控制的目的是保证一个用户的工作不会对另一个用户的工作产生不合理的影响...
  • Redis事务并发控制

    千次阅读 2020-03-04 16:15:28
    什么是Redis事务? Redis事务不保证原子性, 即事务中的某个命令执行失败, 事务不会回滚, 且后续命令会继续执行. 这样一来, Redis事务的功能就和脚本差不多, 都是将命令打包, Redis事务能做的事, 脚本也能做, 而且脚本...
  • 不同事务之间可能会互相影响,比如一个事务修改另一个事务也改了,但是另一个事务的修改把这个事务的修改给覆盖掉了,这就是所说的事务并发控制问题。 如果不对事务进行并发控制,可能会产生四种异常情况 幻读...
  • 第7节 事务并发控制技术.docx
  • 事务并发控制T-SQL

    2018-12-01 12:43:41
    该PPT详细讲解分布式系统的并发控制,包括乐观控制和悲观控制的比较
  • 为有效地保证分布式事务的ACID性质以及解决多个客户程序并发访问某一事务所造成的访问冲突,根据CORBA对象事务服务OTS(Object Transaction Service)、并发控制服务CCS(Concurrency Control Service)及其提供的...
  • 事务处理与并发控制 PostgreSQL提供了多种数据完整性的保证机制,如约束、触发器、约束和锁管理等。 12.1 事务管理简介 事务是PostgreSQL中的基本工作单元,是用户定义的一个数据库操作序列,这些操作要么全做要么...
  • 并发控制与事务处理(For visual studio 2005)
  • HBase 事务并发控制机制原理

    万次阅读 2017-05-25 21:33:35
    为了实现事务特性,HBase采用了各种并发控制策略,包括各种锁机制、MVCC机制等。本文首先介绍HBase的两种基于锁实现的同步机制,再分别详细介绍行锁的实现以及各种读写锁的应用场景,最后重点介绍MVCC机制的实现策略...
  • J2EE事务并发控制策略总结 当前J2EE项目中,面临的一个共同问题就是如果控制事务的并发访问,虽然有些持久层框架已经为我们做了很多工作,但是理解原理,对于我们开发来说还是很有用处
  • 数据库事务并发控制

    千次阅读 2016-06-24 09:46:56
    一、数据库的事务:  事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是不可分割的一个序列。 事务的特征:(ACID) 1、原子性:事务的操作要么全做要么全不做。 2、一致性:事务操作的结果是...
  • MySQL之锁、事务并发控制

    千次阅读 2013-11-24 15:39:09
    并发控制 无论何时,只要不止一个查询同时修改数据,都会产生并发控制问题--并发读和并发写。 读锁(Read Lock)/写锁(Write Lock) 锁系统是用于处理并发读或并发写时出现的数据不一致等问题。也称为共享锁...
  • C、并发控制 D、完整性控制 2、下列说法正确的是___ A、事务故障可以通过运行日志进行恢复 B、介质故障只需将备份恢复到系统中即可实现 正确性 C、检查点是指检查发生故障并进行恢复的时刻 点 D、检查点是DBMS强制使...
  • 嵌入式实时数据库系统中的并发控制除保证数据库一致性不被破坏外,还须考虑事务的定时限制及减少解除数据冲突开销。该文讨论了一个基于封锁的、可避免循环夭折的有条件高优先级天折并发控制协议ACA-HPA-AC,包括其...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 176,651
精华内容 70,660
关键字:

事务与并发控制