关于使用事务从数据库中读取的看法似乎有很多不同.
来自DeveloperWorks文章的引用交易策略:模型和策略概述:
如果您只是在阅读数据,为什么还需要交易?答案是你没有.启动事务以执行只读操作会增加处理线程的开销,并可能导致数据库上的共享读锁(取决于您使用的数据库类型以及隔离级别设置的内容).
作为相反的意见,Hibernate文档中有以下引用非事务性数据访问和自动提交模式
我们的建议是不在应用程序中使用自动提交模式,并且仅在具有明显性能优势或未来代码更改的可能性很小时才应用只读事务.无论您是读取还是写入数据,始终更喜欢常规ACID事务来对数据访问操作进行分组.
也有EclipseLink的邮件列表上一个类似的争论在这里.
真相在哪里呢?交易是否为最佳实践?如果两者都是可行的解决方案,使用交易的标准是什么?
据我所知,只有隔离级别高于'read committed'才会有所不同.它是否正确?
有哪些经验和建议?
我有一个具有propagation = Propagation.REQUIRES_NEW事务属性的方法:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(final UserBean userBean) {
//Some logic here that requires modification in DB
}
Run Code Online (Sandbox Code Playgroud)
此方法可以同时调用多次,并且对于每个事务,如果发生错误而不是回滚(独立于其他事务).
问题是,这可能会迫使Spring创建多个事务,即使另一个事务可用,也可能导致一些性能问题.
Java doc propagation = Propagation.REQUIRED说:Support a current transaction, create a new one if none exists.
这似乎解决了性能问题,不是吗?
回滚问题怎么样?如果新方法调用在使用现有事务时回滚,该怎么办?即使以前的电话会不会回滚整个交易?
[编辑] 我想我的问题不够明确:
我们有数百个客户端连接到我们的服务器.
对于每个客户端,我们自然需要发送有关事务的反馈(OK或exception - > rollback).
我的问题是:如果我使用REQUIRED,是否意味着只使用了一个事务,如果第100个客户端遇到问题,第一个客户端的事务也会回滚?
我正在尝试编写一个具有事务和try/catch块的MS sql脚本.如果它捕获异常,则回滚事务.如果不是,则提交事务.我看过几个不同的网站说这样做:
begin transaction
begin try
--main content of script here
end try
begin catch
rollback transaction
end catch
commit transaction
Run Code Online (Sandbox Code Playgroud)
但即使在捕获异常的情况下,我们仍然不会点击"提交事务"行吗?这不会导致SQL错误,因为事务已经回滚了吗?我认为应该这样做:
declare @success bit = 1
begin transaction
begin try
--main content of script here
end try
begin catch
rollback transaction
set @success = 0
end catch
if(@success = 1)
begin
commit transaction
end
Run Code Online (Sandbox Code Playgroud)
普遍发布的解决方案如何不包含@success变量?提交已经回滚的事务是否没有发生sql错误?我是否错误地说在捕获异常的情况下仍然会遇到第一个代码示例的"提交事务"行?
使用ADO.NET的SQL Server的默认事务隔离级别是什么?我使用SQL Server的默认安装和正常的System.Data.SqlClient类.
我读到了Voltdb的命令日志.命令日志记录事务调用,而不是像在预写日志中那样更改每一行.通过仅记录调用,命令日志保持最低限度,从而限制磁盘I/O对性能的影响.
任何人都可以解释数据库理论背后为什么Voltdb使用命令日志以及为什么标准SQL数据库(如Postgres,MySQL,SQLServer,Oracle)使用预写日志?
好的,每当我尝试替换我的应用程序中的片段时,它只会将容器内部的片段添加到另一个片段中,并保留当前片段.我试过调用replace并引用包含片段的视图,并引用片段本身.这些都不奏效.我可以使用片段事务管理器将一个片段添加到视图中,但即使我尝试在添加它之后将其删除,它也不起作用.任何帮助,将不胜感激.这是我的文件.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Setup the actionabar. Use setDrawableBackground to set a background image for the actionbar.
final ActionBar actionbar = getActionBar();
actionbar.setDisplayShowTitleEnabled(false);
actionbar.setDisplayUseLogoEnabled(true);
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionbar.addTab(actionbar.newTab().setText(R.string.home_tab_text).setTabListener(this),true);
actionbar.addTab(actionbar.newTab().setText(R.string.insert_tab_text).setTabListener(this));
Fragment fragment = new insert_button_frag();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.button_fragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Run Code Online (Sandbox Code Playgroud)
这是布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:id="@+id/button_fragment_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<fragment
android:name="com.bv.silveredittab.home_button_frag"
android:id="@+id/button_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:name="com.bv.silveredittab.quick_insert_frag"
android:id="@+id/quick_insert_frag"
android:layout_width="350dip"
android:layout_height="fill_parent" />
<fragment
android:name="com.bv.silveredittab.editor_frag"
android:id="@+id/editor_frag"
android:layout_width="fill_parent"
android:layout_height="fill_parent" …Run Code Online (Sandbox Code Playgroud) 我们有:
@Transactional(propagation = Propagation.REQUIRED)
public class MyClass implementes MyInterface { ...
Run Code Online (Sandbox Code Playgroud)
MyInterface有一个方法:go().
当go()执行时,我们启动一个新的事务,该事务在方法完成时提交/回滚 - 这很好.
现在让我们说在go()中我们调用MyClass中的私有方法@Transactional(propagation = Propagation.REQUIRES_NEW.似乎Spring"忽略"REQUIRES_NEW注释并且不会启动新事务.我相信这是因为Spring AOP在接口级别(MyInterface)上运行,并且不拦截对MyClass方法的任何调用.它是否正确?
有没有办法在go()事务中启动新事务?是否只能调用另一个配置为REQUIRES_NEW的事务的Spring托管bean?
更新:在客户端执行时添加,go()通过对接口的引用而不是类来执行:
@Autowired
MyInterface impl;
impl.go();
Run Code Online (Sandbox Code Playgroud) 它们会立即回滚吗?它们会在一段时间后回滚吗?他们是否处于未承诺状态?
如果使用连接池并且只是重置连接,行为是否相同?
我想知道在处理多线程时如何以正确的方式使用TransactionScope类?
我们在主线程中创建了一个新的作用域,然后我们生成了几个工作线程,并且我们希望它们参与主作用域,因此,例如,如果作用域永远不会完成,则会在每个作者上调用回滚.
我在内部使用ThreadStaticAttribute阅读了有关TransactionScope的内容,这使得上述不可能/非常困难 - 有人可以验证这两种方式吗?如果我们以同步方式运行代码,那么回滚就可以工作,即内部事务能够参与主事务,但是如果我们切换到线程执行则不行.
谢谢
也许我在这里要解释的没有任何意义,所以我想提前道歉.无论如何,我会尝试.
我正在尝试从文件中读取,执行一些数据库操作并将内容移动到另一个文件.我想知道是否有可能在Java中的原子的方式执行所有作业本,所以如果有什么不顺心的操作列表,回滚完整序列,并回到起点.
在此先感谢您的帮助.
transactions ×10
java ×3
sql ×3
database ×2
spring ×2
sql-server ×2
.net ×1
ado.net ×1
android ×1
data-access ×1
exception ×1
hibernate ×1
logging ×1
try-catch ×1
voltdb ×1