做网站标配,做电影平台网站怎么赚钱的,网站的关于我们页面,证书兼职的正规平台哪里有什么是事务
事务是访问数据库的一个操作序列#xff0c;数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换为另一种状态。
事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性#xff08;atomicity#xff09;、一致性#xff08;…什么是事务
事务是访问数据库的一个操作序列数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换为另一种状态。
事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性atomicity、一致性consistency、隔离性isolation、持久性durability的缩写这四种状态的意思是
1、原子性
即不可分割事务要么全部被执行要么全部不执行。如果事务的所有子事务全部提交成功则所有的数据库操作被提交数据库状态发生变化如果有子事务失败则其他子事务的数据库操作被回滚即数据库回到事务执行前的状态不会发生状态转换
2、一致性
事务的执行使得数据库从一种正确状态转换成另外一种正确状态
3、隔离性
在事务正确提交之前不允许把事务对该数据的改变提供给任何其他事务即在事务正确提交之前它可能的结果不应该显示给其他事务
4、持久性
事务正确提交之后其结果将永远保存在数据库之中即使在事务提交之后有了其他故障事务的处理结果也会得到保存
事务的作用
事务管理对于企业级应用而言至关重要它保证了用户的每一次操作都是可靠的即便出现了异常的访问情况也不至于破坏后台数据的完整性。就像银行的自动提款机ATM通常ATM都可以正常为客户服务但是也难免遇到操作过程中及其突然出故障的情况此时事务就必须确保出故障前对账户的操作不生效就像用户刚才完全没有使用过ATM机一样以保证用户和银行的利益都不受损失。
并发下事务会产生的问题
举个例子事务A和事务B操纵的是同一个资源事务A有若干个子事务事务B也有若干个子事务事务A和事务B在高并发的情况下会出现各种各样的问题。“各种各样的问题”总结一下主要就是五种第一类丢失更新、第二类丢失更新、脏读、不可重复读、幻读。五种之中第一类丢失更新、第二类丢失更新不重要不讲了讲一下脏读、不可重复读和幻读。
1、脏读
所谓脏读就是指事务A读到了事务B还没有提交的数据比如银行取钱事务A开启事务此时切换到事务B事务B开启事务–取走100元此时切换回事务A事务A读取的肯定是数据库里面的原始数据因为事务B取走了100块钱并没有提交数据库里面的账务余额肯定还是原始余额这就是脏读。
2、不可重复读
所谓不可重复读就是指在一个事务里面读取了两次某个数据读出来的数据不一致。还是以银行取钱为例事务A开启事务–查出银行卡余额为1000元此时切换到事务B事务B开启事务–事务B取走100元–提交数据库里面余额变为900元此时切换回事务A事务A再查一次查出账户余额为900元这样对事务A而言在同一个事务内两次读取账户余额数据不一致这就是不可重复读。
3、幻读
所谓幻读就是指在一个事务里面的操作中发现了未被操作的数据。比如学生信息事务A开启事务–修改所有学生当天签到状况为false此时切换到事务B事务B开启事务–事务B插入了一条学生数据此时切换回事务A事务A提交的时候发现了一条自己没有修改过的数据这就是幻读就好像发生了幻觉一样。幻读出现的前提是并发的事务中有事务发生了插入、删除操作。
事务隔离级别
事务隔离级别就是为了解决上面几种问题而诞生的。为什么要有事务隔离级别因为事务隔离级别越高在并发下会产生的问题就越少但同时付出的性能消耗也将越大因此很多时候必须在并发性和性能之间做一个权衡。所以设立了几种事务隔离级别以便让不同的项目可以根据自己项目的并发情况选择合适的事务隔离级别对于在事务隔离级别之外会产生的并发问题在代码中做补偿。
事务隔离级别有4种但是像Spring会提供给用户5种来看一下
1、DEFAULT
默认隔离级别每种数据库支持的事务隔离级别不一样如果Spring配置事务时将isolation设置为这个值的话那么将使用底层数据库的默认事务隔离级别。顺便说一句如果使用的MySQL可以使用select tx_isolation来查看默认的事务隔离级别
2、READ_UNCOMMITTED
读未提交即能够读取到没有被提交的数据所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种因此很少使用
3、READ_COMMITED
读已提交即能够读到那些已经提交的数据自然能够防止脏读但是无法限制不可重复读和幻读
4、REPEATABLE_READ
重复读取即在数据读出来之后加锁类似select * from XXX for update明确数据读取出来就是为了更新用的所以要加一把锁防止别人修改它。REPEATABLE_READ的意思也类似读取了一条数据这个事务不结束别的事务就不可以改这条记录这样就解决了脏读、不可重复读的问题但是幻读的问题还是无法解决
5、SERLALIZABLE
串行化最高的事务隔离级别不管多少事务挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务这样就解决了脏读、不可重复读和幻读的问题了
网上专门有图用表格的形式列出了事务隔离级别解决的并发问题 再必须强调一遍不是事务隔离级别设置得越高越好事务隔离级别设置得越高意味着势必要花手段去加锁用以保证事务的正确性那么效率就要降低因此实际开发中往往要在效率和并发正确性之间做一个取舍一般情况下会设置为READ_COMMITED此时避免了脏读并发性也还不错之后再通过一些别的手段去解决不可重复读和幻读的问题就好了。
事物隔离级别查看及修改
首先说明一下MySQL查看和修改事务隔离级别的几个命令
查看事务隔离级别使用select tx_isolation修改当前会话事务隔离级别使用SET session TRANSACTION ISOLATION LEVEL Serializable;参数可以为Read uncommitted|Read committed|Repeatable read|Serializable修改全局事务隔离级别使用SET global TRANSACTION ISOLATION LEVEL Serializable;参数可以为Read uncommitted|Read committed|Repeatable read|Serializable
修改了会话的事务隔离级别比如MyBatisgetSqlSession()的时候只针对这一次拿到的Session有效比如CMD命令行只对这一次的窗口有效。
修改了全局的事务隔离级别那么针对此后所有的会话有效当前已经存在的会话不受影响。
[Mysql]——通过例子理解事务的4种隔离级别
SQL标准定义了4种隔离级别包括了一些具体规则用来限定事务内外的哪些改变是可见的哪些是不可见的。
低级别的隔离级一般支持更高的并发处理并拥有更低的系统开销。
首先我们使用 test 数据库新建 tx 表并且如图所示打开两个窗口来操作同一个数据库
第1级别Read Uncommitted(读取未提交内容)
(1)所有事务都可以看到其他未提交事务的执行结果 (2)本隔离级别很少用于实际应用因为它的性能也不比其他级别好多少 (3)该级别引发的问题是——脏读(Dirty Read)读取到了未提交的数据
#首先修改隔离级别
set tx_isolationREAD-UNCOMMITTED;
select tx_isolation;
------------------
| tx_isolation |
------------------
| READ-UNCOMMITTED |
------------------#事务A启动一个事务
start transaction;
select * from tx;
------------
| id | num |
------------
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
------------#事务B也启动一个事务(那么两个事务交叉了)在事务B中执行更新语句且不提交
start transaction;
update tx set num10 where id1;
select * from tx;
------------
| id | num |
------------
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
------------#事务A那么这时候事务A能看到这个更新了的数据吗?
select * from tx;
------------
| id | num |
------------
| 1 | 10 | ---可以看到说明我们读到了事务B还没有提交的数据
| 2 | 2 |
| 3 | 3 |
------------#事务B事务B回滚,仍然未提交
rollback;
select * from tx;
------------
| id | num |
------------
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
------------#事务A在事务A里面看到的也是B没有提交的数据
select * from tx;
------------
| id | num |
------------
| 1 | 1 | ---脏读意味着我在这个事务中(A中)事务B虽然没有提交但它任何一条数据变化我都可以看到
| 2 | 2 |
| 3 | 3 |
------------第2级别Read Committed(读取提交内容)
(1)这是大多数数据库系统的默认隔离级别但不是MySQL默认的 (2)它满足了隔离的简单定义一个事务只能看见已经提交事务所做的改变 (3)这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read)不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。 |——导致这种情况的原因可能有(1)有一个交叉的事务有新的commit导致了数据的改变;(2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的commit
#首先修改隔离级别
set tx_isolationread-committed;
select tx_isolation;
----------------
| tx_isolation |
----------------
| READ-COMMITTED |
----------------#事务A启动一个事务
start transaction;
select * from tx;
------------
| id | num |
------------
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
------------#事务B也启动一个事务(那么两个事务交叉了)在这事务中更新数据且未提交
start transaction;
update tx set num10 where id1;
select * from tx;
------------
| id | num |
------------
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
------------#事务A这个时候我们在事务A中能看到数据的变化吗?
select * from tx; ---------------
------------ |
| id | num | |
------------ |
| 1 | 1 |---并不能看到 |
| 2 | 2 | |
| 3 | 3 | |
------------ |——相同的select语句结果却不一样|
#事务B如果提交了事务B呢? |
commit; ||
#事务A: |
select * from tx; ---------------
------------
| id | num |
------------
| 1 | 10 |---因为事务B已经提交了所以在A中我们看到了数据变化
| 2 | 2 |
| 3 | 3 |
------------第3级别Repeatable Read(可重读)
(1)这是MySQL的默认事务隔离级别 (2)它确保同一事务的多个实例在并发读取数据时会看到同样的数据行 (3)此级别可能出现的问题——幻读(Phantom Read)当用户读取某一范围的数据行时另一个事务又在该范围内插入了新行当用户再读取该范围的数据行时会发现有新的“幻影” 行 (4)InnoDB和Falcon存储引擎通过多版本并发控制(MVCCMultiversion Concurrency Control)机制解决了该问题
#首先更改隔离级别
set tx_isolationrepeatable-read;
select tx_isolation;
-----------------
| tx_isolation |
-----------------
| REPEATABLE-READ |
-----------------#事务A启动一个事务
start transaction;
select * from tx;
------------
| id | num |
------------
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
------------#事务B开启一个新事务(那么这两个事务交叉了)在事务B中更新数据并提交
start transaction;
update tx set num10 where id1;
select * from tx;
------------
| id | num |
------------
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
------------
commit;#事务A这时候即使事务B已经提交了,但A能不能看到数据变化
select * from tx;
------------
| id | num |
------------
| 1 | 1 | ---还是看不到的(这个级别2不一样也说明级别3解决了不可重复读问题)
| 2 | 2 |
| 3 | 3 |
------------#事务A只有当事务A也提交了它才能够看到数据变化
commit;
select * from tx;
------------
| id | num |
------------
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
------------第4级别Serializable(可串行化)
(1)这是最高的隔离级别 (2)它通过强制事务排序使之不可能相互冲突从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。 (3)在这个级别可能导致大量的超时现象和锁竞争
#首先修改隔离界别
set tx_isolationserializable;
select tx_isolation;
----------------
| tx_isolation |
----------------
| SERIALIZABLE |
----------------#事务A开启一个新事务
start transaction;#事务B在A没有commit之前这个交叉事务是不能更改数据的
start transaction;
insert tx values(4,4);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
update tx set num10 where id1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction