unix 中的记录锁

如果一个文件被两个人同时修改会出现什么结果呢?在很多unix系统中,该文件的最后状态取决于写该文件的最后一个进程。但是对于有些应用程序(例如数据库),进程有时需要确保它正在单独写一个文件。为了向进程提供这种功能,商用unix系统提供了记录锁机制。

记录锁的功能是:当一个进程正在读或修改文件的某个部分时,它可以组织其他进程修改同一文件区。对于unix系统而言,“记录”这个次是一种误会,因为unix系统内核根本没有使用文件记录这种概念。更适合的术语可能是“字节范围锁”,因为它锁定的是文件中的一个区域,也可以是整个文件。

在unix早期的时候有一种批评是它们不能用来运行数据库系统,其原因就是这些系统不支持部分的对文件加锁。在unix系统开始进入商用计算机领域时,很多系统开发小组以各种不同方式增加了对记录锁的支持。

早起的伯克利版本只支持flock函数。该函数锁整个文件,不能锁文件中的一部分。

SVR3通过fcntl函数增加了记录锁功能。在此基础上构造了lockf函数,它提供了一个简化的接口。这些函数允许调用者锁一个文件中任意字节数的区域,长至整个文件,短至文件中的一个字节。

POSIX.1标准的基础是fcntl。

所希望的锁类型:共享锁(rdlck),独占性写锁(wrlck),解锁一个区域(unlck)

基本原则是:多个进程在一个给定的字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程独用的一把思索。如果一个给定字节上已经有一把或多把读锁,则不能在该字节上再加死锁,如果在一个字节上已经有一把独占性的写锁,则不能再对它加任何读锁

如果一个进程对一个文件区间已经有了一把锁,后来该进程又企图在同一文件区间再加一把锁,那么新锁将替代老锁。例如,若一进程在某文件的16~32字节区间有一把写锁,然后又试图在16~32字节区间加一把读锁,那么该请求将成功执行(假定其他进程此时并不试图向该文件的同一区间加锁),原来的写锁被替换为读锁。

特别需要注意的是加读锁时,该描述符必须是读打开,加写锁时,该描述符必须是写打开。

在设置或释放文件上的锁时,系统按要求组合或裂开相邻区。例如,若字节100~199是加锁的区,需要解锁第150字节,则内核将维持两把锁,一把用于字节100~149,另一把用于字节151~199.

死锁

如果两个进程相互等待对方持有并且锁定的资源时,则这两个进程就处于死锁状态。如果一个进程已经控制了文件中的一个加锁区域,然后它又试图对另一个今晨控制的区域加锁,则它就会休眠,在这种情况下,有可能会发生死锁。

检测到死锁时,内核必须选择一个进程接受出错返回。在本实例中选择了子进程,这是一个实现细节。在某些系统上,总是紫禁城接到出错信息,在另一些系统上,总是父进程接到出错信息。在某些系统上,当时图使用多把锁,有时是子进程接到出错信息,有时则是父进程接到出错信息。

锁的隐含继承和释放

关于记录锁的自动继承和释放有三条规则:

锁与进程和文件两方面有关。这有两重含义:第一重很明显,当一个进程终止时,它所建立的锁全部释放,第二重意思就不很明显,任何时候关闭一个描述符时,则该进程通过这一描述符可以引用的文件上的任何一把锁都被释放(这些锁都是该进程设置的)。

比如我们在在A文件(文件描述符为10)上加了一把锁,然后B=open(a),接着close(B)这时候A上设置的锁被释放。

由fork产生的子进程不继承父进程所设置的锁。这意味着,若一个进程得到一把锁然后调用fork,那么对于父进程的锁而言,子进程被视为另一个进程,对于父进程处继承过来的任一描述符,子进程需要调用fcntl才能获得它自己的锁,这与锁的作用是相一致的。锁的作用是阻止多个进程同时写同一个文(或同一文件区域),如果子进程继承父进程的锁,则父,子进程就可以同时写同一个文件。

在执行exec后,新成勋可以继承原执行程序的锁。但是注意,如果对一个文件描述符设置了close-on-exec标志,那么当作为exec的一部分关闭该文件描述符时,对相应文件的所有锁都被释放了。

建议性锁和强制性锁

考虑数据库访问程序,如果该库中所有函数都以一致的方法处理记录所,则称使用这些函数访问数据库的任何进程集合为合作进程。如果这些函数是仅有的用来访问数据库函数,那么它们使用建议性锁是可行的。但是建议性锁并不能阻止对数据库文件有写权限的任何其他进程对数据库文件进行随意的写操作。没有使用被认可的方法(数据库函数库)访问数据库的进程是一个非合作进程。

强制性锁使内核对每一个open,read和write系统调用都进行检查,检查调用进程对正在访问的文件是否违背了某一把锁的作用,强制性锁有时也被称为强迫方式锁。

时间: 2024-10-11 00:31:01

