MySQL中锁的类型

MySQL中锁的类型

根据锁的范围,MySQL可以分为全局锁、表级锁、行锁等。

一、全局锁

使用场景:全库的逻辑备份,可以使用Flush tables with read lock (FTWRL)命令来加全局读锁,来对整个库的数据备份。

也就是在加锁期间,整个库对外都是只读的,但是在读写分离、一主多从架构下,会出现问题:

  • 如果是主库备份,那么整个架构都不能处理外部的更新操作,整个系统就会停止对外业务的处理。
  • 如果是从库备份,为了保证主从一致性,从库需要定期更新binlog日志,在只读的情况下就不能执行binlog,导致主从数据不一致。

MySQL自带的备份工具mysqldump。如果mysqldump使用了–single-transaction参数,就会在备份之前启动一个事务,获得read view。由于支持了MVCC,备份的过程是可以更新的,也就不会出现上面的问题了。

那么,FTWRL的意义何在呢?

对于MySQL的MyISAM存储引擎并不支持事务,因此也就没有MVCC机制了,我们只能通过FTWRL加锁来保证备份的一致性。

那为什么不能使用set global readonly=true的方式呢?来保证整个库对于外部是只读的呢?

  • readonly 我们通常会用来标志一个库是主库还是从库,所以不建议使用
  • 异常机制,当客户端出现异常了,MySQL会自动释放全局锁。如果使用global readonly,如果客户端出现问题了,整个库会保持readonly状态,导致整个系统出现问题。

表级锁

表级锁分为:表锁和元数据锁

表锁一般是我们通过lock tables…read/write来对某个表加读锁或者写锁,保证当前线程执行的过程中避免其他线程的干扰,

元数据锁(MDL)在访问一个表时会被自动加上来保证读写的正确性,也就是在你增删改查的过程中,避免其他线程对表结构修改。

通常在进行增删改查时,会给表加MDL读锁,在对表结构修改时,会加MDL写锁

MDL读读不互斥,读写、写写是互斥的。

所以尽量避免使用长事务,会阻塞MDL写锁,在进行表结构修改的时候避免锁住增删改查操作,导致系统奔溃。

行锁

对于MySQL中的行锁是个存储引擎自己实现的,所以并不是所有的存储引擎都支持行锁,比如:MyISAM,就只能使用表锁,这样会非常影响并发度。

在InnoDB事务中,行锁是在需要的时候加,但并不是不需要时就释放,需要等到事务结束以后才会释放

行锁虽然能提高表的并发度,但是会引发死锁问题,所以一般我们在一个事务中会把有可能出现并发冲突的行锁放到事务的最后,减少持有锁的时间。

总结:

对于MySQL来说,通过加全局锁来对整个库进行备份(mysqldump工具),如果存储引擎支持事务,可以使用–single-transaction参数来保证在备份的过程中可以执行更新操作(MVCC,一致性视图)。如果不支持事务,可以使用FTWRL。

一般情况下我们能用行级锁就用行级锁,来提供整个表的并发度。行锁的释放是在事务结束

最后使用表级锁(MDL)一定要保证不要因为对表结构的更新阻塞了整个系统的增删改查操作,MDL的释放是在事务提交结束后。

### MySQL 类型概述 在MySQL中,机制用于确保数据的一致性和完整性,防止多个事务同时修改相同的数据而导致冲突。根据不同的应用场景和需求,MySQL提供了多种类型来实现这一目标。 #### 表级 (Table-Level Locks) 表级是最简单的定策略之一,适用于较低并发量的应用环境。当一个会话获得了一张表上的写入时,其他任何试图对该表进行读取或写入操作的会话都将被阻塞直到前者的操作完成并释放[^1]。这种类型虽然简单易懂,但在高并发环境下效率低下,因为它不允许多线程并发执行针对同一表格的操作。 #### 全局 (Global Locks) 全局可以看作是一种极端形式的表级——它不仅限于单个特定的表而是作用在整个实例上。这意味着一旦设置了全局只读模式或其他类似的全库范围内的定措施,则整个服务器内所有未提交的事物都不能再做更改动作;新发起的一切DML语句都会失败除非它们属于那些已经被允许例外处理的情况之外。显然这通常仅用于维护期间如备份恢复等特殊时刻而非日常业务流程之中。 #### 记录 (Row-Level Locks 或 Record Locks) 相比之下更为精细的是记录级别的定方式,也就是常说的行为级或者行级别定。这类方法能够精确到具体某一行甚至某个字段上面去实施保护从而极大提高了系统的吞吐能力特别是在面对大量并发请求的时候表现尤为突出。例如,在`SELECT ... FOR UPDATE`查询里指定条件匹配到的结果集会被加上排他性的X以阻止其它连接对其进行更新删除之类的变更行为直至当前事物结束为止[^3]。 ```sql -- 加读取一条记录 SELECT * FROM table_name WHERE id = 1 FOR UPDATE; ``` 通过上述三种主要类别可以看出,不同层次的定各有优劣之处,合理选用取决于具体的使用场景和技术架构考量因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值