{"id":36650,"date":"2019-10-31T22:12:54","date_gmt":"2019-10-31T19:12:54","guid":{"rendered":"https:\/\/prohoster.info\/blog\/tranzaktsii-v-globalah-intersystems-iris\/"},"modified":"2019-10-31T22:12:54","modified_gmt":"2019-10-31T19:12:54","slug":"tranzaktsii-v-globalah-intersystems-iris","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris","title":{"rendered":"Transactions in InterSystems IRIS globals","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Transactions in InterSystems IRIS globals\" src=\"\/wp-content\/uploads\/2019\/07\/ee4e58369616511dc213f94158b04e4f.jpg\" style=\"display:block;margin: 0 auto;\" \/>The InterSystems IRIS DBMS supports intriguing structures for data storage\u2014globals. Essentially, these are multi-level keys with various additional features such as transactions, fast functions for traversing data trees, locking mechanisms, and its own ObjectScript language.<\/p>\n<p>Learn more about globals in the series of articles 'Globals \u2014 the Sword of Data Storage':<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/263791\/\">Trees. Part 1<\/a><\/noindex> <br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/264173\/\">Trees. Part 2<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/intersystems\/blog\/268465\/\">Sparse Arrays. Part 3<\/a><\/noindex><\/p>\n<p>I became curious about how transactions are implemented in globals and what specific features they have. After all, this structure for data storage is fundamentally different from the familiar tables. It's much more low-level.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nAs known from relational database theory, a good implementation of transactions must meet the following requirements: <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ACID\">ACID<\/a><\/noindex>:<\/p>\n<p><b>A \u2014 Atomicity.<\/b> All changes made in a transaction must be recorded, or none at all.<\/p>\n<p><b>C \u2014 Consistency.<\/b> After a transaction is completed, the logical state of the database must be internally consistent. This requirement largely concerns the programmer, but for SQL databases, it also involves foreign keys.<\/p>\n<p><b>I \u2014 Isolation.<\/b> Transactions running in parallel must not affect each other.<\/p>\n<p><b>D \u2014 Durability.<\/b> After a transaction is successfully completed, issues at lower levels (like power failures) must not affect the data modified by the transaction.<\/p>\n<p>Globals are non-relational data structures. They were created for ultra-fast operation on very limited hardware. Let\u2019s take a closer look at the implementation of transactions in globals using <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/_\/intersystems-iris-data-platform\/plans\/222f869e-567c-4928-b572-eb6a29706fbd?tab=instructions\">the official IRIS Docker image.<\/a><\/noindex>.<\/p>\n<p>To support transactions in IRIS, the following commands are used: <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/irislatest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_ctstart\">TSTART<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/irislatest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_ctcommit\">TCOMMIT<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/irislatest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_ctrollback\">TROLLBACK<\/a><\/noindex>.<\/p>\n<h2>1. Atomicity<\/h2>\n<p>\nIt\u2019s easiest to check atomicity. Let\u2019s check from the database console.<\/p>\n<pre><code class=\"bash\">Kill ^a\nTSTART\nSet ^a(1) = 1\nSet ^a(2) = 2\nSet ^a(3) = 3\nTCOMMIT<\/code><\/pre>\n<p>\nThen we output:<\/p>\n<pre><code class=\"bash\">Write ^a(1), \u201c \u201d, ^a(2), \u201c \u201d, ^a(3)<\/code><\/pre>\n<p>\nWe will get:<\/p>\n<pre><code class=\"bash\">1 2 3<\/code><\/pre>\n<p>\nEverything is in order. Atomicity is preserved: all changes have been recorded.<\/p>\n<p>Let's complicate the task, introduce an error, and see how the transaction is preserved\u2014partially or not at all.<\/p>\n<p>Let\u2019s check atomicity once more:<\/p>\n<pre><code class=\"bash\">Kill ^A\nTSTART\nSet ^a(1) = 1\nSet ^a(2) = 2\nSet ^a(3) = 3<\/code><\/pre>\n<p>\nAfter which we will forcibly stop the container, start it again, and check. <\/p>\n<pre><code class=\"bash\">docker kill my-iris<\/code><\/pre>\n<p>\nThis command is practically equivalent to a forced power off, as it sends an immediate process termination signal SIGKILL.<\/p>\n<p>Could the transaction have been saved partially?<\/p>\n<pre><code class=\"bash\">WRITE ^a(1), ^a(2), ^a(3)\n^\n ^a(1)<\/code><\/pre>\n<p>\n \u2014 No, it wasn't saved.<\/p>\n<p>Let's test the rollback command:<\/p>\n<pre><code class=\"bash\">Kill ^A\nTSTART\nSet ^a(1) = 1\nSet ^a(2) = 2\nSet ^a(3) = 3\nTROLLBACK\n\nWRITE ^a(1), ^a(2), ^a(3)\n^\n ^a(1)<\/code><\/pre>\n<p>\nNothing was saved either.<\/p>\n<h2>2. Consistency<\/h2>\n<p>\nSince in global databases keys are also created on globals (reminding that a global is a lower-level data storage structure than a relational table), to fulfill the consistency requirement the key change must be included in the same transaction as the global change.<\/p>\n<p>For example, we have a global ^person, where we store personal data and use the tax ID as the key.<\/p>\n<pre><code class=\"bash\">^person(1234567, 'firstname') = 'Sergey'\n^person(1234567, 'lastname') = 'Kamenev'\n^person(1234567, 'phone') = '+74995555555\n...<\/code><\/pre>\n<p>\nIn order to facilitate quick searching by surname and first name, we created the key ^index.<\/p>\n<pre><code class=\"bash\">^index('Kamenev', 'Sergey', 1234567) = 1<\/code><\/pre>\n<p>\nTo keep the database consistent, we must add the individual as follows:<\/p>\n<pre><code class=\"bash\">TSTART\n^person(1234567, 'firstname') = 'Sergey'\n^person(1234567, 'lastname') = 'Kamenev'\n^person(1234567, 'phone') = '+74995555555\n^index('Kamenev', 'Sergey', 1234567) = 1\nTCOMMIT<\/code><\/pre>\n<p>\nAccordingly, when deleting we must also use a transaction:<\/p>\n<pre><code class=\"bash\">TSTART\nKill ^person(1234567)\nZKill ^index('Kamenev', 'Sergey', 1234567)\nTCOMMIT<\/code><\/pre>\n<p>\nIn other words, fulfilling the consistency requirement lies entirely on the shoulders of the programmer. But when it comes to globals \u2014 this is normal, given their low-level nature.<\/p>\n<h2>3. Isolation<\/h2>\n<p>\nThis is where things get complicated. Many users are simultaneously working on the same database, modifying the same data.<\/p>\n<p>The situation is comparable to when many users are simultaneously working with the same code repository and trying to commit changes to many files at once.<\/p>\n<p>The database must handle all of this in real-time. Given that in serious companies there is even a dedicated person responsible for version control (for merging branches, resolving conflicts, etc.), and the database must do all this in real-time, the complexity of the task and the correctness of the database design and the code that supports it become apparent.<\/p>\n<p>The database cannot understand the intent of the actions performed by users to prevent conflicts when they are working on the same data. It can only roll back one transaction that contradicts another or execute them sequentially.<\/p>\n<p>Another problem is that during the execution of a transaction (before the commit), the state of the database may be inconsistent. Therefore, it\u2019s preferable for other transactions to have no access to this inconsistent state, which is achieved in relational databases in various ways: by creating snapshots, using multi-versioning of rows, etc.<\/p>\n<p>When executing transactions in parallel, it is important that they do not interfere with each other. This is the property of isolation.<\/p>\n<p>SQL defines 4 levels of isolation:<\/p>\n<ul>\n<li>READ UNCOMMITTED<\/li>\n<li>READ COMMITTED<\/li>\n<li>REPEATABLE READ<\/li>\n<li>SERIALIZABLE<\/li>\n<\/ul>\n<p>\nLet's consider each level separately. The costs to implement each level increase almost exponentially.<\/p>\n<p><b>READ UNCOMMITTED<\/b> \u2014 this is the lowest level of isolation, but it is also the fastest. Transactions can read changes made by each other.<\/p>\n<p><b>READ COMMITTED<\/b> \u2014 this is the next level of isolation, which is a compromise. Transactions cannot read changes made by each other until after the commit, but they can read any changes made after the commit.<\/p>\n<p>If we have a long transaction T1 during which commits occurred in transactions T2, T3 \u2026 Tn that worked with the same data as T1, then when querying data in T1, we will receive different results each time. This phenomenon is called non-repeatable read.<\/p>\n<p><b>REPEATABLE READ<\/b> \u2014 at this level of isolation, we do not experience the non-repeatable read phenomenon because a snapshot of the data results is created for each read request, and the data from the snapshot is used in subsequent reads within the same transaction. However, at this isolation level, reading phantom data is possible. This refers to reading new rows that were added by parallel committed transactions.<\/p>\n<p><b>SERIALIZABLE<\/b> \u2014 the highest level of isolation. It is characterized by the fact that data being used in some way in the transaction (reading or modifying) becomes available to other transactions only after the first transaction is completed.<\/p>\n<p>First, let's determine whether there is isolation of operations in the transaction from the main thread. We'll open 2 terminal windows.<\/p>\n<pre><code class=\"bash\">Kill ^t\n\nWrite ^t(1)\n2<\/code><\/pre>\n<pre><code class=\"bash\">\nTSTART\nSet ^t(1)=2<\/code><\/pre>\n<p>\nThere is no isolation. One thread can see what the other thread doing and that opened the transaction.<\/p>\n<p>Let's see if transactions from different threads can perceive what happens inside them. <\/p>\n<p>We'll open 2 terminal windows and initiate 2 transactions simultaneously.<\/p>\n<pre><code class=\"bash\">kill ^t\nTSTART\nWrite ^t(1)\n3<\/code><\/pre>\n<pre><code class=\"bash\">\nTSTART\nSet ^t(1)=3\n<\/code><\/pre>\n<p>\nParallel transactions can see each other's data. Thus, we have achieved the simplest yet fastest isolation level, READ UNCOMMITTED.<\/p>\n<p>This was somewhat expected for globals, where performance has always been a priority. <\/p>\n<p>What should we do if we need a higher level of isolation in operations on globals?<\/p>\n<p>Here, we need to think about why isolation levels are necessary at all and how they function.<\/p>\n<p>The highest level of isolation, SERIALIZE, ensures that the outcome of concurrently running transactions is equivalent to their sequential execution, thus guaranteeing the absence of collisions.<\/p>\n<p>We can accomplish this using effective locks in ObjectScript, which have a variety of applications: we can perform regular, incremental, and multiple locks using the command <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.intersystems.com\/latest\/csp\/docbook\/DocBook.UI.Page.cls?KEY=RCOS_clock\">LOCK<\/a><\/noindex>.<\/p>\n<p>Lower isolation levels are compromises aimed at increasing database performance.<\/p>\n<p>Let's look at how we can achieve different levels of isolation using locks.<\/p>\n<p>This operator allows for not only exclusive locks necessary for changing data, but also so-called shared locks, which can be held simultaneously by multiple threads when they need to read data that should not be changed by other processes while reading.<\/p>\n<p>More on the two-phase locking method in Russian and English:<\/p>\n<p>\u2192 <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%94%D0%B2%D1%83%D1%85%D1%84%D0%B0%D0%B7%D0%BD%D0%B0%D1%8F_%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0\">Two-phase locking<\/a><\/noindex><br \/>\n\u2192 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Two-phase_locking\">\u0414\u0432\u0443\u0445\u0444\u0430\u0437\u043d\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430<\/a><\/noindex><\/p>\n<p>The challenge is that during a transaction, the state of the database can be inconsistent, but this inconsistent data is visible to other processes. How can we avoid this?<\/p>\n<p>We will create visibility windows with locks where the state of the database will be consistent. All accesses to these visibility windows of consistent state will be controlled by locks.<\/p>\n<p>Shared locks on the same data are reusable \u2014 multiple processes can acquire them. These locks prevent other processes from modifying the data, meaning they are used to establish windows of consistent database state.<\/p>\n<p>Exclusive locks are used for data modifications \u2014 only one process can acquire such a lock. An exclusive lock can be acquired by:<\/p>\n<ol>\n<li>Any process if the data is free<\/li>\n<li>Only the process that has a shared lock on the data and was the first to request an exclusive lock.<\/li>\n<\/ol>\n<p>\n<img decoding=\"async\" alt=\"Transactions in InterSystems IRIS globals\" src=\"\/wp-content\/uploads\/2019\/07\/bb91ed1268925bc1b9266763ab82646a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nThe narrower the visibility window, the longer other processes have to wait, but the more consistent the database state can be within it.<\/p>\n<p><b>READ_COMMITTED<\/b> \u2014 the essence of this level is that we only see committed data from other threads. If the data in another transaction has not yet been committed, we see its old version.<\/p>\n<p>This allows us to parallelize work instead of waiting for a lock to be released.<\/p>\n<p>Without special tricks, we will not be able to see the old version of data in IRIS, so we will have to rely on locks.<\/p>\n<p>Accordingly, we will need to allow data reading only at moments of consistency using shared locks.<\/p>\n<p>Let's say we have a user database ^person, where users transfer money to each other.<\/p>\n<p>The moment of transfer from person 123 to person 242:<\/p>\n<pre><code class=\"bash\">LOCK +^person(123), +^person(242)\nSet ^person(123, amount) = ^person(123, amount) - amount\nSet ^person(242, amount) = ^person(242, amount) + amount\nLOCK -^person(123), -^person(242)<\/code><\/pre>\n<p>\nThe moment of querying the amount of money from person 123 before withdrawal must be accompanied by an exclusive lock (by default):<\/p>\n<pre><code class=\"bash\">LOCK +^person(123)\nWrite ^person(123)<\/code><\/pre>\n<p>\nIf we need to display the account status in the personal dashboard, we can use a shared lock or not use it at all:<\/p>\n<pre><code class=\"bash\">LOCK +^person(123)#\u201dS\u201d\nWrite ^person(123)<\/code><\/pre>\n<p>\nHowever, if we assume that database operations are performed almost instantaneously (let me remind you that globals are a much lower-level structure than a relational table), then the necessity for this level diminishes.<\/p>\n<p><b>REPEATABLE READ<\/b> \u2014 in this level of isolation, it is allowed that there may be multiple reads of data that can be modified by parallel transactions. <\/p>\n<p>Accordingly, we will need to place a shared lock on the data we are reading and exclusive locks on the data we are modifying.<\/p>\n<p>The LOCK operator allows you to detail all the necessary locks in a single operator, which can be quite numerous.<\/p>\n<pre><code class=\"bash\">LOCK +^person(123, amount)#\u201dS\u201d\nreading ^person(123, amount)<\/code><\/pre>\n<p>\nother operations (during this time, parallel threads are trying to change ^person(123, amount), but cannot)<\/p>\n<pre><code class=\"bash\">LOCK +^person(123, amount)\nmodifying ^person(123, amount)\nLOCK -^person(123, amount)\n\nreading ^person(123, amount)\nLOCK -^person(123, amount)#\u201dS\u201d<\/code><\/pre>\n<p>\nWhen listing locks separated by commas, they are taken sequentially, but if done like this:<\/p>\n<pre><code class=\"bash\">LOCK +(^person(123),^person(242))<\/code><\/pre>\n<p>\nthey are taken atomically all at once.<\/p>\n<p><b>SERIALIZE<\/b> \u2014 we will need to set locks in such a way that ultimately all transactions that share data execute sequentially. For this approach, most locks need to be exclusive and taken on the smallest areas of the global for performance.<\/p>\n<p>If we talk about funds withdrawal in global ^person, then only the SERIALIZE isolation level is acceptable, since funds must be spent strictly in sequence, otherwise it is possible to spend the same amount multiple times.<\/p>\n<h2>4. Durability<\/h2>\n<p>\nI conducted tests with the hard shutdown of the container via<\/p>\n<pre><code class=\"bash\">docker kill my-iris<\/code><\/pre>\n<p>\nThe database handled it well. No issues were detected.<\/p>\n<h2>Conclusion<\/h2>\n<p>\nFor globals in InterSystems IRIS, there is support for transactions. They are truly atomic, reliable. However, to ensure database consistency in globals requires programmer effort and the use of transactions, as there are no complex built-in constructs like foreign keys.<\/p>\n<p>The isolation level for globals without using locks is READ UNCOMMITTED, and with locks, it can be ensured up to the SERIALIZE level.<\/p>\n<p>The correctness and speed of transactions on globals heavily depend on the programmer's skill: the more widely shared locks are used during reading, the higher the isolation level, while the more narrowly exclusive locks are taken, the better the performance.<br \/>\n<br \/>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/461753\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u0433\u043b\u043e\u0431\u0430\u043b\u044b. \u041f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e \u043c\u043d\u043e\u0433\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u043b\u044e\u0448\u043a\u0430\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439, \u0431\u044b\u0441\u0442\u0440\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u043e\u0431\u0445\u043e\u0434\u0430 \u0434\u0435\u0440\u0435\u0432\u044c\u0435\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 ObjectScript. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0433\u043b\u043e\u0431\u0430\u043b\u0430\u0445 \u0432 \u0446\u0438\u043a\u043b\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 \u00ab\u0413\u043b\u043e\u0431\u0430\u043b\u044b \u2014 \u043c\u0435\u0447\u0438-\u043a\u043b\u0430\u0434\u0435\u043d\u0446\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445\u00bb: \u0414\u0435\u0440\u0435\u0432\u044c\u044f. \u0427\u0430\u0441\u0442\u044c 1 \u0414\u0435\u0440\u0435\u0432\u044c\u044f. \u0427\u0430\u0441\u0442\u044c 2 \u0420\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u044b. \u0427\u0430\u0441\u0442\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27448,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36650","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u0430\u0445 InterSystems IRIS | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:12:54+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:12:54+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Transactions in globals InterSystems IRIS | ProHoster","description":"The InterSystems IRIS DBMS supports interesting structures.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u0430\u0445 InterSystems IRIS | ProHoster","og:description":"\u0421\u0423\u0411\u0414 InterSystems IRIS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tranzaktsii-v-globalah-intersystems-iris","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:12:54+00:00","article:modified_time":"2019-10-31T19:12:54+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36650","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:17:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:41:52","updated":"2026-01-22 04:17:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/36650","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=36650"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/36650\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/27448"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=36650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=36650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=36650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}