Bank card transaction, what is it in simple words. Bank card transaction, what is it in simple words 1c 8 transactions from external sources

14.02.2024 Windows and disks

This article contains, to a large extent, theoretical information necessary to understand the importance of transactions and locks in 1C:Enterprise and the DBMS, and this is reflected in the performance of 1C:Enterprise. The article popularly describes the relationship between transactions and locks through isolation levels and concurrency problems.
This article does not provide practical advice for solving specific problems, but is the basis for understanding the following articles, which describe steps to optimize and improve 1C:Enterprise performance related to transactions and locks.

Productivity is directly related to 1C:Enterprise TRANSACTIONS

"Lock conflict during transaction:
Microsoft OLE DB Provider for SQL Server: Lock request time out period exceeded.
HRESULT=80040E31, SQLSrvr: SQLSTATE=HYT00, state=34, Severity=10, native=1222, line=1"

If 1C:Enterprise produces an error similar to this, then you are dealing with performance problems associated with blocking. Solving this kind of problem is not always trivial and requires certain special knowledge on the operation of DBMS and 1C:Enterprise, which neither 1C:Enterprise programmers nor system administrators often have. The next series of articles should fill the gap of this knowledge.

Transactions 1C:Enterprise

A transaction is an indivisible sequence of operations on data. It works on an all-or-nothing basis and translates the database
from one integral state to another integral state. If for some reason one of the transaction actions is not executable or some kind of system disruption occurs, the database returns to the state that was before the transaction began (the transaction is rolled back).

There are a number of requirements for the transaction mechanism (known by the abbreviation ACID): Atomicity (Atomicity), Consistency (Consistency), Isolation (Isolation), Sustainability (Durability)

Atomicity (Atomicity). This requirement is that all data that the transaction operates on must be either confirmed ( commit), or canceled ( rollback). There should not be a situation where some changes are confirmed and others are cancelled.

For 1C:Enterprise, the Transaction Atomicity properties ensure the logical integrity of the data. For example, when recording a document, its header data is written to one physical DBMS table, and the tabular part data to another. Recording a document in a transaction guarantees that the data in both physical tables (headers and table parts) will be consistent (it is impossible to write a table part without a header or vice versa).

Isolation (Isolation). Transactions must be performed autonomously and independently of other transactions. When many competing transactions are running simultaneously, any update to a particular transaction will be hidden from others until the transaction is committed. There are several levels of transaction isolation that allow you to choose the most optimal solution in terms of performance and data integrity. The main method for implementing these levels is locking, which will be discussed in this article.

Transaction Log (SQL Server)

Every SQL Server database has a transaction log that records all data changes made in each transaction. If the transaction for some reason did not complete (rolled back or was interrupted), then the SQL server, using the transaction log, cancels all transaction operations sequentially in the reverse order. This means that a long-running write transaction will take a long time and be canceled.

The transaction log is a critical component of the database and, in the event of a system failure, may be required to bring the database into a consistent state. The transaction log should not be deleted or modified unless the possible consequences are known.

Depending on the database settings (recovery model), the transaction transaction log can be trimmed (old transaction data is deleted) either automatically or manually (recovery model=FULL). Sometimes the system administrator forgets to trim the log and an error may occur: " The transaction log for database is full"

Physically, the MS SQL Server DBMS transaction log is located in the .LDF file (and the data file is .MDF).

Transactions in the 1C:Enterprise system

The 1C:Enterprise system implicitly calls transactions when performing any actions related to modifying information stored in the database. For example, all event handlers located in object and recordset modules associated with modification of database data are called in a transaction.

Example of an implicit transaction: sequence of events when posting a document from a form

In practice, you can determine that a 1C:Enterprise object record (for example, a document) is a TV transaction by conducting the following experiment: Try to post and close (click “OK” in the document form) a new document knowing in advance that it will not be posted (for example, by indicating a large quantity of goods to be written off) . Since the balances are checked at the document posting stage, in the "Processing Posting()" handler, by this moment the document itself should already be written to the database, since the document is written earlier between the "BeforeWriting()" and "OnWriting()" events. But after an error message appears (the required quantity is missing), we will find that the document is not recorded in the database (the modification flag “*” will remain and the document will not appear in the list). This happens because the transaction is rolled back after an error occurs (rollback).

Using an Explicit Transaction Call

Method StartTransaction() allows you to open a transaction. All changes to database information made by subsequent statements can then be either entirely accepted or rejected entirely. To accept the changes made, use the method CommitTransaction().
To undo all changes made in an open transaction, use the method CancelTransaction().

The degree of transaction isolation is determined by the isolation levels. The highest level of isolation ensures complete independence of the transaction from other concurrently executing transactions, but the degree of concurrency is also significantly reduced - other transactions have to wait for access to resources used in the current transaction. The lowest isolation level is the opposite: it provides the maximum degree of parallel operation, which leads to a significant impact of other transactions on the current one and the appearance of concurrency problems. In multi-user systems, a trade-off must be made between concurrency (simultaneous access to resources) and transaction isolation levels. The SQL language standard defines isolation levels that, when set, prevent specific concurrency problems.

Concurrency Issues

When executing transactions in parallel, the following problems are possible:
- lost update(eng. lost update) - when one data block is simultaneously changed by different transactions, one of the changes is lost;
- "dirty" reading(eng. dirty read) - reading data added or changed by a transaction that is subsequently not confirmed (rolled back);
- non-repetitive reading(English non-repeatable read) - when reading again within one transaction, the previously read data turns out to be changed;
- phantom reading(English phantom reads) - one transaction, during its execution, selects many rows several times according to the same criteria. Another transaction, between these selections, adds or deletes rows that fall within the selection criteria of the first transaction and ends successfully. As a result, it turns out that the same selections in the first transaction give different sets of rows.

Let's consider situations in which these problems may arise:

Lost update

Dirty reading

If the previous problem occurs when writing data, then a dirty read is possible when one transaction tries to read data that another concurrent transaction is working on.
Suppose there are two transactions opened by different applications in which the following SQL statements are executed:

Non-repetitive reading

Suppose there are two transactions opened by different applications in which the following SQL statements are executed:

Transaction 1 Transaction 2
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;

In Transaction2, the value of field f2 is selected, then in Transaction1 the value of field f2 is changed. If you try to select the value from field f2 again in transaction 1, you will get a different result. This situation is especially unacceptable when data is read with the intent of partially modifying it and writing it back to the database.

Phantom reading

Suppose there are two transactions opened by different applications in which the following SQL statements are executed:

Transaction 1 Transaction 2
SELECT SUM(f2) FROM tbl1;
INSERT INTO tbl1 (f1,f2) VALUES (15,20);
SELECT SUM(f2) FROM tbl1;

Transaction2 executes an SQL statement that uses all the values ​​in field f2. A new row is then inserted in Transaction 1, causing the SQL statement to be re-executed in Transaction 2 to produce a different result. This situation is called a phantom insertion and is a special case of non-repeating read.

Transaction isolation levels

The isolation level is a property of a transaction that determines the independence of the transaction from other transactions running in parallel.

The standard introduces the following four isolation levels, the use of which prevents certain concurrency problems:
- READ_UNCOMMITTED- unfixed reading. This isolation level solves the "lost update" problem, but it is possible to obtain different results for the same queries without regard to transaction commit (possibly a "dirty read" problem). This is the lowest isolation level used in a DBMS and provides maximum concurrency.
- READ_COMMITTED- fixed reading. This isolation level prevents the "dirty read" problem, but allows you to get different results for the same requests in a transaction (the possibility of "non-repeated read" is preserved);
- REPEATABLE_READ- repeated reading. This isolation level solves the "non-repeated read" problem. At this level, it is still possible to execute INSERT statements that lead to a “phantom insert” conflict situation. This level is useful if executing SQL statements are not affected by the addition of new rows;
- SERIALIZABLE- sequential execution. Third level. This level guarantees the prevention of all the concurrency problems described above, but accordingly, the lowest degree of concurrency is observed, since transaction processing (with access to the same resources) is carried out only sequentially.

The solution to the problem of parallel transaction access and isolation levels in the form of a table can be depicted as follows (“+” - the problem is eliminated):

Concurrency Issues and Isolation Levels Phantom reading Non-repetitive reading Dirty reading Lost update
SERIALIZABLE + + + +
REPEATABLE_READ - + + +
READ_COMMITTED - - + +
READ_UNCOMMITTED - - - +

At the SQL server level, you can set the isolation level yourself:
for the entire session, for example by directive
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

for a specific query using the WITH construct
SELECT Name FROM Contracts WITH SERIALIZABLE

Find out the isolation level set in the current session
select transaction_isolation_level from sys.dm_exec_sessions
where session_id = @@spid

Automatic mode (the old mode that was used in 8.0) of data lock management uses transaction isolation levels REPEATABLE_READ And SERIALIZABLE provided by the database management system. These transaction isolation levels ensure consistent and consistent reading of data without requiring any additional lock management efforts from the developer.

Managed locking mode (starting from version 8.1) allows you to increase user concurrency in the client-server mode by using a lower level of database transaction isolation ( READ_COMMITTED); the same isolation level is set by default
and in MS SQL server. When writing data to a transaction, built-in language objects automatically lock the required data. But when reading, the developer needs to manage data locks in cases where business logic requires consistent and consistent reading of data in a transaction.

For version 8.3, managed mode uses isolation level READ_COMMITTED_SNAPSHOT.

conclusions

Transactions are a necessary DBMS mechanism that is actively used in 1C:Enterprise. To solve concurrency problems, transactions in a DBMS can be performed with different levels of isolation.

Isolation level used by 1C:Enterprise READ_COMMITTED solves the “Lost Update” and “Dirty Read” problems: changed data is locked until the end of the transaction for both reading and modification (an exclusive lock is imposed).

Isolation level READ_COMMITTED does not solve the "Non-repeating read" and "Phantom read" problems. To solve these problems, you need to use 1C:Enterprise controlled locks installed programmatically.

8.3 uses a more flexible isolation level READ_COMMITTED_SNAPSHOT.

The word “transaction” came to us only in the late nineties. This was the period of development of the modern banking system and the general computer boom. Then this concept began to appear in colloquial and literary speech. And while ordinary people rarely encounter problems with programmers, everyone has to deal with banks. Almost any operation - from checking the status of an account to complex intra-bank payment transfers - can qualify as transactions. This word is present in banking operations almost more often than concepts such as “money” or “credit”. However, few of the bank's clients fully understand its essence.

Meaning of the word

Transactions are certain procedures for the interaction of any objects over a certain period of time. Such procedures were formed by programmers. They have a clear procedural character. Any transaction is a combination of three essential components:

  • request;
  • execution;
  • report.

The process of a normal transaction can be quite complex, but the result of this procedure has only two states. That is, the transaction may or may not be completed.

Bank transactions

What does the word "transaction" mean? What processes occur when it occurs? To be precise, transactions are any banking operations related to the movement of funds. But most often this term is used when using electronic invoices. Or it directly points to transactions with bank cards.

The phrase “conduct transactions” means transactions using an electronic account. This includes paying utility bills, purchasing goods in a store using a plastic card, depositing salaries and scholarships, and many other money transactions.

Types of transactions

In banking, there are two types of operations:

  1. Online transactions are the manipulation of non-cash money by connecting to a banking center in real time. The most obvious example is working with a terminal.
  2. Offline transactions are the execution of a banking transaction without direct contact between the participants. For example, crediting employees' salaries. Funds are debited from the organization's account, and the employee only receives a notification about the replenishment of the balance of his current account.

To better understand the essence of banking transactions, let's consider several of their options.

Money transaction

The simplest example of such an operation is a transfer between your own accounts, receiving or depositing money, depositing cash through an ATM or terminal. Such transactions are usually carried out by the bank without commission. The situation is more complicated with transfers between two different persons - within the same financial institution, the transfer fee can reach 3%. If we are talking about different banks within the country, the commission will be even higher. The most expensive transfer is to foreign institutions, since, in addition to the commission, they often charge a so-called transaction fee.

Translations

Transfers from one account to another sometimes lead to annoying errors. The slightest inaccuracy in the spelling of the recipient's last name can result in blocking manipulation of the electronic security system. An automatic transaction will solve the problem. This happens, for example, when funds are credited to the recipient’s balance using a bank card number. This significantly reduces the likelihood of error. If the transaction is reset, the money is simply returned to the owner’s balance. True, this happens within ten or fifteen calendar days.

If the sender does not have a bank account, you can use a money transfer service. The most famous international operators are MoneyGram, Western Union, Anelik, Contact and others. The main advantage of such operations is the high transaction speed. The main disadvantage is the rather high commission.

What to do if a transaction fails?

In case of any unusual situation related to the transfer of funds, you must immediately report this to the bank or terminal operator. In this case, there is a high probability that the money will return to the sender’s balance or will be used for its intended purpose.
The operator will help you if:

  • During the transaction, a failure occurred (the program froze, the electricity went out), and the money was already gone. A call to the hotline will record your request. After checking and eliminating the error, specialists will be able to complete the operation manually.
  • The terminal or ATM did not issue a receipt for the transaction. The reason may be trivial - the lack of a cash register tape in the machine. After contacting the operator, you will be offered a duplicate receipt. Usually it is sent to the specified email address.
  • There is an error in the specified details. The money was gone, but the recipient never saw it.
    The operator can help solve this problem: for example, find an error in the recipient's account number. In this case, the money does not reach the client simply because of security rules. Such funds are not withdrawn by the bank, but are stored for 10 days in a special temporary account. If the sender contacts the financial institution on time, indicates the time of the transaction, the amount of the transfer and answers several questions, the money will be unblocked. After deducting the transaction fee, the amount will be returned to the sender’s balance.

As you can see, banking transactions are an interesting, necessary procedure in the life of each of us. Next time, when making a simple transfer or withdrawing money from a card, think about how much easier such manipulations make our lives. After all, by now you probably already know what transactions are. The meaning of the word is no secret to you.

Many people wonder what a transaction is? After all, this word comes up all the time, especially if a person works with money. If we take it globally - the sequence of data exchange operations, after which system changes are made.

The most common use of the term is in making money transfers and purchasing goods. It could be:

  • Cash withdrawal from an ATM or bank branch;
  • Purchasing a certain number of shares on the stock exchange;
  • Payment by card in the store.

As soon as the operation has been confirmed and the money has been sent, the transaction is considered successfully completed. Money is withdrawn from the account of the buyer or client of the institution, and the goods are transferred to the individual. We can say that the transaction serves as a way to voluntarily transfer money from a person’s account to the person providing the service. All transactions are recorded in the financial institution's database. It doesn't matter whether the operation was successful or not. For example, in case of incorrect crediting of funds to a bank card.

But don’t think that the concept of a transaction applies only to the financial sector. IT companies also often use this term, especially when it comes to database programming. In this case, the term will mean a certain sequence of changes made to the data base.

There are also two application options here. When an operation is approved, “Commit” is assigned to it, but if for some reason a refusal occurs, then “Rollback” is assigned. Most often, this happens when they wanted to divide one of the numbers by zero or entered an amount that does not correspond to what was previously entered into the database.

Kinds

The most common case of using a transaction is payment with a payment card from a bank on the territory of any shopping center, store or financial institution. The operation begins when the owner wishes to pay for the goods, after which he gives his bank card to the employee responsible for the cash register.

Next, the card is placed in a special terminal, where you only need to confirm the subsequent operation. To do this, you need to enter data and a predetermined PIN code. Next, the terminal will decide whether the entered password was correct or should be rejected. In any case, information about the transaction will be recorded in a specific database. This happens due to the transfer of data to the payment system servicing this card. And already at this stage, a full verification of the authenticity of the entered data takes place. After all, they may or may not be present on the payment slip.

But if everything is correct, the transaction is successfully completed and sent straight to the issuing bank. The production of this payment card was carried out through him. Then the information about the transaction is sent to the pressing center, where information about the rights to use the payment system is established.

It is worth noting that if an error or data discrepancy is detected at one of the stages, then the transaction is simply refused.

Areas of use

In different areas of application, different notations for the word “transaction” are used:

  • Economics refers to the transfer of funds from one flow account to another. This is especially true for purchase and sale transactions;
  • Operations with ATMs result in the issuance of cash to a client who used a bank card or account number to receive it;
  • A political explanation carries an agreement on mutually beneficial terms between two parties.

Much depends on the card issued by the bank. Debit and credit card are handled differently. The login priority, which is set by the financial institution that issued the card, also has a direct impact. Depending on these factors, the speed of the operation will vary.

Transactions with small amounts of money look simpler. If a person has specified a certain setting in the parameters, he will have the opportunity not to enter a password during the transaction. It will be carried out automatically and if there is a sufficient amount of funds in the account, they will be written off, and information about the operation will be recorded in the database.

Even areas completely unrelated to finance operate with the concept of “transactions.” Psychology is given as an example. Specialists in this field call a transaction the exchange of stimuli that arises during a conversation between two individuals. This application is somewhat far-fetched, but has a right to exist. Now you know what transactions are.

You need to know at least the above information about transactions, since it is simply impossible to do without them in the modern world. This means you should still have a minimal idea.

Each client has his own repeating habits and traditions. Whether it’s a favorite day to shop, preferences for the average cost of a product, or for additional options for a product. All this information will help us encourage the client to make a second purchase and move from a new user to a regular customer.

We are moving from one-time purchases to regular customers

Well, you managed to convert the client. This is cool, but what next? According to statistics, from 30% to 80% of buyers in the e-commerce industry make an order only once during their entire life cycle. In the gaming industry, 60% of customers make a second order. How can we get loyal customers with such disappointing numbers?

This question worries marketers around the world. They work hard, putting all their efforts into converting clients from one-time clients to permanent ones. Be it initial orders in retail or deposits in online games. Why is the second order so important? If a customer makes their second order or makes a second deposit, the likelihood of making a third order increases tenfold compared to customers who have only made one order.

The table below combines data from ten leading ecommerce companies in Europe and the USA. As can be seen from the graph, the probability of making the next transaction increases with the number of current transactions.


Probability of the next transaction depending on the number of current transactions

Many companies group one-time customers into one group and use different techniques and messages to encourage a second purchase. Sounds like a good plan, right? One way or another, all clients in the group are one-time buyers. But we are here to discuss a different approach. This second method involves dividing a group of one-time customers into different segments based on the characteristics of their first transaction. Let's dive deeper and consider the prerequisites for such segmentation.

Day of the week

We'll start by analyzing the behavior of repeat buyers of the top 10 companies and try to understand whether there is a relationship between the day of the first order and the day of the second order. Let's start with an analysis of sports betting. In this theme, the client makes a deposit on the day when the most matches of his favorite team take place, usually on Saturday or Sunday. The likelihood of such clients returning and placing bets these days is quite high.

We collected data and ran tests and the results were the same as we expected. Basically, the second deposit was left on the same day of the week as the first. This can be seen from the maximum probability value located on the diagonal of the square.


Probability of making a second transaction depending on the day of the week of the first transaction in sports betting

The dependency between these two transactions can help better target promotional activities to different cohorts of one-time customers (in this case we have 7 groups based on the day of the first transaction) and remind the second transaction on appropriate days. A more interesting step is to test this hypothesis in retail.


Probability of making a second transaction depending on the day of the week of the first transaction in retail

We can see a similar situation. Customers make their second purchase on the same day of the week as their first. It is important to note that the dispersion in the retail industry was higher than in the sports betting industry. But the dependence itself manifested itself for each company. The most popular day for shopping is Monday, the least popular is Sunday. If we consider the dependencies between orders for only one brand, we get this.


Probability of making a second transaction depending on the day of the week of the first retail transaction for one brand

We have a simple explanation for this behavior in sports betting, but why do we see this result in retail? The reason may be that buyers have certain patterns in their lives. You go to the gym on Thursdays and Fridays, hang out with your family on the weekends, stay late at work on Mondays, and meet friends on Fridays. The buying pattern doesn't look strange considering all the others.

Times of Day

As you might have guessed, we tested similar hypotheses for time of day. Is there a correlation between the time of day of the first order and the second, if the second order was made at least seven days later? We divided the day into 4 periods: night, morning, evening and afternoon - and checked the distribution of second orders for each time period for 6 brands.


Probability of a second order depending on the time of day of the first order

The relationship between the first and second order by time of day seems obvious. Customers who order late at night for the first time are likely to place a second order at the same time.

Cost of goods in the order

As marketers, we strive to increase the number of items ordered. Upselling is a way of life in the marketing world, and if it's not, it should be. But should we always try to upsell a product? Is this the best solution for all of our clients? In our analysis, we examined whether the cost of goods in the second order increases compared to the first.

Different brands are used as data sources, so for each brand we identified separate segments with the value of the product. This resulted in 6 price groups.


Probability of the cost of the second order depending on the cost of the first order

Most of the customers whose orders were placed in the low price range remained in the same range in the second order.

Conclusion

Our analysis above shows what we can learn from the first orders. The main thing we need to remember is that we should not put all one-time clients in one group. It is worth segmenting customers depending on their day of the week and time of purchase, and the cost of the order.
Using these methods and steps will help you better understand how to increase LTV and gain more loyal customers.

2017-08-12

Create custom transactions for maintaining OM objects.

Introduction

I think that many functional SAP consultants have encountered the transaction of maintaining organizational management objects. Namely, the transaction PP01

Using this transaction provides the user with the ability to administer organizational management infotypes for those object types that are used in the business processes being automated. Very often this transaction is used as a single entry point for working with all types of organizational management objects, which, in reality, is not a very good practice. Well, or not very convenient. Although certainly common. Next, I will try to tell you what an alternative there might be.

Table T77S0, group "TCODE"

When setting up OM object objects, you will probably touch the setting located in the following path in SPRO:

IMG: Personnel Management -> Organizational Management -> Basic Settings -> Data Model Enhancement -> Maintain Object Types

Here you create new OM objects, come up with names for them, select icons and define some settings for them... At the moment we are interested in the node " Object Type Key + Transaction"

