事务,隔离级别和锁

1:事务是什么

  一般来说,事务必须满足4个条件:原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

  1. 原子性:该事务的sql语句要么全部执行完成,要么一个都不完成,当执行出现错误时,会回滚到事务执行前的情况,就像这个事务没有执行过一样。
  2. 一致性:事务开始之前和结束之后,数据库的完整性没有破坏。(比如:A向B转账,不可能A扣了钱,B却没有收到)
  3. 隔离性:数据库允许多个事务对数据库进行读写和修改,隔离性保证了多个事务并行执行的过程中,由于交织在一起而导致的数据不一致。事物的隔离性有以下几个:
    1. 读未提交。
    2. 读已提交。
    3. 可重复读。
    4. 串行化。
  4. 持久性:事务结束后,对数据库的修改是持久的。不会因为系统崩溃了,而导致数据的丢失。

2:事务隔离级别是什么?有哪些隔离级别?每种隔离级别分别会出现什么情况?

  上面描述的隔离性同有4种,分别是读未提交,读提交,可重复读,串行化4种隔离级别,后面详细介绍灭种隔离级别。在mysql中出现的常见错误有:

  1. 脏读:指事务A修改数据库中数据,但是还没有提交到数据库中来,然而事务B却能在访问数据库中获得事务A修改的没有提交的数据。
  2. 不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)。
  3. 幻读:事务在插入已经检查过不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测获取到的数据如同鬼影一般。

  区别:

  1. 不可重复读是读取了其他事务更改的数据,针对update操作。解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。
  2. 幻读是读取了其他事务新增的数据,针对insert与delete操作。解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。

  幻读和不可重复读都是指的一个事务范围内的操作受到其他事务的影响了。只不过幻读是重点在插入和删除,不可重复读重点在修改

   在常见的隔离级别中每种不同的级别可能导致不同的错误。

  1. 读未提交:是指事务B能够读出事务A修改的数据,但是还没有提交的。这种隔离级别对导致脏读,这种低级别的错误,所有数据库基本上都能避免。那么不可重复读尼?显然,事务A两次访问数据表中数据,在事务A没有提交的时候,事务B在其期间修改了数据库,也在没有提交的时候。显然事务A可以访问到修改事务B没有提交的数据,显然会出现不可重复读!那么幻读尼?显然也会出现!
  2. 读已提交:只可以读那些已经提交的数据!这种情况下:事务A修改数据表,在事务A提交之前,事务B读数据,那么读的是原始数据,在事务A提交后,在读数据会是事务A修改之后的数据,这两次读的数据是不同的,这就是不可重读!当前以此类推也会幻读。
  3. 可重复读:事务A和事务B,事务A提交之后的数据,事务B读取不到,事务B是可重复读取数据,这种隔离级别高于读已提交,换句话说,对方提交之后的数据,我还是读取不到,这种隔离级别可以避免“不可重复读取”,达到可重复读取,比如1点和2点读到数据是同一个,MySQL默认级别是不可重复读。在其他数据库里面隔离级别为可重复读的的会避免脏读和不可重复读错误,但是依然会出现幻读。但是MySQL在这里解决了幻读问题。
  4. 串行化:
    • 事务A和事务B,事务A在操作数据库时,事务B只能排队等待
    • 这种隔离级别很少使用,吞吐量太低,用户体验差
    • 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发。

3:锁是什么?mysql有哪些锁?有什么用?

  当有多个请求来读取表中的数据时可以不采取任何操作,但是多个请求里有读请求,又有修改请求时必须有一种措施来进行并发控制。不然很有可能会造成不一致。
  解决上述问题很简单,只需用两种锁的组合来对读写请求进行控制即可,这两种锁被称为:读写锁。

  • 共享锁(shared lock),又叫做"读锁"
    读锁是可以共享的,或者说多个读请求可以共享一把锁读数据,不会造成阻塞。

  • 排他锁(exclusive lock),又叫做"写锁"
    写锁会排斥其他所有获取锁的请求,一直阻塞,直到写入完成释放锁。


     
     
  • 总结:通过读写锁,可以做到读读可以并行,但是不能做到写读,写写并行

  • 普通的select * from table where a =1的读sql语句是不会任何加锁的。select * from table where a =1 lock in share mode 这种是加共享锁(读锁)。
  • 如果是select * from table where a =1 for update这种加的写锁,排他锁。
  • 写操作insert,删除操作delete以及更新操作update操作都是会进行加写锁即排他锁。
  • 所有的锁都会随着commit之后,而被释放。

4:MySQL如何实现读已提交和可重读的尼?

 

posted @ 2020-04-10 17:59  大朱123  阅读(254)  评论(0编辑  收藏  举报