可以做渐变色块拼接的网站,苏州哪家网站建设,做视频网站视频用什么插件吗,品牌公关活动如果对表中的数据进行CRUD操作时#xff0c;不加控制#xff0c;会带来一些问题。 比如下面这种场景#xff1a; 有一个tickets表#xff0c;这个数据库被两个客户端机器A和B用时连接对此表进行操作。客户端A检查tickets表中还有一张票的时候#xff0c;将票出售了#x…如果对表中的数据进行CRUD操作时不加控制会带来一些问题。 比如下面这种场景 有一个tickets表这个数据库被两个客户端机器A和B用时连接对此表进行操作。客户端A检查tickets表中还有一张票的时候将票出售了而火车票的总数是一个固定值客户端A此时还没有来得及更新数据库 这时客户端B检查了票数发现还有一张又卖了一次票。这种情况就出现了同一张票被卖了两次的场景。
这就是在进行CRUD时不加控制带来的问题。 只要当进进行CRUD时满足以下属性才能解决上面的问题
买票的过程得是原子的买票互相应该不能影响买完票应该要永久有效买前和买后都要是确定的状态
而MySQL的事务机制就能够有效的解决此问题。
1. MySQL事务
事务就是一组DML语句组成这些语句在逻辑上存在相关性这一组DML语句要么全部成功要么全部失败是一个整体。
MySQL提供一种机制保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。
事务就是要做的或所做的事情主要用于处理操作量大复杂度高的数据。假设一种场景你毕业了,学校的教务系统后台MySQL中不再需要你的数据要删除你的所有信息, 那么要删除你的基本信息(姓名电话籍贯等)的同时也删除和你有关的其他信息比如你的各科成绩你在校表现甚至你在论坛发过的文章等。这样就需要多条 MySQL 语句构成那么所有这些操作合起来就构成了一个事务。
一个 MySQL数据库可不止一个事务在运行同一时刻甚至有大量的请求被包装成事务在向MySQL服务器发起事务处理请求。而每条事务至少一条 SQL 最多很多SQL ,这样如果大家都访问同样的表数据在不加保护的情况就绝对会出现问题。甚至因为事务由多条SQL构成那么也会存在执行到一半出错或者不想再执行的情况那么已经执行的怎么办呢
所以一个完整的事务不仅仅是简单的DML组合而成还要满足以下4个特点
原子性Atomicity 事务中的所有操作要么全部完成要么全部不完成。一致性Consistency 事务执行前后数据库的状态必须保持一致。隔离性Isolation 一个事务的执行不能被其他事务干扰。持久性Durability 一旦事务提交其对数据库的修改应该永久保存。
以上 四个属性可以简称为ACID。
所以事务就是一条或者多条SQL语句组成并包含ACID。
有了事务这种机制后能够简化我们的编程模型, 不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我 们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服 务的.而不是伴随着数据库系统天生就有的。
1.1 MySQL事务支持的版本
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务 MyISAM不支持。 使用show engines可以查看。 1.2 事务的提交方式
事务的提交方式常见的有两种
自动提交手动提交
使用show variables like autocommit;可以查看事务提交的方式。 ON表示为自动提交。
可以通过set autocommit来更改自动提交模式。值为0表示禁止自动提交。 值为1表示开启自动提交。 1.3 事务常见的操作方式
为了方便演示这里创建一张测试表account。
create table if not exists account(
id int primary key,
name varchar(50) not null default ,
blance decimal(10,2) not null default 0.0
)ENGINEInnoDB DEFAULT CHARSETUTF8;这里还需要不同的主机连接到同一个数据库中我使用本地和服务器的mysql客户端进行连接。 使用SHOW PROCESSLIST;可以查看数据库的连接情况。 除此之外还需要将mysql的默认隔离级别设置成读未提交。 set global transaction isolation level READ UNCOMMITTED; 使用此命令设置完成后重启客户端进行连接隔离级别才会生效。 先查看事务是否是自动提交,使用show variables like autocommit;命令进行查看。 ON表示开启自动提交。以下提交的方式都是自动提交的。
1.3.1 开始一个事务
开始一个事务可以使用being或者start transaction。 1.3.2 创建一个保存点
使用savepoint 保存点名进行设置一个保存点 1.3.3 回滚到保存点
使用rollback to 保存点名即可回滚到指定的保存点中。 使用rollback可以直接回滚到最开始。 使用示例-事务的开始和回滚 此时另一个客户端在查询时也可以查询到。做到了一致性。 这样两个客户端同时操作一个表的时候就可以有效的解决冲突了。 事务使用示例-自动回滚 当提交方式为自动提交的时候客户端崩溃的后MySQL会自动回滚。(隔离级别设置为提交未读)
在客户端A中使用事务进行插入。如下。 插入一条记录后从另一个客户端B中就可以查询到如下
此时客户端A崩溃了那么MySQL就会自动回滚。 自动回滚后在客户端B中就无法查询到插入的这条记录了。 事务使用示例-提交后客户端崩溃后MySQL的数据不会在受到影响。(持久化特性) 在客户端A事务中插入一条记录然后手动提交客户端A崩溃。 此时在另一个客户端B中进行查询依然可以查询到。 事务做到了数据持久化不会被影响。 事务使用示例-begin操作会自动更改提交方式不会受MySQL是否自动提交影响 事务使用示例-单条 SQL 与事务的关系 单条SQL: 此时客户端B在进行查询的时候就无法查询到此记录。 事务 此时客户端B在进行查询的时候依然可以查询到此记录。数据已经被持久化了。 1.4 总结
只要输入begin或者start transaction事务便必须要通过commit提交才会持久化与是 否设置set autocommit无关。事务可以手动回滚同时当操作异常MySQL会自动回滚对于 InnoDB 每一条 SQL 语言都默认封装成事务自动提交。select有特殊情况因为 MySQL 有 MVCC
事务操作注意事项
如果没有设置保存点也可以回滚只能回滚到事务的开始。直接使用 rollback(前提是事务 还没有提交)。如果一个事务被提交了commit则不可以回退rollback可以选择回退到哪个保存点InnoDB 支持事务 MyISAM 不支持事务开始事务可以使 start transaction 或者 begin。begin更简洁 推荐使用。
2. 事务隔离级别
MySQL服务可能会同时被多个客户端进程线程访问访问的方式以事务的方式进行。一个事务可能由多条SQL语句构成也就意味着任何一个事务都有执行前、执行中和执行后三个阶段而所谓的原子性就是让用户层要么看到执行前要么看到执行后执行中如果出现问题可以随时进行回滚所以单个事务对用户表现出来的特性就是原子性。但毕竟每个事务都有一个执行的过程在多个事务各自执行自己的多条SQL时仍然可能会出现互相影响的情况比如多个事务同时访问同一张表甚至是表中的同一条记录。数据库中为了保证事务执行过程中尽量不受干扰就有了一个重要特征隔离性数据库中允许事务受不同程度的干扰就有了一种重要特征隔离级别
数据库的隔离级别一共有以下四种。
读未提交【Read Uncommitted】 在该隔离级别所有的事务都可以看到其他事务没有提交的 执行结果。实际生产中不可能使用这种隔离级别的但是相当于没有任何隔离性也会有很多 并发问题如脏读幻读不可重复读等上面为了做实验方便用的就是这个隔离性。读提交【Read Committed】 该隔离级别是大多数数据库的默认的隔离级别不是 MySQL 默 认的。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读即一个事务执行时如果多次 select 可能得到不同的结果。可重复读【Repeatable Read】 这是 MySQL 默认的隔离级别它确保同一个事务在执行中多次读取操作数据时会看到同样的数据行。但是会有幻读问题。串行化【Serializable】: 这是事务的最高隔离级别它通过强制事务排序使之不可能相互冲突 从而解决了幻读的问题。它在每个读的数据行上面加上共享锁。但是可能会导致超时和锁竞争 这种隔离级别太极端实际生产基本不使用
2.1 查看隔离性
SELECT global.tx_isolation;查看全局的隔离级别 SELECT session.tx_isolation; 或者 SELECT tx_isolation;查看当前会话的隔离级别
2.2 设置隔离级别
设置当前会话 or 全局隔离级别语法:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | Serializable}比如设置当前会话隔离级别为Serializable。 设置全局隔离性的话另起一个会话就会被影响。重启MySQL客户端生效 2.2.1 读未提交【Read Uncommitted】
该隔离级别效率虽然很高但是问题太多严重不建议使用。 问题如下 1、将事务的隔离级别设置为Read Uncommitted 2、在一个终端A中开启事务然后插入一条记录。不进行提交。 3、在另一个终端中进行查询 这就是Read Uncommitted隔离级别做严重的问题读到了未提交的数据。这种现象称之为脏读~
2.2.2 读提交【Read Committed】
按照命名来看对比读未提交读提交只读已提交的数据。但是这种隔离级别有新的问题。读到的值不同。问题如下 1、将隔离级别设置为Read Committed 2、开启事务不提交在另一个客户端进行查询 在另一个终端中读不到。 3、进行提交在另一个终端再次读取。 终端A使用commit提交后在终端B中就可以查到了。 到此读提交解决了读未提交的问题。 但是如果在终端A更新插入一条记录不提交终端B就能读到了。回到了读未提交的现象。 终端B还是读到了 这种现象叫做不可重复读解决这个问题又有了新的隔离级别。 可重复读【Repeatable Read】
2.2.3 可重复读【Repeatable Read】
这种隔离级别解决了读未提交和读提交的问题但是又带来了幻读的问题。如下 1、设置隔离级别为Repeatable Read 2、开启事务插入记录 不提交此时在另一个终端就无法进行查询到。解决读未提交的问题。 继续在终端A中插入一条记录 此时在终端中就能查询到了。 继续插入不提交另一个终端也无法查到。
同样的在终端A中插入一条记录并提交结束事务。 然后再终端B查询终端Acommit后的纪律。 但是多次查询后在终端B中无法查询到A commit到的记录。
这倒也没有什么影响也符合可重复的特点。 但是一般的数据库在可重复读情况的时候无法屏蔽其他事务insert的数据(为什么因为隔离性实现是对数据加锁完成的而insert待插入的数据因为并不存在那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的但是insert的数据在可重复读情况被读取出来导致多次查找时会多查找出来新的记录就如同产生了幻觉。这种现象叫做幻读 (phantom read)。
2.2.4 串行化【Serializable】
对所有操作全部加锁进行串行化不会有问题但是只要串行化效率很低几乎完全不会被采用。
两个终端都使用事务当A进行更新的时候会一直阻塞直到终端B提交后才可以。 实际这种完全不会被采用。
2.2.5 总结
事务隔离级别越严格安全性越高但数据库的并发性能也就越低往往需要在两者之间找一个平衡点。不可重复读的重点是修改和删除同样的条件, 你读取过的数据,再次读取出来发现值不一样了幻读的重点在于新增同样的条件, 第1次和第2次读出来的记录数不一样说明 mysql 默认的隔离级别是可重复读,一般情况下不要修改上面的例子可以看出事务也有长短事务这样的概念。事务间互相影响指的是事务在并行执行的 时候即都没有commit的时候影响会比较大。 3. 事务的一致性
事务执行的结果必须使数据库从一个一致性状态变到另一个一致性状态。当数据库只包含事务 成功提交的结果时数据库处于一致性状态。如果系统运行发生中断某个事务尚未完成而被迫中 断而改未完成的事务对数据库所做的修改已被写入数据库此时数据库就处于一种不正确不一 致的状态。因此一致性是通过原子性来保证的。其实一致性和用户的业务逻辑强相关一般MySQL提供技术支持但是一致性还是要用户业务逻辑 做支撑也就是说一致性是由用户决定的。而技术上通过AID保证C