【什么是事务】
事务是逻辑上的一组操作,要么全部执行,要么全部放弃。最典型的例子就是银行转账,此消彼长是原则,全部的操作必须是一个事务,中间环节若失败,则回滚至最初状态。
【事务的特性】
事务的特性即:ACID
- 原子性(Atomicity):事务是最小的执行单位,不允许分割。
- 一致性(Consistency):执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的。
- 隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立。
- 持久性(Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
【事务在并发下的问题】
并发场景下,多个事务操作同样的数据。可能带来以下问题:
- 脏读 (Dirty read):读取了未提交生效的数据。即一个事务update期间(未提交),另一个事务read。
- 丢失修改 (Lost to modify):修改了前序事务未修改完成的数据。即一个事务update期间(未提交),另一个事务也update。
- 不可重复读 (Unrepeatable read):两次读取read&read期间,另一个事务做了修改update操作。
- 幻读 (Phantom read):两次读取read&read期间,另一个事务做了新增insert / 删除delete操作。
【解决事务并发问题:事务隔离】
为了解决以上并发导致的问题,SQL标准定义了四种隔离级别(从低到高):
- 读取未提交 (Read-Uncommitted) :最低级别,允许读取未提交的数据。
- 读取已提交 (Read-Committed) :只允许读取已经提交的数据。可以防止脏读!
- 可重复读 (Repeatable-Read) :同一字段的多次读取结果是一致的,除非自身进行了修改。可以防止脏读、不可重复读。MySQL InnoDB 存储引擎的默认支持的隔离级别(使用了Next-Key Lock 锁算法,因此InnoDB的该级别可以达到可串行化的SQL标准级别)。
- 可串行化 (Serializable) :最高级别,完全遵从ACID隔离级别,所有事务相互独立,互不干扰。可以防止脏读、不可重复读、幻读。
隔离级别 | 防止脏读 | 防止不可重复读 | 防止幻读 |
---|---|---|---|
READ-UNCOMMITTED | × | × | × |
READ-COMMITTED | √ | × | × |
REPEATABLE-READ | √ | √ | × |
SERIALIZABLE | √ | √ | √ |
可以在SQL中使用以下命令来查看隔离级别:
SELECT @@transaction_isolation
【SQL执行慢的原因】
一、偶尔很慢:
1、数据库正在刷新脏页,占用资源。
数据库更新时,首先是刷新内存,而不是即刻持久化(IO操作比较耗时);然后把更新的操作写入到redo log中,待数据库空闲时再刷新到磁盘。因为redo log模块容量有限,当它被写满后,数据库就不得不停止其他操作,优先完成数据到磁盘的持久化。这个过程就是刷新脏页。此时客户端提交的SQL操作因为资源问题,执行速度会变慢。
2、数据库在做并发操作,无法获取到锁。
多个客户端请求在操作同一张表或同一行数据时,因为数据库的锁机制,后来的操作必须等到前序操作完成释放锁之后,才能进行。因此速度可能也会变慢。使用show processlist命令可以判断当前操作是否在等待锁。
二、一直很慢:
SQL一直很慢多数情况下,就必须考虑SQL的用法是否存在问题了。
1、未使用索引。没有建立索引,或者因为字段运算、函数操作未能使用索引。
2、数据库的优化器选错了索引。
参考文献:(文章仅做交流学习,侵权即删!!)