MySQL 事务控制和锁定语句

2017-08-31  本文已影响102人  微日月

MySQL 支持对 MyISAM 和 MEMORY 存储引擎的表进行表级锁定,对 BDB 存储引擎的表进行页级锁定,对 InnoDB 存储引擎的表进行行级锁定。默认情况下,表锁和行锁都是自动获得的,不需要额外的命令。但是在有的情况下,用户需要明确地进行锁表或者进行事务的控制,以便确保整个事务的完整性,这样就需要使用事务控制和锁定语句来完成

lock table 和 unlock table

LOCK TABLES 可以锁定用于当前线程的表。如果表被其他线程锁定,则当前线程会等待,直到可以获取所有锁定为止

UNLOCK TABLES 可以释放当前线程获得的任何锁定。当前线程执行另一个 LOCK TABLES 时,或当与服务器的连接被关闭时,所有由当前线程锁定的表被隐含地解锁,具体语法如下:

LOCK TABLES
tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
UNLOCK TABLES

事务控制

MySQL 通过 set autocommitstart transactioncommitrollback 等语句支持本地事务,具体语法如下:

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

默认情况下,MySQL 是自动提交(Autocommit)的,如果需要通过明确的 CommitRollback 来提交和回滚事务,那么需要通过明确的事务控制命令来开始事务 start transactionbegin 语句可以开始一项新的事务

commitrollback 用来提交或者回滚事务

chainrelease 子句分别用来定义在事务提交或者回滚之后的操作,chain 会立即启动一个新事物,并且和刚才的事务具有相同的隔离级别,release 则会断开和客户端的连接

set autocommit 可以修改当前连接的提交方式,如果设置了 set autocommit=0,则设置之后的所有事务都需要通过明确的命令进行提交或者回滚

如果只是对某些语句需要进行事务控制,则使用 start transaction 语句开始一个事务比较方便,这样事务结束之后可以自动回到自动提交的方式,如果希望所有的事务都不是自动提交的,那么通过修改 set autocommit=0 来控制事务比较方便,这样不用在每个事务开始的时候再执行 start transaction 语句

如果在锁表期间,用 start transaction 命令开始一个新事务,会造成一个隐含的 unlock tables 被执行

在事务中可以通过定义 savepoint,指定回滚事务的一个部分,但是不能指定提交事务的一个部分。对于复杂的应用,可以定义多个不同的 savepoint,满足不同的条件时,回滚不同的 savepoint。需要注意的是,如果定义了相同名字的 savepoint,则后面定义的 savepoint 会覆盖之前的定义。对于不再需要使用的 savepoint,可以通过 release savepoint 命令删除 savepoint,删除后的 savepoint,不能再执行 rollback to savepoint 命令

分布式事务的使用

当前分布式事务只支持 InnoDB 存储引擎。一个分布式事务会涉及多个行动,这些行动本身是事务性的。所有行动都必须一起成功完成,或者一起被回滚

分布式事务的原理

在 MySQL 中,使用分布式事务的应用程序涉及一个或多个资源管理器和一个事务管理器

MySQL 执行 XA MySQL 时,MySQL 服务器相当于一个用于管理分布式事务中的 XA 事务的资源管理器。与 MySQL 服务器连接的客户端相当于事务管理器

要执行一个分布式事务,必须知道这个分布式事务涉及到了哪些资源管理器,并且把每个资源管理器的事务执行到事务可以被提交或回滚时。根据每个资源管理器报告的有关执行情况的内容,这些分支事务必须作为一个原子性操作全部提交或回滚。要管理一个分布式事务,必须要考虑任何组件或连接网络可能会出现故障

用于执行分布式事务的过程使用两阶段提交,发生时间在由分布式事务的各个分支需要进行的行动已经被执行之后

在有些情况下,一个分布式事务可能会使用一阶段提交。例如,当一个事务管理器发现,一个分布式事务只由一个事务资源组成(即单一分支),则该资源可以被告知同时进行预备和提交

分布式事务的语法

分布式事务(XA 事务)的 SQL 语法主要包括:

XA {START|BEGIN} xid [JOIN|RESUME]

XA START xid 用于启动一个带给定 xid 值的 XA 事务。每个 XA 事务必须有一个唯一的 xid 值,因此该值当前不能被其他的 XA 事务使用xid 是一个 XA 事务标识符,用来唯一标识一个分布式事务。xid 值由客户端提供,或由MySQL 服务器生成。xid 值包含 1~3 个部分:

xid: gtrid [, bqual [, formatID ]]

下面其他 XA 语法中用到的 xid 值,都必须和 START 操作使用的 xid 值相同,也就是表示对这个启动的 XA 事务进行操作

XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid

使事务进入 PREPARE 状态,也就是两阶段提交的第一个提交阶段

XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid

这两个命令用来提交或者回滚具体的分支事务。也就是两阶段提交的第二个提交阶段,分支事务被实际的提交或者回滚

XA RECOVER

XA RECOVER 返回当前数据库中处于 PREPARE 状态的分支事务的详细信息

分布式的关键在于如何确保分布式事务的完整性,以及在某个分支出现问题时的故障解决。XA 的相关命令就是提供给应用如何在多个独立的数据库之间进行分布式事务的管理,包括启动一个分支事务、使事务进入准备阶段以及事务的实际提交回滚操作等

存在的问题

虽然 MySQL 支持分布式事务,但是在测试过程中,还是发现存在一些问题

如果分支事务在达到 prepare 状态时,数据库异常重新启动,服务器重新启动以后,可以继续对分支事务进行提交或者回滚得操作,但是提交的事务没有写 binlog,存在一定的隐患,可能导致使用 binlog 恢复丢失部分数据。如果存在复制的数据库,则有可能导致主从数据库的数据不一致

上一篇 下一篇

猜你喜欢

热点阅读