Transactional 和 Locking Statements

START TRANSACTION, COMMIT, and ROLLBACK Statements 

START TRANSACTION
    [transaction_characteristic [, transaction_characteristic] ...]

transaction_characteristic: {
    WITH CONSISTENT SNAPSHOT
  | READ WRITE
  | READ ONLY
}

BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET autocommit = {0 | 1}

这些语句提供了对transactions使用的控制:

  • START TRANSACTIONBEGIN开始一个新的 transaction。
  • COMMIT 提交当前事务,使其更改永久生效。 
  • ROLLBACK 回滚当前事务,取消其更改。
  • SET autocommit 禁用或启用当前会话的默认自动提交模式。

默认情况下,MySQL在启用自动提交模式的情况下运行 。这意味着,当不在事务内时,每个语句都是原子的,就像它被START TRANSACTIONCOMMIT包围一样。您不能ROLLBACK用来撤消效果。但是,如果在语句执行期间发生错误,则会回滚该语句。

要隐式禁用单个语句系列的自动提交模式,请使用以下START TRANSACTION 语句:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

使用时START TRANSACTION,自动提交保持禁用状态,直到您使用COMMITROLLBACK结束事务 。然后,自动提交模式将恢复为之前的状态。

START TRANSACTION允许使用几个修饰符来控制transaction特征。要指定多个修饰符,请用逗号分隔。

  • WITH CONSISTENT SNAPSHOT修饰符为能够使用它的存储引擎启动 consistent read,这仅适用于InnoDB。效果与从任何InnoDB table 发出START TRANSACTION后跟 SELECT相同。WITH CONSISTENT SNAPSHOT修饰符不会更改当前 transaction  isolation level,因此仅当当前隔离 level 是允许一致读取的隔离时,它才会提供一致的快照。允许一致读取的唯一隔离级别是 REPEATABLE READ 。对于所有其他隔离级别,将忽略WITH CONSISTENT SNAPSHOT子句。从 MySQL 5.7.2 开始,忽略WITH CONSISTENT SNAPSHOT子句时会生成警告。
  • READ WRITEREAD ONLY修饰符设置 transaction 访问模式。它们允许或禁止对 transaction 中使用的表进行更改。READ ONLY限制可防止事务修改或锁定其他事务可见的事务表和非事务表;事务仍然可以修改或锁定临时表。

当已知事务是只读的时, MySQL可以对InnoDB表查询进行额外的优化 。通过指定READ ONLY 可确保在无法自动确定只读状态的情况下应用这些优化。

如果未指定访问模式,则应用默认模式。除非更改了默认值,否则它是读/写的。不允许在同一语句中同时指定READ WRITE 和READ ONLY

在只读模式下,仍然可以使用DML语句更改用TEMPORARY关键字创建的表。与永久表一样,不允许使用DDL语句进行更改。

如果启用了read_only系统变量,则使用START TRANSACTION READ WRITE显式启动 transaction 需要 SUPER特权。

重要

许多用于编写MySQL客户端应用程序的API(例如JDBC)提供了自己的启动事务的方法,这些方法可以(有时应该)用于代替从客户端发送START TRANSACTION语句。

要显式禁用自动提交模式,请使用以下语句:

SET autocommit=0;

通过将autocommit变量设置为零来禁用自动提交模式后 ,对事务安全表(例如for InnoDB或 NDB)的更改不会立即变为永久更改 。您必须使用COMMIT将更改存储到磁盘或ROLLBACK忽略更改。

autocommit是会话变量,必须为每个会话设置。要为每个新连接禁用自动提交模式,请参见第5.1.7节“服务器系统变量”中对autocommit系统变量 的描述 。

支持BEGINBEGIN WORK作为START TRANSACTION的别名来启动 transaction。START TRANSACTION是标准的SQL语法,是启动临时事务的推荐方法,并且允许使用BEGIN 不允许的修饰符。

BEGIN语句与用于启动BEGIN ... END 复合语句的BEGIN关键字的用法不同 。后者不会开始 transaction。

注意

在所有存储的程序(存储的过程和功能,触发器和事件)中,解析器将BEGIN [WORK]视为BEGIN ... END块的开始 。而是在这种情况下使用START TRANSACTION替代开始事务 。

