13.3 事务和锁语句
参考官方文档:
https:// dev.mysql.com/doc/refma n/5.7/en/sql-syntax-transactions.html
MySQL通过诸如SET autocommit,START TRANSACTION,COMMIT和ROLLBACK之类的语句支持本地事务(在给定的客户端会话中)。
XA事务支持还使MySQL能够参与分布式事务。
13.3.1 START TRANSACTION,COMMIT,ROLLBACK 语法
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}
这些语句提供了对事务使用的控制:
- START TRANSACTION 或 BEGIN 开启一个新事务
- COMMIT 提交当前事务,使其永久化。
- ROLLBACK 回滚当前事务,取消其变更
- SET autocommit 为当前会话启用或者禁用默认的自动提交模式
默认情况下,MySQL在启用自动提交模式的情况下运行。 这意味着,只要您执行更新(修改)表的语句,MySQL就会将更新存储在磁盘上以使其永久生效。 更改无法回滚。
要为单个系列语句隐式禁用自动提交模式,请使用START TRANSACTION语句:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;
使用START TRANSACTION,自动提交将保持禁用状态,直到您使用COMMIT或ROLLBACK结束事务。 自动提交模式然后恢复到之前的状态。
START TRANSACTION允许一些控制事务特征的修饰符。 要指定多个修饰符,请用逗号分隔它们。
- WITH CONSISTENT SNAPSHOT修饰符为具有能力的存储引擎启动一致的读取。 这仅适用于InnoDB。 效果与在任何InnoDB表中发出START TRANSACTION和SELECT后相同。 请参见第14.5.2.3节“一致性非锁定读取”。 WITH CONSISTENT SNAPSHOT修饰符不会更改当前事务隔离级别,因此只有在当前隔离级别允许一致性读取的情况下,它才会提供一致的快照。 允许一致读取的唯一隔离级别是REPEATABLE READ。 对于所有其他隔离级别,WITH CONSISTENT SNAPSHOT子句将被忽略。 从MySQL 5.7.2开始,当WITH CONSISTENT SNAPSHOT子句被忽略时,会生成警告。
- READ WRITE和READ ONLY修饰符设置事务访问模式。 他们允许或禁止更改事务中使用的表。 READ ONLY限制可防止事务修改或锁定对其他事务可见的事务和非事务表; 该事务仍然可以修改或锁定临时表。
当事务已知为只读时,MySQL为InnoDB表上的查询启用额外的优化。 指定READ ONLY可确保在只读状态无法自动确定的情况下应用这些优化。
如果未指定访问模式,则应用默认模式。 除非默认值已更改,否则它是可读写的。 不允许在同一个语句中同时指定READ WRITE和READ ONLY。
在只读模式下,仍然可以使用DML语句更改使用TEMPORARY关键字创建的表。 正如永久表一样,不允许使用DDL语句进行更改。
如果启用read_only系统变量,则使用START TRANSACTION READ WRITE明确启动事务需要SUPER权限。
注意:
许多用于编写MySQL客户端应用程序(如JDBC)的API提供了自己的方法来启动可以(有时应该)使用(而不是从客户端发送START TRANSACTION语句)事务
要显式禁用自动提交模式,请使用以下语句:
SET autocommit=0;
通过将autocommit变量设置为零来禁用自动提交模式后,对事务安全表(如InnoDB或NDB)的更改不会立即生效。 您必须使用COMMIT将更改存储到磁盘或ROLLBACK以忽略更改。
autocommit是一个会话变量,必须为每个会话设置。 要为每个新连接禁用自动提交模式,请参见第5.1.5节“服务器系统变量”中有关自动提交系统变量的描述。
BEGIN和BEGIN WORK作为START TRANSACTION的别名支持以启动交易。 START TRANSACTION是标准的SQL语法,是启动ad-hoc事务的推荐方式,并且允许BEGIN不允许的修饰符。
BEGIN语句与使用启动BEGIN ... END复合语句的BEGIN关键字不同。 后者不会开始事务。
注意:
在所有存储的程序(存储过程和函数,触发器和事件)中,解析器将BEGIN [WORK]视为BEGIN ... END块的开始。 在这种情况下用START TRANSACTION开始一个事务。
COMMIT和ROLLBACK支持可选的WORK关键字,CHAIN和RELEASE子句也是如此。 CHAIN和RELEASE可用于额外控制事务完成。 completion_type系统变量的值决定了默认的完成行为。
AND CHAIN子句在当前结束时立即开始新的事务,并且新事务与刚刚结束的事务具有相同的隔离级别。 新事务也使用与刚刚终止的事务相同的访问模式(READ WRITE或READ ONLY)。 RELEASE子句会导致服务器在终止当前事务后断开当前客户端会话。 包含NO关键字可抑制CHAIN或RELEASE完成。 completion_type 设置为 cause chaining 或者是默认的 release completion 将很有用
开始一个事务也会导致用LOCK TABLES获取的表锁被释放,就像你执行了UNLOCK TABLES一样。 开始事务不会释放用FLUSH TABLES WITH READ LOCK获取的全局读锁。
为获得最佳结果,应仅使用由单个事务安全存储引擎管理的表执行事务。 否则,可能会出现以下问题:
- 如果您使用来自多个事务安全存储引擎(如InnoDB)的表,并且事务隔离级别不是SERIALIZABLE,则有可能在一个事务提交时,使用相同表的另一个正在进行的事务将仅看到部分事务 第一笔事务所做的更改。 也就是说,混合引擎无法保证事务的原子性,并且可能导致不一致。 (如果混合引擎事务不频繁,您可以根据需要使用SET TRANSACTION ISOLATION LEVEL将隔离级别设置为SERIALIZABLE。)
- 如果您在事务中使用不是事务安全的表,则无论自动提交模式的状态如何,对这些表的更改都会立即存储。
- 如果在更新事务中的非事务表后发出ROLLBACK语句,则会发生ER_WARNING_NOT_COMPLETE_ROLLBACK警告。 对事务安全表的更改会回滚,但不会更改为非事务安全表。
在COMMIT时,每个事务都存储在一个块中的二进制日志中。 回滚的事务不记录。 (例外:对非事务表的修改无法回滚,如果回滚的事务包括对非事务表的修改,则整个事务最后会以ROLLBACK语句记录,以确保对非事务表的修改得到复制。)
回滚可能是一种缓慢的操作,可能在用户没有明确要求(例如,发生错误时)时隐式发生。 因此,SHOW PROCESSLIST在会话的状态列中显示回滚,不仅用于使用ROLLBACK语句执行的显式回滚,还用于隐式回滚。
注意:
在MySQL 5.7中,BEGIN,COMMIT和ROLLBACK不受--replicate-do-db或--replicate-ignore-db规则的影响。
13.3.2 不能回滚的语句
一些语句不能回滚。 通常,这些包括数据定义语言(DDL)语句,如创建或删除数据库的语句,创建,删除或更改表或存储例程的语句。
你应该设计事务不包括这样的语句。 如果您在一个事务中提前发出一个无法回滚的语句,然后另一个语句以后失败,则在这种情况下,通过发出ROLLBACK语句无法回滚事务的完整效果。
13.3.3 导致隐式提交的语句
本节中列出的语句(及其任何同义词)隐式地结束当前会话中的任何活动事务,就像在执行语句之前执行了COMMIT一样。
大多数这些语句在执行后也会导致隐式提交。 目的是在它自己的特殊事务中处理每个这样的语句,因为它无论如何都不能被回滚。 事务控制和锁定语句是例外情况:如果隐式提交在执行之前发生,则另一个事件不会在之后发生。
- 定义或修改数据库对象的数据定义语言(DDL)语句。
ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME , ALTER EVENT , ALTER PROCEDURE , ALTER SERVER , ALTER TABLE , ALTER VIEW , CREATE DATABASE , CREATE EVENT , CREATE INDEX , CREATE PROCEDURE , CREATE SERVER , CREATE TABLE , CREATE TRIGGER , CREATE VIEW , DROP DATABASE , DROP EVENT , DROP INDEX , DROP PROCEDURE , DROP SERVER , DROP TABLE , DROP TRIGGER , DROP VIEW , INSTALL PLUGIN (MySQL 5.7.6), RENAME TABLE , TRUNCATE TABLE , UNINSTALL PLUGIN
与存储函数一起使用时,ALTER FUNCTION,CREATE FUNCTION和DROP FUNCTION也会导致隐式提交,但不会与用户定义的函数一起使用。 (ALTER FUNCTION只能用于存储的功能。)
如果使用TEMPORARY关键字,则CREATE TABLE和DROP TABLE语句不会提交事务。 (这不适用于临时表上的其他操作,如ALTER TABLE和CREATE INDEX,这些操作确实会导致提交。)但是,虽然没有发生隐式提交,但语句也不会回滚,这意味着使用此类语句 导致事务性原子性被违反。 例如,如果您使用CREATE TEMPORARY TABLE然后回滚该事务,该表仍然存在。
InnoDB中的CREATE TABLE语句作为单个事务处理。 这意味着来自用户的ROLLBACK不会撤销用户在该事务期间所做的CREATE TABLE语句。
在创建非临时表时,CREATE TABLE ... SELECT会在语句执行前后执行隐式提交。 (对于CREATE TEMPORARY TABLE ... SELECT没有提交。)
- 隐式使用或修改mysql数据库中的表的语句。 ALTER USER , CREATE USER , DROP USER , GRANT , RENAME USER , REVOKE , SET PASSWORD .
- 事务控制和锁语句 。BEGIN,LOCK TABLES,SET autocommit = 1(如果该值不是1),START TRANSACTION,UNLOCK TABLES。
UNLOCK TABLES只在当前任何表已被LOCK TABLES锁定以获取非事务表锁的情况下才提交事务。 对于FLUSH TABLES WITH READ LOCK之后的UNLOCK TABLES,不会发生提交,因为后者的语句不会获取表级锁。
事务不能嵌套。 当您发出START TRANSACTION语句或其同义词之一时,这是对任何当前事务执行的隐式提交的结果。
当事务处于ACTIVE状态时,导致隐式提交的语句不能用于XA事务中。
BEGIN语句与使用启动BEGIN ... END复合语句的BEGIN关键字不同。 后者不会导致隐式提交。
- 数据加载语句。 LOAD DATA INFILE . LOAD DATA INFILE
仅对使用NDB存储引擎的表进行隐式提交。
- 管理语句 . ANALYZE TABLE , CACHE INDEX , CHECK TABLE , FLUSH , LOAD INDEX INTO CACHE , OPTIMIZE TABLE , REPAIR TABLE , RESET .
- 复制控制语句。 START SLAVE , STOP SLAVE , RESET SLAVE , CHANGE MASTER TO .
13.3.4 SAVEPOINT, ROLLBACK TO SAVEPOINT, 和 RELEASE SAVEPOINT 语法
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
InnoDB支持SQL语句SAVEPOINT,ROLLBACK TO SAVEPOINT,RELEASE SAVEPOINT和ROLLBACK的可选WORK关键字。
SAVEPOINT语句设置一个名为标识符的命名事务保存点。 如果当前事务具有名称相同的保存点,则旧的保存点将被删除并设置一个新的保存点。
ROLLBACK TO SAVEPOINT语句将事务回滚到指定的保存点而不终止事务。 当前事务在保存点设置后进行的修改在回滚中被取消,但InnoDB不会释放保存点后存储在内存中的行锁。 (对于新插入的行,锁定信息由存储在该行中的事务标识携带;该锁没有单独存储在内存中,在这种情况下,行锁定在undo中被释放)。 晚于指定保存点时间的保存点将被删除。
如果ROLLBACK TO SAVEPOINT语句返回以下错误,则意味着不存在具有指定名称的保存点:
ERROR 1305 (42000): SAVEPOINT identifier does not exist
RELEASE SAVEPOINT语句从当前事务的一组保存点中删除指定的保存点。 没有提交或回滚发生。 如果保存点不存在,则出现错误的。
如果执行COMMIT或没有命名保存点的ROLLBACK,则删除当前事务的所有保存点。
当调用存储函数或激活触发器时,将创建新的保存点级别。 以前级别的保存点不可用,因此不会与新级别的保存点冲突。 当函数或触发器终止时,它所创建的任何保存点都会被释放,并恢复以前的保存点级别。
--存储过程中或触发器中有保存点。
13.3.5 LOCK tables 和 unlock ta bles 语法
LOCK TABLES tbl_name [[AS] alias ] lock_type [, tbl_name [[AS] alias ] lock_type ] ...
lock_type : READ [LOCAL] | [LOW_PRIORITY] WRITE
UNLOCK TABLES
MySQL允许客户端会话明确获取表锁,以便与其他会话协作访问表,或者防止其他会话在会话需要对其进行独占访问期间修改表。 会话只能为自己获取或释放锁。 一个会话无法获取或释放另一个会话的锁定。
更新表,可以使用锁来模拟事务或获得更多速度。 本节后面将对此进行更详细的说明。
LOCK TABLES显式获取当前客户端会话的表锁。 可以为基表或视图获取表锁。 您必须具有LOCK TABLES权限,并且每个对象的SELECT权限都要锁定。
对于视图锁定,LOCK TABLES将视图中使用的所有基表添加到要锁定的一组表并将其自动锁定。 如果您使用LOCK TABLES显式锁定表,则触发器中使用的任何表也会隐式锁定。
UNLOCK TABLES显式释放当前会话持有的任何表锁。 LOCK TABLES在获取新锁之前隐式释放当前会话持有的任何表锁。
UNLOCK TABLES的另一个用途是释放使用FLUSH TABLES WITH READ LOCK语句获取的全局读锁定,该语句使您可以锁定所有数据库中的所有表。 请参见第13.7.6.3节“FLUSH语法”。 (如果您拥有可以及时拍摄快照的文件系统(如Veritas),则这是一种非常方便的备份方式。)
表锁只能防止其他会话不适当的读取或写入。 持有WRITE锁的会话可以执行表级操作,例如DROP TABLE或TRUNCATE TABLE。 对于持有READ锁的会话,不允许使用DROP TABLE和TRUNCATE TABLE操作。
以下讨论仅适用于非TEMPORARY表。 对于TEMPORARY表,允许(但忽略)锁定表。创建该表的会话可以自由访问该表,无论其他锁可能有效。 不需要锁定,因为没有其他会话可以看到该表。
锁定获得规则
要获取当前会话中的表锁,请使用LOCK TABLES语句。 以下锁定类型可用:
READ [LOCAL] 锁:
- 持有锁的会话可以读取表(但不能写入)。
- 多个会话可以同时获取表的READ锁。
- 其他会话可以在不明确获取READ锁的情况下读取表。
- LOCAL修饰符允许其他会话在执行锁定时执行非冲突INSERT语句(并发插入)。 (请参见第8.11.3节“并发插入”)。但是,如果要在持有锁的同时使用服务器外部的进程操作数据库,则不能使用READ LOCAL。 对于InnoDB表,READ LOCAL与READ相同。
[LOW_PRIORITY] WRITE 锁:
- 持有该锁的会话可以读和写表
- 只要持有该锁的会话可以访问该表。其他会话要等锁被释放之后才能访问。
- 在持有写入锁的同时,锁定其他会话对该表的锁定请求。
- LOW_PRIORITY修饰符不起作用。 在以前的MySQL版本中,它会影响锁定行为,但这不再成立。 它现在已被弃用,其使用会产生警告。 改用WRITE而不用LOW_PRIORITY。
如果LOCK TABLES语句必须等待由于任何表上的其他会话持有的锁,它将阻塞,直到可以获取所有锁。
需要锁定的会话必须获取单个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数据库中的表例外。 即使会话持有使用LOCK TABLES获得的表锁,也可以在不被显式锁定的情况下访问它们。
您不能在使用相同名称的单个查询中多次引用锁定的表。 改为使用别名,并为表和每个别名获取一个单独的锁:
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发生错误,因为对于锁定的表有两个同名的引用。 第二个INSERT成功,因为对该表的引用使用不同的名称。
如果您的语句通过别名引用表,则必须使用相同的别名锁定表。 没有指定别名就无法锁定表:
mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias; ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
WRITE锁通常比READ锁具有更高的优先级,以确保尽快处理更新。 这意味着,如果一个会话获得READ锁定,然后另一个会话请求WRITE锁定,则后续的READ锁定请求会一直等待,直到请求WRITE锁定的会话获得锁定并将其释放。
LOCK TABLE 需求锁定如下:
1.按照内部定义的顺序对所有表进行排序。 从用户的角度来看,这个顺序是不确定的。
2.如果要使用读取锁定和写入锁定来锁定表,请在读取锁定请求之前放置写入锁定请求。
3.一次锁定一个表,直到会话获得所有锁定。
该策略确保表锁定是无死锁的。
注意:
LOCK TABLES或UNLOCK TABLES应用于分区表时,始终锁定或解锁整个表; 这些语句不支持分区锁修剪。
锁释放的规则
当一个会话持有的表锁被释放时,它们全部被同时释放。 会话可以显式释放它的锁,或者锁可以在某些条件下隐式释放
- 会话可以使用UNLOCK TABLES明确释放它的锁。
- 如果会话发出LOCK TABLES语句以在已经持有锁的情况下获取锁,则在授予新锁之前,会先隐式释放其现有锁。
- 如果会话开始一个事务(例如,使用START TRANSACTION),将执行一个隐式UNLOCK TABLES,这会导致释放现有的锁。
如果客户端会话的连接终止,无论是正常还是异常,服务器都会隐式释放会话持有的所有表锁(事务性和非事务性)。 如果客户端重新连接,锁定将不再有效。 另外,如果客户端有一个活动事务,服务器在断开连接时回滚事务,并且如果发生重新连接,则新的会话从启用自动提交开始。 出于这个原因,客户可能希望禁用自动重新连接。 有了自动重新连接,如果发生重新连接,客户端将不会收到通知,但任何表锁或当前事务都将丢失。 在禁用自动重新连接的情况下,如果连接断开,则发出下一个语句时会发生错误。 客户端可以检测到错误并采取适当的措施,例如重新获取锁或重做事务。
注意:
如果您在锁定的表上使用ALTER TABLE,它可能会解锁。 例如,如果您尝试第二次ALTER TABLE操作,则结果可能是错误表'tbl_name'未使用LOCK TABLES锁定。 要处理这个问题,请在第二次更改之前再次锁定表。
13.3.5.1 表和事务的交互
LOCK TABLES和UNLOCK TABLES与交易的使用相互作用如下:
- 在试图锁定表之前,LOCK TABLES不是事务安全的,并隐含地提交任何活动事务。
- UNLOCK TABLES隐式地提交任何活动的事务,但前提是已经使用LOCK TABLES来获取表锁。 例如,在以下一组语句中,UNLOCK TABLES释放全局读锁但不提交事务,因为没有表锁有效:
FLUSH TABLES WITH READ LOCK;
START TRANSACTION;
SELECT ... ; UNLOCK TABLES;
- 开始一个事务(例如,使用START TRANSACTION)隐式提交任何当前事务并释放现有表锁。
- FLUSH TABLES WITH READ LOCK获取一个全局读锁而不是表锁,所以它在锁表和锁隐式提交方面不会受到与LOCK TABLES和UNLOCK TABLES相同的行为。 例如,START TRANSACTION不释放全局读锁。
- 其他隐式导致事务提交的语句不释放现有的表锁
- 在事务表(如InnoDB表)中使用LOCK TABLES和UNLOCK TABLES的正确方法是使用SET autocommit = 0(不是START TRANSACTION),然后是LOCK TABLES开始一个事务,并且在提交事务之前不要显式调用UNLOCK TABLES。 例如,如果您需要写入表t1并从表t2读取,则可以这样做:
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在下次提交时释放内部表锁,但是为了释放其表锁,MySQL必须调用UNLOCK TABLES。 不应该是autocommit = 1,因为InnoDB在LOCK TABLES调用后立即释放它的内部表锁,并且很容易发生死锁。 如果autocommit = 1,InnoDB根本不会获取内部表锁,以帮助旧应用程序避免不必要的死锁。
- ROLLBACK 不会释放表锁。
13.3.6 SET TRANSACTION 语法
SET [GLOBAL | SESSION] TRANSACTION
transaction_characteristic [, transaction_characteristic ] ... transaction_characteristic :
ISOLATION LEVEL level
| READ WRITE
|READ ONLY
level :
REPEATABLE READ
| READ COMMITTED
| READ UNCOMMITTED
| SERIALIZABLE
此语句指定事务特征。 它采用由逗号分隔的一个或多个特征值的列表。 这些特征设置事务隔离级别或访问模式。 隔离级别用于InnoDB表上的操作。 访问模式可以指定事务是以读/写还是只读模式运行。
另外,SET TRANSACTION可以包含一个可选的GLOBAL或SESSION关键字来表示语句的范围。
事务特征值的范围
您可以为全局,当前会话或下一个事务设置交易特征:
- 使用GLOBAL关键字,该语句适用于所有后续会话。 现有会话不受影响
- 使用SESSION关键字,该语句适用于当前会话中执行的所有后续事务。
- 如果没有任何SESSION或GLOBAL关键字,则该语句适用于在当前会话中执行的下一个(未启动)事务。 后续事务恢复为使用SESSION隔离级别。
对事务特征的全局改变需要SUPER特权。 任何会话都可以自由更改其会话特征(即使在事务中),或者其下一个事务的特征。
存在活动事务时,不允许SET GLOBAL或SESSION事务:
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
要在服务器启动时设置全局默认隔离级别,请在命令行或选项文件中对mysqld使用--transaction-isolation =level选项。 此选项的级别值使用破折号而非空格,因此允许的值为READ-UNCOMMITTED,READ-COMMITTED,REPEATABLE-READ或SERIALIZABLE。 例如,要将默认隔离级别设置为REPEATABLE READ,请在选项文件的[mysqld]部分中使用以下行:
[mysqld]
transaction-isolation = REPEATABLE-READ
通过使用transaction_isolation系统变量,可以在运行时检查或设置全局和会话事务隔离级别:
SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation;
SET GLOBAL transaction_isolation='REPEATABLE-READ';
SET SESSION transaction_isolation='SERIALIZABLE';
在MySQL 5.7.20之前,使用tx_isolation而不是transaction_isolation。
同样,要在服务器启动时或运行时设置事务访问模式,请使用--transaction-read-only选项或transaction_read_only系统变量。 默认情况下,这些是关闭的(模式是读/写),但可以设置为开启默认模式为只读。
在MySQL 5.7.20之前,使用tx_read_only而不是transaction_read_only。
设置transaction_isolation或transaction_read_only的全局或会话值等同于使用SET GLOBAL TRANSACTION或SET SESSION TRANSACTION设置隔离级别或访问模式。
事务访问模式
事务访问模式可以用SET TRANSACTION指定。 默认情况下,事务以读/写模式进行,读写允许事务中使用的表。 该模式可以使用READ WRITE访问模式明确指定。
如果事务访问模式设置为READ ONLY,则禁止更改表。 这可能使存储引擎在不允许写入时可以提高性能。
不允许在同一个语句中同时指定READ WRITE和READ ONLY。
在只读模式下,仍然可以使用DML语句更改使用TEMPORARY关键字创建的表。 正如永久表一样,不允许使用DDL语句进行更改。
也可以使用START TRANSACTION语句为单个事务指定READ WRITE和READ ONLY访问模式。