一、前言
本文章介绍了梧桐数据库中事务与锁的相关内容,数据库通过使用锁来管理对共享资源的并发访问,确保数据的完整性和一致性,希望通过该篇介绍帮助数据库管理员及开发者更好的设计数据库应用。
二、锁的类型
- 行级锁(Row-Level Locks):
说明: 行级锁是最细粒度的锁,用于确保事务在修改数据行时不会与其他事务冲突。
使用场景: 当需要对单个数据行进行更新或删除操作时使用,以避免其他事务在同一行上发生冲突。
优点: 提供了最细粒度的锁,减少了锁的争用,提高了并发性能。
缺点: 管理成本较高,尤其是在高并发环境下,可能会导致大量的锁请求和释放,增加系统开销。
- 表级锁(Table-Level Locks):
说明: 表级锁用于在对整个表进行操作时防止并发问题,例如TRUNCATE或ALTER TABLE。
使用场景: 在执行如TRUNCATE TABLE或ALTER TABLE等需要对整个表进行操作的事务时使用。
优点: 操作简单,易于理解,可以快速锁定整个表。
缺点: 粒度较粗,可能会导致整个表的并发访问受限,影响性能。
- 事务级锁(Transaction-Level Locks)
说明: 事务级锁是针对整个事务的锁,确保事务的隔离性。
使用场景: 在需要确保整个事务的隔离性时使用,例如,当一个事务需要对多个表或多个行进行操作时。
优点: 可以确保事务的原子性和一致性,防止其他事务干扰。
缺点: 可能导致锁的持有时间过长,增加死锁的风险。
- 共享锁(Share Locks)
说明: 共享锁允许多个事务读取同一资源,但不能修改。例如,SELECT … LOCK SHARE语句。
使用场景: 当多个事务需要读取同一资源但不需要修改时使用,例如,普通的SELECT查询。
优点: 允许多个事务并发读取,提高了读取操作的并发性。
缺点: 如果事务需要修改数据,必须先升级为排它锁,这可能会导致锁的升级开销。
- 排它锁(Exclusive Locks)
说明: 排它锁防止其他事务对同一资源进行读取或修改。例如,SELECT … FOR UPDATE或DELETE语句。
使用场景: 需要修改数据时使用,例如,INSERT、UPDATE或DELETE操作。
优点: 确保了数据的一致性,防止其他事务在修改期间读取或修改数据。
缺点: 阻止了其他事务对同一资源的访问,可能会降低并发性。
三、锁的应用
在梧桐数据库中行级锁、表级锁会在命令执行时隐性申请,命令完成后立即释放;以下两种锁可以在事务中主动申请,事务执行结束后释放:
-
排它锁(Exclusive Locks):加上排它锁,则其他的事务不能对它读取和修改
-
共享锁(Share Locks):加上共享锁,则该数据库对象可以被其他事务读取,但不能修改
LOCK语法:
lock tablename in lock_mode;
lock_mode值有:ACCESS SHARE、ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE
备注:LOCK 语句只在事务模式下工作。
应用案例:
某系统融合层模型设计,一张表包含100个以上字段,由2个及以上的存储过程共同生成,其任务为同级任务,存在并行运行的情况,若不为该表添加排它锁将出现数据丢失的问题,添加排它锁后会按照获得锁的时间顺序写入宽表,保证数据完整性。
- 下述通过创建一个过程测试锁情况:
create or replace function public.p_dw_***_***_dm_test (
IN i_date varchar,
OUT o_return_code varchar,
OUT o_return_msg varchar
) returns record as
$BODY$
DECLARE
vd_stat_date date;
begin
lock
table public.dw_***_***_dm_test in access exclusive mode;
truncate
table public.dw_***_***_dm_test;
insert into
public.dw_***_***__dm_test
select
*
from
dmdb.dw_cust_custinfo_dm;
o_return_code := 0;
o_return_msg := '储存过程运行成功';
RETURN;
EXCEPTION
WHEN OTHERS THEN o_return_code := SQLSTATE;
o_return_msg := 'SQL存储过程报错:' || SQLERRM;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
四、数据库中查询锁的情况及处理
查询数据库中正在运行的任务:
select * from pg_stat_activity where state <> 'idle'
依据任务的ID(pid)查询获得锁情况:
select locktype,relation,mode,granted,query
from pg_lock_status() a
left join pg_stat_activity b on a.pid=b.pid and b. state <> 'idle'
通过lava管理页面(5.4版本)查询锁信息
可以通过以下语句终止任务,也可通过lava管理页面(5.4版本)终止任务:
select pg_cancel_backend_global(‘host’,pid);
五、总结
在实际应用中,当多个事务需要读取同一数据时,可以使用共享锁来提高并发性能;当多个事务需要修改同一数据时,需要使用排他锁来保证数据的一致性;根据具体的业务需求和数据访问模式来选择合适的锁策略,以确保数据的一致性和系统的高性能。