mysql ACID、隔离级别-子查询锁表
阅读数:246 评论数:0
跳转到新版页面分类
数据库
正文
一、事务的ACID
Transactions are often composed of multiple statements. Atomicity guarantees that each transaction is treated as a single "unit", which either succeeds completely, or fails completely: if any of the statements constituting a transaction fails to complete, the entire transaction fails and the database is left unchanged. An atomic system must guarantee atomicity in each and every situation, including power failures, errors and crashes.
事务中所有操作作为一个整体,像原子一样不可分割,要么全部成功,要么全部失败。
Consistency ensures that a transaction can only bring the database from one valid state to another, maintaining database invariants: any data written to the database must be valid according to all defined rules, including constraints, cascades, triggers, and any combination thereof. This prevents database corruption by an illegal transaction, but does not guarantee that a transaction is correct.
事务开始前和结束后,数据库的完整性约束没有被破坏,都是合法的数据状态。
Transactions are often executed concurrently (e.g., reading and writing to multiple tables at the same time). Isolation ensures that concurrent execution of transactions leaves the database in the same state that would have been obtained if the transactions were executed sequentially. Isolation is the main goal of concurrency control; depending on the method used, the effects of an incomplete transaction might not even be visible to other transactions.
并发执行的事务不会相会影响,其对数据库的影响和它们串行执行时一样。
Durability guarantees that once a transaction has been committed, it will remain committed even in the case of a system failure (e.g., power outage or crash). This usually means that completed transactions (or their effects) are recorded in non-volatile memory.
事务一旦提交,其对数据库的更新就是持久的,任务事务或故障都不会导致数据丢失。
总结:
在事务的ACID特性中,一致性是事务的追求,而对数据库的一致性破坏主要来自两个方面:
(1)事务的并发执行
(2)事务故障或系统故障。
二、隔离级别
事务的隔离性使用的是锁机制。
脏读 | 一个事务对数据进行增删改,但并没有提交,但另一个事务却能读到未提交的数据。 |
不可重复读 | 一个事务对数据进行更新或删除操作,另一个事务两次查询的数据不一致。(行级锁) |
幻读 | 一事务对数据进行新增操作,另一事务两次查询结果不一致。(表级锁) |
当事物A首先进行了一次数据读取,然后事务B对这数据进行了改变(如果是update或delete即是不可重复读,如果是insert即是幻读),然后事物A再次进行一次同样的数据读取,发现数据两次不一致。
数据库事务的隔离级别有四个:
read uncommitted | 存在脏读、不可重复读、幻读 |
read commited | 存在不可重复读、幻读 |
repetable read(RR) | 存在幻读 |
serializable |
1、可重复读
实现原理是MVCC。
InnoDB在每行记录中隐藏版本号,当数据被修改时,新的数据版本号会加1,从而当前读事务的版本号小于实际数据的版本号,自然就读不到更新后的数据了。
2、子查询锁表
mysql默认是repetable read(Oracle是RC),所以为了保证事务中每个select是可以重复读的,select 的表会被锁住,这样当使用
update ..select * from
insert into ...select * from
都会锁住子表,造成死锁,可以改变mysql的隔离级别
show global variables like '%isolation%';
set global transaction_isolation='read-commited';
三、mysql日志
mysql通过WAL(write-ahead logging)来保证事务。
Myisam引擎只支持binlog,而innodb支持binlog、redolog、undolog。
binlog常用来进行数据恢复、数据复制。
binlog有两种记录模式,statement格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后都有。
binlog和redo log必须保持一致,不允许出现binlog有记录但redolog没有的情况,反之亦然。
当执行更新语句时,redo log会首先写入log buffer,在事务提交前,只要将redo log持久化即可,不需要将数据持久化,当mysql重启进行恢复时会重新执行redo log记录的sql进行数据恢复。
在同一个事务中,每当数据库进行修改数据操作时,将修改结果更新到内存后,会在redo log添加一行记录记录“需要在哪个数据页上做什么修改”,并将该记录状态置为prepare,等到commit提交事务后,会将此次事务中在redo log添加的记录的状态都置为commit状态,之后将修改落盘时,会将redo log中状态为commit的记录的修改都写入磁盘。
有了redo log,当数据库发生宕机重启后,可通过redo log将未落盘的数据恢复,即保证已经提交的事务记录不会丢失。
在操作任何数据之前,首先将数据备份到undo log,用于数据的回滚。
比如:当我们执行一条insert语句时,Undo Log就记录一条相反的delete语句。