我想做这样的事情:
begin;
select * from foos where owner_id=123 and unread=true order by id for update;
update foos set unread=false where owner_id=123 and unread=true;
commit;
Run Code Online (Sandbox Code Playgroud)
目标是避免两个进程同时执行 UPDATE 时出现死锁。此处详细描述了问题:Why am I get a deadlock for a single UPDATE query?
在我获取锁的语句中,我不需要有关行的任何信息。我只想锁定那些特定的行。有没有办法做到这一点(优雅或hacky),告诉postgres不要做任何实际给我数据的工作?
假设我有一个以下形式的查询:
INSERT INTO tableA (...) select ... from tableB;
Run Code Online (Sandbox Code Playgroud)
现在,这个查询在执行时是否有可能阻止普通INSERT语句tableB?附加信息:
FOR UPDATE语句中没有子句SELECT(我什至不确定是否可以在INSERT...SELECT构造中做到这一点)REPEATABLE READ当我有一个包含多个查询的事务时,我可以通过使用waitfor和检查dm_tran_locks.
但我不能将一个查询“暂停”一半。具体来说,我想知道这个查询将如何持有锁:
update my_table set column1=new_value
where column2=filter_value
Run Code Online (Sandbox Code Playgroud)
这会从一开始就采取更新锁定吗?还是会先获取共享锁,直到确定指定的行where,然后请求 U 锁?
我尝试复制此处给出的场景: https: //www.sqlskills.com/blogs/paul/the-curious-case-of-the-bulk_operation-lock-during-a-heap-nolock-scan/
创建了 2 个表 - table1 带有聚集索引,table2 没有任何索引。
当我在 table1 上编写选择查询时with (lock),会应用 Sch-S 锁。同样,当我在 table2 上编写相同的查询时,也有一个 Sch-S 锁。
这两种情况都应用了 S 锁,如上面的链接所示。
要检查锁,我使用以下查询:
SELECT * FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID()
AND resource_associated_entity_id = OBJECT_ID(N'dbo.table1');
Run Code Online (Sandbox Code Playgroud)
是否使用 nolock 块写入器从堆(没有聚集索引的表)中选择数据?
SQL Server 中的读已提交快照和快照隔离级别消除了大多数锁定,除了以下一种情况:一个写入者仍会锁定其他写入者。
该文档小心翼翼地说了这么多,随后没有记录任何其他值得了解的内容:
它真的只是被独占锁定的修改行吗?或者它也可以是不相关的行(例如索引中相邻的行)或页面?
我确实查看了其中的锁sys.dm_tran_locks,并且在未提交的事务期间只看到了修改行上的独占锁 - 页面仅被锁定为IX.
我还测试了两个事务是否可以在一个非常小的表(可能适合一页)中的两个未提交事务期间同时修改两个不同的行,并且效果也很好。
如果确实只有修改的行被独占锁定,那么如果确保没有两个连接同时写入同一行,那么这将为具有数据库独占访问权限的应用程序提供无锁写入的保证。
在我想到的场景中这是可能的 - 但如果页面锁发挥作用,几乎没有办法做类似的事情,因为无法预测哪些行到底会受到影响。
我有一张如下表:
Newid1 a b c
1 null 40 50
2 null 45 55
3 null 46 56
4 null 47 57
5 null 48 58
Run Code Online (Sandbox Code Playgroud)
现在我想通过将 C 列值更新到其中来更新列中的值(例如:50 到第二行,55 到第三行,56 到第四行......)。如何使用 WHILE 命令执行此操作。提前谢谢大家。
我在 Oracle 11g RAC 环境中维护一些存储过程,这些过程是与其他系统进行数据交换的步骤管道的一部分。特别是其中之一一直在产生重复的记录。文件由 ETL 作业加载到一组暂存表中,然后调用这个没有参数的存储过程(除了被调用 ETL 代码忽略的 OUT 参数,但这是另一个问题)。该过程的主体以如下语句开头
For I in ( SELECT * from SOME_STAGING_TABLE where status = 'NEW' order by X_ID) LOOP
Run Code Online (Sandbox Code Playgroud)
但是,调用它的 ETL 作业又被另一个 ETL 作业调用,该作业查找所有尚未处理的“文件”并并行调用它,每个文件一次。我认为正在发生的事情是:
一种解决方案可能是在 ETL 服务中强制执行序列化。另一种可能是更改存储过程的调用约定,以便将文件 ID 作为参数。但是,假设我需要在数据库中执行此操作。有没有办法设置存储过程,以便一次只有一个连接可以执行其中的指定代码块?
(在 C 或 Java 中,这将被称为“互斥锁”或“同步块”,我知道 MySQL 有一个“LOCK TABLES”语句可用于该目的;Oracle 11g 有类似的功能吗?)
我是一名系统管理员,不会做大量的 dba 工作。对于一个项目,我可以访问一个生产服务器——我不是系统管理员——有一个巨大的 40,000,000 行 > 10 GB MySQL InnoDB 表。我想导出两个小列,其中一个是 INT(11),另一个是该表中的 VARCHAR(20) 到 CSV 或 .SQL 文件(两者都可以,我会写一个人行横道下一步没问题)。
我们可以将列 ColumnA 和 ColumnB 以及表称为 SampleTable。
MySQLdump 不是正确的工具,因为我无法指定列,而且我不需要导出一个只有两个小列的大型表。
我知道我可以执行 SELECT INTO 语句(创建一个仅包含列的新表,或者执行 SELECT INTO OUTFILE 以跳过中间步骤),但我担心这会导致生产服务器上的表级锁定. 该表是 InnoDB。
为了避免给服务器上的任何实时流量带来不便或锁定任何东西,我最好的选择是什么?
谢谢
我有一个应用程序由于超时而关闭。在这些时间里,我们看到保存 ASP 会话状态的数据库的响应时间大幅增加。
为了诊断问题,我使用SP_CONFIGURE'blocked process threshold',15并运行跟踪以捕获任何触发的事件。在下一个事件期间,跟踪捕获会话状态数据库中的一些阻塞事件。
我已经确定了主要拦截器,可以看到它已暂停并等待。
<blocked-process-report>
<blocked-process>
<process id="process53fb4c8"
taskpriority="0" logused="0"
waitresource="KEY: 10:72057594039238656 (594b17b7493c)" waittime="20631"
ownerId="9710782702" transactionname="UPDATE"
lasttranstarted="2013-06-27T17:29:38.130" XDES="0xc429df950" lockMode="U"
schedulerid="14" kpid="6912" status="suspended" spid="359" sbid="0" ecid="0"
priority="0" trancount="2" lastbatchstarted="2013-06-27T17:29:38.130"
lastbatchcompleted="2013-06-27T17:29:38.107"
clientapp=".Net SqlClient Data Provider" hostname="WEB03" hostpid="7520"
loginname="State" isolationlevel="read committed (2)" xactid="9710782702"
currentdb="10" lockTimeout="4294967295"
clientoption1="536870944" clientoption2="128056">
<executionStack>
<frame line="18" stmtstart="1114" stmtend="4494"
sqlhandle="0x03000a00210f020741a1be0058a000000100000000000000"/>
</executionStack>
<inputbuf>
Proc [Database Id = 10 Object Id = 117575457]
</inputbuf>
</process>
</blocked-process>
<blocking-process>
<process status="suspended" waittime="1046" spid="217" sbid="0" ecid="0"
priority="0" trancount="1" lastbatchstarted="2013-06-27T17:29:29.113"
lastbatchcompleted="2013-06-27T17:29:29.010" …Run Code Online (Sandbox Code Playgroud) 我希望更新READ_ONLY数据库上的几个用户。
由于数据库在全球范围内 24/7 全天候使用,并且维护窗口刚刚过去,我想在活动量低的时刻执行此操作(以便能够遵守截止日期)。
我目前正在考虑使用:
USE MASTER
GO
ALTER DATABASE SQL SET READ_WRITE
GO
USE SQL
GO
EXEC sp_addrolemember N'db_datareader', N'USER'
GO
USE MASTER
GO
ALTER DATABASE SQL SET READ_ONLY
GO
Run Code Online (Sandbox Code Playgroud)
但是我想:
由于我无法将这些命令放入事务中,而且我在 DEV 或 STG 环境中没有方便的应用程序服务器来预先测试更改,是否有任何有关更改read_only单个操作状态的文档?(我确实测试了 T-SQL 语句,并且它们有效)
另外,由于这需要对数据库进行排他锁,我什至有可能通过我的语句吗?
我倾向于只是提出这将不得不等到下一个维护窗口期间。但我希望这里有人能证明我错了。
locking ×10
sql-server ×5
mysql ×2
blocking ×1
export ×1
innodb ×1
insert ×1
mariadb ×1
oracle ×1
postgresql ×1
profiler ×1
session ×1
t-sql ×1
transaction ×1
update ×1