1-什么是transaction?
中文大家习惯翻译为“事务”。 transaction我更喜欢的翻译是:交易。交易就涉及到多方:付款方,收款方。这也是为啥大家总喜欢拿银行转账举例子的原因。
所以,什么transaction?https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_transaction
Transactions are atomic units of work that can be committed or rolled back. When a transaction makes multiple changes to the database, either all the changes succeed when the transaction is committed, or all the changes are undone when the transaction is rolled back. Database transactions, as implemented by InnoDB, have properties that are collectively known by the acronym ACID, for atomicity, consistency, isolation, and durability.
transaction就是一系列的sql操作(1个或多个),可以提交或者全部回滚的工作单元。且对于innodb引擎事物是具有acid特性,即:原子性 一致性 隔离性 持久性。也就是大家说的acid:https://dev.mysql.com/doc/refman/8.0/en/mysql-acid.html
怎么理解事务呢,就是在业务场景中我们实现一个功能比如转账涉及到用户a的金额扣减和用户b的金额增加两步操作,我需要保证这个transaction要么全部成功要么全部回滚当没发生过,不然就会出现问题。所以必须要有一种机制来保证实现这种多条sql同时执行成功或者失败,这就是transaction。
所以在transaction中atomicity就是指这一系列操作看作一个atom操作(原子(atom),是指化学反应不可再分的基本微粒),只有0和1;consistency就是指执行完成这个transaction后前后的逻辑是一致的,比如a的余额减少了100,b的增加了100,这是逻辑一致的。isolation则是指当前执行的transaction不会被别的transaction影响;durability则是指transaction执行完成,所有相关的东西都完成提交了,不会再变动了,这个事情相关方的状态都变化完成了是持久的。
1.1-transaction的atomicity
要想日志undo https://dev.mysql.com/doc/refman/8.0/en/innodb-undo-logs.html
问题来了,如果我想满足atomicity原子性这个操作,意味着要么全部成功要么全部失败回滚到以前的状态,所以必须要有个地方来记录我修改前的值,不然我怎么回滚?这就是undo日志
1.2-transaction的consistency
1>update set user balance = 90 where user_id=1;
2>update set user balance = 110 where user_id=2;
1-先保存原来的那一行数据userid=1 balance=100到undo log中 准备随时回滚(**_rolled back.)
2-再保存原来的那一行数据user_id=2 balance=100到undo log中 准备随时回滚(rolled back.)
3-原来的user_id=1 balance=90到redo log中,如果这时候服务器挂了,还可以根据redo log重新执行丢失的事物。这也是redo的repeated的意义。
4-原来的user_id=2 balance=110到redo log中,如果这时候服务器挂了,还可以根据redo log重新执行**丢失的事物。这也是redo的repeated的意义。
5-上面代码如果有问题error了,可以把user_id=1的钱会滚到100,user_id=2的会滚到100;如果服务器在事物没提交之前挂了(没有生成binlong),可以继续redo log重新执行完成这个事务。
6-如果全部没问题,commit提交数据修改数据,生成binlog日志。
redo https://dev.mysql.com/doc/refman/8.0/en/innodb-redo-log.html
1.3-transaction的isolation
所谓隔离性,很容易理解就是不希望别人打扰。mysql是怎么做到不被人打扰以及希望不被人打扰的程度到哪一步呢?那就要说到mysql的四个isolation级别:
One of the foundations of database processing. Isolation is the I in the acronym ACID; the isolation level is the setting that fine-tunes the balance between performance and reliability, consistency, and reproducibility of results when multiple transactions are making changes and performing queries at the same time. From highest amount of consistency and protection to the least, the isolation levels supported by InnoDB are: SERIALIZABLE, REPEATABLE READ, READ COMMITTED, and READ UNCOMMITTED. With InnoDB tables, many users can keep the default isolation level (REPEATABLE READ) for all operations. Expert users might choose the READ COMMITTED level as they push the boundaries of scalability with OLTP processing, or during data warehousing operations where minor inconsistencies do not affect the aggregate results of large amounts of data. The levels on the edges (SERIALIZABLE and READ UNCOMMITTED) change the processing behavior to such an extent that they are rarely used.
https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_isolation_level
1.3.1-REPEATABLE READ
The default isolation level for InnoDB. It prevents any rows that are queried from being changed by other transactions, thus blocking non-repeatable reads but not phantom reads. It uses a moderately strict locking strategy so that all queries within a transaction see data from the same snapshot, that is, the data as it was at the time the transaction started. When a transaction with this isolation level performs UPDATE … WHERE, DELETE … WHERE, SELECT … FOR UPDATE, and LOCK IN SHARE MODE operations, other transactions might have to wait. SELECT … FOR SHARE replaces SELECT … LOCK IN SHARE MODE in MySQL 8.0.1, but LOCK IN SHARE MODE remains available for backward compatibility.
mysql默认的隔离级别:允许你读到重复的数据。会出现幻读,怎么每次读到的都是一样的数据没变化。
解决了可重复读(我不理解这个隔离级别有什么业务场景需要。。),也就是一个事务中你多次读到的数据都是一样的,即使已经被另外一个人commit改了。
当前隔离级别下如果你执行的是delete update for update等ddl语句其他的事务是会被阻塞等待的。
1.3.2-READ COMMITTED
An isolation level that uses a locking strategy that relaxes some of the protection between transactions, in the interest of performance. Transactions cannot see uncommitted data from other transactions, but they can see data that is committed by another transaction after the current transaction started. Thus, a transaction never sees any bad data, but the data that it does see may depend to some extent on the timing of other transactions. When a transaction with this isolation level performs UPDATE … WHERE or DELETE … WHERE operations, other transactions might have to wait. The transaction can perform SELECT … FOR UPDATE, and LOCK IN SHARE MODE operations without making other transactions wait. SELECT … FOR SHARE replaces SELECT … LOCK IN SHARE MODE in MySQL 8.0.1, but LOCK IN SHARE MODE remains available for backward compatibility.
1.3.3-READ UNCOMMITTED
The isolation level that provides the least amount of protection between transactions. Queries employ a locking strategy that allows them to proceed in situations where they would normally wait for another transaction. However, this extra performance comes at the cost of less reliable results, including data that has been changed by other transactions and not committed yet (known as dirty read). Use this isolation level with great caution, and be aware that the results might not be consistent or reproducible, depending on what other transactions are doing at the same time. Typically, transactions with this isolation level only do queries, not insert, update, or delete operations.
允许你读到未提交后的数据。会出现脏读,也就是脏数据被你读到了。
1.3.4-SERIALIZABLE
The isolation level that uses the most conservative locking strategy, to prevent any other transactions from inserting or changing data that was read by this transaction, until it is finished. This way, the same query can be run over and over within a transaction, and be certain to retrieve the same set of results each time. Any attempt to change data that was committed by another transaction since the start of the current transaction, cause the current transaction to wait. This is the default isolation level specified by the SQL standard. In practice, this degree of strictness is rarely needed, so the default isolation level for InnoDB is the next most strict, REPEATABLE READ.
1.3.5-mvvc
基于事务的不同隔离级别形成了mvvc多版本控制,也就是不同的隔离级别你可以读取到不同的数据。从另一方面讲在其他事务操作的时候还能读取到数据,而不是直接锁死。你想在update一条数据的时候会有排他锁,那么意味着这条数据不能被其他事物操作(包括select),那么岂不是严重影响业务逻辑?所以mvvc存在的意义就如文档所说就是提高了并发能力:
mvvc:https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_mvcc
Acronym for “multiversion concurrency control”. This technique lets InnoDB transactions with certain isolation levels perform consistent read operations; that is, to query rows that are being updated by other transactions, and see the values from before those updates occurred. This is a powerful technique to increase concurrency, by allowing queries to proceed without waiting due to locks held by the other transactions. This technique is not universal in the database world. Some other database products, and some other MySQL storage engines, do not support it.