做网站智能工具,做商业网站,网页界面设计与分析,电商app开发解决方案文章目录 一、事务概述二、事务基本操作三、事务保存点四、事务的隔离级别1. READ UNCOMMITTED设置事务的隔离级别 2. READ COMMITTED3. REPEATABLE READ4. SERIALIZABLE 五、MySQL的锁InnoDB的锁类型1. InnoDB的行级锁2. InnoDB的表级锁 死锁 在开发过程中#xff0c;我们经常… 文章目录 一、事务概述二、事务基本操作三、事务保存点四、事务的隔离级别1. READ UNCOMMITTED设置事务的隔离级别 2. READ COMMITTED3. REPEATABLE READ4. SERIALIZABLE 五、MySQL的锁InnoDB的锁类型1. InnoDB的行级锁2. InnoDB的表级锁 死锁 在开发过程中我们经常为了完成某一功能而编写一组SQL语句。为了确保每一组SQL语句操作数据的完整性MySQL引入了事务的管理。事务处理机制可以保证在同一个事务中的操作具有同步性从而让整个应用程序更加安全。 一、事务概述
在MySQL中事务就是针对数据库的一组操作它可以由一条或多条SQL语句组成。在程序执行过程中只要有一条SQL语句执行失败或发生错误其他语句都不会执行也就是说事务中的语句要么都执行要么都不执行。 数据库之所以提供事务的机制主要有以下两个目的
为数据库的一组操作提供了一个从失败中恢复到正常状态的途径同时保证了数据库即使在异常状态下也仍能保持数据的一致性。当多个应用程序并发访问数据库时可以在这些应用程序之间提供一个隔离方法以防止彼此的操作互相干扰。
MySQL中的事务必须满足四个特性即事务的ACID特性分别是原子性、一致性、隔离性和持久性。
原子性Atomictity 原子性是指一个事务必须被视为一个不可分割的最小工作单元只有事务中所有的数据库操作都执行成功才算整个事务执行成功。事务中的所有DML操作要么全部执行成功要么全部执行失败不会存在部分执行成功部分执行失败的情况。事务中如果有任何一个SQL语句执行失败已经执行成功的SQL语句也必须撤销数据库的状态退回到执行事务前的状态相当于事务没有执行过。一致性Consistency 一致性是指事务在开始执行前和事务执行结束后数据库中数据的完整性没有被破坏。数据从一个一致状态转变为另一个一致状态并且完全符合所有的预设规则数据不会存在一个中间的状态。隔离性Isolation 隔离性是指一个事务在执行时不会受到其他事务的影响。隔离性保证了未完成事务的所有操作与数据库系统的隔离直到事务完成之后才能看到事务的执行结果。当多个用户并发访问数据库时数据库为每一个用户开启的事务不能被其他事务的操作数据所干扰多个并发事务之间要相互隔离。持久性Durability 持久性是指事务一旦提交对数据库中数据的修改就是永久性的。数据不会因为系统出现故障而丢失。为了实现事务的持久性MySQL在提交事务时采用的是预写日志的方式。即提交事务时先写日志再写数据。只要日志成功写入就是事务提交成功。 事务的持久性不能做到百分之百的持久只能从事务本身的角度来保证永久性如果一些外部原因导致数据库发生故障如硬盘损坏那么所有提交的数据可能都会丢失。 二、事务基本操作
在MySQL中用户执行的每一条SQL语句默认都会当成单独的事务自动提交。如果想要将一组SQL语句作为一个事务需要在执行这组SQL语句之前显式地开启事务。事务开启后后续的每一条SQL语句将不再自动提交。想要提交时需要手动提交事务。只有事务提交后事务中的SQL语句才会生效。如果不想提交当前事务还可以回滚事务。 相关语句如下
# 开启事务
START TRANSACTION;
# 也可以使用BEGIN
BEGIN;# 提交事务
COMMIT;# 回滚事务
ROLLBACK;ROLLBACK语句只针对未提交的事务执行回滚已经提交的事务是不能回滚的。 当执行COMMIT或ROLLBACK后当前事务就会自动结束。 MySQL中事务不允许嵌套如果执行START TRANSACTION语句之前上一个事务还没有提交则此时会隐式执行上一个事务的提交操作。 MySQL中的事务默认是自动提交如果用户想要设置事务的自动提交方式可以通过更改AUTOCOMMIT的值来实现。其值为0表示关闭事务自动提交值为1表示开启事务自动提交。修改、查看的语句如下 # 查看当前会话的AUTOCOMMIT
SELECT AUTOCOMMIT# 关闭当前会话的事务自动提交
SET AUTOCOMMIT0# 开启当前会话的事务自动提交
SET AUTOCOMMIT1三、事务保存点
在回滚事务时事务内的所有操作都将被撤销。如果希望只撤销事务内的部分操作则可以借助事务的保存点实现。在事务中设置保存点后可以将事务回滚到指定的保存点。不用时也可以删除指定的保存点。相关语法
# 创建保存点
SAVEPOINT name;# 回滚到指定保存点
ROLLBACK TO SAVEPOINT name;# 删除指定的保存点
RELEASE SAVEPOINT name;一个事务可以创建多个保存点。 一旦提交事务事务中的保存点都会被删除。 如果事务回滚到某个保存点后该保存点之后创建的其他保存点也会被删除。 四、事务的隔离级别
MySQL支持多线程并发访问用户可以通过不同的线程执行不同的事务。为保证多个事务之间互不影响就需要为事务设置适当的隔离级别。 在MySQL中事务有4种隔离级别分别为READ UNCOMMITTED读未提交、READ COMMITTED读已提交、REPEATABLE READ可重复读和SERIALIZABLE串行化。 不同的事务隔离级别可能存在不同的问题
事务隔离级别脏读不可重复读幻读读未提交YYY读已提交-YY可重复读--Y串行化---
1. READ UNCOMMITTED
READ UNCOMMITTED是事务隔离级别中最低的级别该级别下的所有事务可以读取其他事务中未提交的数据这种读取方式也被称为脏读Dirty Read。在这种级别上可能会产生很多问题除非用户真的知道自己在做什么并且有很好的理由选择这样做。本隔离级别很少应用于实际应用中。
设置事务的隔离级别
MySQL的默认隔离级别是REPEATABLE READ该级别可以避免脏读。修改方式有两种
配置文件修改mysql.ini配置文件在最后加上事务隔离级别的配置即可全局修改事务隔离级别。
[mysqld]
transaction-isolationREPEATABLE READ
# 这里全局修改为REPEATABLE READ级别其实默认就是这个级别。set session针对当前session可以使用set session命令修改。
# 将当前客户端中事务的隔离级别设置为READ UNCOMMITTED;
SET SESSION TRANSATION ISOLATION LEVEL READ UNCOMMITTED;2. READ COMMITTED
在READ COMMITTED级别下事务只能读取其他事务已经提交的内容可以避免脏读现象但是会出现不可重复读和幻读的情况。不可重复读是指在事务内重复读取别的线程已经提交的数据由于多次查询期间其他事务作了更新操作因此出现多次读取的结果不一致的现象。 不可重复读并不算错误但在有些情况下去不符合实际需求。
3. REPEATABLE READ
REPEATABLE READ是MySQL默认的事务隔离级别它可以避免脏读、不可重复读。但在理论上该级别会出现幻读。幻读又称为虚读是指在一个事务内两次查询中的数据条数不一致。幻读和不可重复读类似 都是在两次查询过程中不同的是幻读是由于其他事务作了插入记录的操作导致记录数有所增加。 MySQL的存储引擎通过多版本并发控制机制解决了该问题当事务的隔离级别为REPEATABLE READ时可以避免幻读。
4. SERIALIZABLE
SERIALIZABLE是事务的最高隔离级别它会在每个读的数据行上加锁从而解决脏读、幻读、重复读的问题。这个级别可能导致大量的超时和锁竞争现象因此也是性能最低的一种隔离级别。
五、MySQL的锁
在并发环境下为了解决并发一致性问题保证事务的隔离性MySQL采用了锁的机制。当一个事务在进行操作时会对操作的数据进行加锁从而限制另一个事务的操作。为保证数据库的效率和性能加锁的粒度不宜太大。
InnoDB的锁类型
MySQL的不同存储引擎采用的锁机制不完全相同。MyISAM存储引擎和Memory存储引擎采用表级锁而InnoDB存储引擎既支持行级锁也支持表级锁。
1. InnoDB的行级锁
InnoDB默认采用的是行级锁并实现了以下两种类型的行级锁。
共享锁S 共享锁Share Lock也叫读锁。在同一个数据对象上可以有多把共享锁。如果一个事务在数据对象上加上了共享锁则该事务可以读取数据但不能修改数据。其他的事务也可以在该数据对象上继续添加共享锁也可以读取该数据但同样也不能修改数据。排他锁X 排他锁Exclusive Lock也叫写锁。在同一个数据对象上只允许有一把排他锁获取到数据排他锁的事务可以读取数据和修改数据。一旦数据被加上了排他锁其他事务就不允许再对该数据添加任何类型的行级锁。 查询语句SELECT默认不会添加任何锁类型。因此当数据上有了排他锁还是可以通过查询语句SELECT获取数据的。 使用查询语句SELECT也可以为数据加锁。如使用select ... fro update语句可以为数据添加排他锁使用select ... lock in share mode语句可以为数据添加共享锁。 InnoDB的行锁是通过索引实现的这意味着只有通过索引查询数据时InnoDB引擎才会使用行级锁。否则InnoDB存储引擎将使用表级锁。要注意的是等级锁不是针对表中的行加锁。如果表上没有对应的索引或者使用了相同的索引也会造成锁的冲突进而导致整张表加上排他锁。
2. InnoDB的表级锁
InnoDB为了实现同时支持行级锁和表级锁在其内部使用了两种类型的意向锁Intention Locks来实现多粒度锁机制。这两种意向锁都是表级锁。
意向共享锁IS 事务在给数据添加行级共享锁之前必须先取得该表的意向共享锁。意向排他锁IX 事务在给数据添加等级排他锁之前必须先取得该表的意向排他锁。 由于意向锁是InnoDB存储引擎自动加的不需要用户干预是其内部使用的锁机制因此对于普通用户来说不需要过多地关注这两种类型锁。 如果一个事务请求的锁模式与当前数据的锁模式兼容InnoDB引擎就将事务请求的锁授予该事务反之如果两者不兼容该事务就要等待当前的锁释放。下表展示InnoDB引擎锁与锁之间的兼容模式。
事务请求的锁\事务已有的锁XIXSISX冲突冲突冲突冲突IX冲突兼容冲突兼容S冲突冲突兼容兼容IS冲突兼容兼容兼容
死锁
死锁是指两个或两个以上事务在执行过程中因为互相的等待或因为争抢相同的资源而造成的互相等待现象。 死锁的避免
以固定的顺序访问表和行。如两个任务批量更新的情形简单方法是对id列表先排序后执行这样就避免了交叉等待锁的情形。大事务拆小。大事务更倾向死锁如果业务允许将大事务拆小。在同一个事务中尽可能做到一次锁定所需要的所有资源减少死锁概率。降低隔离级别。如果业务允许将隔离级别调低也是较好的选择。为表添加合理的索引。