Part of the setup view will open in front of you T77S0 with filtered group values

Worth paying attention to the group TCODE in which, if you look closely, you can find the technical names of transactions that you most likely had to work with. Moreover, in the column Value indicates the type of object for which a particular transaction is intended.

What is special about these transactions?

By using transactions that are designed to maintain a specific type of object, you no longer need to select these very types of objects that are available, by default, in a transaction PP01. That is, by launching, for example, a transaction PO09, you immediately start working with objects like L

Creating a new transaction for your own organizational management object

In one of my previous posts, I talked about how you can create a new OM object + add a structural search for it

I won’t go far from this material. As a demonstration, I'll create a new transaction to maintain an object 91.

Defining a new object type in T77S0

Define the name of the future transaction in the setup view T77S0

The value "ZP91M" in this case is the name of the future transaction for maintaining the object 91 . Save your changes.

Creating a new transaction to maintain an OM object

Via transaction SE93 create a transaction to maintain your object. Below is a video fragment with the sequence of actions that must be performed to create the corresponding transaction

Note the values ​​that were used for the fields Program, Screen Number,Authorization Object. Now start a new transaction

The user has the opportunity to work only with a certain type of object, which, in a certain sense, can be called convenience, and, if you like, minimizing additional actions to select the desired object.

The title came out catchy, but it boiled over. I’ll say right away that we’ll be talking about 1C. Dear 1C users, you do not know how to work with transactions and do not understand what exceptions are. I came to this conclusion by looking at a large amount of 1C code generated in the wilds of the domestic enterprise. In typical configurations, this is all quite good, but a terrifying amount of custom code is written incompetently from the point of view of working with the database. Have you ever seen the error “This transaction has already encountered errors”? If yes, then the title of the article applies to you too. Let's finally figure out what transactions are and how to handle them correctly when working with 1C.

Why should we sound the alarm?

First, let's figure out what the "Errors have already occurred in this transaction" error is. This is, in fact, an extremely simple thing: you are trying to work with the database inside an already rolled back (cancelled) transaction. For example, somewhere the CancelTransaction method was called, and you are trying to commit it.


Why is that bad? Because this error doesn't tell you anything about where the problem actually happened. When a screenshot with such text comes to support from a user, and especially for server code that no one can interact with interactively, it’s... I wanted to write “critical error,” but I thought it was a buzzword that no one pays attention to anymore... This is an ass. This is a programming error. This is not a random glitch. This is a bug that needs to be fixed immediately. Because when your background server processes go down at night and the company starts rapidly losing money, then “Errors have already occurred in this transaction” is the last thing you want to see in the diagnostic logs.


There is, of course, a possibility that the server’s technological log (it’s turned on in production, right?) will somehow help diagnose the problem, but right now I can’t think of an option off the top of my head - how exactly to find the real cause of this error in it. But the real reason is one - the programmer Vasya received an exception within a transaction and decided that once was not a bad idea, “just think, it’s a mistake, let’s move on.”

What are transactions in 1C

It’s awkward to write about elementary truths, but apparently a little will be necessary. Transactions in 1C are the same as transactions in a DBMS. These are not some special “1C” transactions, these are transactions in the DBMS. According to the general idea of ​​transactions, they can either be executed entirely or not executed at all. All changes to database tables made within a transaction can be immediately undone, as if nothing had happened.


Next, you need to understand that 1C does not support nested transactions. As a matter of fact, they are not supported “in 1C”, but not supported at all. At least those DBMSs that 1C can work with. Nested transactions, for example, do not exist in MS SQL and Postgres. Each “nested” call to StartTransaction simply increments the transaction counter, and each call to “CommitTransaction” simply decreases this counter. This behavior is described in many books and articles, but the conclusions from this behavior are apparently not sufficiently analyzed. Strictly speaking, in SQL there is a so-called. SAVEPOINT, but 1C does not use them, and this thing is quite specific.



Procedure Very Useful and Important Code(List of Directory Links) StartTransaction();

For Each Link From the List of Directory Links Loop Directory Object = Link.GetObject();

Directory Object.SomeField = "I was changed from program code";


Directory object.Write(); EndCycle;.


Please note that the code is simple. There is simply a lot of this in your 1C systems. And it contains at least 3 errors at once. Think at your leisure how many errors there are in more complex scenarios for working with transactions written by your 1C programmers :)

Object locks

So, the first mistake. In 1C there are object locks, the so-called “optimistic” and “pessimistic”. I don’t know who coined the term, I would have killed him :). It is absolutely impossible to remember which of them is responsible for what. They have been written about in detail, as well as in other general IT literature.