COMMITROLLBACK支持可选的WORK关键字,CHAINRELEASE子句也支持。 CHAINRELEASE可用于对 transaction 完成的附加控制。 completion_type系统变量的 value 确定默认的完成行为。

AND CHAIN子句使新事务在当前事务结束时立即开始,并且新事务具有与刚刚终止的事务相同的隔离级别。新事务还使用与刚刚终止的事务相同的访问模式(READ WRITEREAD ONLY)。RELEASE子句使服务器在终止当前事务之后断开当前客户端会话的连接。包含NO关键字会抑制CHAINRELEASE完成,如果将completion_type系统变量设置为默认情况下导致链接或释放完成,这可能很有用。

开始 transaction 会导致任何挂起的 transaction 被提交。

开始 transaction 也会导致使用 LOCK TABLES获取的 table 锁被释放,就像你已经执行了 UNLOCK TABLES一样。开始事务不会释放通过FLUSH TABLES WITH READ LOCK获取的全局读取锁。

为了获得最佳结果,应仅使用由单个 transaction-safe 存储引擎管理的表来执行 transactions。否则,可能会出现以下问题:

  • 如果您使用来自多个事务安全存储引擎(例如InnoDB)的表,而事务隔离级别不是 SERIALIZABLE,则当一个事务提交时,使用相同表的另一个正在进行的事务可能仅会看到一些更改。由第一次 transaction 完成。也就是说,使用混合引擎无法保证事务的原子性,并且可能导致不一致。(如果不经常使用混合引擎事务,则可以使用 SET TRANSACTION ISOLATION LEVEL将所需的每个事务基准隔离级别设置为SERIALIZABLE。)
  • 如果在事务中使用不安全事务的表,则无论自动提交模式的状态如何,都将立即存储对这些表的更改。
  • 如果在更新事务中的非事务表之后发出ROLLBACK 语句,则会发生 ER_WARNING_NOT_COMPLETE_ROLLBACK 警告。将回滚对事务安全表的更改,但不回滚对非事务安全表的更改。

每个 transaction 均以块的形式存储在二进制日志中,在到达 COMMIT后。回滚的事务不会记录。例外:对非事务性表的修改不能被回滚,如果事务回滚包含修改的非事务表。在最后执行 ROLLBACK语句时,会将整个事务记录到日志中,以确保对非事务表的修改可以复制 (replicated)

您可以使用SET TRANSACTION语句更改 transactions 的隔离 level 或访问模式。

回滚可能是一种缓慢的操作,可能会在没有用户明确要求的情况下隐式发生(例如,发生错误时)。因此, SHOW PROCESSLIST会在会话的状态字段展示Rolling back。 ROLLBACK statement不仅用于显示回滚,还用于隐式回滚。

注意
在 MySQL 5.7,BEGINCOMMITROLLBACK不受--replicate-do-db--replicate-ignore-db规则的影响。

无法回滚的语句

某些语句无法回滚。通常,这些语句包括数据定义语言(DDL)语句,例如创建或删除数据库的语句,创建,删除或更改表或存储例程的语句。

您应设计您的 transactions不包含此类声明。如果在 transaction 的早期发出一个无法回滚的语句,然后又有另一个语句失败,则在这种情况下,不能通过发出一条ROLLBACK 语句来回滚事务的全部效果 。

导致隐式提交的语句

本章节的语句列表在在当前会话中隐式结束了任一活跃的事务,仿佛你在正在执行的语句中执行了 COMMIT

这些语句大多数在执行后也会导致隐式提交。目的是在其自己的特殊 transaction 中处理每个这样的语句,因为它无论如何都无法回滚。 事务控制和锁定语句是例外:如果在执行之前发生隐式提交,则之后另一个不会发生。

ALTER FUNCTIONCREATE FUNCTION and DROP FUNCTION 在与存储函数一起使用时也会导致隐式提交,但和 user-defined functions一起使用时不会(ALTER FUNCTION can only be used with stored functions.)

如果使用TEMPORARY关键字,CREATE TABLE and DROP TABLE  statements 不提交 transaction。 (这不适用于临时表上的其他操作,例如 ALTER TABLE and CREATE INDEX,它们会导致 commit.)然而,尽管没有隐式提交发生,但是语句也不能回滚,这意味着使用此类语句会导致事务性原子化,例如,如果你使用 CREATE TEMPORARY TABLE然后回滚 transaction,table 仍然存在。

InnoDB中的 CREATE TABLE语句作为单个 transaction 处理。这意味着用户的ROLLBACK不会撤消用户在 transaction 期间所做的 CREATE TABLE  statements。

在创建非临时表时,CREATE TABLE ... SELECT 会在执行语句之前和之后导致隐式提交。  (No commit occurs for CREATE TEMPORARY TABLE ... SELECT.)

UNLOCK TABLES仅在当前已使用LOCK TABLES锁定任一表以获取非事务性表锁时,才提交事务。UNLOCK TABLES后续 FLUSH TABLES WITH READ LOCK不会发生提交,因为后一个语句没有获取表级锁。

Transactions 不能嵌套。这是由于在发出START TRANSACTION语句或其同义词之一时会对任何当前事务执行隐式提交的结果。

当事务处于ACTIVE状态时,不能在XA事务中使用导致隐式提交的语句 。

BEGIN 语句与BEGIN 用于启动一个BEGIN ... END复合语句的关键字的用法不同。后者不会导致隐式提交。

SAVEPOINT,ROLLBACK 到 SAVEPOINT 和 RELEASE SAVEPOINT 语法

SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier

InnoDB支持 SQL statements SAVEPOINTROLLBACK TO SAVEPOINTRELEASE SAVEPOINT 和ROLLBACK的可选WORK关键字。

SAVEPOINT语句用name标识符设置命名 transaction 保存点。如果当前 transaction 具有相同 name 的保存点,则会删除旧保存点并设置新保存点。

ROLLBACK TO SAVEPOINT语句将 transaction 回滚到指定的保存点,而不终止 transaction。设置保存点后当前 transaction 对行所做的修改在回滚中撤消。但是InnoDB不会释放保存点之后存储在 memory 中的行锁。 (对于新插入的行,锁定信息由存储在行中的 transaction ID 携带;锁不单独存储在 memory 中.在这种情况下,行锁在“撤消”中被释放.)将删除在指定保存点之后设置的保存点。

如果ROLLBACK TO SAVEPOINT语句返回以下错误,则表示不存在具有指定 name 的保存点:

ERROR 1305 (42000): SAVEPOINT identifier does not exist

RELEASE SAVEPOINT语句从当前事务的保存点集中删除命名的保存点。不会发生提交或回滚。如果保存点不存在则会出错。

如果执行COMMIT,则删除当前 transaction 的所有保存点,或者不命名保存点的 ROLLBACK

当调用存储的 function 或激活触发器时,将创建新的保存点级别。先前级别上的保存点变得不可用,因此不会与新 level 上的保存点冲突。当 function 或触发器终止时,将释放它创建的任何保存点,并恢复先前的保存点 level。

LOCK TABLES and UNLOCK TABLES Statements

LOCK TABLES
    tbl_name [[AS] alias] lock_type
    [, tbl_name [[AS] alias] lock_type] ...

lock_type: {
    READ [LOCAL]
  | [LOW_PRIORITY] WRITE
}

UNLOCK TABLES

MySQL 使 client 会话能够显式获取 table 锁,以便与其他会话协作以访问表,或者在 session 需要对其进行独占访问期间防止其他会话修改表。 session 只能为自己获取或释放锁。一个 session 无法为另一个 session 获取锁定或释放另一个 session 持有的锁定。

锁定可用于模拟 transactions 或在更新表时获得更快的速度。这在 Table-Locking Restrictions and Conditions.中有更详细的解释。

LOCK TABLES显式获取当前 client session 的 table 锁。可以为基表或视图获取 Table 锁。您必须具有 LOCK TABLES权限,并且要锁定的每个对象的选择权限。

对于视图锁定, LOCK TABLES将视图中使用的所有基表添加到要锁定的表集中并自动锁定它们。如果使用 LOCK TABLES显式锁定 table,则触发器中使用的任何表也将被隐式锁定,如 LOCK TABLES and Triggers.中所述。

