事务概念

数据库事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。但不是任意的数据库操作序列都能成为事务  
对mysql常见的引擎有:MyISAM和InnoDB,MyISAM是默认高速的引擎并不支持事务功能,InnoDB支持行锁定和事务处理,速度比MyISAM稍慢。  
它的存在包含有以下两个目的:  
    1.为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。  
    2.当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。  

事务四大特性(ACID)

  • 原子性(Autmic):一个原子事务要么完整执行,要么干脆不执行。也就是说,工作单元中的每项任务都必须正确执行,如果有任一任务执行失败,则整个事务就会被终止并且此前对数据所作的任何修改都将被撤销。如果所有任务都被成功执行,事务就会被提交,那么对数据所作的修改将会是永久性的
  • 一致性(Consistency):一致性代表了底层数据存储的完整性。 它是由事务系统和应用开发人员共同来保证。事务系统通过保证事务的原子性,隔离性和持久性来满足这一要求; 应用开发人员则需要保证数据库有适当的约束(主键,引用完整性等),并且工作单元中所实现的业务逻辑不会导致数据的不一致(数据预期所表达的现实业务情况不相一致)。例如,在刚才的AB转账过程中,从A账户中扣除的金额必须与B账户中存入的金额相等。
  • 隔离性(Isolation):隔离性是指事务必须在不干扰其他事务的前提下独立执行,也就是说,在事务执行完毕之前,其所访问的数据不能受系统其他部分的影响。
  • 持久性(Durability):持久性指明当系统或介质发生故障时,确保已提交事务的更新数据不能丢失,也就意味着一旦事务提交,DBMS保证它对数据库中数据的改变应该是永久性的,耐得住任何系统故障,持久性可以通过数据库备份和恢复来保证。

隔离级别

  • READ_UNCOMMITTED:这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据,会出现脏读、不可重复读、幻读 (隔离级别最低,并发性能高)

  • READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。可以避免脏读,但会出现不可重复读、幻读问题(锁定正在读取的行,mysql默认隔离级别)

  • REPEATABLE_READ:可以防止脏读、不可重复读,但会出幻读(锁定所读取的所有行)

  • SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。保证所有的情况不会发生(锁表,并发性及其低)

隔离级别 读未提交 不可重复读 幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE
  • 读未提交:事务T2能读取事务T1未提交的数据,当事务T1执行回滚时,T2读取的数据就无效
  • 不可重复读:事务T2读取事务T1未开启时和T1提交后的数据不一致(主要是数据更新导致不一致
  • 幻读:事务T2读取事务T1未开启时和T1提交后的数据不一致(此时已锁定T2读取行,主要是插入和删除数据导致不一致

    // 设置当前连接的事务隔离级别
    SET SESSION TRANSACTION ISOLATION LEVEL 事务隔离级别;
    //设置全部连接(包括新连接)的事务隔离级别
    SET GLOBAL TRANSACTION ISOLATION LEVEL 事务隔离级别;

    悲观锁和乐观锁的

悲观锁:假设会发生并发冲突,回避一切可能违反数据完整性的操作。

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性,注意乐观锁并不能解决脏读的问题(关于脏读稍后解析)。

在一般情况下,悲观锁依靠数据库的锁机制实现,以保证操作最大程度的排他性和独占性,因而会导致数据库性能的大量开销和并发性很低,特别是对长事务而言,这种开销往往过于巨大而无法承受。为了解决这样的问题,乐观锁机制便出现了。乐观锁,大多情况下是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则给予更新,否则认为是过期数据。ok~,关于悲观锁和乐观锁的简单概念就先了解到这。

共享锁与排他锁

在mysql中,为了保证数据一致性和防止数据处理冲突,引入了加锁和解锁的技术,这样可以使数据库中特定的数据在使用时不让其他用户(进程或事务)操作而为该数据加锁,直到该数据被处理完成后再进行解锁。根据使用目的不同把锁分为共享锁定(也称为读取锁定)和排他锁定(写入锁定)。

共享锁定:将对象数据变为只读形式的锁定,这样就允许多方同时读取一个数据,此时数据将无法修改。
排他锁定:在对数据进行insert/update/delete时进行锁定,在此时其他用户(进程或事务)一律不能读取数据,从而也保证数据完整性。

事务、隔离级别、锁之间的关系

通过上述的分析,我们也理解了事务、锁和隔离级别的概念,但锁和事务以及分离水平关系如何呢?实际上,事务是解决多条sql执行执行过程的原子性、一致性、隔离性、持久性的整体解决方案,而事务分离水平则是并发控制的整体解决方案,其实际是综合利用各种类型的锁来解决并发问题。锁是数据库并发控制的内部基础机制。对应用开发人员来说,只有当事务分离水平无法解决并发问题和需求时,才有必要在语句中手动设置锁。关于锁的锁定,对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁,事务可以通过以下语句显示给记录集加共享锁或排他锁。请注意InnoDB行锁是通过给索引上的索引项加锁来实现的,也就是说,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。