MySQL数据库(十三)_事务与锁

By | 2019年 11月 23日

锁是计算机协调多个进程或线程并发访问某一资源的机制。锁保证数据并发访问的一致性、有效性;锁冲突也是影响数据库并发访问性能的一个重要因素。锁是Mysql在服务器层和存储引擎层的的并发控制。
加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否是否已解除、释放锁等

  1. 锁粒度:
    • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
    • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
    • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
  2. 锁的读写类型:
    • 读锁:也称共享锁,只读不可写(包括当前事务),多个读互不阻塞
    • 写锁:也称独占锁、排它锁,写锁会阻塞其它事务(不包括当前事务)的读和它锁
  3. 兼容:如果事务T1获得了行r的共享锁,那么事务T2也可以获得行r的共享锁,这种情况称之为锁兼容,事务T3需要等行r释放共享锁,才能获得排他锁,这叫锁不兼容。
  4. 实现
    • 存储引擎:自行实现其锁策略和锁粒度
    • 服务器级:实现了锁,表级锁,用户可显式请求
  5. 分类:
    • 隐式锁:由存储引擎自动施加锁
    • 显式锁:用户手动请求

显式使用锁

  1. LOCK TABLES 加锁
LOCK TABLES
    tbl_name [[AS] alias] lock_type
    [, tbl_name [[AS] alias] lock_type] ...

lock_type:
    READ [LOCAL]
  | [LOW_PRIORITY] WRITE

示例

lock tables students write;
  1. 解锁
UNLOCK TABLES;
  1. 关闭正在打开的表(清除查询缓存),通常在备份前加全局读锁
#全局锁
FLUSH TABLES [tb_name[,...]] [WITH READ LOCK]
  1. 查询时加写或读锁
    SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]

查看当前事务锁的信息
information_schema这个库的3张表:
INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS

  1. 死锁
    死锁:是指两个或以上的事务在执行过程中,因争夺资源造成的一种互相等待的现象.
    解决1:将任何的等待转化为回滚,并且事务重新开始。但这会浪费性能
    解决2:超时。当一个等待时间超过设置的值时,事务进行回滚。参数:innodb_lock_wait_timeout

事务

事务Transactions:一组原子性的SQL语句,或一个独立工作单元
事务日志:记录事务信息,实现undo,redo等故障恢复功能

  1. ACID特性:
    • A:atomicity原子性;整个事务中的所有操作要么全部成功执行,要么全部失败后回滚
    • C:consistency一致性;数据库总是从一个一致性状态转换为另一个一致性状态
    • I:Isolation隔离性;一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,实现并发
    • D:durability持久性;一旦事务提交,其所做的修改会永久保存于数据库中
  2. Transaction生命周期

事务的分类

扁平事务、带有保存点的扁平事务、链事务、嵌套事务、分布式事务
1. 扁平事务:最简单,使用最多的事务

#情况1:成功执行,提交 
BEGIN WORK
...
Operation ...
...
COMMIT WORK

#情况2:发生错误或超时,回滚
BEGIN WORK
...
Operation ...
(Errot !)
...
ROLLBACK WORK

扁平事务无法分段执行,要么全提交,要么全回滚。
比如说A-->B-->C-->D,其中执行了A-->B-->C然后出错了,就得重新来了。
如果想要从B开始,就得使用带有保存点的扁平事务。
  1. 带有保存点的扁平事务
    玩过单机游戏可能就好理解,带有保存点的扁平事务就相当于你的存档,当角色死亡时,可以选择最近的存档,不至于需要从头开始。
  2. 链事务
    有点像带有保存点的扁平事务,但链事务只能回滚到上一个事务。上一个事务的提交触发下一个事务的开始。
  3. 嵌套事务
    由一个顶层事务控制着各层次的事务。顶层事务一般不用于访问数据库等操作,只负责逻辑控制,实际工作由子事务来完成。
  4. 分布式事务
    通常是在分布式环境下运行的扁平事务

启动事务:

  1. 启动事务:
BEGIN
或
BEGIN WORK
或
START TRANSACTION
  1. 结束事务:
#提交
COMMIT
#回滚
ROLLBACK

注意:只有事务型存储引擎中的DML语句方能支持此类操作
注意:ROLLBACK回滚后,就得需要重新启动事务了。
注意:事务的回滚只针对DML语句

  1. 自动提交:
    set autocommit={1|0}默认为1,为0时设为非自动提交
    建议:显式请求和提交事务,而不要使用“自动提交”功能
  2. 事务支持保存点:savepoint
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier

事务隔离级别

  1. 事务隔离级别:从上至下更加严格
    • READ UNCOMMITTED 浏览访问:可读取到未提交数据,产生脏读
    • READ COMMITTED 游标稳定:可读取到提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,导致每次读取数据不一致
    • REPEATABLE READ 可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。此默认设置
    • SERIALIZABILE 可串行化,未提交的读事务阻塞修改事务,或者未提交的修改事务阻塞读事务。导致并发性能差

MVCC: 多版本并发控制,和事务级别相关

事务隔离级别|脏读可能性|不可重复可能性|幻读可能性|加锁读
-|-|-|-|-
读未提交

read-uncommitted|是|是|是|否
不可重复读

read-committed|否|是|是|否
可重复读

repeatable-read|否|否|是|否
串行化

serializable|否|否|否|是

指定事务隔离级别:

服务器变量tx_isolation指定,默认为REPEATABLE-READ,可在GLOBAL和SESSION级进行设置

#默认值
MariaDB [hellodb]> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+

#临时配置
SET tx_isolation='type'
#type:{READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE }
#配置文件
vim /etc/my.cnf
    [mysqld]
    transaction-isolation=SERIALIZABLE

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注