程序员

1.2.MySQL事务

2019-11-02  本文已影响0人  老苏GO

1.2.MySQL事务(Transaction)

1.2.1.事务概念

事务:

ACID特性:

1.2.2.事务原子性和持久性

事务状态:

1.2.3.事务隔离性

可串行化(serializable): 在并发执行中, 通过保证所执行的任何调度的效果都与没有并发执行的调度效果一样, 则可以确保数据库的一致性. 也就是说: 调度应该在某种意义上等价于一个串行调度.

1.2.4.可串行化

冲突(conflict): 当I和J是不同事物在相同数据项Q上的操作, 并且其中至少有一个是write(Q)指令时, 则I和J是冲突的.

冲突等价(conflict equivalent): 如果调度A可以经过一系列非冲突指令交换转换成B, 称A和B是冲突等价的.

冲突可串行化(conflict serializable): 若一个调度S与一个串行调度冲突等价, 则称调度S是冲突可串行化的.

1.2.5.可恢复性

  1. 可恢复调度(recoverable schedule): 应满足: 对于每对事务A和B, 如果B读取了之前由A所写的数据项, 则A先于B提交.
  2. 无级联调度(cascadeless schedule)
    • 级联回滚(cascading rollback): 因单个事务故障导致一系列事务回滚的现象.
    • 无级联调度: 对于每对事务A和B, 如果B读取了先前由A所写的数据项, 则A必须在B这一读操作前进行提交.
    • 每一个无级联调度也都是一个可恢复调度.
  3. 事务隔离级别
    • 可串行化(serializable): 通常保证可串行化调度. 是最高的隔离级别, 通过强制事务串行执行, 避免了幻读的问题. 简单来说: 可串行化会在读取的每一行数据上都加锁, 所以可能导致大量的超时和锁争用的问题. 实际应用中, 很少考虑这个级别, 只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别.
    • 可重复读(repeatable read):只允许读取已提交数据, 而且在一个事务两次读取一个数据项期间, 其他事务不得更新该数据.解决了脏读的问题. 该级别保证了在同一个事务中多次读取同样记录的结果是一致的.但无法解决幻读(phantom read)的问题. 幻读: 指的是当某个事务在读取某个范围内的记录时, 另外一个事务又在该范围内插入了新的记录, 当之前的事务再次读取该范围的记录时, 会产生幻行(phantom row). InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题. 可重复读是MySQL的默认事务隔离级别.
    • 已提交读(read committed): 只允许读取已提交数据, 但不要求可重复读. 一个事务开始时,只能"看见"已经提交的事务所做的修改. 换句话说: 一个事务从开始直到提交之前, 所做的任何修改对其他事务都是不可见的. 也叫做不可重复读(nonrepeatable read), 因为两次执行同样的查询,可能会得到不一样的结果.
    • 未提交读(read uncommitted): 允许读取未提交读. 事务可以读取未提交的数据, 这种也被称为脏读(dirty read). 实际应用中一般很少使用.
    • 以上所有隔离级别都不允许脏写(dirty write), 即如果一个数据项已经被另外一个尚未提交或中止的事务写入, 则不允许对该数据项执行写操作.

1.2.6.死锁

死锁(dead lock): 指两个或多个事务在同一资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性资源竞争的现象.

1.2.7.事务日志

事务日志: 使用事务日志, 存储引擎在修改表的数据时, 只需要修改其内存拷贝, 再把该修改行为记录到持久在硬盘上的事务日志中, 而不用每次都将修改的数据本身持久到磁盘.

特点: 事务日志采用追加的方式, 因此写日志的操作时磁盘上一小块区域内的顺序IO, 而不像随机IO需要在磁盘的多个地方移动磁头, 所以采用事务日志的方式相对来说会很快.

预写式日志(write-ahead logging): 事务日志持久以后, 内存中被修改的数据在后台可以慢慢地刷回到磁盘. 所以修改数据需要写两次磁盘.

系统崩溃情况: 如果数据的修改已经记录到事务日志并持久化, 但数据本身还没有写入到磁盘, 此时系统崩溃, 存储引擎在重启时能够自动恢复这部分修改的数据.

隔离级别设置

  1. 通过SET TRANSACTION语句设置
// GLOBAL:适用于所有后续会话 但已存在的会话不受影响;需要root用户权限
// SESSION:适用于当前会话中执行的所有后续事务,但不影响当前事务
// 既不是GLOBAL 也不是SESSION:仅适用于当前会话中的下一个事务;不允许在事务执行过程中设置
SET [GLOBAL | SESSION] TRANSACTION
    transaction_characteristic [, transaction_characteristic] ...

transaction_characteristic: {
    ISOLATION LEVEL level // READ UNCOMMITTED/READ COMMITTED / REPEATABLE READ /SERIALIZABLE
  | access_mode
}

level: {
     REPEATABLE READ
   | READ COMMITTED
   | READ UNCOMMITTED
   | SERIALIZABLE
}

access_mode: { // 访问模式 只读:READ ONLY 读写:READ WRITE
     READ WRITE
   | READ ONLY
}
// 示例
SET GLOBAL TRANSACTION READ COMMITTED; GLOBAL
SET SESSION TRANSACTION READ COMMITTED; SESSION
SET TRANSACTION READ COMMITTED; NEXT TRANSACTION ONLY
  1. 通过配置文件设置
[mysqld]
transaction-isolation = REPEATABLE-READ
transaction-read-only = OFF
  1. 通过SET variables设置
SET GLOBAL transaction_isolation = READ COMMITTED; GLOBAL
SET @@GLOBAL.transaction_isolation = READ COMMITTED; GLOBAL
SET SESSION transaction_isolation = READ COMMITTED; SESSION
SET @@SESSION.transaction_isolation = READ COMMMITTED; SESSION
SET transaction_isolation = READ COMMITTED; SESSION
SET @@transaction_isolation = READ COMMITTED; NEXT TRANSACTION ONLY
  1. 检查当前隔离级别
SELECT @@GLOBAL.transaction_isolation, @@GLOBAL.transaction_read_only; GLOBAL
SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only; SESSION
上一篇 下一篇

猜你喜欢

热点阅读