The essence of the problem is that in the specified code example, a database object is changed, but in another session there may be an interactive user (or a neighboring background thread) who will also change this object. Here, one of you may receive the error "the entry has been modified or deleted." If this happens in an interactive session, the user will scratch his butt, swear, and try to reopen the form. If this happens in a background thread, then you will have to look for it in the logs. And the logbook, as you know, is slow, and only a few people in our industry set up the ELK stack for 1C logs... (we, by the way, are among those who set up and help others set up :))


In short, this is an annoying mistake and better not to have it. Therefore, the development standards clearly state that before changing objects, it is necessary to place an object lock on them using the " Directory object.Lock()". Then the concurrent session (which must also do this) will not be able to start the update operation and will receive the expected, controlled failure.

And now about transactions

We've dealt with the first mistake, let's move on to the second.


If you do not provide exception checking in this method, then an exception (for example, very likely in the “Write()” method) will throw you out of this method without completing the transaction. An exception from the “Write” method can be thrown for a variety of reasons, for example, some application checks in the business logic are triggered, or the above-mentioned object lock occurs. Anyway, the second error says: The code that started the transaction is not responsible for its completion.



That's exactly what I would call this problem. In our static 1C code analyzer based on SonarQube, we even separately built in such diagnostics. Now I’m working on its development, and the imagination of 1C programmers, whose code comes to me for analysis, sometimes leaves me in shock and awe...


Why? Because an exception thrown at the top inside a transaction in 90% of cases will not allow this transaction to be committed and will lead to an error. It should be understood that 1C automatically rolls back an unfinished transaction only after returning from the script code to the platform code level.


As long as you are at the 1C code level, the transaction remains active.


Let's go up one level in the call stack:

Procedure ImportantCode() LinkList = GetLinkListWhere();

VeryUsefulAndImportantCode(LinkList); End of Procedure

Look what happens. Our problematic method is called from somewhere outside, higher up the stack. At the level of this method, the developer has no idea whether there will be any transactions inside the Very Useful and Important Code method or not. And if there are, will they all be completed... We are all here for peace and encapsulation, right? The author of the "ImportantCode" method should not think about what exactly happens inside the method he calls. The same one in which the transaction is processed incorrectly. As a result, an attempt to work with the database after an exception has been thrown from within a transaction will most likely result in the following: “In this transaction blah blah...” Spreading transactions across methods The second rule of "transaction-safe" code:


The transaction reference count at the beginning of the method and at its end must have the same value


. You cannot start a transaction in one method and end it in another. It is probably possible to find exceptions to this rule, but this will be some kind of low-level code written by more competent people. In general, you can't write this way.

For example:


Procedure ImportantCode() LinkList = GetLinkListWhere();

VeryUsefulAndImportantCode(LinkList);

Let's go back to the original method and try to fix it. I’ll say right away that we won’t fix the object lock for now, just so as not to complicate the example code.

The first approach of a typical 1C nickname

Typically, 1C programmers know that an exception may be thrown when recording. They are also afraid of exceptions, so they try to catch them all. For example, like this:


Procedure Very Useful and Important Code(List of Directory Links) StartTransaction();

For Each Link From the List of Directory Links Loop Directory Object = Link.GetObject();


Directory Object.SomeField = "I was changed from program code";


AttemptDirectoryObject.Write();


Exception Log.Error("Could not write element %1", Link); Continue; EndAttempt;

EndCycle;

CommitTransaction(); End of Procedure

  • Well, things have gotten better, right? After all, now possible recording errors are processed and even logged. Exceptions will no longer be thrown when writing an object. And in the log you can even see on which object, I wasn’t too lazy and included a link in the message instead of the laconic “Error in writing a directory,” as developers who are always in a hurry often like to write. In other words, there is a concern for the user and an increase in competencies.
  • CommitTransaction()
  • CancelTransaction()
  • TransactionActive()

The first 3 methods are obvious and do what their names say. The last method returns True if the transaction counter is greater than zero.


And there is an interesting feature. The transaction exit methods (Commit and Cancel) throw exceptions if the transaction count is zero. That is, if you call one of them outside of a transaction, an error will occur.


How to use these methods correctly? It’s very simple: you need to read the rule formulated above:


How to comply with this rule? Let's try:


We already understood above that the Do Something method is potentially dangerous. It may throw some kind of exception, and the transaction will “crawl out” of our method. Okay, let's add a possible exception handler:


