我如何保证我可以搜索我的数据库中是否存在用户名,然后将该用户名作为新行插入数据库而不在SELECT和INSERT语句之间进行任何拦截?
几乎就像我锁定了一个不存在的行.我想用用户名"Foo"锁定不存在的行,这样我现在可以检查它是否存在于数据库中并将其插入到数据库中(如果它尚不存在而没有任何中断).
我知道使用LOCK IN SHARE MODE和FOR UPDATE存在,但据我所知,这只适用于已经存在的行.我不知道在这种情况下该怎么做.
在SQL Server 2008中我有一个观点V在表A和B看起来大致是
create view V as
select * from A
union all
select * from B
Run Code Online (Sandbox Code Playgroud)
读取V会导致查询在基表上获取意图共享锁,但也会在视图对象本身上获取意图共享锁.
很清楚为什么我们需要表上的IS锁,我们可以看到视图上的IS锁阻止了对视图底层表的并发修改.没关系.
查询计划不包含视图.它已完全编译出来,在这种情况下生成的计划是两个基表中的行的简单连接.实际上,查询计划XML中唯一提到的视图是在语句文本中.
如果U在表上添加第二个视图,则读取V不会导致任何锁定U.这排除了发动机只需要对所有意见IS锁了A和B.
数据库引擎如何知道对视图进行锁定?
有关详细信息,请参阅相应的问题dba.stackexchange.
当我尝试在db表中插入/更新某些内容时,Oracle会锁定整个表还是仅锁定/更新的行?
这是可以通过外部配置控制的吗?
我正在阅读一本关于innodb交易的手册,但仍然有很多不清楚的东西给我.例如,我不太了解以下行为:
-- client 1 -- client 2
mysql> create table simple (col int)
engine=innodb;
mysql> insert into simple values(1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into simple values(2);
Query OK, 1 row affected (0.00 sec)
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
mysql> begin;
Query OK, 0 rows affected (0.01 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update simple set col=10 where col=1;
Query OK, 1 row affected …Run Code Online (Sandbox Code Playgroud) TL;DR:我们有长时间运行的导入,它们似乎在父分区表上持有锁,即使没有任何东西直接引用父表。
在我们的系统中,我们有inventories和inventory_items。库存往往有 200k 左右的物品,对于我们的访问模式来说,使用本机分区对inventory_items表进行分区是有意义的inventory_id(我们使用的是 Postgres 12)。换句话说,每个库存都有自己的 inventory_items 分区表。这是通过以下 DDL 完成的:
CREATE TABLE public.inventory_items (
inventory_id integer NOT NULL,
/* ... */
)
PARTITION BY LIST (inventory_id);
Run Code Online (Sandbox Code Playgroud)
在我们的应用程序代码中,当通过 Web 仪表板创建库存时,我们会通过以下方式自动创建分区子 inventory_items 表:
CREATE TABLE IF NOT EXISTS inventory_items_#{inventory_id}
PARTITION OF inventory_items
FOR VALUES IN (#{inventory_id});
Run Code Online (Sandbox Code Playgroud)
这些库存通常每天通过 CSV 或其他方式完全重新加载/重新导入一次,并且这些导入任务有时可能需要一段时间。
我们注意到,当这些长时间导入正在运行时,不可能创建新的清单,因为如上所述,创建清单意味着创建分区子表inventory_items,并且长时间运行的导入和创建分区子表之间存在一些锁争用。网络仪表板中的库存,这很糟糕:我们不能仅仅因为发生了完全不相关的导入就阻止用户创建库存。
我在 psql 中使用以下查询来确定谁持有哪些锁:
select pid, relname, mode
from pg_locks l
join pg_class t on l.relation = t.oid
where t.relkind …Run Code Online (Sandbox Code Playgroud) database postgresql database-partitioning database-locking postgresql-12
我已经彻底阅读了关于表提示的MSDN,我似乎没有找到默认的锁定粒度.假设我有以下查询:
SELECT TOP (1) * FROM MyTable WITH (UPDLOCK, READPAST) ORDER BY SomeColumn ASC;
Run Code Online (Sandbox Code Playgroud)
你看,我指定UPDLOCK和READPAST提示,但没有任何粒度提示,如TABLOCK或ROWLOCK.
默认情况下使用哪种粒度锁定级别?
sql-server locking granularity sql-server-2008 database-locking
我正在尝试开发一个预订系统,在检查其可用性后预订不同的资产。系统首先尝试从数据库读取记录并检查正在预订的插槽是否可用。如果是这样,系统会通过将新记录插入系统来为他们预订时隙。
现在的问题是,如果有多个用户请求预订,并且由于对 db 的多个请求可以交错,那么就有可能发生这种情况。
User 1 -> read request start
User 2 -> read request start
User 1 -> read request success (booking available)
User 2 -> read request success (booking available)
User 1 -> write a new record to the db (new booking)
User 2 -> write a new record to the db (new booking) but this conflicts with User 1.
Run Code Online (Sandbox Code Playgroud)
为了避免这种情况,我理想情况下甚至在读取操作开始之前就必须获取一个集合级锁,并且只有在最终写入完成后才释放锁。
我的理解正确吗?如果可以,这可以在 MongoDB 中完成吗?
非常欢迎使用 MongoDB、Mongoose 或@tsed/mongoose 的任何解决方案。
我遇到了需要在 9.6 上解决这个问题,但是关于 9.6 或更高版本的任何信息将不胜感激。
我的应用程序在数据库调用时被阻塞,因为它试图获取transactionid另一个正在运行的事务的隐式锁,我遇到了问题。我不明白的是为什么。
我知道每个事务在开始时都会获取一个ExclusiveLock自己的事务 ID ( pg_locks )。没关系。同一页面说,“通常”,只有“更改数据库状态”的事务才会被分配一个永久 ID。我在锁表中看到了永久 ID,所以我认为这发生了。但是,描述不太清楚,因为该页面既没有说明“通常”的含义,也没有说明什么是“数据库状态的变化”。
但是后来我找不到任何信息来指定语句何时会尝试获取SharedLock某个其他交易的 a。pg_locks的唯一声明是:
当一个进程发现有必要专门等待另一个事务结束时,它会尝试获取另一个事务 ID 的共享锁(虚拟或永久 ID,具体取决于情况)
这真的很模糊。没有办法请求事务锁(至少我没有在Explicit Locking 中看到它们)
所以我正在寻找以下答案:
transactionid另一个事务 ID 的锁?transactionid在这种特殊情况下是什么让插入查询获得锁(也不太重要,因为如果我有参考,我可以自己确定)现在,出于特殊原因,我的查询在这种情况下被阻止:
相关pg_locks内容:
x=# select locktype,transactionid,virtualtransaction,pid,mode,granted
x-# from pg_locks where transactionid = '33682979' ;
locktype | transactionid | virtualtransaction | pid | mode | granted
---------------+---------------+--------------------+--------+---------------+---------
transactionid | 33682979 | 7/27909 | 476513 | …Run Code Online (Sandbox Code Playgroud) 我有一个Django应用程序,将对象保存到数据库中,还有一个芹菜任务,该任务定期对其中一些对象进行一些处理。问题在于,在芹菜任务已选择要处理的对象之后,但芹菜任务实际完成处理并保存之前,用户可以删除对象。因此,当celery任务确实调用时.save(),即使用户删除了该对象,该对象也会重新出现在数据库中。当然,这对于用户来说确实很诡异。
所以这是一些显示问题的代码:
def my_delete_view(request, pk):
thing = Thing.objects.get(pk=pk)
thing.delete()
return HttpResponseRedirect('yay')
@app.task
def my_periodic_task():
things = get_things_for_processing()
# if the delete happens anywhere between here and the .save(), we're hosed
for thing in things:
process_thing(thing) # could take a LONG time
thing.save()
Run Code Online (Sandbox Code Playgroud)
我考虑过尝试通过添加原子块和事务来修复它,然后在保存对象之前测试该对象是否确实存在,以进行修复:
@app.task
def my_periodic_task():
things = Thing.objects.filter(...some criteria...)
for thing in things:
process_thing(thing) # could take a LONG time
try:
with transaction.atomic():
# just see if it still exists:
unused = Thing.objects.select_for_update().get(pk=thing.pk) …Run Code Online (Sandbox Code Playgroud) database-locking ×10
locking ×3
database ×2
innodb ×2
mysql ×2
postgresql ×2
sql-server ×2
celery ×1
django ×1
granularity ×1
mongodb ×1
mongoose ×1
oracle ×1
oracle11g ×1
python ×1
rowlocking ×1
sql ×1
transactions ×1
view ×1