zoukankan      html  css  js  c++  java
  • mysql事务

    事务的四大特性(ACID)

    • 原子性(Atomicity)
    • 一致性(Consistency)
    • 隔离性(Isolation)
    • 持久性(Durability)

    原子性:事务内执行的sql操作当作一个整体,要么同时成功,要么同时失败回滚
    一致性:强调的是数据的状态,指的是数据库从一个一致性状态到另外一个一致性状态,打个比方,A有200,B有100,A转100给B,那么最后的一致性状态是A有100,B有200,如果状态是A有100,B还是原来的100,那这就不符合数据的一致性
    隔离性:一个事务所做的修改在最终提交以前,对其他事务是不可见的,也就是说,A有200,B有100,A转100,B加100,还没有提交的时候,又开启了一个事物,此时看到的是A有200,B有100,也就是第一个事物没有commit之前的状态;还有一点就是说事物对某 行的某个字段进行加操作,那么在没有提交之前,其他事物是不能修改这一行的这个字段的,因为mysql此时的行锁被第一个事物拿到,commit之后才会释放
    持久性:事物一旦进行了提交,那么数据落盘,所做的修改会永久保存到数据库

    事务的隔离级别

    事务的隔离级别是为了解决mysql并发问题的几种控制手段。

    事务的并发问题

    1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
    2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
    3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
    小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
    单条修改数据的命令会自动的触发事务,包括insert、update、delete。
    而在SQL语句中有手动开启事务的原因是:可以进行多次数据的修改,如果成功一起成功,否则一起会滚到之前的数据.

    4种隔离级别

    Read Uncommitted(读取未提交内容)

    在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

    Read Committed(读取提交内容)

    这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。,因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果,这就是不可重复读

    Repeatable Read(可重读)

    这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

    Serializable(可串行化)

    这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

    在测试的时候,把mysql事务级别设置成 Repeatable Read,一个事务往里插数据,另一个事务是看不到其他事务插入的数据的,即读的不是最新数据,我们把这种现象也看作是幻读

    查看和设置隔离级别

    SELECT @@tx_isolation
    设置mysql的隔离级别:set session transaction isolation level 设置事务隔离级别

    pymysql

    对于pymysql有几个点需要注意

    默认支持事务

    pymysql默认开启事务,从每次执行执行增删改都需要最终commit就能知道。

    通过pymysql增加数据但未提交时候,发现表的AUTO_INCREMENT是一直递增的(说明数据库已经收到插入指令了,就等着拍板呢),这是为了解决并发的考量,并且如果回滚AUTO_INCREMENT并不会减少,而是一直递增下去,这样才不会出错。

    cursor对象存放查询的数据

    import pymysql
    conn = pymysql.connect(host='localhost', user='root', password="123456",database='test', port=3306, charset='utf8')
    cur = conn.cursor()
    cur.execute('select * from department')
    Out[5]: 4
    cur.fetchone()
    Out[6]: (200, '技术')
    cur.execute('select * from employee')
    Out[7]: 18
    cur.fetchone()
    Out[8]: 
    (1,
     'egon',
     'male',
     18,
     datetime.date(2017, 3, 1),
     '办事处外交大使',
     None,
     7300.33,
     401,
     1)
    
    

    通过上面我们可以发现,当我们查询的时候,取数据没有取完就执行另一条查询语句,那么先前的查询结果会被覆盖。也就是说执行了一条查询语句,那么就应该立即取出结果,否则拿着这个cursor去执行任何增删改查操作,原来存储的查询数据都会被清掉

    pymysql模块的threadsafety = 1

    如果在多个线程中的cursor共用一个conn连接,那么就会报类似pymysql.err.InternalError: Packet sequence number wrong - got 45 expected 0的错误

    1. 每个线程拥有自己的连接
    2. 所有线程共用一个连接池,需要考虑线程总数和连接池连接数上限的问题

    pymysql遇到的幻读

    之前我开了两个线程,一个线程取数据,一个线程往表插入数据,最终的结果是每次取得的数据都是一样的,但是数据表确确实实是在不停地增加数据。这是因为数据库的隔离级别造成的.解决办法有两个:

    1. 修改隔离级别
    2. 建立conn的时候加上autocommit=True参数
  • 相关阅读:
    window.location.Reload()和window.location.href 区别
    PHP substr(),mb_substr()及mb_strcut的区别和用法
    jstree节点展开设置
    关于Jquery中ajax方法data参数用法
    HTML相对路径(Relative Path)和绝对路径(Absolute Path)
    Win32基础编程了解窗口类
    Visual C++ ActiveX 开发指南:第一章 什么是ActiveX
    分粥
    蛙蛙推荐:ASP实现自定义标签模板
    蛙蛙请教:如何利用委托实现多个方法同时调用.
  • 原文地址:https://www.cnblogs.com/longyunfeigu/p/9323511.html
Copyright © 2011-2022 走看看