zoukankan      html  css  js  c++  java
  • MySql 事务与锁

    事务介绍

    首先,什么是事务?事务就是一段sql 语句的批处理,但是这个批处理是一个atom(原子),不可分割,要么都执行,要么回滚(rollback)都不执行。

    MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

    • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
    • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
    • 事务用来管理 insert,update,delete 语句

    一般来说,事务是必须满足4个条件(ACID): Atomicity(原子性)、Consistency(稳定性)、Isolation(隔离性)、Durability(可靠性)

    • 1、事务的原子性:一组事务,要么成功;要么撤回。
    • 2、稳定性 :有非法数据(外键约束之类),事务撤回。
    • 3、隔离性:事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
    • 4、可靠性:软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 选项 决定什么时候吧事务保存到日志里。

    事务并发并不进行事务隔离造成的脏读、幻读、不可重复读

    • 脏读:事务A读到未提交事务B修改的数据,如果此时事务B中途执行失败回滚,那么此时事务A读取到的就是脏数据。比如事务A对money进行修改,此时事务B读取到事务A的更新结果,但是如果后面事务A回滚,那么事务B读取到的就是脏数据了。
    • 不可重复读:同一个事务中,对同一份数据读取的结果不一致。事务A在事务B对数据更新前进行读取,然后事务B更新提交,事务A再次读取,这时候两次读取的数据不同。
    • 幻读:(同一个事务中,同一个查询多次返回的结果不一样。事务B查询表的记录数,然后事务A对表插入一条记录,接着事务B再次查询发现记录数不同。注意这个解释是不正确,网络上有很多这样的解释,包括我认为比较权威的专家,但是经过实验发现并不正确。所以这是需要注意的)。可以做这样一个实验,事务A查询记录数,事务B插入一条记录(主键值为6),提交,然后事务A查询记录数,发现记录数没有改变,但是此时插入一条主键值为6的记录发现冲突了,感觉像出现了幻觉。

    区别

    1、脏读和不可重复读:脏读是事务读取了还未提交事务的更新数据。不可重复读是同一个事务中,几次读取的数据不同。

    2、不可重复读和幻读的区别:都是在同一个事务中,前者是几次读取数据不同,后者是几次读取数据整体不同。

    隔离级别

    隔离级别作用
    Serializable(串行化) 避免脏读、不可重复读、幻读
    Repeatable(可重复读) 避免脏读、不可重复读
    Read committed(读已提交) 避免脏读
    Read uncommitted(读未提交) none
    • 隔离级别改变影响锁的周期
    • mysql支持上面4种隔离级别,默认为可重复读

     锁


    MySQL有三种锁的级别:页级、表级、行级。

      MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);

      BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;

      InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。

    MySQL这3种锁的特性可大致归纳如下:
    1、表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

      表级锁让多线程可以同时从数据表中读取数据,但是如果另一个线程想要写数据的话,就必须要先取得排他访问(默认加排他表锁);(共享读锁(Table Read Lock))

      更新数据时,必须要等到更新完成了,其他线程才能访问(读)这个表。(独占写锁(Table Write Lock))

    2、行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    3、页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

    原则上数据表有一个读锁时,其它进程无法对此表进行更新操作,但在一定条件下,MyISAM表也支持查询和插入操作的并发进行。

    一般MyISAM引擎的表也支持查询和插入操作的并发进行(原则上数据表有一个读锁时,其它进程无法对此表进行更新操作)

      MyISAM引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2:  

        a、concurrent_insert为0,不允许并发插入。
        b、concurrent_insert为1,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。
        c、concurrent_insert为2,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。

    如果有读写请求同时进行的话,MYSQL将会优先执行写操作。这样MyISAM表在进行大量的更新操作时(特别是更新的字段中存在索引的情况下),会造成查询操作很难获得读锁,从而导致查询阻塞。

    我们还可以调整MyISAM读写的优先级别:

      a、通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。
      b、通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
      c、通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。

    MyISAM使用的是 flock 类的函数,直接就是对整个文件进行锁定(叫做文件锁定),MyISAM的数据表是按照单个文件存储的,可以针对单个表文件进行锁定;

    InnoDB使用的是 fcntl 类的函数,可以对文件中局部数据进行锁定(叫做行锁定),InnoDB是一整个文件,把索引、数据、结构全部保存在 ibdata 文件里,所以必须用行锁定。

    事物控制语句:

        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 事务处理主要有两种方法:

    1、用 BEGIN, ROLLBACK, COMMIT来实现

        BEGIN 开始一个事务
        ROLLBACK 事务回滚
        COMMIT 事务确认

    2、直接用 SET 来改变 MySQL 的自动提交模式:

        SET AUTOCOMMIT=0 禁止自动提交
        SET AUTOCOMMIT=1 开启自动提交

    注意点

    1、如果事务中sql正确运行,后面没有commit,结果是不会更新到数据库的,所以需要手动添加commit。

    2、如果事务中部分sql语句出现错误,那么错误语句后面不会执行。而我们可能会认为正确操作会回滚撤销,但是实际上并没有撤销正确的操作,此时如果再无错情况下进行一次commit,之前的正确操作会生效,数据库会进行更新。

    参考链接:

    https://www.cnblogs.com/leonardchen/p/7048187.html

    https://www.cnblogs.com/metoy/p/5545580.html

    http://blog.csdn.net/andyxm/article/details/44810313

  • 相关阅读:
    修改ubuntu DNS的步骤/wget url报错: unable to resolve host address的解决方法
    MySQL5.7 Replication主从复制配置教程
    总结一下安装linux系统经验-版本选择-安装ubuntu
    分布式与集群的联系与区别
    spring 后置处理器BeanFactoryPostProcessor和BeanPostProcessor的用法和区别
    mysql几种性能测试的工具使用
    mysql max_allowed_packet查询和修改
    mysql主从复制(超简单)
    10 个免费的网络监控工具(转)
    DOS批处理中%cd%和%~dp0的区别
  • 原文地址:https://www.cnblogs.com/ericli-ericli/p/7268796.html
Copyright © 2011-2022 走看看