-
2021-04-14 04:42:40
回滚操作将撤消当前事务所做的所有更改,即,如果调用Connection接口的rollBack()方法,则所有修改都将还原到最后一次提交。
您还可以通过将所需的Savepoint对象作为参数传递给此方法,将数据库中的更改回滚到特定的保存点,如下所示://Setting the save point
con.rollback("MysavePoint");
回滚事务
使用DriverManager类的registerDriver()方法将驱动程序注册为-//注册驱动程序
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
使用getConnection()DriverManager类的方法获取连接,如下所示://获得连接
String url = "jdbc:mysql://localhost/mydatabase";
Connection con = DriverManager.getConnection(url, "root", "password");
使用setAutoCommit()方法关闭自动提交,如下所示://将自动提交设置为false-
con.setAutoCommit(false);
使用setSavepoint()设置保存点,或者使用以下commit()方法提交事务:Savepoint savePoint = con.setSavepoint("MysavePoint");
Con.commit();
最后,回滚到最后一个保存点,或者使用rollback()或rollback(Savepoint savepoint)方法最后提交。con.rollback()
Or,
con. rollback(mySavepoint);
让我们使用CREATE语句在MySQL数据库中创建一个名为MyPlayers的表,如下所示-CREATE TABLE MyPlayers(
ID INT,
First_Name VARCHAR(255),
Last_Name VARCHAR(255),
Date_Of_Birth date,
Place_Of_Birth VARCHAR(255),
Country VARCHAR(255),
PRIMARY KEY (ID)
);
现在,我们将使用INSERT语句在MyPlayers表中插入7条记录-insert into MyPlayers values(1, 'Shikhar', 'Dhawan', DATE('1981-12-05'), 'Delhi', 'India');
insert into MyPlayers values(2, 'Jonathan', 'Trott', DATE('1981-04-22'), 'CapeTown', 'SouthAfrica');
insert into MyPlayers values(3, 'Kumara', 'Sangakkara', DATE('1977-10-27'), 'Matale', 'Srilanka');
insert into MyPlayers values(4, 'Virat', 'Kohli', DATE('1988-11-05'), 'Delhi', 'India');
insert into MyPlayers values(5, 'Rohit', 'Sharma', DATE('1987-04-30'), 'Nagpur', 'India');
insert into MyPlayers values(6, 'Ravindra', 'Jadeja', DATE('1988-12-06'), 'Nagpur', 'India');
insert into MyPlayers values(7, 'James', 'Anderson', DATE('1982-06-30'), 'Burnley', 'England');
以下JDBC程序演示了Connection接口的rollback()方法。在这里,我们在Myplayers表中插入了一条新记录。使用该commit()方法完成事务,删除先前插入的记录,然后回滚到创建的保存点,并显示表的内容
示例import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Connection_rollBack {
public static void main(String args[]) throws SQLException {
//注册驱动程序
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//获得连接
String url = "jdbc:mysql://localhost/mydatabase";
Connection con = DriverManager.getConnection(url, "root", "password");
System.out.println("Connection established......");
//将自动提交设置为false-
con.setAutoCommit(false);
//创建一个Statement对象
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
//检索数据
ResultSet rs = stmt.executeQuery("select * from MyPlayers");
System.out.println("Contents of the table initially");
while(rs.next()) {
System.out.print("ID: "+rs.getString("ID")+", ");
System.out.print("First_Name: "+rs.getString("First_Name")+", ");
System.out.print("Last_Name: "+rs.getString("Last_Name")+", ");
System.out.print("Date_Of_Birth: "+rs.getString("Date_Of_Birth")+", ");
System.out.print("Place_Of_Birth: "+rs.getString("Place_Of_Birth")+", ");
System.out.print("Country: "+rs.getString("Country"));
System.out.println("");
}
PreparedStatement pstmt = con.prepareStatement("INSERT INTO MyPlayers VALUES (?, ?, ?, ?, ?, ?)");
pstmt.setInt(1, 8);
pstmt.setString(2, "Ishant");
pstmt.setString(3, "Sharma");
pstmt.setDate(4, new Date(904694400000L));
pstmt.setString(5, "Delhi");
pstmt.setString(6, "India");
pstmt.executeUpdate();
//提交事务
con.commit();
//删除记录
stmt.execute("Delete from MyPlayers where id = 8");
//回滚到保存点
con.rollback();
//回滚后表的内容
System.out.println("Contents of the table");
rs = stmt.executeQuery("select * from MyPlayers");
while(rs.next()) {
System.out.print("ID: "+rs.getString("ID")+", ");
System.out.print("First_Name: "+rs.getString("First_Name")+", ");
System.out.print("Last_Name: "+rs.getString("Last_Name")+", ");
System.out.print("Date_Of_Birth: "+rs.getString("Date_Of_Birth")+", ");
System.out.print("Place_Of_Birth: "+rs.getString("Place_Of_Birth")+", ");
System.out.print("Country: "+rs.getString("Country"));
System.out.println("");
}
}
}
现在,您可以观察结果中保存点之前创建的新记录,尽管我们已将其删除。
如果我们回滚一个事务,那么在上一次提交之后所做的所有更改都将被还原。
由于我们已在设置提交后删除了第8条记录,因此在回滚时将还原此删除。
输出结果Connection established......
Contents of the table initially
ID: 1, First_Name: Shikhar, Last_Name: Dhawan, Date_Of_Birth: 1981-12-05, Place_Of_Birth: Delhi, Country: India
ID: 2, First_Name: Jonathan, Last_Name: Trott, Date_Of_Birth: 1981-04-22, Place_Of_Birth: CapeTown, Country: SouthAfrica
ID: 3, First_Name: Kumara, Last_Name: Sangakkara, Date_Of_Birth: 1977-10-27, Place_Of_Birth: Matale, Country: Srilanka
ID: 4, First_Name: Virat, Last_Name: Kohli, Date_Of_Birth: 1988-11-05, Place_Of_Birth: Mumbai, Country: India
ID: 5, First_Name: Rohit, Last_Name: Sharma, Date_Of_Birth: 1987-04-30, Place_Of_Birth: Nagpur, Country: India
ID: 6, First_Name: Ravindra, Last_Name: Jadeja, Date_Of_Birth: 1988-12-06, Place_Of_Birth: Nagpur, Country: India
ID: 7, First_Name: James, Last_Name: Anderson, Date_Of_Birth: 1982-06-30, Place_Of_Birth: Burnley , Country: England
Contents of the table after rollback
ID: 1, First_Name: Shikhar, Last_Name: Dhawan, Date_Of_Birth: 1981-12-05, Place_Of_Birth: Delhi, Country: India
ID: 2, First_Name: Jonathan, Last_Name: Trott, Date_Of_Birth: 1981-04-22, Place_Of_Birth: CapeTown, Country: SouthAfrica
ID: 3, First_Name: Kumara, Last_Name: Sangakkara, Date_Of_Birth: 1977-10-27, Place_Of_Birth: Matale, Country: Srilanka
ID: 4, First_Name: Virat, Last_Name: Kohli, Date_Of_Birth: 1988-11-05, Place_Of_Birth: Mumbai, Country: India
ID: 5, First_Name: Rohit, Last_Name: Sharma, Date_Of_Birth: 1987-04-30, Place_Of_Birth: Nagpur, Country: India
ID: 6, First_Name: Ravindra, Last_Name: Jadeja, Date_Of_Birth: 1988-12-06, Place_Of_Birth: Nagpur, Country: India
ID: 7, First_Name: James, Last_Name: Anderson, Date_Of_Birth: 1982-06-30, Place_Of_Birth: Burnley , Country: England
ID: 8, First_Name: Ishant, Last_Name: Sharma, Date_Of_Birth: 1998-09-02, Place_Of_Birth: Delhi, Country: India
更多相关内容 -
SQL事务用法begin tran,commit tran和rollback tran的用法
2020-09-11 02:37:04Sql Server 2005/2008中提供了begin tran,commit tran和rollback tran来使用事务。begin tran表示开始事务, commit tran表示提交事务,rollback tran表示回滚事物 -
RollBack Rx PRO v11.1 正式永久使用无限制
2019-04-18 13:07:51RollBack Rx v11.1 正式永久使用无限制,内包括正式版本SN(注册码) 非破解版本。 -
mysql错误Please use SHOW DDL to check it, and then recover or rollback it using RECOVER DDL or ...
2020-12-14 14:27:42mysql执行DDL语句的时候提示错误: [Err] 4644 – [1065507aa5d0c000][10.0.85.135:3306][test]ERR-CODE: [TDDL-4644][ERR_PENDING_DDL_JOB_EXISTS] Another DDL job ‘1181437929186181120’ with operation ... -
Ansible-rollback.zip
2019-09-18 09:40:41Ansible-rollback.zip,在capistrano styleansistrano中负责回滚脚本应用程序(如php、python、ruby等),ansible是一个简单而强大的自动化引擎。它用于帮助配置管理、应用程序部署和任务自动化。 -
Rollback
2020-04-28 22:38:39Rollback Sometimes things don’t go as planned when attempting an upgrade. This section explains how to perform a rollback to an earlier HBase release. Note that this should only be needed between Ma...- Rollback
Sometimes things don’t go as planned when attempting an upgrade. This section explains how to perform a rollback to an earlier HBase release. Note that this should only be needed between Major and some Minor releases. You should always be able to downgrade between HBase Patch releases within the same Minor version. These instructions may require you to take steps before you start the upgrade process, so be sure to read through this section beforehand.
12.1. Caveats
Rollback vs DowngradeThis section describes how to perform a rollback on an upgrade between HBase minor and major versions. In this document, rollback refers to the process of taking an upgraded cluster and restoring it to the old version while losing all changes that have occurred since upgrade. By contrast, a cluster downgrade would restore an upgraded cluster to the old version while maintaining any data written since the upgrade. We currently only offer instructions to rollback HBase clusters. Further, rollback only works when these instructions are followed prior to performing the upgrade.
When these instructions talk about rollback vs downgrade of prerequisite cluster services (i.e. HDFS), you should treat leaving the service version the same as a degenerate case of downgrade.
ReplicationUnless you are doing an all-service rollback, the HBase cluster will lose any configured peers for HBase replication. If your cluster is configured for HBase replication, then prior to following these instructions you should document all replication peers. After performing the rollback you should then add each documented peer back to the cluster. For more information on enabling HBase replication, listing peers, and adding a peer see Managing and Configuring Cluster Replication. Note also that data written to the cluster since the upgrade may or may not have already been replicated to any peers. Determining which, if any, peers have seen replication data as well as rolling back the data in those peers is out of the scope of this guide.
Data LocalityUnless you are doing an all-service rollback, going through a rollback procedure will likely destroy all locality for Region Servers. You should expect degraded performance until after the cluster has had time to go through compactions to restore data locality. Optionally, you can force a compaction to speed this process up at the cost of generating cluster load.
Configurable LocationsThe instructions below assume default locations for the HBase data directory and the HBase znode. Both of these locations are configurable and you should verify the value used in your cluster before proceeding. In the event that you have a different value, just replace the default with the one found in your configuration * HBase data directory is configured via the key ‘hbase.rootdir’ and has a default value of ‘/hbase’. * HBase znode is configured via the key ‘zookeeper.znode.parent’ and has a default value of ‘/hbase’.
12.2. All service rollbackIf you will be performing a rollback of both the HDFS and ZooKeeper services, then HBase’s data will be rolled back in the process.
RequirementsAbility to rollback HDFS and ZooKeeper
Before upgrade
No additional steps are needed pre-upgrade. As an extra precautionary measure, you may wish to use distcp to back up the HBase data off of the cluster to be upgraded. To do so, follow the steps in the ‘Before upgrade’ section of ‘Rollback after HDFS downgrade’ but copy to another HDFS instance instead of within the same instance.
Performing a rollbackStop HBase Perform a rollback for HDFS and ZooKeeper (HBase should remain stopped) Change the installed version of HBase to the previous version Start HBase Verify HBase contents—use the HBase shell to list tables and scan some known values.
12.3. Rollback after HDFS rollback and ZooKeeper downgrade
If you will be rolling back HDFS but going through a ZooKeeper downgrade, then HBase will be in an inconsistent state. You must ensure the cluster is not started until you complete this process.
RequirementsAbility to rollback HDFS Ability to downgrade ZooKeeper
Before upgrade
No additional steps are needed pre-upgrade. As an extra precautionary measure, you may wish to use distcp to back up the HBase data off of the cluster to be upgraded. To do so, follow the steps in the ‘Before upgrade’ section of ‘Rollback after HDFS downgrade’ but copy to another HDFS instance instead of within the same instance.
Performing a rollbackStop HBase Perform a rollback for HDFS and a downgrade for ZooKeeper (HBase should remain stopped) Change the installed version of HBase to the previous version Clean out ZooKeeper information related to HBase. WARNING: This step will permanently destroy all replication peers. Please see the section on HBase Replication under Caveats for more information. Clean HBase information out of ZooKeeper [hpnewton@gateway_node.example.com ~]$ zookeeper-client -server zookeeper1.example.com:2181,zookeeper2.example.com:2181,zookeeper3.example.com:2181 Welcome to ZooKeeper! JLine support is disabled rmr /hbase quit Quitting... Start HBase Verify HBase contents—use the HBase shell to list tables and scan some known values.
12.4. Rollback after HDFS downgrade
If you will be performing an HDFS downgrade, then you’ll need to follow these instructions regardless of whether ZooKeeper goes through rollback, downgrade, or reinstallation.
RequirementsAbility to downgrade HDFS Pre-upgrade cluster must be able to run MapReduce jobs HDFS super user access Sufficient space in HDFS for at least two copies of the HBase data directory
Before upgrade
Before beginning the upgrade process, you must take a complete backup of HBase’s backing data. The following instructions cover backing up the data within the current HDFS instance. Alternatively, you can use the distcp command to copy the data to another HDFS cluster.
Stop the HBase cluster Copy the HBase data directory to a backup location using the distcp command as the HDFS super user (shown below on a security enabled cluster) Using distcp to backup the HBase data directory [hpnewton@gateway_node.example.com ~]$ kinit -k -t hdfs.keytab hdfs@EXAMPLE.COM [hpnewton@gateway_node.example.com ~]$ hadoop distcp /hbase /hbase-pre-upgrade-backup Distcp will launch a mapreduce job to handle copying the files in a distributed fashion. Check the output of the distcp command to ensure this job completed successfully.
Performing a rollback
Stop HBase Perform a downgrade for HDFS and a downgrade/rollback for ZooKeeper (HBase should remain stopped) Change the installed version of HBase to the previous version Restore the HBase data directory from prior to the upgrade as the HDFS super user (shown below on a security enabled cluster). If you backed up your data on another HDFS cluster instead of locally, you will need to use the distcp command to copy it back to the current HDFS cluster. Restore the HBase data directory [hpnewton@gateway_node.example.com ~]$ kinit -k -t hdfs.keytab hdfs@EXAMPLE.COM [hpnewton@gateway_node.example.com ~]$ hdfs dfs -mv /hbase /hbase-upgrade-rollback [hpnewton@gateway_node.example.com ~]$ hdfs dfs -mv /hbase-pre-upgrade-backup /hbase Clean out ZooKeeper information related to HBase. WARNING: This step will permanently destroy all replication peers. Please see the section on HBase Replication under Caveats for more information. Clean HBase information out of ZooKeeper [hpnewton@gateway_node.example.com ~]$ zookeeper-client -server zookeeper1.example.com:2181,zookeeper2.example.com:2181,zookeeper3.example.com:2181 Welcome to ZooKeeper! JLine support is disabled rmr /hbase quit Quitting... Start HBase Verify HBase contents–use the HBase shell to list tables and scan some known values.
-
snapshot and rollback for conf files-开源
2021-05-06 11:43:26快照和回滚支持Linux发行版上的配置文件。 可以手动/定期/自动保存配置的工具。 用于查看存储文件中差异的工具以及用于还原它们的工具。 -
Android RollBack机制实现原理剖析
2020-10-18 14:18:59这样的确可以极大的提升用户的体验,但是因为这块的逻辑较复杂,我们以module_crash_rollback_test为例,来看下具体的实现逻辑。 代码路径如下: ./base/services/core/java/com/android/server/rollback ./base/...
功能介绍:
在Android 10.0中,Google新增加了个功能。
如果用户对新升级的APP不满意,可以通过“回到过去”,回滚到旧版。
当然,如果新安装的apk出现了各种问题无法使用,也可以进行回滚的操作。
这样的确可以极大的提升用户的体验,但是因为这块的逻辑较复杂,我们以module_crash_rollback_test为例,来看下具体的实现逻辑。
代码路径如下:
./base/services/core/java/com/android/server/rollback ./base/core/java/android/content/rollback
工作原理:
如何验证这个功能是否逻辑生效,我们可以使用这个方法:
1. adb install -r -d --enable-rollback --staged ***.apk 2. adb reboot 3. adb shell dumpsys rollback 4. adb root 5. adb shell am crash *** (10 times) 6. adb reboot 7. adb wait-for-devices 1 mins 8. adb shell dumpsys rollback
我们即可从RollBack的状态,检查rollback机制是否被激活以及使用。
dumpsys的code在代码中对应如下:代码路径为:frameworks/base/services/core/java/com/android/server/rollback/Rollback.java
void dump(IndentingPrintWriter ipw) { synchronized (mLock) { ipw.println(info.getRollbackId() + ":"); ipw.increaseIndent(); ipw.println("-state: " + getStateAsString()); ipw.println("-timestamp: " + getTimestamp()); if (getStagedSessionId() != -1) { ipw.println("-stagedSessionId: " + getStagedSessionId()); } ipw.println("-packages:"); ipw.increaseIndent(); for (PackageRollbackInfo pkg : info.getPackages()) { ipw.println(pkg.getPackageName() + " " + pkg.getVersionRolledBackFrom().getLongVersionCode() + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode()); } ipw.decreaseIndent(); if (isCommitted()) { ipw.println("-causePackages:"); ipw.increaseIndent(); for (VersionedPackage cPkg : info.getCausePackages()) { ipw.println(cPkg.getPackageName() + " " + cPkg.getLongVersionCode()); } ipw.decreaseIndent(); ipw.println("-committedSessionId: " + info.getCommittedSessionId()); } if (mExtensionVersions.size() > 0) { ipw.println("-extensionVersions:"); ipw.increaseIndent(); ipw.println(mExtensionVersions.toString()); ipw.decreaseIndent(); } ipw.decreaseIndent(); } }
从dumpsys中,我们就可以看到rollback的当前执行状态。
String getStateAsString() { synchronized (mLock) { return rollbackStateToString(mState); } }
逻辑很简单,即为将RollBack中的mState变量值置为String并且打出。
变量定义如下:/** * The current state of the rollback. * ENABLING, AVAILABLE, or COMMITTED. */ @GuardedBy("mLock") private @RollbackState int mState;
会有四个状态值,来对应当前的mState.
@IntDef(prefix = { "ROLLBACK_STATE_" }, value = { ROLLBACK_STATE_ENABLING, ROLLBACK_STATE_AVAILABLE, ROLLBACK_STATE_COMMITTED, ROLLBACK_STATE_DELETED })
那么在执行module_crash_rollback_test的时候,我们的逻辑是怎么生效的呢?
首先是在rollbackmanagerservice中:/** * Service that manages APK level rollbacks. Publishes * Context.ROLLBACK_SERVICE. * * @hide */ public final class RollbackManagerService extends SystemService { private RollbackManagerServiceImpl mService; public RollbackManagerService(Context context) { super(context); } @Override public void onStart() { mService = new RollbackManagerServiceImpl(getContext()); publishBinderService(Context.ROLLBACK_SERVICE, mService); } @Override public void onUnlockUser(int user) { mService.onUnlockUser(user); } @Override public void onBootPhase(int phase) { if (phase == SystemService.PHASE_BOOT_COMPLETED) { mService.onBootCompleted(); } }
可以看到的是,在PHASE_BOOT_COMPLETED时,将会调用onBootCompleted的函数。
如果看过之前的文章的同学,可能也明白了这个函数是在系统启动完成后,针对全局发出的通知。@AnyThread void onBootCompleted() { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ROLLBACK_BOOT, mExecutor, properties -> updateRollbackLifetimeDurationInMillis()); getHandler().post(() -> { updateRollbackLifetimeDurationInMillis(); runExpiration(); // Check to see if any rollback-enabled staged sessions or staged // rollback sessions been applied. List<Rollback> enabling = new ArrayList<>(); List<Rollback> restoreInProgress = new ArrayList<>(); Set<String> apexPackageNames = new HashSet<>(); synchronized (mLock) { Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { Rollback rollback = iter.next(); if (!rollback.isStaged()) { // We only care about staged rollbacks here continue; } PackageInstaller.SessionInfo session = mContext.getPackageManager() .getPackageInstaller().getSessionInfo(rollback.getStagedSessionId()); if (session == null || session.isStagedSessionFailed()) { iter.remove(); rollback.delete(mAppDataRollbackHelper); continue; } if (session.isStagedSessionApplied()) { if (rollback.isEnabling()) { enabling.add(rollback); } else if (rollback.isRestoreUserDataInProgress()) { restoreInProgress.add(rollback); } } apexPackageNames.addAll(rollback.getApexPackageNames()); } } for (Rollback rollback : enabling) { makeRollbackAvailable(rollback); } for (Rollback rollback : restoreInProgress) { rollback.setRestoreUserDataInProgress(false); } for (String apexPackageName : apexPackageNames) { // We will not recieve notifications when an apex is updated, // so check now in case any rollbacks ought to be expired. The // onPackagedReplace function is safe to call if the package // hasn't actually been updated. onPackageReplaced(apexPackageName); } synchronized (mLock) { mOrphanedApkSessionIds.clear(); } mPackageHealthObserver.onBootCompletedAsync(); }); }
这段主要说的是在系统启动过程中,我们将会对rollback的功能开启,各个session的状态,以及实际的packageName进行replaced,restore userdata的操作。这边分析一下onPackageReplaced函数:
/** * Called when a package has been replaced with a different version. * Removes all backups for the package not matching the currently * installed package version. */ @WorkerThread private void onPackageReplaced(String packageName) { // TODO: Could this end up incorrectly deleting a rollback for a // package that is about to be installed? long installedVersion = getInstalledPackageVersion(packageName); synchronized (mLock) { Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { Rollback rollback = iter.next(); // TODO: Should we remove rollbacks in the ENABLING state here? if ((rollback.isEnabling() || rollback.isAvailable()) && rollback.includesPackageWithDifferentVersion(packageName, installedVersion)) { iter.remove(); rollback.delete(mAppDataRollbackHelper); } } } }
当包被其他版本替换时调用时,我们会通过installedVersion来保存APK的版本号,
并且在下面将会删除与当前安装的包版本不匹配的包的所有备份。
在操作完,将会执行onBootCompletedAsync函数,而这边是进行的通知。/** Verifies the rollback state after a reboot and schedules polling for sometime after reboot * to check for native crashes and mitigate them if needed. */ public void onBootCompletedAsync() { mHandler.post(()->onBootCompleted()); }
那么这个onBootCompleted在做什么工作呢?
private void onBootCompleted() { RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class); if (!rollbackManager.getAvailableRollbacks().isEmpty()) { // TODO(gavincorkery): Call into Package Watchdog from outside the observer PackageWatchdog.getInstance(mContext).scheduleCheckAndMitigateNativeCrashes(); } SparseArray<String> rollbackIds = popLastStagedRollbackIds(); for (int i = 0; i < rollbackIds.size(); i++) { WatchdogRollbackLogger.logRollbackStatusOnBoot(mContext, rollbackIds.keyAt(i), rollbackIds.valueAt(i), rollbackManager.getRecentlyCommittedRollbacks()); } }
这边的重头戏来了,scheduleCheckAndMitigateNativeCrashes看上去和我们要验证的module_crash_rollback_test非常的相似。
/** * Since this method can eventually trigger a rollback, it should be called * only once boot has completed {@code onBootCompleted} and not earlier, because the install * session must be entirely completed before we try to rollback. */ public void scheduleCheckAndMitigateNativeCrashes() { Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check " + "and mitigate native crashes"); mShortTaskHandler.post(()->checkAndMitigateNativeCrashes()); }
只是打印了log,就来执行check的操作。
/** * This method should be only called on mShortTaskHandler, since it modifies * {@link #mNumberOfNativeCrashPollsRemaining}. */ private void checkAndMitigateNativeCrashes() { mNumberOfNativeCrashPollsRemaining--; // Check if native watchdog reported a crash if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) { // We rollback everything available when crash is unattributable onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH); // we stop polling after an attempt to execute rollback, regardless of whether the // attempt succeeds or not } else { if (mNumberOfNativeCrashPollsRemaining > 0) { mShortTaskHandler.postDelayed(() -> checkAndMitigateNativeCrashes(), NATIVE_CRASH_POLLING_INTERVAL_MILLIS); } } }
这边就非常奇怪了,为什么会有sys.init.updatable_crashing这个systemproperties呢?
这个properties是定义在什么地方?
代码路径: system/core/init/service.cpp// If we crash > 4 times in 4 minutes or before boot_completed, // reboot into bootloader or set crashing property boot_clock::time_point now = boot_clock::now(); if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART)) { bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false); if (now < time_crashed_ + 4min || !boot_completed) { if (++crash_count_ > 4) { if (flags_ & SVC_CRITICAL) { // Aborts into bootloader LOG(FATAL) << "critical process '" << name_ << "' exited 4 times " << (boot_completed ? "in 4 minutes" : "before boot completed"); } else { LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times " << (boot_completed ? "in 4 minutes" : "before boot completed"); // Notifies update_verifier and apexd SetProperty("sys.init.updatable_crashing_process_name", name_); SetProperty("sys.init.updatable_crashing", "1"); } } } else { time_crashed_ = now; crash_count_ = 1; } }
这里其实是对Crash的一个检查,如果在开机以后,规定时间内有四次以上的crash,然后就会触发这个properties的定义。
同时会记录当前进程的名字:sys.init.updatable_crashing_process_name。
但是在正常的过程中,这个应该不会出现。
但是在我们之前测试步骤中,当我们连续crash apk多次,那么重启后是否就会激活rollback呢?
应该是的,我们继续看看状态的改变过程。/** * Called when a process fails due to a crash, ANR or explicit health check. * * <p>For each package contained in the process, one registered observer with the least user * impact will be notified for mitigation. * * <p>This method could be called frequently if there is a severe problem on the device. */ public void onPackageFailure(List<VersionedPackage> packages, @FailureReasons int failureReason) { if (packages == null) { Slog.w(TAG, "Could not resolve a list of failing packages"); return; } mLongTaskHandler.post(() -> { synchronized (mLock) { if (mAllObservers.isEmpty()) { return; } boolean requiresImmediateAction = (failureReason == FAILURE_REASON_NATIVE_CRASH || failureReason == FAILURE_REASON_EXPLICIT_HEALTH_CHECK); if (requiresImmediateAction) { handleFailureImmediately(packages, failureReason); } else { for (int pIndex = 0; pIndex < packages.size(); pIndex++) { VersionedPackage versionedPackage = packages.get(pIndex); // Observer that will receive failure for versionedPackage PackageHealthObserver currentObserverToNotify = null; int currentObserverImpact = Integer.MAX_VALUE; // Find observer with least user impact for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) { ObserverInternal observer = mAllObservers.valueAt(oIndex); PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null && observer.onPackageFailureLocked( versionedPackage.getPackageName())) { int impact = registeredObserver.onHealthCheckFailed( versionedPackage, failureReason); if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; currentObserverImpact = impact; } } } // Execute action with least user impact if (currentObserverToNotify != null) { currentObserverToNotify.execute(versionedPackage, failureReason); } } } } }); }
当package failureReason 的原因为Native_Crash和FAILURE_REASON_EXPLICIT_HEALTH_CHECK时,将会立刻对问题进行处理。
使用函数为:handleFailureImmediately。/** * For native crashes or explicit health check failures, call directly into each observer to * mitigate the error without going through failure threshold logic. */ private void handleFailureImmediately(List<VersionedPackage> packages, @FailureReasons int failureReason) { VersionedPackage failingPackage = packages.size() > 0 ? packages.get(0) : null; PackageHealthObserver currentObserverToNotify = null; int currentObserverImpact = Integer.MAX_VALUE; for (ObserverInternal observer: mAllObservers.values()) { PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null) { int impact = registeredObserver.onHealthCheckFailed( failingPackage, failureReason); if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; currentObserverImpact = impact; } } } if (currentObserverToNotify != null) { currentObserverToNotify.execute(failingPackage, failureReason); } }
在使用后,会执行execute的函数:
@Override public boolean execute(@Nullable VersionedPackage failedPackage, @FailureReasons int rollbackReason) { if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) { rollbackAll(); return true; } RollbackInfo rollback = getAvailableRollback(failedPackage); if (rollback == null) { Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage); return false; } rollbackPackage(rollback, failedPackage, rollbackReason); // Assume rollback executed successfully return true; }
这里面我们主要关注的是NATIVE_CRASH的实现,所以将会去看rollbackAll的具体实现。
private void rollbackAll() { Slog.i(TAG, "Rolling back all available rollbacks"); RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class); List<RollbackInfo> rollbacks = rollbackManager.getAvailableRollbacks(); // Add all rollback ids to mPendingStagedRollbackIds, so that we do not reboot before all // pending staged rollbacks are handled. synchronized (mPendingStagedRollbackIds) { for (RollbackInfo rollback : rollbacks) { if (rollback.isStaged()) { mPendingStagedRollbackIds.add(rollback.getRollbackId()); } } } for (RollbackInfo rollback : rollbacks) { VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom(); rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH); } }
RollBackPackage具体的实现逻辑如下:
/** * Rolls back the session that owns {@code failedPackage} * * @param rollback {@code rollbackInfo} of the {@code failedPackage} * @param failedPackage the package that needs to be rolled back */ private void rollbackPackage(RollbackInfo rollback, VersionedPackage failedPackage, @FailureReasons int rollbackReason) { final RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class); int reasonToLog = WatchdogRollbackLogger.mapFailureReasonToMetric(rollbackReason); final String failedPackageToLog; if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) { failedPackageToLog = SystemProperties.get( "sys.init.updatable_crashing_process_name", ""); } else { failedPackageToLog = failedPackage.getPackageName(); } VersionedPackage logPackageTemp = null; if (isModule(failedPackage.getPackageName())) { logPackageTemp = WatchdogRollbackLogger.getLogPackage(mContext, failedPackage); } final VersionedPackage logPackage = logPackageTemp; WatchdogRollbackLogger.logEvent(logPackage, FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE, reasonToLog, failedPackageToLog); final LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> { int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, RollbackManager.STATUS_FAILURE); if (status == RollbackManager.STATUS_SUCCESS) { if (rollback.isStaged()) { int rollbackId = rollback.getRollbackId(); synchronized (mPendingStagedRollbackIds) { mPendingStagedRollbackIds.add(rollbackId); } BroadcastReceiver listener = listenForStagedSessionReady(rollbackManager, rollbackId, logPackage); handleStagedSessionChange(rollbackManager, rollbackId, listener, logPackage); } else { WatchdogRollbackLogger.logEvent(logPackage, FrameworkStatsLog .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS, reasonToLog, failedPackageToLog); } } else { if (rollback.isStaged()) { markStagedSessionHandled(rollback.getRollbackId()); } WatchdogRollbackLogger.logEvent(logPackage, FrameworkStatsLog .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, reasonToLog, failedPackageToLog); } }); mHandler.post(() -> rollbackManager.commitRollback(rollback.getRollbackId(), Collections.singletonList(failedPackage), rollbackReceiver.getIntentSender())); }
这里面我们不去具体的分析某个session,而是回到前文中,提到的具体的状态,这里就会看到最后的这么一个逻辑。
mHandler.post(() -> rollbackManager.commitRollback(rollback.getRollbackId(), Collections.singletonList(failedPackage), rollbackReceiver.getIntentSender()));
这里面是调用了rollbackManager的commitRollback方法:
@Override public void commitRollback(int rollbackId, ParceledListSlice causePackages, String callerPackageName, IntentSender statusReceiver) { enforceManageRollbacks("commitRollback"); final int callingUid = Binder.getCallingUid(); AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); appOps.checkPackage(callingUid, callerPackageName); getHandler().post(() -> commitRollbackInternal(rollbackId, causePackages.getList(), callerPackageName, statusReceiver)); }
其实也就是获取package,然后去通过commitRollbackInternal处理。
/** * Performs the actual work to commit a rollback. * The work is done on the current thread. This may be a long running * operation. */ @WorkerThread private void commitRollbackInternal(int rollbackId, List<VersionedPackage> causePackages, String callerPackageName, IntentSender statusReceiver) { Slog.i(TAG, "commitRollback id=" + rollbackId + " caller=" + callerPackageName); Rollback rollback = getRollbackForId(rollbackId); if (rollback == null) { sendFailure( mContext, statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE, "Rollback unavailable"); return; } rollback.commit(mContext, causePackages, callerPackageName, statusReceiver); }
rollback的commit将会去具体的更改某个rollback的状态:
/** * Commits the rollback. */ void commit(final Context context, List<VersionedPackage> causePackages, String callerPackageName, IntentSender statusReceiver) { synchronized (mLock) { if (!isAvailable()) { sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE, "Rollback unavailable"); return; } if (containsApex() && wasCreatedAtLowerExtensionVersion()) { PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); if (extensionVersionReductionWouldViolateConstraint(mExtensionVersions, pmi)) { sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE, "Rollback may violate a minExtensionVersion constraint"); return; } } // Get a context to use to install the downgraded version of the package. Context pkgContext; try { pkgContext = context.createPackageContextAsUser(callerPackageName, 0, UserHandle.of(mUserId)); } catch (PackageManager.NameNotFoundException e) { sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE, "Invalid callerPackageName"); return; } PackageManager pm = pkgContext.getPackageManager(); try { PackageInstaller packageInstaller = pm.getPackageInstaller(); PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); parentParams.setRequestDowngrade(true); parentParams.setMultiPackage(); if (isStaged()) { parentParams.setStaged(); } parentParams.setInstallReason(PackageManager.INSTALL_REASON_ROLLBACK); int parentSessionId = packageInstaller.createSession(parentParams); PackageInstaller.Session parentSession = packageInstaller.openSession( parentSessionId); for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) { if (pkgRollbackInfo.isApkInApex()) { // No need to issue a downgrade install request for apk-in-apex. It will // be rolled back when its parent apex is downgraded. continue; } PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); String installerPackageName = mInstallerPackageName; if (TextUtils.isEmpty(mInstallerPackageName)) { installerPackageName = pm.getInstallerPackageName( pkgRollbackInfo.getPackageName()); } if (installerPackageName != null) { params.setInstallerPackageName(installerPackageName); } params.setRequestDowngrade(true); params.setRequiredInstalledVersionCode( pkgRollbackInfo.getVersionRolledBackFrom().getLongVersionCode()); if (isStaged()) { params.setStaged(); } if (pkgRollbackInfo.isApex()) { params.setInstallAsApex(); } int sessionId = packageInstaller.createSession(params); PackageInstaller.Session session = packageInstaller.openSession(sessionId); File[] packageCodePaths = RollbackStore.getPackageCodePaths( this, pkgRollbackInfo.getPackageName()); if (packageCodePaths == null) { sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE, "Backup copy of package: " + pkgRollbackInfo.getPackageName() + " is inaccessible"); return; } for (File packageCodePath : packageCodePaths) { try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(packageCodePath, ParcelFileDescriptor.MODE_READ_ONLY)) { final long token = Binder.clearCallingIdentity(); try { session.write(packageCodePath.getName(), 0, packageCodePath.length(), fd); } finally { Binder.restoreCallingIdentity(token); } } } parentSession.addChildSessionId(sessionId); } final LocalIntentReceiver receiver = new LocalIntentReceiver( (Intent result) -> { int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); if (status != PackageInstaller.STATUS_SUCCESS) { // Committing the rollback failed, but we still have all the info we // need to try rolling back again, so restore the rollback state to // how it was before we tried committing. // TODO: Should we just kill this rollback if commit failed? // Why would we expect commit not to fail again? // TODO: Could this cause a rollback to be resurrected // if it should otherwise have expired by now? synchronized (mLock) { mState = ROLLBACK_STATE_AVAILABLE; mRestoreUserDataInProgress = false; info.setCommittedSessionId(-1); } sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL, "Rollback downgrade install failed: " + result.getStringExtra( PackageInstaller.EXTRA_STATUS_MESSAGE)); return; } synchronized (mLock) { if (!isStaged()) { // All calls to restoreUserData should have // completed by now for a non-staged install. mRestoreUserDataInProgress = false; } info.getCausePackages().addAll(causePackages); RollbackStore.deletePackageCodePaths(this); RollbackStore.saveRollback(this); } // Send success. try { final Intent fillIn = new Intent(); fillIn.putExtra( RollbackManager.EXTRA_STATUS, RollbackManager.STATUS_SUCCESS); statusReceiver.sendIntent(context, 0, fillIn, null, null); } catch (IntentSender.SendIntentException e) { // Nowhere to send the result back to, so don't bother. } Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED); for (UserInfo userInfo : UserManager.get(context).getUsers(true)) { context.sendBroadcastAsUser(broadcast, userInfo.getUserHandle(), Manifest.permission.MANAGE_ROLLBACKS); } } ); mState = ROLLBACK_STATE_COMMITTED; info.setCommittedSessionId(parentSessionId); mRestoreUserDataInProgress = true; parentSession.commit(receiver.getIntentSender()); } catch (IOException e) { Slog.e(TAG, "Rollback failed", e); sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE, "IOException: " + e.toString()); } } }
在执行完后,会将mState置为ROLLBACK_STATE_COMMITTED;
mState = ROLLBACK_STATE_COMMITTED;
所以,当我们检查初始化状态为
ROLLBACK_STATE_ENABLING,
开机后的状态为
ROLLBACK_STATE_AVAILABLE,
执行完crash,rollback后的状态为
ROLLBACK_STATE_COMMITTED
这个功能的实现和验证就成功了,实现应用回滚的具体操作。
-
第六十七章 SQL命令 ROLLBACK
2021-11-06 08:07:03文章目录 第六十七章 SQL命令 ROLLBACK大纲参数描述不回滚回滚日志事务挂起ObjectScript事务命令 第六十七章 SQL命令 ROLLBACK 回滚事务。 大纲 ROLLBACK [WORK] ROLLBACK TO SAVEPOINT pointname 参数 point...第六十七章 SQL命令 ROLLBACK 回滚事务。
大纲
ROLLBACK [WORK] ROLLBACK TO SAVEPOINT pointname
参数
pointname
- 作为标识符指定的现有保存点的名称。
描述
ROLLBACK
语句将回滚事务,撤消已执行但未提交的工作,减少$TLEVEL事务级别计数器,并释放锁。
ROLLBACK
用于将数据库恢复到以前的一致状态。ROLLBACK
回滚当前事务期间完成的所有工作,将$TLEVEL
事务级别计数器重置为0
,并释放所有锁。
这会将数据库恢复到事务开始之前的状态。
ROLLBACK
和ROLLBACK WORK
是等价的语句;
这两个版本都支持兼容性。ROLLBACK TO SAVEPOINT pointname
将回滚自指定保存点以来已完成的所有工作,并按未完成的保存点的数量递减$TLEVEL
事务级别计数器。
当所有保存点都被回滚或提交,并且事务级别计数器重置为零时,事务就完成了。
如果指定的保存点不存在,或者已经回滚,ROLLBACK
将发出SQLCODE -375
错误并回滚整个当前事务。
回滚到
SAVEPOINT
必须指定一个点名。
如果不这样做,将导致SQLCODE -301
错误。如果事务操作未能成功完成,则会发出
SQLCODE -400
错误。不回滚
ROLLBACK
操作不影响以下项目:- 回滚不会减少默认类的
IDKey
计数器。
IDKey
是由$INCREMENT
(或$SEQUENCE
)自动生成的,它维护一个独立于SQL
事务的计数。 - 回滚不会逆转缓存查询的创建、修改或清除。
这些操作不被视为事务的一部分。 - 在事务中发生的
DDL
操作或调优表操作可以创建并运行临时例程。
这个临时例程与缓存查询一样被处理。
也就是说,临时例程的创建、编译和删除不被视为事务的一部分。
临时例程的执行被认为是事务的一部分。
回滚日志
提示回滚发生的消息和回滚操作中遇到的错误都记录在
MGR
目录下的Messages.log
文件中。
您可以通过“管理门户系统操作”、“系统日志”、“消息日志”选项查看“Messages.Log
”。事务挂起
%SYSTEM.Process
类的TransactionsSuspending()
方法可用于挂起和恢复系统范围内的所有当前事务。挂起事务会挂起更改的日志记录。因此,如果在当前事务期间发生事务挂起,则ROLLBACK
不能回滚在事务挂起期间所做的任何更改;但是,回滚将回滚在事务挂起生效之前或之后在当前事务期间所做的任何更改。ObjectScript事务命令
ObjectScript
和SQL TRANSACTION
命令完全兼容且可互换,但以下情况除外:如果没有当前事务,
ObjectScript TSTART
和SQL START TRANSACTION
都会启动事务。但是,START TRANSACTION
不支持嵌套事务。因此,如果需要(或可能需要)嵌套事务,最好使用TSTART
启动事务。如果需要与SQL标准兼容,请使用START TRANSACTION
。ObjectScript
事务处理为嵌套事务提供有限的支持。SQL事务处理为事务内的保存点提供支持。ClassMethod ROLLBACK() { &sql(SET TRANSACTION %COMMITMODE EXPLICIT) w !,"Set transaction mode, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(START TRANSACTION) w !,"Start transaction, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(SAVEPOINT a) w !,"Set Savepoint a, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(SAVEPOINT b) w !,"Set Savepoint b, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(SAVEPOINT c) w !,"Set Savepoint c, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(ROLLBACK) w !,"Rollback transaction, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL }
DHC-APP>d ##class(PHA.TEST.SQLCommand).ROLLBACK() Set transaction mode, SQLCODE=0 Transaction level=0 Start transaction, SQLCODE=0 Transaction level=1 Set Savepoint a, SQLCODE=0 Transaction level=2 Set Savepoint b, SQLCODE=0 Transaction level=3 Set Savepoint c, SQLCODE=0 Transaction level=4 Rollback transaction, SQLCODE=0 Transaction level=0
以下嵌入式SQL示例演示了回滚到保存点名称如何将事务级别(
$TLEVEL
)恢复到紧靠指定保存点之前的级别:ClassMethod ROLLBACK1() { &sql(SET TRANSACTION %COMMITMODE EXPLICIT) w !,"Set transaction mode, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(START TRANSACTION) w !,"Start transaction, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL &sql(SAVEPOINT a) w !,"Set Savepoint a, SQLCODE=",SQLCODE w !,"Transaction level at a=",$TLEVEL &sql(SAVEPOINT b) w !,"Set Savepoint b, SQLCODE=",SQLCODE w !,"Transaction level at b=",$TLEVEL &sql(ROLLBACK TO SAVEPOINT b) w !,"Rollback to b, SQLCODE=",SQLCODE w !,"Rollback transaction level=",$TLEVEL &sql(SAVEPOINT c) w !,"Set Savepoint c, SQLCODE=",SQLCODE w !,"Transaction level at c=",$TLEVEL &sql(SAVEPOINT d) w !,"Set Savepoint d, SQLCODE=",SQLCODE w !,"Transaction level at d=",$TLEVEL &sql(COMMIT) w !,"Commit transaction, SQLCODE=",SQLCODE w !,"Transaction level=",$TLEVEL }
DHC-APP>d ##class(PHA.TEST.SQLCommand).ROLLBACK1() Set transaction mode, SQLCODE=0 Transaction level=0 Start transaction, SQLCODE=0 Transaction level=1 Set Savepoint a, SQLCODE=0 Transaction level at a=2 Set Savepoint b, SQLCODE=0 Transaction level at b=3 Rollback to b, SQLCODE=0 Rollback transaction level=2 Set Savepoint c, SQLCODE=0 Transaction level at c=3 Set Savepoint d, SQLCODE=0 Transaction level at d=4 Commit transaction, SQLCODE=0 Transaction level=0
-
Win系统多点还原软件(RRx)RollBack Rx Pro V10.7带序列号版
2018-12-24 09:10:39Win系统多点还原软件(RRx)RollBack Rx Pro V10.7带序列号版,可以对系统进行快照,多点记录,随时还原到记录点,快速还原 -
雨过天晴RollBack 中英文版
2017-03-15 11:11:23RollBack 10.2 雨过天晴 20161207 请分别看压缩包注释,不用winRAR打开可能看不到哦。 -
PDO::rollBack讲解
2020-12-19 23:50:28PDO::rollBack PDO::rollBack — 回滚一个事务(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0) 说明 语法 bool PDO::rollBack ( void ) 回滚由PDO::beginTransaction()发起的当前事务。如果没有事务激活,将抛出一个 ... -
mysql rollback 原理以及若干疑问
2021-01-27 17:59:58如果在commit之前发生异常,进入catch里显式rollback,会造成什么隐形后果,如果在catch里去掉rollback,因为也没有commit所以数据还是不会提交,什么情况下会rollback才会真正发挥作用,并且这个作... -
Win系统多点还原软件(RRx)RollBack Rx Pro V10.7
2018-12-09 21:41:28Win系统多点还原软件(RRx)RollBack Rx Pro V10.7无限制序列号版 -
PostgreSQL事务特性之ROLLBACK
2021-03-15 15:45:48CREATE TABLE postgres=# \dt List of relations Schema | Name | Type | Owner --------+------+-------+---------- public | test | table | postgres (1 row) postgres=# rollback ; ROLLBACK postgres=# \dt No... -
9.2.4 执行ROLLBACK命令
2021-05-08 01:24:479.2.4 执行ROLLBACK命令需要记住的是,如果出现任何错误,那么后台进程就会完全自动地回滚正在进行的事务。例如,如果启动某个事务的会话失败(运行用户进程的计算机可能重启,或者网络连接可能中断),那么PMON进程会... -
MySQL事务-ROLLBACK,COMMIT用法详解
2021-01-19 07:24:56使用ROLLBACK既然我们已经知道了什么是事务处理,下面讨论事务处理的管理中所涉及的问题。管理事务处理的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。MySQL使用下面的语句来标识... -
MYSQL的COMMIT和ROLLBACK使用讲解
2021-02-07 12:06:02MYSQL的COMMIT和ROLLBACK从功能上划分,SQL 语言可以分为DDL,DML和DCL三大类。1. DDL(Data Definition Language)数据定义语言,用于定义和管理 SQL数据库中的所有对象的语言 ;CREATE---创建表ALTER---修改表DROP---... -
回滚SQL:通过ROLLBACK SQL查询回滚事务
2020-07-15 15:59:08The rollback SQL statement is used to manually rollback transactions in MS SQL Server. 回滚SQL语句用于在MS SQL Server中手动回滚事务。 Transactions in SQL Server are used to execute a set of SQL... -
oracle中rollback语句作用范围
2021-05-01 09:42:03(4)正常提交如exit等commit,非正常提交如突然断电rollback 四,ROLLBACK:回滚语句使数据库状态回到上次最后提交事务的状态 ROLLBACK [WORK] TO [SAVEPOINT]//回退到某一点 一个事务起始于DML语句,终止于DDL、DCL... -
oracle中rollback的使用
2021-05-01 11:45:06----》rollback使用SQL> create table tbl(name varchar2(10));Table created.SQL> insert into tbl values('zhiqiao');1 row created.SQL> select * from tbl;NAME----------zhiqiaoSQL> delete tbl;1 ... -
MySql之commit、rollback等事务控制命令
2021-03-03 18:02:39MYSQL 事务处理主要有两种方法1、用 begin, rollback, commit来实现begin或/start transaction)开始一个事务rollback事务回滚commit事务确认2、直接用 SET 来改变 MySQL 的自动提交模式:set autocommit=0禁止自动... -
jdbc rollback,该怎么解决
2021-04-24 13:42:05jdbc rollback Connection conn = null; Statement smt = null; ResultSet result = null; // 注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/... -
MySQL的rollback--大事务回滚
2021-12-06 14:53:46+----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_rollback_on_timeout | OFF | | innodb_rollback_segments | 128 | +----------------------... -
innodb_rollback_on_timeout的作用
2021-02-07 12:06:00导读有时候会发生事务超时的情况,此时MySQL会返回类似这样的错误:那事务...innodb_rollback_on_timeout变量这是官方文档5.7的对innodb_rollback_on_timeout的解释:Command-Line Format--innodb_rollback_on_timeout... -
@Transactional(rollbackFor)
2021-10-27 15:03:52在回滚的设置上,spring提供的是rollbackFor,jdk提供的是rollbackOn,在使用方法上是一致的。 这两个注解在我有限的测试里表现是一样的。 用在哪里 @Transactional注解既可以写在方法上也可以写在类上。写在类上则... -
Flink实战问题(三): Failed to rollback to checkpoint/savepoint
2021-12-27 22:48:33Caused by: java.lang.IllegalStateException: Failed to rollback to checkpoint/savepoint hdfs://127.0.0.1/flink-checkpoints/78f7cb6b577fe6db19648ca63607e640/chk-6976. Cannot map checkpoint/savepoint ... -
Evaluation of rollback points on multiprocessor systems
2021-06-29 18:48:33Evaluation of rollback points on multiprocessor systems Evaluation of Rollback Points on Multiprocessor Systems Kiyomitsu Yoneda, Takashi Matsubara, and Yoshiaki Koga Department of Computer ...