UNLOCK TABLES显式释放当前 session 持有的任何 table 锁。LOCK TABLES在获取新锁之前隐式释放当前 session 持有的任何 table 锁。

 UNLOCK TABLES的另一个用途是释放使用 FLUSH TABLES WITH READ LOCK 语句获取的 global 读锁,这使您可以锁定所有数据库中的所有表。 See Section 13.7.6.3, “FLUSH Statement”. 如果您有一个文件系统(如Veritas)可以及时拍摄快照,那么这是一种获取备份的非常方便的方法

table 锁仅保护其他会话不适当的读取或写入。持有WRITE锁的 session 可以执行 table-level 操作,例如DROP TABLETRUNCATE TABLE。对于持有READ锁的会话,不允许DROP TABLETRUNCATE TABLE操作。

以下讨论仅适用于非TEMPORARY表。对于TEMPORARY table,允许(但忽略) LOCK TABLES可以通过创建表的会话自由访问该表,而不考虑可能执行了哪些其他锁定。无需锁定,因为没有其他会话可以看到该表。

表锁定获取

要在当前 session 中获取 table 锁,请使用 LOCK TABLES语句,该语句获取元数据锁

可以使用以下锁定类型:

READ [LOCAL]锁:

  • 持有锁的 session 可以读取 table(但不能写它)。
  • 多个会话可以在同一 time 获取 table 的READ锁。
  • 其他会话可以在不明确获取READ锁的情况下读取 table。
  • LOCAL修饰符允许在保持锁定时执行其他会话的非冲突 INSERT statements(并发插入)。 (请参阅第 8.11.3 节,“并发插入” .)但是,如果要在保持锁定时使用服务器外部的进程操作数据库,则不能使用READ LOCAL。对于InnoDB表,READ LOCALREAD相同。

[LOW_PRIORITY] WRITE锁:

  • 持有锁的 session 可以读写 table。
  • 只有持有锁的 session 才能访问 table。在释放锁之前,没有其他 session 可以访问它。
  • 在保持WRITE锁定时,其他会话阻止对 table 的请求。
  • LOW_PRIORITY修饰符无效。在以前的MySQL版本中,它影响了锁定行为,但现在不再如此。现在已弃用,使用它会产生警告。使用不带 LOW_PRIORITY的WRITE代替。

WRITE锁通常具有比READ锁更高的优先级,以确保尽快处理更新。这意味着如果一个 session 获得READ锁,然后另一个 session 请求WRITE锁,则后续READ锁请求将等待,直到请求WRITE锁的 session 获得锁并释放它。( max_write_lock_count 系统变量的小值是一个例外,请参阅第 8.11.4 节,“元数据锁定” .)

如果该LOCK TABLES语句由于任何其他表上的其他会话持有的锁而必须等待,则它将阻塞直到可以获取所有锁为止。

需要锁的 session 必须在单个LOCK TABLES 语句中获取所需的所有锁。在保留由此获得的锁的同时,会话只能访问锁定的表。例如,在以下语句序列中,尝试访问t2时发生错误,因为它未在 LOCK TABLES语句中锁定:

mysql> LOCK TABLES t1 READ;
mysql> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
|        3 |
+----------+
mysql> SELECT COUNT(*) FROM t2;
ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES

INFORMATION_SCHEMA数据库中的表是 exception。即使 session 持有 LOCK TABLES获得的 table 锁,也可以在不显式锁定的情况下访问它们。

您不能在使用相同名称的单个查询中多次引用锁定的表。请改用别名,并为表和每个别名获取单独的锁:

mysql> LOCK TABLE t WRITE, t AS t1 READ;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;

第一个 INSERT发生错误,因为对于锁定的 table,两次引用同一名字。第二个 INSERT成功,因为 table 的 references 使用不同的名称。

如果 statements 通过别名引用 table,则必须使用相同的别名锁定 table。如果不指定别名,则无法锁定 table:

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

相反,如果使用别名锁定 table,则必须使用该别名在 statements 中引用它:

mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;

