数据机房的几种“锁”
此锁非彼锁,今天介绍几种数据锁。
1、文件锁
当多个进程可能会对同样的数据执行操作时,这些进程需要保证其它进程没有也在操作,以免损坏数据,进程会使用一个「锁文件」,也就是建立一个文件来告诉别的进程自己在运行,如果检测到那个文件存在则认为有操作同样数据的进程在工作。具体参考笔者的文章-Linux的文件锁flock ,crontab定时任务里面使用flock来加锁,防止任务进程卡阻。
2、数据库的几把锁
数据操作的类型来分读锁(共享锁)和写锁(排它锁),数据操作的粒度来分表锁和行锁。
2.1表锁
MyISAM存储引擎是表锁,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发度低。MyISAM不适合做写为主的表的引擎,因为写锁后,其他线程不能做任何操作。Mysql数据库磁盘IO达到100%的解决方法里面有使用flush tables with read lock来锁定表。
2.2行锁
InnoDB存储引擎是行锁,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,但并发度高。InnoDB的锁定机制的实现方面所带来的性能损耗可能比表级锁定会更高一些,但是在整体并发处理能力方面要远远优于MyISAM的表级锁定。
InnoDB的行锁是加在索引上面的,如果没有索引会升级为表锁。
2.3读锁(共享锁S)
当一个事务读取一个数据行时,其他事务也可以读,但是不能对该数据行进行增删改的操作。一种是自动提交模式下的select查询语句,不需要加任何锁,直接返回查询结果,时一致性非锁定读;第二种是select …… lock in share mode在被读取的行加一个读锁,其他事务可以读,但是想申请加锁就会被阻塞。
2.4写锁(排它锁X)
一个事务在获取一个数据行的写锁后,其他事务就不能获得该数据行的其他锁,写锁优先级最高。一些DML语句都会对行记录加写锁,比较特殊的是select for update会对读取行记录加一个写锁,那么其他事务就不能对被锁定行加任何锁。
3、分布式锁
分布式架构也会存在一些问题,最严重的问题便是数据一致性问题,因为业务是部署在多台机器上,由于时间空间的不一致,从而导致数据会不一样。有三种实现方式:基于数据库、基于redis、基于Zookeeper,笔者没有做过分布式锁的案例,分布式锁的实现 里面有详细的介绍。
4、编程实现信号锁
笔者使用虚拟仪器LabVIEW里面的信号量,可以根据具有访问权限的循环更新。下面的案例使用信号量循环执行两个循环中的代码,用于限制可在同一个共享(受保护)资源上同时执行的任务的数量。将并行数量改为1,那么同时执行任务只能有一个循环,实现信号锁。 查看底层代码,发现信号量是通过队列来实现的,利用队列每次只能出队列一次来的原理来实现。
信号量实现的资源隔离可以用在对同一个资源(串口、网络、文件等)操作时的锁定,可以防止资源竞争。