unix 中的记录锁的相关文章

详解 MySql InnoDB 中的三种行锁(记录锁、间隙锁与临键锁)

详解 MySql InnoDB 中的三种行锁(记录锁.间隙锁与临键锁) 前言 InnoDB 通过 MVCC 和 NEXT-KEY Locks,解决了在可重复读的事务隔离级别下出现幻读的问题.MVCC 我先挖个坑,日后再细讲,这篇文章我们主要来谈谈那些可爱的锁. 什么是幻读? 幻读是在可重复读的事务隔离级别下会出现的一种问题,简单来说,可重复读保证了当前事务不会读取到其他事务已提交的 UPDATE 操作.但同时,也会导致当前事务无法感知到来自其他事务中的 INSERT 或 DELETE 操作,这就

SylixOS文件记录锁使用

1. 文件记录锁介绍 文件锁锁定的是整个文件,而记录锁定还可以锁定文件的某一特定部分,即从文件的某一相对位置开始的一段连续的字节流. 当一个进程正在读取或者修改文件的某个部分时,使用文件记录锁可以阻止其他进程修改同一文件的相同区域.它可以用来锁定文件的某个区域或者整个文件,SylixOS 支持多种文件记录锁 API. 注:SylixOS 支持多种设备驱动模型,但是目前只有 NEW_1 型设备驱动支持文件记录锁功能,此类驱动文件节点类似于UNIX 系统的 vnode. 2. 文件记录锁设置 Syl

unix中文件I/O

在unix中可用的文件I/O函数包括打开文件,读文件,写文件等. Unix系统中的大多数文件I/O需要用到5个函数:open,read,write,lseek,close. 这里要说明的是read,write的文件I/O都是不带缓冲的,所谓的不带缓冲意思是它们都是走的内核中的一个系统调用. 对于内核而言,所有打开的文件都是通过文件描述符进行引用,文件描述符是一个非负整数.当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符.当读或写一个文件时,使用open,create返回文件描述

[13]APUE:(文件)记录锁

[a] 概念 建议锁:在遵循相同记录锁规则的进程间生效,通常用于保证某个程序自身多个进程间的数据一致性 强制锁:意在保证所有进程间的数据一致性,但不一定有效:如不能应对先 unlink 后建立同名副本的行为 [b] fcntl #include <fcntl.h> int fcntl(int fd, int cmd, struct flock *flockp) //出错返回 -1  struct flock { short l_type; //锁类型:F_RDLCK / F_WRLCK / F

记录锁(record locking)机制

要讲解记录锁机制,首先要介绍fcntl函数,如下给出该函数原型: #include <fcntl.h> int fcntl(int filedes, int cmd, ... /* struct flock *flockptr */) 函数返回值:若成功则依赖于cmd,若出错则返回-1. 对于记录锁,cmd是F_GETLK, F_SETLOCK, F_SETLKW.第三个参数(称其为flockptr)是一个指向flock结构的指针: struct flock { short l_type; /

hibernate中的乐观锁和悲观锁

hibernate支持两种锁:悲观锁(Pessimistic Locking)和乐观锁(Optimistic Locking) 悲观锁:指的是对数据库数据被外界的修改持保守态度(无论是本系统的事务处理,或者是外部系统的事务处理),在整个数据处理的过程数据都处于锁定的状态.hibernate中的悲观锁,是依靠数据库中的锁机制(因为只有数据库层才能控制本系统和外部系统对数据库的数据操作). 例如"select * from user where userName='Johnson' for upda

数据库中的悲观锁和乐观锁详解

数据中的锁分为两类:悲观锁和乐观锁,锁还有表级锁.行级锁 表级锁例如: SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除 行级锁例如: select * from table_name where id = 1 for update; 悲观锁(Pressimistic Locking) 对数据被外界(包括本系统当前的其他事务,以及来自

文件记录锁的释放

引言:apue中提到文件记录锁的释放中的两条规则:当进程终止的时候,进程在文件上建立的记录锁会全部释放:当关闭文件,执行close(fd)函数的时候,进程释放描述符可以引用的文件上的任何一把锁.对于第一条规则的理解应该没有分歧.但对于第二条规则的理解,则会出现疑惑,执行close(fd)的时候,是仅仅释放closf(fd)调用进程在文件上的记录锁,还是会释放所有进程(包括非调用进程)在文件上的记录锁.本文通过具体相关程序对此问题进行验证. 思路:需要设计验证程序对此问题进行验证,通过fork产生

Sql Server中清空所有数据表中的记录

清空所有数据表中的记录: 代码如下:exec sp_msforeachtable  @Command1 ='truncate table ?'删除所有数据表: 代码如下:exec sp_msforeachtable 'delete   N''?'''清空SQL Server数据库中所有表数据的方法(有约束的情况) 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间可能形成相互约束关系,删除操作可能陷入死循环,二是这里使用了微软未正式公