注意
LOCK TABLESUNLOCK TABLES,当应用于分区 table 时,始终锁定或解锁整个 table;这些语句不支持分区锁定修剪。见第 22.6.4 节,“分区和锁定”

表锁定释放

当释放 session 持有的 table 锁时,它们都在同一时间释放。 session 可以显式释放其锁,或者可以在某些条件下隐式释放锁。

  • session 可以使用 UNLOCK TABLES显式释放其锁。
  • 如果 session 在已经持有锁的情况下发出 LOCK TABLES语句来获取锁,则在授予新锁之前将隐式释放其现有锁。
  • 如果 session 开始 transaction(for example,使用START TRANSACTION),则执行隐式 UNLOCK TABLES,这会导致释放现有锁。

如果 client session 的连接终止,无论是正常还是异常,服务器都会隐式释放 session(transactional 和 nontransactional)所持有的所有 table 锁。如果 client 重新连接,则锁将不再有效。此外,如果 client 具有 active transaction,则服务器在断开连接时回滚 transaction,如果发生重新连接,则新的 session 将以启用自动提交开始。出于这个原因,客户可能希望禁用 auto-reconnect。在 auto-reconnect 生效的情况下,如果发生重新连接,则不会通知 client,但任何 table 锁定或当前 transaction 都将丢失。禁用 auto-reconnect 后,如果连接断开,则发出的下一个语句会发生错误。 client 可以检测错误并采取适当的操作,例如重新获取锁或重做 transaction。

注意
如果在锁定的 table 上使用ALTER TABLE,它可能会解锁。例如,如果您尝试第二次ALTER TABLE操作,结果可能是错误Table 'tbl_name' was not locked with LOCK TABLES。要处理此问题,请在第二次更改之前再次锁定 table。

Table Locking 和 Transactions 的交互

LOCK TABLESUNLOCK TABLES与事务的使用进行交互,如下所示:

  • LOCK TABLES 不是事务安全的,而是在尝试锁定表之前隐式提交任何活动事务。
  • UNLOCK TABLES隐式提交任何活动事务,但前提是LOCK TABLES已用于获取表锁。例如,在以下语句集中, UNLOCK TABLES释放全局读锁,但由于没有表锁有效,因此不提交事务:
FLUSH TABLES WITH READ LOCK;
START TRANSACTION;
SELECT ... ;
UNLOCK TABLES;
SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;

调用时LOCK TABLES, InnoDB内部会使用自己的表锁,而MySQL则会使用自己的表锁。InnoDB在下次提交时释放其内部 table 锁,但是为了释放其 table 锁,你必须调用UNLOCK TABLES。你不应该有autocommit = 1,因为在LOCK TABLES调用之后InnoDB会立即释放它的内部 table 锁,并且很容易发生死锁。如果autocommit = 1InnoDB根本不会获取内部 table 锁,以帮助旧的 applications 避免不必要的死锁。

锁定表和触发器

如果使用LOCK TABLES显式锁定 table,则触发器中使用的任何表也将被隐式锁定:

  • 这些锁与使用该LOCK TABLES语句显式获取的锁在同一时间获取。
  • 触发器中使用的表上的锁取决于该表是否仅用于读取。如果是这样,则读锁就足够了。否则,将使用写锁。
  • 如果 table 被显式锁定以便使用 LOCK TABLES进行读取,但需要锁定以进行写入,因为它可能在触发器中被修改,则会执行写入锁定而不是读取锁定。 (也就是说,由于 table 在触发器中的出现而需要隐式写锁定会导致 table 的显式读锁定请求转换为写锁定 request.)

假设您使用以下语句锁定两个表t1t2

LOCK TABLES t1 WRITE, t2 READ;

如果t1t2有任何触发器,则触发器中使用的表也将被锁定。假设t1有一个如下定义的触发器:

CREATE TRIGGER t1_a_ins AFTER INSERT ON t1 FOR EACH ROW
BEGIN
  UPDATE t4 SET count = count+1
      WHERE id = NEW.id AND EXISTS (SELECT a FROM t3);
  INSERT INTO t2 VALUES(1, 2);
END;

