zoukankan      html  css  js  c++  java
  • 事务相关

    事务

    事务(Transaction)是一组SQL组成的执行单元(unit),是数据库并发控制和恢复回滚的基本单位

    一个事务可能包含多个SQL,要么都失败,要么都成功

    事务具备4个基本属性:

    Atomic,同一个事务里,要么都提交,要么都回滚

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

    Isolation,并发事务间的数据是彼此隔离的

    Durability,事务提交后,所有结果务必被持久化

    支持事务的引擎:InnoDB、TokuDB、MyRocks

    不支持事务的引擎:MyISAM、MEMORY/HEAP

    mysql> show enginesG

    显示开始事务 

    START TRANSACTION

        [READ WRITE]  默认

        [WITH CONSISTENT SNAPSHOT]

        [READ ONLY]

    BEGIN/BEGIN WORK

    开启/关闭自动提交

    set autocommit | @@autocommit = 0 | 1

    提交事务

    显示提交

    COMMIT

    隐式提交

    BEGIN/BEGIN WORK

    START TRANSACTION

    SET AUTOCOMMIT = 1

    其他非事务语句(DDL/DCL)

    回滚事务

    显式回滚

    ROLLBACK

    隐式回滚

    连接断开,mysql > exit;

    超时断开,mysql > timeout; 锁等待超时

    被kill,mysql > kill x;

    异常宕机

    autocommit = 0 必要吗

    好处:

        多语句提交时,不会每个SQL单独提交,提高事务提交效率

    麻烦:

        有个事务忘记提交,锁一直未释放

        另一个事务长期锁等待,严重影响tps

    Python中的autocommit

    import MySQLdb
    from time import sleep
    conn = MySQLdb.connect(host='1.2.3.4',port=3306,user='app')
    conn.autocommit = True
    cur = conn.cursor()
    cur.execute("show global status")
    while 1:
        sleep(1)

    是Python方法,而不是数据库的

    cur.execute("set autocommit=1") 才是数据库的

    事务隔离级别

    如果没有事务控制的话,那么并发读写数据库会有什么隐患

    脏读:

    事务T1修改了一行数据,事务T2在事务T1提交之前读到了该行数据

    不可重复读:

    同样的条件,读取过的数据,再次读取出来发现值不一样了,更改数据(修改或删除)

    幻读:

    同样的条件,第1次和第2次读取出来的记录数不一样,新增数据

    丢失更新:

    第一类丢失更新,即回滚导致的另一个事务的更新丢失

    第二类丢失更新,即事务A覆盖事务B已经提交的数据

    Read Uncommitted (读未提交) 隔离级别最低

    允许脏读,允许事务查看其他事务所进行的未提交的更改

    Read Committed (读已提交)

    允许幻读,不可重复读,允许事务查看其他事务所进行的已提交的更改

    Repeatable Read (可重复读)

    消除了脏读,不可重复读,幻读,保证事务一致性

    确保每个事务的读取结果总是一样,默认隔离级别

    Serializable (串行) 隔离级别最高

    串行化读,每次读都需要获得表级共享锁,读写间相互都会阻塞

    隔离级别和可能发现的现象总结如下:

    my.cnf配置

    [mysqld]分段中,加入一行

    transaction-isolation = "READ-COMMITTED" #默认值是REPEATABLE-READ

    在线(全局)修改

    set [global] transaction isolation level read committed;

    查看当前隔离级别

    select @@global.transaction_isolation,@@session.transaction_isolation;

    https://blog.csdn.net/qq_37771475/article/details/86493631 很详细

    InnoDB读

    快照读,snapshot read

        基于read view读可见版本,不加锁

        start transaction with consistent read + select

        普通select

        由基于某个时间点的一组InnoDB内部(活跃)事务构建而成的列表

    当前读,current read

        读(已提交的)最新版本,并加锁

        select ... for update/lock in share mode

        DML

    InnoDB只读事务

    5.6开始支持

    5.7进一步优化,不记录redo log

    5.7起,非显示声明的事务,默认都是以只读模式启动,事务过程中有数据被修改时,才自动变更为读写模式

    显式声明的只读事务时innodb_trx.trx_is_read_only = 1

    mysql> start transaction read only; 

    mysql> select * from t1;

    InnoDB是如何解决幻读的

    RR级别下解决了幻读问题

    引入gap lock,把2条记录中间的gap锁住,避免其他事务写入

    存在幻读的条件:

        <= RC级别

        innodb_locks_unsafe_for_binlog = 1

    8.0版本innodb_lock_unsafe_for_binlog没有这个参数

    InnoDB semi-consistent read

    semi-consistent read是read committed与consistent read的结合 

    一个update语句,如果读到一行已经加锁的记录,此时InnoDB返回记录最近提交的版本,由MySQL上层判断此版本是否满足update的where条件。若满足,则MySQL会重新发起一次读操作,此时会读取行的最新版本(并加锁)

    semi-consistent read发生的条件:

        <= read committed隔离级别

        innodb_locks_unsafe_for_binlog = 1 时

        update请求(不含insert、delete)

  • 相关阅读:
    vue3学习笔记
    学习笔记-Python-爬虫5-Selenium + PhantomJS
    学习笔记-Python-爬虫4-数据提取-正则、XML、XPath、BeautifulSoup4
    学习笔记-Python-爬虫7-Scrapy、分布式爬虫
    学习笔记-Python-爬虫6-验证码
    学习笔记-Python-爬虫3-requests
    学习笔记-Python-爬虫2-SSL、js加密、ajax
    学习笔记-Python-爬虫1-urllib、chardet
    Java多线程同步问题
    jQuery限制文本框只能输入正整数
  • 原文地址:https://www.cnblogs.com/allenhu320/p/11365064.html
Copyright © 2011-2022 走看看