StartTransaction(); Try DoSomething(); Exception // but what should I write here? EndAttempt; CommitTransaction();

Great, we caught the error that was occurring, but what should we do about it? Write a message to the log? Well, maybe if the error logging code should be exactly at this level and we are waiting for an error here. And if not? What if we didn't expect any errors here? Then we should just pass that exception up and let another layer of the architecture deal with it. This is done with the "CauseException" operator without arguments. In these Javascripts of yours, this is done in exactly the same way with the throw operator.


StartTransaction(); Try DoSomething(); Exception ThrowException; EndAttempt; CommitTransaction();

So, wait... If we just throw the exception further, then why is there a need for an Attempt at all? Here's why: the rule forces us to ensure the completion of the transaction we started.


StartTransaction(); Try DoSomething(); ExceptionCancelTransaction();

throwException; EndAttempt; CommitTransaction(); Now it seems to be beautiful. However, we remember that we do not trust the Do Something() code. What if the author inside didn’t read this article and doesn’t know how to work with transactions? What if he took it there and called the CancelTransaction method or, on the contrary, committed it? It is very important for us that the exception handler did not throw a new exception

, otherwise the original error will be lost and troubleshooting will become impossible. And we remember that the Commit and Cancel methods can throw an exception if the transaction does not exist. This is where the TransactionActive method comes in handy.

Final version


**UPD: the comments suggested a safer option when CommitTransaction is located inside the Attempt block. This particular option is shown here; previously Fixation was located after the Attempt-Exception block.


StartTransaction(); Try DoSomething();

CommitTransaction(); Exception If TransactionIsActive() Then CancelTransaction(); endIf; throwException; EndAttempt; Wait, but it’s not only “CancelTransaction” that can produce errors. Why then isn't "CommitTransaction" wrapped in the same condition with "TransactionActive"? Again, using the same rule:.

The code that started the transaction should be responsible for completing it.

Our transaction is not necessarily the very first; it can be nested. At our level of abstraction, we are only required to care about our transaction. All others should be of no interest to us. They are strangers, we should not be responsible for them. Precisely they SHOULD NOT. No attempt should be made to determine the actual transaction counter level. This will again break encapsulation and lead to “smearing” transaction management logic. We only checked for activity in the exception handler and only to make sure that our handler


will not generate a new exception, “hiding” the old one


Refactoring checklist

Let's look at some of the most common situations that require code intervention.


will not generate a new exception, “hiding” the old one


Pattern:

StartTransaction(); DoSomething(); CommitTransaction();


Wrap it in a “safe” design with Attempt, Keep Alive and Throw an Exception.


If NotTransactionActive() ThenStartTransaction()EndIf

Analysis and Refactoring. The author didn't understand what he was doing. It is safe to start nested transactions. There is no need to check the condition, you just need to start the nested transaction. Below the module, it is probably still distorted there with their fixation. This is guaranteed hemorrhoids.


will not generate a new exception, “hiding” the old one


A roughly similar option:
  1. If Transaction is Active() Then CommitTransaction() EndIf
  2. similarly: committing a transaction by condition is strange. Why is there a condition here? What, someone else could have already recorded this transaction? Reason for trial.
  3. StartTransaction() While Select.Next() Loop // reading an object by reference // writing an object EndCycle; CommitTransaction();

will not generate a new exception, “hiding” the old one


StartTransaction() While Select.Next() Loop Attempt Object.Write();

Exception Report("Failed to write");

EndAttempt; EndCycle; CommitTransaction();

This transaction will no longer complete in the event of an exception. There's no point in continuing the cycle. The code needs to be rewritten, checking the original task. Additionally provide a more informative error message.

Finally

I, as you probably already guessed, am one of the people who loves the 1C platform and development on it. Of course, there are complaints about the platform, especially in the Highload environment, but in general, it allows you to inexpensively and quickly develop very high-quality enterprise applications. Providing out of the box an ORM, a GUI, a web interface, Reporting, and much more. In the comments on Habré they usually write all sorts of arrogant things, so guys - the main problem with 1C, as an ecosystem, is not a platform or a vendor. This is too low a threshold for entry, which allows people to enter the industry who do not understand what a computer, database, client-server, network and all that is. 1C has made enterprise application development too easy. In 20 minutes I can write an accounting system for purchases/sales with flexible reports and a web client. After this, it’s easy for me to think to myself that on a larger scale you can write in much the same way. Somehow 1C will do everything internally, I don’t know how, but it will probably do it. Let me write "StartTransaction()"....