LOCK TABLES 语句 的结果是t1和 t2被锁定,因为它们出现在语句中,t3t4 被锁定,因为它们在触发器中使用:

  • 根据WRITE锁定请求,t1被锁定以进行写入。
  • t2被锁定以进行写入,即使该请求是针对READ锁定的。发生这种情况是因为t2被插入到触发器内,因此READ请求被转换为WRITE请求。
  • t3被锁定以进行读取,因为它只能从触发器中读取。
  • t4被锁定以进行写入,因为它可能在触发器中更新。

Table-Locking 限制和条件

您可以放心地使用KILL来终止正在等待表锁的会话。

LOCK TABLES和 UNLOCK TABLES不能在存储的程序中使用。

performance_schema数据库中的 表不能用LOCK TABLES锁定,但 setup_xxx表除外 。

当 LOCK TABLES语句生效时,以下语句被禁止:CREATE TABLE, CREATE TABLE ... LIKECREATE VIEW, DROP VIEWand DDL statements on stored functions and procedures and events.

对于某些操作,必须访问mysql数据库中的系统表。For example, HELP statement需要服务器端帮助表的内容,而CONVERT_TZ()可能需要读取 time zone 表。服务器隐式锁定系统表以供必要时读取,以便您无需显式锁定它们。这些表如上所述:

mysql.help_category
mysql.help_keyword
mysql.help_relation
mysql.help_topic
mysql.proc
mysql.time_zone
mysql.time_zone_leap_second
mysql.time_zone_name
mysql.time_zone_transition
mysql.time_zone_transition_type

 

如果要在带有LOCK TABLES语句的任何表中显式放置WRITE锁,则该表必须是唯一一个被锁定的表。同一条语句不能锁定其他表。

通常,您不需要锁定表,因为所有单个UPDATE statements 都是原子的;没有其他 session 可以干扰任何其他当前正在执行的 SQL 语句。但是,在某些情况下,锁定表可能会提供一个优势:

  • 如果要在一组MyISAM表上运行许多操作,则锁定要使用的表会快得多。锁定MyISAM表会加快插入,更新或删除它们,因为 MySQL 在调用UNLOCK TABLES之前不会刷新锁定表的 key 缓存。通常,在每个 SQL 语句之后刷新 key 缓存。
  • 锁定表的不利之处在于,没有会话可以更新READ锁定表(包括持有锁的那个),没有会话可以访问拥有 WRITE锁的表除了持有lock的之外。
  • 如果要将表用于非事务性存储引擎,则必须使用锁表,如果要确保没有其他 session 修改表在SELECTUPDATE之间的。此处显示的 example 需要锁表来安全执行:
LOCK TABLES trans READ, customer WRITE;
SELECT SUM(value) FROM trans WHERE customer_id=some_id;
UPDATE customer
  SET total_value=sum_from_previous_statement
  WHERE customer_id=some_id;
UNLOCK TABLES;

如果没有锁表,则执行 SELECTUPDATE statements 之间,另一个 session 可能会插入trans table 中新行。

在许多情况下,您可以通过使用相对更新(UPDATE customer SET value=value+new_value)或LASTINSERT_ID() function 来避免使用锁表

在某些情况下,您还可以通过使用用户级咨询锁定功能GET_LOCK()RELEASE_LOCK()来避免锁定表 。这些锁保存在服务器的哈希表中, pthread_mutex_lock()pthread_mutex_unlock()以高速实现。

SET TRANSACTION 语法

SET [GLOBAL | SESSION] TRANSACTION
    transaction_characteristic [, transaction_characteristic] ...

transaction_characteristic: {
    ISOLATION LEVEL level
  | access_mode
}

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

access_mode: {
     READ WRITE
   | READ ONLY
}

此语句指定s transaction 特性。它采用逗号分隔的一个或多个特征值的列表。每个特征 value sets transaction isolation level 或访问模式。隔离 level 用于InnoDB表上的操作。访问模式指定 transactions 是否以 read/write 或 read-only 模式运行。

此外,SET TRANSACTION可以包含可选的GLOBALSESSION关键字来指示语句的范围。

Transaction 隔离级别

要设置 transaction 隔离 level,请使用ISOLATION LEVEL level子句。不允许在同一SET TRANSACTION语句中指定多个ISOLATION LEVEL子句。

