美文网首页
MySQL事务&锁机制

MySQL事务&锁机制

作者: 老衲灬 | 来源:发表于2018-09-19 22:07 被阅读46次

    一、事务(transaction)

    1、概念
    事物用于保护多个SQL语句的执行,只要有一个失败则全部失败,反之都成功。
    2、事务语法(SQL语句)
    开启事务:start transactionbegin
    提交事务:commit
    回滚事务:rollback
    注意:
    -> 存储引擎必须是innodb
    -> 默认是开启事务的
    -> 后期通过PHP判断是否都执行成功commit,失败rollback
    3、PHP业务逻辑示例

    #1.创建PDO对象
    $pdo = new PDO('mysql:dbname=db2', 'root', 'root');
    #2.开启事务
    $pdo->beginTransaction();
    #3.业务逻辑代码
    $rs = $pdo->exec('执行SQL语句插入主表');
    if (!$rs) {
        $pdo->rollback();
        exit;
    }
    
    foreach ($orderInfos as $orderInfo) {
        $rs = $pdo->exec('执行SQL语句插入从表');
        if (!$rs) {
            $pdo->rollback();
            exit;
        }
    }
    
    $pdo->commit();
    echo '订单创建成功';
    
    #1.连接数据库
    try {
        $pdo = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
        die("数据库连接失败".$e->getMessage());
    }
    
    #2.执行数据操作
    try{
        //开启事物 
        $pdo->beginTransaction();
        //插入数据
        $rs = $pdo->exec('执行SQL语句插入主表');
        if (!$rs) throw new Exception("主表插入失败");
        //-------------------------------------------
        foreach ($orderInfos as $orderInfo) {
            $rs = $pdo->exec('执行SQL语句插入从表');
            if (!$rs) throw new Exception("从表插入失败");
        }
        $pdo->commit();
        echo '订单创建成功';
    }catch(PDOException $e){
        echo '执行失败'.$e->getMessage();
        $pdo->rollback();
    }
    

    5、事务的特性(ACID)
    原子性(Atomicity):开启事物后的所有操作要么全部提交成功,要么全部失败回滚
    隔离性(Isolation):多用户操作,A开启事物后,不会被B干扰
    一致性(Consistency):数据库数据从一个一致性的状态转换到另一个一致性的状态。
    举例假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来还得是5000,这就是事务的一致性
    永久性(Durability):提交事务后对数据的修改是永久性的

    二、锁机制

    1、概念
    在MySQL数据库中MyISAM存储引擎采用的是表级锁,InnoDB存储引擎采用的是行级锁、也支表级锁。
    锁分两种模式:
    ①共享读锁/共享锁(lock table 表名 read
    特性:自己-只能读,其他(读-可以,写-堵塞)
    ②独占写锁/排它锁(lock table 表名 write
    特性:自己-可读可写,其他(读-堵塞,写-堵塞)
    释放锁:unlock table

    2、示例(表锁)
    -> MyISAM表锁

    create table lock_t1 (
    id int primary key auto_increment,
    name varchar(30) not null 
    )engine=myisam charset=utf8;
    
    #session1,开启共享锁:自己-仅可以读,其他人(读-可以,写-堵塞)
    lock table lock_t1 read;
    #session1,读(可以)
    #session1,写(不可以-报错)
    #session2,读(可以)
    #session2,写(不可以-堵塞)
    unlock table;
    
    #session1,开启排他锁:自己-可读可写,其他人(读-堵塞,写-堵塞)
    lock table lock_t1 write;  
    #session1,读(可以)
    #session1,写(可以)
    #session2,读(不可以-堵塞)
    #session2,写(不可以-堵塞)
    unlock table;
    

    -> InnoDB表锁

    create table lock_t2 (
    id int primary key auto_increment,
    name varchar(30) not null 
    )engine=innodb charset=utf8;
    
    #session1,开启共享锁
    lock table lock_t2 read;  
    #session1,读(可以)
    #session1,写(不可以-报错)
    #session2,读(可以)
    #session2,写(不可以-堵塞)
    unlock table;
    
    #session1,开启排他锁
    lock table lock_t2 write;  
    #session1,读(可以)
    #session1,写(可以)
    #session2,读(不可以-堵塞)
    #session2,写(不可以-堵塞)
    unlock table;
    

    3、示例(行锁)
    行锁就是锁一条数据

    create table lock_t3 (
    id int primary key auto_increment,
    name varchar(30) not null 
    )engine=innodb charset=utf8;
    
    insert into lock_t3 value (null, 'aaa');
    insert into lock_t3 value (null, 'aaa');
    
    #窗口1
    begin;
    update lock_t3 set name = 'bb' where id = 1;
    
    #窗口2(行级锁所以堵塞)
    update lock_t3 set name = 'ccc' where id = 1;
    
    #发现:窗口2堵塞,这时候打开窗口1执行commit发现执行完毕后,窗口后陆续执行
    #最后:查询lock_t3表结果,结果为ccc因为窗口2后执行
    

    4、表锁与行锁的区别
    表级锁代表(MyISAM):
    -> 开销小,加锁快
    -> 发生锁冲突的概率最高,并发度最低(堵塞频率高)
    行级锁(InnoDB):
    -> 开销大,加锁慢
    -> 发生锁冲突概率最低,并发度也最高(堵塞频率低)

    相关文章

      网友评论

          本文标题:MySQL事务&锁机制

          本文链接:https://www.haomeiwen.com/subject/etywnftx.html