一 .事务
1.1 事务的概念
mysql把多条写操作视为一个整体去执行,要么全部成功,要么全部失败,我们把mysql的这种处理叫做事务。(“多条”很好理解就是至少两条sql语句,“写操作”就是指对msyql内容修改的操作(insert、update、delete))。
1.2事务的特性
原子性: 确保工作单元内的所有操作都成功完成,否则事务将被中止在故障点,和以前的操作将回滚到以前的状态。
一致性: 确保数据库正确地改变状态后,成功提交的事务。
隔离性: 使事务操作彼此独立的和透明的。
持久性: 确保提交的事务的结果或效果的系统出现故障的情况下仍然存在。
1.3事务的隔离级别
为了尽可能的高并发,事务的隔离性被分为四个级别:读未提交、读已提交、可重复读和串行化。用户可以根据需要选择不同的级别。
未提交读(READ UNCOMMITTED):一个事务还未提交,它的变更就能被别的事务看到。
示例:事务 A 可以读到事务 B 修改的但还未提交的数据,会导致脏读(可能事务 B 在提交后失败了,事务 A 读到的数据是脏的)。
提交读(READ COMMITTED):一个事务提交后,它的变更才能被其他事务看到。大多数据库系统的默认级别,但 Mysql 不是。
示例 :事务 A 只能读到事务 B 修改并提交后的数据,会导致不可重复读(事务 A 中执行两次查询,一次在事务 B 提交过程中,一次在事务 B 提交之后,会导致两次读取的结果不一致)。
可重复读(REPEATABLE READ):未提交的事务的变更不能被其他事务看到,同时一次事务过程中多次读取同样记录的结果是一致的。
示例:事务 A 在执行过程中多次获取某范围内的记录,事务 B 提交后在此范围内插入或者删除 N条记录,事务 A 执行过程中多次范围读会存在不一致,即幻读(Mysql 的默认级别,InnoDB 通过 MVVC 解决了幻读的问题)。
可串行化(SERIALIZABLE):当两个事务间存在读写冲突时,数据库通过加锁强制事务串行执行,解决了前面所说的所有问题(脏读、不可重复读、幻读)。是最高隔离的隔离级别。
1.4 MySQL如何支持事务
MYSQL的事务处理主要有两种方法
1.用begin,rollback,commit来实现
begin开始一个事务
rollback事务回滚
commit 事务确认
2.直接用set来改变mysql的自动提交模式
mysql默认是自动提交的,也就是你提交一个query,就直接执行!可以通过
set autocommit = 0 禁止自动提交
set autocommit = 1 开启自动提交
来实现事务的处理
1.5事务并发问题
1.5.1 丢失更新问题
设两个事务T1,T2,当他们同时读入一个数据加以修改时,事务T2提交的结果会破坏事务T1提交的结果,由此导致T1的修改被丢失了,这就是由于数据库并发操作引起的数据一致性问题。
特点:事务 T1,T2对统一数据进行修改操作。
解决丢失问题思路:悲观锁,乐观锁
1.5.2不可重复度
设两个事务T1,T2,不可重复读是指事务T1读取一数据之后,事务T2对该数据进行了修改操作,使事务T1无法再现上次的读取结果。
事务T1读取数据后,事务T2对其做了修改,当事务T1再次读取该数据的时候得到了与之前读取不同的值。
特点:事务T1对数据进行修改,事务T2对数据进行读
1.5.3 幻读
(1)事务T1按照一定的条件从数据库中读取某些记录之后,事务T2删除了相同条件下的部分数据记录,当事务按照相同条件读取数据时,发现某些记录神秘的消失了。
(2)事务T1按照一定的条件从数据库中读取某些记录之后,事务T2在相同条件下增加了部分数据记录,当事务按照相同条件读取数据时,发现得到的数据结果集比之前增加了。
特点:事务T1对数据进行修改,事务T2对数据进行读
1.5.4读脏数据
设事务T1,T2,读脏数据是指事务T1修改了某一数据并将数据写回了磁盘里,事务T2也读取了相同的数据,事务T1由于某些操作进行了撤销操作,这时事务T1已经被修改过的数据恢复了原来的值,事务T2读到的数据就与数据库中的数据不一致,则事务T2读到的数据就是一条“脏”数据,即不正确的数据。
特点:事务T1对数据进行修改,事务T2对数据进行读取
1.5.5 不可重复读与幻读的区别
不可重复读针对的是其他事务提交前后数据本身的对比,重点在于数据的本身。
幻读针对的是其他事务提交前后,数据记录条数的对比。
1.6 查看和设置mysql 事务的隔离级别
在MySQL数据库中查看当前事务的隔离级别:
select @@tx_isolation;
在MySQL数据库中设置事务的隔离 级别:
set [glogal | session] transaction isolation level 隔离级别名称;
set tx_isolation=’隔离级别名称;’
注意事项:
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
二. MySQL锁
2.1 MySQL锁的概述
数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则。对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外。MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎所针对的应用场景特点都不太一样,为了满足各自特定应用场景的需求,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。MySQL各存储引擎使用了三种类型(级别)的锁定机制:表级锁定,行级锁定和页级锁定。
2.2三种类型(级别)的锁定机制
2.2.1表级锁定(table-level)
表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。
当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。
使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。
2.2.2行级锁定(row-level)
行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。
使用行级锁定的主要是InnoDB存储引擎。
2.2.3页级锁定(page-level)
页级锁定是MySQL中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。
在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。
使用页级锁定的主要是BerkeleyDB存储引擎。
2.3 三种类型锁(级别)的特性
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
适用:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。