默认隔离 level 是 REPEATABLE READ。其他允许的值为 READ COMMITTEDREAD UNCOMMITTED, and SERIALIZABLE.

Transaction 访问模式

要设置 transaction 访问模式,请使用READ WRITEREAD ONLY子句。不允许在同一SET TRANSACTION语句中指定多个 access-mode 子句。

默认情况下,transaction 在 read/write 模式下发生,对 transaction 中使用的表允许读写。可以使用SET TRANSACTION显式指定此模式,访问模式为READ WRITE

如果 transaction 访问模式设置为READ ONLY,则禁止对表进行更改。这可以使存储引擎能够在不允许写入时进行性能改进。

在 read-only 模式下,仍然可以使用 DML statements 更改使用TEMPORARY关键字创建的表。与永久表一样,不允许使用 DDL statements 进行更改。

也可以使用START TRANSACTION语句为单个 transaction 指定READ WRITEREAD ONLY访问模式。

Transaction Characteristic Scope

您可以为全局,当前 session 或仅为下一个 transaction 设置 transaction 特性:

  • 使用GLOBAL关键字:
  1. 该语句适用于所有后续会话。
  2. 现有会话不受影响。
  • 使用SESSION关键字:
  1. 该语句适用于当前 session 中执行的所有后续 transactions。
  2. transactions 中允许使用该语句,但不会影响当前正在进行的 transaction。
  3. 如果在 transactions 之间执行,则该语句将覆盖任何前面的语句,该语句设置指定特征的 next-transaction value。
  • 没有任何SESSIONGLOBAL关键字:
  1. 该语句仅适用于 session 中执行的下一个 transaction。
  2. 后续 transactions 将恢复使用命名特征的 session value。
  3. transactions 中不允许使用该语句:
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)

mysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ERROR 1568 (25001): Transaction characteristics can't be changed
while a transaction is in progress

对 global transaction 特性的更改需要super特权。任何 session 都可以自由地改变它的 session 特性(即使在 transaction 的中间),或者它的下一个 transaction 的特征(在 transaction 开始之前)。

要在服务器启动时设置 global isolation level,请在命令 line 或选项文件中使用--transaction-isolation=level选项。此选项的level值使用破折号而不是空格,因此允许的值为READ-UNCOMMITTEDREAD-COMMITTEDREPEATABLE-READSERIALIZABLE

同样,要在服务器启动时设置 global transaction 访问模式,请使用--transaction-read-only选项。默认值为OFF(read/write 模式),但 value 可以设置为ON以获得只读模式。

For example, 要将隔离 level 设置为 REPEATABLE READ 并将访问模式设置为READ WRITE,请在选项文件的[mysqld]部分中使用这些 lines:

[mysqld]
transaction-isolation = REPEATABLE-READ
transaction-read-only = OFF

可以使用SET TRANSACTION语句间接设置 global,session 和 next-transaction 范围级别的特征,如前所述。也可以使用 SET 语句直接设置它们,以便为transaction_isolationtransaction_read_only系统变量赋值:

下表显示了每个SET TRANSACTION和 variable-assignment 语法设置的特征范围 level。

SET TRANSACTION Transaction 特性的语法

SyntaxAffected Characteristic Scope
SET GLOBAL TRANSACTION transaction_characteristicGlobal
SET SESSION TRANSACTION transaction_characteristicSession
SET TRANSACTION transaction_characteristicNext transaction only

Transaction 特征的 SET 语法

SyntaxAffected Characteristic Scope
SET GLOBAL var_name = valueGlobal
SET @@GLOBAL.var_name = valueGlobal
SET SESSION var_name = valueSession
SET @@SESSION.var_name = valueSession
SET var_name = valueSession
SET @@var_name = valueNext transaction only

可以在运行时检查 transaction 特性的 global 和 session 值:

SELECT @@GLOBAL.transaction_isolation, @@GLOBAL.transaction_read_only;
SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only;

在 MySQL 5.7.20 之前,使用tx_isolationtx_read_only而不是transaction_isolationtransaction_read_only

XA Transactions

略,后续待补。。。。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值